1 // SPDX-License-Identifier: GPL-2.0-only 2 /* 3 * POWER Data Stream Control Register (DSCR) fork test 4 * 5 * This testcase modifies the DSCR using mtspr, forks and then 6 * verifies that the child process has the correct changed DSCR 7 * value using mfspr. 8 * 9 * When using the privilege state SPR, the instructions such as 10 * mfspr or mtspr are priviledged and the kernel emulates them 11 * for us. Instructions using problem state SPR can be exuecuted 12 * directly without any emulation if the HW supports them. Else 13 * they also get emulated by the kernel. 14 * 15 * Copyright 2012, Anton Blanchard, IBM Corporation. 16 * Copyright 2015, Anshuman Khandual, IBM Corporation. 17 */ 18 #include "dscr.h" 19 20 int dscr_inherit(void) 21 { 22 unsigned long i, dscr = 0; 23 pid_t pid; 24 25 SKIP_IF(!have_hwcap2(PPC_FEATURE2_DSCR)); 26 27 srand(getpid()); 28 set_dscr(dscr); 29 30 for (i = 0; i < COUNT; i++) { 31 unsigned long cur_dscr, cur_dscr_usr; 32 33 dscr++; 34 if (dscr > DSCR_MAX) 35 dscr = 0; 36 37 if (i % 2 == 0) 38 set_dscr_usr(dscr); 39 else 40 set_dscr(dscr); 41 42 pid = fork(); 43 if (pid == -1) { 44 perror("fork() failed"); 45 exit(1); 46 } else if (pid) { 47 int status; 48 49 if (waitpid(pid, &status, 0) == -1) { 50 perror("waitpid() failed"); 51 exit(1); 52 } 53 54 if (!WIFEXITED(status)) { 55 fprintf(stderr, "Child didn't exit cleanly\n"); 56 exit(1); 57 } 58 59 if (WEXITSTATUS(status) != 0) { 60 fprintf(stderr, "Child didn't exit cleanly\n"); 61 return 1; 62 } 63 } else { 64 cur_dscr = get_dscr(); 65 if (cur_dscr != dscr) { 66 fprintf(stderr, "Kernel DSCR should be %ld " 67 "but is %ld\n", dscr, cur_dscr); 68 exit(1); 69 } 70 71 cur_dscr_usr = get_dscr_usr(); 72 if (cur_dscr_usr != dscr) { 73 fprintf(stderr, "User DSCR should be %ld " 74 "but is %ld\n", dscr, cur_dscr_usr); 75 exit(1); 76 } 77 exit(0); 78 } 79 } 80 return 0; 81 } 82 83 int main(int argc, char *argv[]) 84 { 85 return test_harness(dscr_inherit, "dscr_inherit_test"); 86 } 87