]>
Commit | Line | Data |
---|---|---|
2874c5fd | 1 | // SPDX-License-Identifier: GPL-2.0-or-later |
fcf73a6b AK |
2 | /* |
3 | * Ptrace test for TAR, PPR, DSCR registers in the TM context | |
4 | * | |
5 | * Copyright (C) 2015 Anshuman Khandual, IBM Corporation. | |
fcf73a6b AK |
6 | */ |
7 | #include "ptrace.h" | |
8 | #include "tm.h" | |
9 | #include "ptrace-tar.h" | |
10 | ||
11 | int shm_id; | |
12 | unsigned long *cptr, *pptr; | |
13 | ||
14 | ||
15 | void tm_tar(void) | |
16 | { | |
17 | unsigned long result, texasr; | |
18 | unsigned long regs[3]; | |
19 | int ret; | |
20 | ||
21 | cptr = (unsigned long *)shmat(shm_id, NULL, 0); | |
22 | ||
23 | trans: | |
24 | cptr[1] = 0; | |
25 | asm __volatile__( | |
26 | "li 4, %[tar_1];" | |
27 | "mtspr %[sprn_tar], 4;" /* TAR_1 */ | |
28 | "li 4, %[dscr_1];" | |
29 | "mtspr %[sprn_dscr], 4;" /* DSCR_1 */ | |
30 | "or 31,31,31;" /* PPR_1*/ | |
31 | ||
32 | "1: ;" | |
33 | "tbegin.;" | |
34 | "beq 2f;" | |
35 | ||
36 | "li 4, %[tar_2];" | |
37 | "mtspr %[sprn_tar], 4;" /* TAR_2 */ | |
38 | "li 4, %[dscr_2];" | |
39 | "mtspr %[sprn_dscr], 4;" /* DSCR_2 */ | |
40 | "or 1,1,1;" /* PPR_2 */ | |
41 | "tsuspend.;" | |
42 | "li 0, 1;" | |
43 | "stw 0, 0(%[cptr1]);" | |
44 | "tresume.;" | |
45 | "b .;" | |
46 | ||
47 | "tend.;" | |
48 | "li 0, 0;" | |
49 | "ori %[res], 0, 0;" | |
50 | "b 3f;" | |
51 | ||
52 | /* Transaction abort handler */ | |
53 | "2: ;" | |
54 | "li 0, 1;" | |
55 | "ori %[res], 0, 0;" | |
56 | "mfspr %[texasr], %[sprn_texasr];" | |
57 | ||
58 | "3: ;" | |
59 | ||
60 | : [res] "=r" (result), [texasr] "=r" (texasr) | |
61 | : [sprn_dscr]"i"(SPRN_DSCR), [sprn_tar]"i"(SPRN_TAR), | |
62 | [sprn_ppr]"i"(SPRN_PPR), [sprn_texasr]"i"(SPRN_TEXASR), | |
63 | [tar_1]"i"(TAR_1), [dscr_1]"i"(DSCR_1), [tar_2]"i"(TAR_2), | |
5249497a | 64 | [dscr_2]"i"(DSCR_2), [cptr1] "b" (&cptr[1]) |
fcf73a6b AK |
65 | : "memory", "r0", "r1", "r3", "r4", "r5", "r6" |
66 | ); | |
67 | ||
68 | /* TM failed, analyse */ | |
69 | if (result) { | |
70 | if (!cptr[0]) | |
71 | goto trans; | |
72 | ||
73 | regs[0] = mfspr(SPRN_TAR); | |
74 | regs[1] = mfspr(SPRN_PPR); | |
75 | regs[2] = mfspr(SPRN_DSCR); | |
76 | ||
77 | shmdt(&cptr); | |
78 | printf("%-30s TAR: %lu PPR: %lx DSCR: %lu\n", | |
79 | user_read, regs[0], regs[1], regs[2]); | |
80 | ||
81 | ret = validate_tar_registers(regs, TAR_4, PPR_4, DSCR_4); | |
82 | if (ret) | |
83 | exit(1); | |
84 | exit(0); | |
85 | } | |
86 | shmdt(&cptr); | |
87 | exit(1); | |
88 | } | |
89 | ||
90 | int trace_tm_tar(pid_t child) | |
91 | { | |
92 | unsigned long regs[3]; | |
93 | ||
94 | FAIL_IF(start_trace(child)); | |
95 | FAIL_IF(show_tar_registers(child, regs)); | |
96 | printf("%-30s TAR: %lu PPR: %lx DSCR: %lu\n", | |
97 | ptrace_read_running, regs[0], regs[1], regs[2]); | |
98 | ||
99 | FAIL_IF(validate_tar_registers(regs, TAR_2, PPR_2, DSCR_2)); | |
100 | FAIL_IF(show_tm_checkpointed_state(child, regs)); | |
101 | printf("%-30s TAR: %lu PPR: %lx DSCR: %lu\n", | |
102 | ptrace_read_ckpt, regs[0], regs[1], regs[2]); | |
103 | ||
104 | FAIL_IF(validate_tar_registers(regs, TAR_1, PPR_1, DSCR_1)); | |
105 | FAIL_IF(write_ckpt_tar_registers(child, TAR_4, PPR_4, DSCR_4)); | |
106 | printf("%-30s TAR: %u PPR: %lx DSCR: %u\n", | |
107 | ptrace_write_ckpt, TAR_4, PPR_4, DSCR_4); | |
108 | ||
109 | pptr[0] = 1; | |
110 | FAIL_IF(stop_trace(child)); | |
111 | return TEST_PASS; | |
112 | } | |
113 | ||
114 | int ptrace_tm_tar(void) | |
115 | { | |
116 | pid_t pid; | |
117 | int ret, status; | |
118 | ||
119 | SKIP_IF(!have_htm()); | |
120 | shm_id = shmget(IPC_PRIVATE, sizeof(int) * 2, 0777|IPC_CREAT); | |
121 | pid = fork(); | |
122 | if (pid == 0) | |
123 | tm_tar(); | |
124 | ||
125 | pptr = (unsigned long *)shmat(shm_id, NULL, 0); | |
126 | pptr[0] = 0; | |
127 | ||
128 | if (pid) { | |
129 | while (!pptr[1]) | |
130 | asm volatile("" : : : "memory"); | |
131 | ret = trace_tm_tar(pid); | |
132 | if (ret) { | |
133 | kill(pid, SIGTERM); | |
134 | shmdt(&pptr); | |
135 | shmctl(shm_id, IPC_RMID, NULL); | |
136 | return TEST_FAIL; | |
137 | } | |
138 | shmdt(&pptr); | |
139 | ||
140 | ret = wait(&status); | |
141 | shmctl(shm_id, IPC_RMID, NULL); | |
142 | if (ret != pid) { | |
143 | printf("Child's exit status not captured\n"); | |
144 | return TEST_FAIL; | |
145 | } | |
146 | ||
147 | return (WIFEXITED(status) && WEXITSTATUS(status)) ? TEST_FAIL : | |
148 | TEST_PASS; | |
149 | } | |
150 | return TEST_PASS; | |
151 | } | |
152 | ||
153 | int main(int argc, char *argv[]) | |
154 | { | |
155 | return test_harness(ptrace_tm_tar, "ptrace_tm_tar"); | |
156 | } |