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 privileged and the kernel emulates them |
11 | * for us. Instructions using problem state SPR can be executed |
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 | |