1 // SPDX-License-Identifier: GPL-2.0-only 2 /* 3 * Copyright (C) 2022 ARM Limited. 4 * Original author: Mark Brown <broonie@kernel.org> 5 */ 6 7 // SPDX-License-Identifier: GPL-2.0-only 8 9 #include <linux/sched.h> 10 #include <linux/wait.h> 11 12 #define EXPECTED_TESTS 1 13 14 static void putstr(const char *str) 15 { 16 write(1, str, strlen(str)); 17 } 18 19 static void putnum(unsigned int num) 20 { 21 char c; 22 23 if (num / 10) 24 putnum(num / 10); 25 26 c = '0' + (num % 10); 27 write(1, &c, 1); 28 } 29 30 static int tests_run; 31 static int tests_passed; 32 static int tests_failed; 33 static int tests_skipped; 34 35 static void print_summary(void) 36 { 37 if (tests_passed + tests_failed + tests_skipped != EXPECTED_TESTS) 38 putstr("# UNEXPECTED TEST COUNT: "); 39 40 putstr("# Totals: pass:"); 41 putnum(tests_passed); 42 putstr(" fail:"); 43 putnum(tests_failed); 44 putstr(" xfail:0 xpass:0 skip:"); 45 putnum(tests_skipped); 46 putstr(" error:0\n"); 47 } 48 49 int fork_test(void); 50 int verify_fork(void); 51 52 /* 53 * If we fork the value in the parent should be unchanged and the 54 * child should start with the same value. This is called from the 55 * fork_test() asm function. 56 */ 57 int fork_test_c(void) 58 { 59 pid_t newpid, waiting; 60 int child_status, parent_result; 61 62 newpid = fork(); 63 if (newpid == 0) { 64 /* In child */ 65 if (!verify_fork()) { 66 putstr("# ZA state invalid in child\n"); 67 exit(0); 68 } else { 69 exit(1); 70 } 71 } 72 if (newpid < 0) { 73 putstr("# fork() failed: -"); 74 putnum(-newpid); 75 putstr("\n"); 76 return 0; 77 } 78 79 parent_result = verify_fork(); 80 if (!parent_result) 81 putstr("# ZA state invalid in parent\n"); 82 83 for (;;) { 84 waiting = waitpid(newpid, &child_status, 0); 85 86 if (waiting < 0) { 87 if (errno == EINTR) 88 continue; 89 putstr("# waitpid() failed: "); 90 putnum(errno); 91 putstr("\n"); 92 return 0; 93 } 94 if (waiting != newpid) { 95 putstr("# waitpid() returned wrong PID\n"); 96 return 0; 97 } 98 99 if (!WIFEXITED(child_status)) { 100 putstr("# child did not exit\n"); 101 return 0; 102 } 103 104 return WEXITSTATUS(child_status) && parent_result; 105 } 106 } 107 108 #define run_test(name) \ 109 if (name()) { \ 110 tests_passed++; \ 111 } else { \ 112 tests_failed++; \ 113 putstr("not "); \ 114 } \ 115 putstr("ok "); \ 116 putnum(++tests_run); \ 117 putstr(" " #name "\n"); 118 119 int main(int argc, char **argv) 120 { 121 int ret, i; 122 123 putstr("TAP version 13\n"); 124 putstr("1.."); 125 putnum(EXPECTED_TESTS); 126 putstr("\n"); 127 128 putstr("# PID: "); 129 putnum(getpid()); 130 putstr("\n"); 131 132 /* 133 * This test is run with nolibc which doesn't support hwcap and 134 * it's probably disproportionate to implement so instead check 135 * for the default vector length configuration in /proc. 136 */ 137 ret = open("/proc/sys/abi/sme_default_vector_length", O_RDONLY, 0); 138 if (ret >= 0) { 139 run_test(fork_test); 140 141 } else { 142 putstr("# SME support not present\n"); 143 144 for (i = 0; i < EXPECTED_TESTS; i++) { 145 putstr("ok "); 146 putnum(i); 147 putstr(" skipped\n"); 148 } 149 150 tests_skipped += EXPECTED_TESTS; 151 } 152 153 print_summary(); 154 155 return 0; 156 } 157