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 18 extern int test_fpu(double *darray, pid_t *pid); 19 20 double darray[] = {0.1, 0.2, 0.3, 0.4, 0.5, 0.6, 0.7, 0.8, 0.9, 1.0, 21 1.1, 1.2, 1.3, 1.4, 1.5, 1.6, 1.7, 1.8, 1.9, 2.0, 22 2.1}; 23 24 int syscall_fpu(void) 25 { 26 pid_t fork_pid; 27 int i; 28 int ret; 29 int child_ret; 30 for (i = 0; i < 1000; i++) { 31 /* test_fpu will fork() */ 32 ret = test_fpu(darray, &fork_pid); 33 if (fork_pid == -1) 34 return -1; 35 if (fork_pid == 0) 36 exit(ret); 37 waitpid(fork_pid, &child_ret, 0); 38 if (ret || child_ret) 39 return 1; 40 } 41 42 return 0; 43 } 44 45 int test_syscall_fpu(void) 46 { 47 /* 48 * Setup an environment with much context switching 49 */ 50 pid_t pid2; 51 pid_t pid = fork(); 52 int ret; 53 int child_ret; 54 FAIL_IF(pid == -1); 55 56 pid2 = fork(); 57 /* Can't FAIL_IF(pid2 == -1); because already forked once */ 58 if (pid2 == -1) { 59 /* 60 * Couldn't fork, ensure test is a fail 61 */ 62 child_ret = ret = 1; 63 } else { 64 ret = syscall_fpu(); 65 if (pid2) 66 waitpid(pid2, &child_ret, 0); 67 else 68 exit(ret); 69 } 70 71 ret |= child_ret; 72 73 if (pid) 74 waitpid(pid, &child_ret, 0); 75 else 76 exit(ret); 77 78 FAIL_IF(ret || child_ret); 79 return 0; 80 } 81 82 int main(int argc, char *argv[]) 83 { 84 return test_harness(test_syscall_fpu, "syscall_fpu"); 85 86 } 87