1 | // SPDX-License-Identifier: GPL-2.0-or-later |
2 | /* |
3 | * Ptrace test for VMX/VSX registers in the TM context |
4 | * |
5 | * Copyright (C) 2015 Anshuman Khandual, IBM Corporation. |
6 | */ |
7 | #include "ptrace.h" |
8 | #include "tm.h" |
9 | #include "ptrace-vsx.h" |
10 | |
11 | int shm_id; |
12 | unsigned long *cptr, *pptr; |
13 | |
14 | unsigned long fp_load[VEC_MAX]; |
15 | unsigned long fp_store[VEC_MAX]; |
16 | unsigned long fp_load_ckpt[VEC_MAX]; |
17 | unsigned long fp_load_ckpt_new[VEC_MAX]; |
18 | |
19 | __attribute__((used)) void load_vsx(void) |
20 | { |
21 | loadvsx(p: fp_load, tmp: 0); |
22 | } |
23 | |
24 | __attribute__((used)) void load_vsx_ckpt(void) |
25 | { |
26 | loadvsx(p: fp_load_ckpt, tmp: 0); |
27 | } |
28 | |
29 | void tm_vsx(void) |
30 | { |
31 | unsigned long result, texasr; |
32 | int ret; |
33 | |
34 | cptr = (unsigned long *)shmat(shm_id, NULL, 0); |
35 | |
36 | trans: |
37 | cptr[1] = 0; |
38 | asm __volatile__( |
39 | "bl load_vsx_ckpt;" |
40 | |
41 | "1: ;" |
42 | "tbegin.;" |
43 | "beq 2f;" |
44 | |
45 | "bl load_vsx;" |
46 | "tsuspend.;" |
47 | "li 7, 1;" |
48 | "stw 7, 0(%[cptr1]);" |
49 | "tresume.;" |
50 | "b .;" |
51 | |
52 | "tend.;" |
53 | "li 0, 0;" |
54 | "ori %[res], 0, 0;" |
55 | "b 3f;" |
56 | |
57 | "2: ;" |
58 | "li 0, 1;" |
59 | "ori %[res], 0, 0;" |
60 | "mfspr %[texasr], %[sprn_texasr];" |
61 | |
62 | "3: ;" |
63 | : [res] "=r" (result), [texasr] "=r" (texasr) |
64 | : [sprn_texasr] "i" (SPRN_TEXASR), [cptr1] "b" (&cptr[1]) |
65 | : "memory" , "r0" , "r3" , "r4" , |
66 | "r7" , "r8" , "r9" , "r10" , "r11" , "lr" |
67 | ); |
68 | |
69 | if (result) { |
70 | if (!cptr[0]) |
71 | goto trans; |
72 | |
73 | shmdt((void *)cptr); |
74 | storevsx(p: fp_store, tmp: 0); |
75 | ret = compare_vsx_vmx(store: fp_store, load: fp_load_ckpt_new); |
76 | if (ret) |
77 | exit(1); |
78 | exit(0); |
79 | } |
80 | shmdt((void *)cptr); |
81 | exit(1); |
82 | } |
83 | |
84 | int trace_tm_vsx(pid_t child) |
85 | { |
86 | unsigned long vsx[VSX_MAX]; |
87 | unsigned long vmx[VMX_MAX + 2][2]; |
88 | |
89 | FAIL_IF(start_trace(child)); |
90 | FAIL_IF(show_vsx(child, vsx)); |
91 | FAIL_IF(validate_vsx(vsx, load: fp_load)); |
92 | FAIL_IF(show_vmx(child, vmx)); |
93 | FAIL_IF(validate_vmx(vmx, load: fp_load)); |
94 | FAIL_IF(show_vsx_ckpt(child, vsx)); |
95 | FAIL_IF(validate_vsx(vsx, load: fp_load_ckpt)); |
96 | FAIL_IF(show_vmx_ckpt(child, vmx)); |
97 | FAIL_IF(validate_vmx(vmx, load: fp_load_ckpt)); |
98 | memset(vsx, 0, sizeof(vsx)); |
99 | memset(vmx, 0, sizeof(vmx)); |
100 | |
101 | load_vsx_vmx(load: fp_load_ckpt_new, vsx, vmx); |
102 | |
103 | FAIL_IF(write_vsx_ckpt(child, vsx)); |
104 | FAIL_IF(write_vmx_ckpt(child, vmx)); |
105 | pptr[0] = 1; |
106 | FAIL_IF(stop_trace(child)); |
107 | return TEST_PASS; |
108 | } |
109 | |
110 | int ptrace_tm_vsx(void) |
111 | { |
112 | pid_t pid; |
113 | int ret, status, i; |
114 | |
115 | SKIP_IF_MSG(!have_htm(), "Don't have transactional memory" ); |
116 | SKIP_IF_MSG(htm_is_synthetic(), "Transactional memory is synthetic" ); |
117 | shm_id = shmget(IPC_PRIVATE, sizeof(int) * 2, 0777|IPC_CREAT); |
118 | |
119 | for (i = 0; i < 128; i++) { |
120 | fp_load[i] = 1 + rand(); |
121 | fp_load_ckpt[i] = 1 + 2 * rand(); |
122 | fp_load_ckpt_new[i] = 1 + 3 * rand(); |
123 | } |
124 | |
125 | pid = fork(); |
126 | if (pid < 0) { |
127 | perror("fork() failed" ); |
128 | return TEST_FAIL; |
129 | } |
130 | |
131 | if (pid == 0) |
132 | tm_vsx(); |
133 | |
134 | if (pid) { |
135 | pptr = (unsigned long *)shmat(shm_id, NULL, 0); |
136 | while (!pptr[1]) |
137 | asm volatile("" : : : "memory" ); |
138 | |
139 | ret = trace_tm_vsx(child: pid); |
140 | if (ret) { |
141 | kill(pid, SIGKILL); |
142 | shmdt((void *)pptr); |
143 | shmctl(shm_id, IPC_RMID, NULL); |
144 | return TEST_FAIL; |
145 | } |
146 | |
147 | shmdt((void *)pptr); |
148 | ret = wait(&status); |
149 | shmctl(shm_id, IPC_RMID, NULL); |
150 | if (ret != pid) { |
151 | printf("Child's exit status not captured\n" ); |
152 | return TEST_FAIL; |
153 | } |
154 | |
155 | return (WIFEXITED(status) && WEXITSTATUS(status)) ? TEST_FAIL : |
156 | TEST_PASS; |
157 | } |
158 | return TEST_PASS; |
159 | } |
160 | |
161 | int main(int argc, char *argv[]) |
162 | { |
163 | return test_harness(ptrace_tm_vsx, "ptrace_tm_vsx" ); |
164 | } |
165 | |