1 // SPDX-License-Identifier: GPL-2.0-or-later 2 /* 3 * Copyright 2015, Cyril Bur, IBM Corp. 4 * 5 * This test attempts to see if the FPU registers change across a syscall (fork). 6 */ 7 8 #include <stdio.h> 9 #include <unistd.h> 10 #include <sys/syscall.h> 11 #include <sys/time.h> 12 #include <sys/types.h> 13 #include <sys/wait.h> 14 #include <stdlib.h> 15 16 #include "utils.h" 17 #include "fpu.h" 18 19 extern int test_fpu(double *darray, pid_t *pid); 20 21 double darray[32]; 22 23 int syscall_fpu(void) 24 { 25 pid_t fork_pid; 26 int i; 27 int ret; 28 int child_ret; 29 30 randomise_darray(darray, ARRAY_SIZE(darray)); 31 32 for (i = 0; i < 1000; i++) { 33 /* test_fpu will fork() */ 34 ret = test_fpu(darray, &fork_pid); 35 if (fork_pid == -1) 36 return -1; 37 if (fork_pid == 0) 38 exit(ret); 39 waitpid(fork_pid, &child_ret, 0); 40 if (ret || child_ret) 41 return 1; 42 } 43 44 return 0; 45 } 46 47 int test_syscall_fpu(void) 48 { 49 /* 50 * Setup an environment with much context switching 51 */ 52 pid_t pid2; 53 pid_t pid = fork(); 54 int ret; 55 int child_ret; 56 FAIL_IF(pid == -1); 57 58 pid2 = fork(); 59 /* Can't FAIL_IF(pid2 == -1); because already forked once */ 60 if (pid2 == -1) { 61 /* 62 * Couldn't fork, ensure test is a fail 63 */ 64 child_ret = ret = 1; 65 } else { 66 ret = syscall_fpu(); 67 if (pid2) 68 waitpid(pid2, &child_ret, 0); 69 else 70 exit(ret); 71 } 72 73 ret |= child_ret; 74 75 if (pid) 76 waitpid(pid, &child_ret, 0); 77 else 78 exit(ret); 79 80 FAIL_IF(ret || child_ret); 81 return 0; 82 } 83 84 int main(int argc, char *argv[]) 85 { 86 return test_harness(test_syscall_fpu, "syscall_fpu"); 87 88 } 89