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 FPU registers change across a syscall (fork). 662306a36Sopenharmony_ci */ 762306a36Sopenharmony_ci 862306a36Sopenharmony_ci#include <stdio.h> 962306a36Sopenharmony_ci#include <unistd.h> 1062306a36Sopenharmony_ci#include <sys/syscall.h> 1162306a36Sopenharmony_ci#include <sys/time.h> 1262306a36Sopenharmony_ci#include <sys/types.h> 1362306a36Sopenharmony_ci#include <sys/wait.h> 1462306a36Sopenharmony_ci#include <stdlib.h> 1562306a36Sopenharmony_ci 1662306a36Sopenharmony_ci#include "utils.h" 1762306a36Sopenharmony_ci 1862306a36Sopenharmony_ciextern int test_fpu(double *darray, pid_t *pid); 1962306a36Sopenharmony_ci 2062306a36Sopenharmony_cidouble darray[] = {0.1, 0.2, 0.3, 0.4, 0.5, 0.6, 0.7, 0.8, 0.9, 1.0, 2162306a36Sopenharmony_ci 1.1, 1.2, 1.3, 1.4, 1.5, 1.6, 1.7, 1.8, 1.9, 2.0, 2262306a36Sopenharmony_ci 2.1}; 2362306a36Sopenharmony_ci 2462306a36Sopenharmony_ciint syscall_fpu(void) 2562306a36Sopenharmony_ci{ 2662306a36Sopenharmony_ci pid_t fork_pid; 2762306a36Sopenharmony_ci int i; 2862306a36Sopenharmony_ci int ret; 2962306a36Sopenharmony_ci int child_ret; 3062306a36Sopenharmony_ci for (i = 0; i < 1000; i++) { 3162306a36Sopenharmony_ci /* test_fpu will fork() */ 3262306a36Sopenharmony_ci ret = test_fpu(darray, &fork_pid); 3362306a36Sopenharmony_ci if (fork_pid == -1) 3462306a36Sopenharmony_ci return -1; 3562306a36Sopenharmony_ci if (fork_pid == 0) 3662306a36Sopenharmony_ci exit(ret); 3762306a36Sopenharmony_ci waitpid(fork_pid, &child_ret, 0); 3862306a36Sopenharmony_ci if (ret || child_ret) 3962306a36Sopenharmony_ci return 1; 4062306a36Sopenharmony_ci } 4162306a36Sopenharmony_ci 4262306a36Sopenharmony_ci return 0; 4362306a36Sopenharmony_ci} 4462306a36Sopenharmony_ci 4562306a36Sopenharmony_ciint test_syscall_fpu(void) 4662306a36Sopenharmony_ci{ 4762306a36Sopenharmony_ci /* 4862306a36Sopenharmony_ci * Setup an environment with much context switching 4962306a36Sopenharmony_ci */ 5062306a36Sopenharmony_ci pid_t pid2; 5162306a36Sopenharmony_ci pid_t pid = fork(); 5262306a36Sopenharmony_ci int ret; 5362306a36Sopenharmony_ci int child_ret; 5462306a36Sopenharmony_ci FAIL_IF(pid == -1); 5562306a36Sopenharmony_ci 5662306a36Sopenharmony_ci pid2 = fork(); 5762306a36Sopenharmony_ci /* Can't FAIL_IF(pid2 == -1); because already forked once */ 5862306a36Sopenharmony_ci if (pid2 == -1) { 5962306a36Sopenharmony_ci /* 6062306a36Sopenharmony_ci * Couldn't fork, ensure test is a fail 6162306a36Sopenharmony_ci */ 6262306a36Sopenharmony_ci child_ret = ret = 1; 6362306a36Sopenharmony_ci } else { 6462306a36Sopenharmony_ci ret = syscall_fpu(); 6562306a36Sopenharmony_ci if (pid2) 6662306a36Sopenharmony_ci waitpid(pid2, &child_ret, 0); 6762306a36Sopenharmony_ci else 6862306a36Sopenharmony_ci exit(ret); 6962306a36Sopenharmony_ci } 7062306a36Sopenharmony_ci 7162306a36Sopenharmony_ci ret |= child_ret; 7262306a36Sopenharmony_ci 7362306a36Sopenharmony_ci if (pid) 7462306a36Sopenharmony_ci waitpid(pid, &child_ret, 0); 7562306a36Sopenharmony_ci else 7662306a36Sopenharmony_ci exit(ret); 7762306a36Sopenharmony_ci 7862306a36Sopenharmony_ci FAIL_IF(ret || child_ret); 7962306a36Sopenharmony_ci return 0; 8062306a36Sopenharmony_ci} 8162306a36Sopenharmony_ci 8262306a36Sopenharmony_ciint main(int argc, char *argv[]) 8362306a36Sopenharmony_ci{ 8462306a36Sopenharmony_ci return test_harness(test_syscall_fpu, "syscall_fpu"); 8562306a36Sopenharmony_ci 8662306a36Sopenharmony_ci} 87