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