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 srand(getpid()); 26 set_dscr(dscr); 27 28 for (i = 0; i < COUNT; i++) { 29 unsigned long cur_dscr, cur_dscr_usr; 30 31 dscr++; 32 if (dscr > DSCR_MAX) 33 dscr = 0; 34 35 if (i % 2 == 0) 36 set_dscr_usr(dscr); 37 else 38 set_dscr(dscr); 39 40 pid = fork(); 41 if (pid == -1) { 42 perror("fork() failed"); 43 exit(1); 44 } else if (pid) { 45 int status; 46 47 if (waitpid(pid, &status, 0) == -1) { 48 perror("waitpid() failed"); 49 exit(1); 50 } 51 52 if (!WIFEXITED(status)) { 53 fprintf(stderr, "Child didn't exit cleanly\n"); 54 exit(1); 55 } 56 57 if (WEXITSTATUS(status) != 0) { 58 fprintf(stderr, "Child didn't exit cleanly\n"); 59 return 1; 60 } 61 } else { 62 cur_dscr = get_dscr(); 63 if (cur_dscr != dscr) { 64 fprintf(stderr, "Kernel DSCR should be %ld " 65 "but is %ld\n", dscr, cur_dscr); 66 exit(1); 67 } 68 69 cur_dscr_usr = get_dscr_usr(); 70 if (cur_dscr_usr != dscr) { 71 fprintf(stderr, "User DSCR should be %ld " 72 "but is %ld\n", dscr, cur_dscr_usr); 73 exit(1); 74 } 75 exit(0); 76 } 77 } 78 return 0; 79 } 80 81 int main(int argc, char *argv[]) 82 { 83 return test_harness(dscr_inherit, "dscr_inherit_test"); 84 } 85