1 // SPDX-License-Identifier: GPL-2.0+ 2 /* This testcase operates with the test_fpu kernel driver. 3 * It modifies the FPU control register in user mode and calls the kernel 4 * module to perform floating point operations in the kernel. The control 5 * register value should be independent between kernel and user mode. 6 */ 7 8 #define _GNU_SOURCE 9 #include <stdio.h> 10 #include <errno.h> 11 #include <string.h> 12 #include <fenv.h> 13 #include <unistd.h> 14 #include <fcntl.h> 15 16 const char *test_fpu_path = "/sys/kernel/debug/selftest_helpers/test_fpu"; 17 18 int main(void) 19 { 20 char dummy[1]; 21 int fd = open(test_fpu_path, O_RDONLY); 22 23 if (fd < 0) { 24 printf("[SKIP]\tcan't access %s: %s\n", 25 test_fpu_path, strerror(errno)); 26 return 0; 27 } 28 29 if (read(fd, dummy, 1) < 0) { 30 printf("[FAIL]\taccess with default rounding mode failed\n"); 31 return 1; 32 } 33 34 fesetround(FE_DOWNWARD); 35 if (read(fd, dummy, 1) < 0) { 36 printf("[FAIL]\taccess with downward rounding mode failed\n"); 37 return 2; 38 } 39 if (fegetround() != FE_DOWNWARD) { 40 printf("[FAIL]\tusermode rounding mode clobbered\n"); 41 return 3; 42 } 43 44 /* Note: the tests up to this point are quite safe and will only return 45 * an error. But the exception mask setting can cause misbehaving kernel 46 * to crash. 47 */ 48 feclearexcept(FE_ALL_EXCEPT); 49 feenableexcept(FE_ALL_EXCEPT); 50 if (read(fd, dummy, 1) < 0) { 51 printf("[FAIL]\taccess with fpu exceptions unmasked failed\n"); 52 return 4; 53 } 54 if (fegetexcept() != FE_ALL_EXCEPT) { 55 printf("[FAIL]\tusermode fpu exception mask clobbered\n"); 56 return 5; 57 } 58 59 printf("[OK]\ttest_fpu\n"); 60 return 0; 61 } 62