162306a36Sopenharmony_ci// SPDX-License-Identifier: GPL-2.0-or-later 262306a36Sopenharmony_ci/* 362306a36Sopenharmony_ci * Copyright 2015, Cyril Bur, IBM Corp. 462306a36Sopenharmony_ci * 562306a36Sopenharmony_ci * This test attempts to see if the VMX registers change across a syscall (fork). 662306a36Sopenharmony_ci */ 762306a36Sopenharmony_ci 862306a36Sopenharmony_ci#include <altivec.h> 962306a36Sopenharmony_ci#include <stdio.h> 1062306a36Sopenharmony_ci#include <unistd.h> 1162306a36Sopenharmony_ci#include <sys/syscall.h> 1262306a36Sopenharmony_ci#include <sys/time.h> 1362306a36Sopenharmony_ci#include <stdlib.h> 1462306a36Sopenharmony_ci#include <sys/types.h> 1562306a36Sopenharmony_ci#include <sys/wait.h> 1662306a36Sopenharmony_ci#include "utils.h" 1762306a36Sopenharmony_ci 1862306a36Sopenharmony_civector int varray[] = {{1, 2, 3, 4}, {5, 6, 7, 8}, {9, 10,11,12}, 1962306a36Sopenharmony_ci {13,14,15,16},{17,18,19,20},{21,22,23,24}, 2062306a36Sopenharmony_ci {25,26,27,28},{29,30,31,32},{33,34,35,36}, 2162306a36Sopenharmony_ci {37,38,39,40},{41,42,43,44},{45,46,47,48}}; 2262306a36Sopenharmony_ci 2362306a36Sopenharmony_ciextern int test_vmx(vector int *varray, pid_t *pid); 2462306a36Sopenharmony_ci 2562306a36Sopenharmony_ciint vmx_syscall(void) 2662306a36Sopenharmony_ci{ 2762306a36Sopenharmony_ci pid_t fork_pid; 2862306a36Sopenharmony_ci int i; 2962306a36Sopenharmony_ci int ret; 3062306a36Sopenharmony_ci int child_ret; 3162306a36Sopenharmony_ci for (i = 0; i < 1000; i++) { 3262306a36Sopenharmony_ci /* test_vmx will fork() */ 3362306a36Sopenharmony_ci ret = test_vmx(varray, &fork_pid); 3462306a36Sopenharmony_ci if (fork_pid == -1) 3562306a36Sopenharmony_ci return -1; 3662306a36Sopenharmony_ci if (fork_pid == 0) 3762306a36Sopenharmony_ci exit(ret); 3862306a36Sopenharmony_ci waitpid(fork_pid, &child_ret, 0); 3962306a36Sopenharmony_ci if (ret || child_ret) 4062306a36Sopenharmony_ci return 1; 4162306a36Sopenharmony_ci } 4262306a36Sopenharmony_ci 4362306a36Sopenharmony_ci return 0; 4462306a36Sopenharmony_ci} 4562306a36Sopenharmony_ci 4662306a36Sopenharmony_ciint test_vmx_syscall(void) 4762306a36Sopenharmony_ci{ 4862306a36Sopenharmony_ci /* 4962306a36Sopenharmony_ci * Setup an environment with much context switching 5062306a36Sopenharmony_ci */ 5162306a36Sopenharmony_ci pid_t pid2; 5262306a36Sopenharmony_ci pid_t pid; 5362306a36Sopenharmony_ci int ret; 5462306a36Sopenharmony_ci int child_ret; 5562306a36Sopenharmony_ci 5662306a36Sopenharmony_ci // vcmpequd used in vmx_asm.S is v2.07 5762306a36Sopenharmony_ci SKIP_IF(!have_hwcap2(PPC_FEATURE2_ARCH_2_07)); 5862306a36Sopenharmony_ci 5962306a36Sopenharmony_ci pid = fork(); 6062306a36Sopenharmony_ci FAIL_IF(pid == -1); 6162306a36Sopenharmony_ci 6262306a36Sopenharmony_ci pid2 = fork(); 6362306a36Sopenharmony_ci ret = vmx_syscall(); 6462306a36Sopenharmony_ci /* Can't FAIL_IF(pid2 == -1); because we've already forked */ 6562306a36Sopenharmony_ci if (pid2 == -1) { 6662306a36Sopenharmony_ci /* 6762306a36Sopenharmony_ci * Couldn't fork, ensure child_ret is set and is a fail 6862306a36Sopenharmony_ci */ 6962306a36Sopenharmony_ci ret = child_ret = 1; 7062306a36Sopenharmony_ci } else { 7162306a36Sopenharmony_ci if (pid2) 7262306a36Sopenharmony_ci waitpid(pid2, &child_ret, 0); 7362306a36Sopenharmony_ci else 7462306a36Sopenharmony_ci exit(ret); 7562306a36Sopenharmony_ci } 7662306a36Sopenharmony_ci 7762306a36Sopenharmony_ci ret |= child_ret; 7862306a36Sopenharmony_ci 7962306a36Sopenharmony_ci if (pid) 8062306a36Sopenharmony_ci waitpid(pid, &child_ret, 0); 8162306a36Sopenharmony_ci else 8262306a36Sopenharmony_ci exit(ret); 8362306a36Sopenharmony_ci 8462306a36Sopenharmony_ci FAIL_IF(ret || child_ret); 8562306a36Sopenharmony_ci return 0; 8662306a36Sopenharmony_ci} 8762306a36Sopenharmony_ci 8862306a36Sopenharmony_ciint main(int argc, char *argv[]) 8962306a36Sopenharmony_ci{ 9062306a36Sopenharmony_ci return test_harness(test_vmx_syscall, "vmx_syscall"); 9162306a36Sopenharmony_ci 9262306a36Sopenharmony_ci} 93