Commit | Line | Data |
---|---|---|
a18b55bf AK |
1 | /* |
2 | * Ptrace test for VMX/VSX registers in the TM Suspend context | |
3 | * | |
4 | * Copyright (C) 2015 Anshuman Khandual, IBM Corporation. | |
5 | * | |
6 | * This program is free software; you can redistribute it and/or | |
7 | * modify it under the terms of the GNU General Public License | |
8 | * as published by the Free Software Foundation; either version | |
9 | * 2 of the License, or (at your option) any later version. | |
10 | */ | |
11 | #include "ptrace.h" | |
12 | #include "tm.h" | |
13 | #include "ptrace-vsx.h" | |
14 | ||
15 | int shm_id; | |
16 | int *cptr, *pptr; | |
17 | ||
18 | unsigned long fp_load[VEC_MAX]; | |
19 | unsigned long fp_load_new[VEC_MAX]; | |
20 | unsigned long fp_store[VEC_MAX]; | |
21 | unsigned long fp_load_ckpt[VEC_MAX]; | |
22 | unsigned long fp_load_ckpt_new[VEC_MAX]; | |
23 | ||
24 | __attribute__((used)) void load_vsx(void) | |
25 | { | |
26 | loadvsx(fp_load, 0); | |
27 | } | |
28 | ||
29 | __attribute__((used)) void load_vsx_new(void) | |
30 | { | |
31 | loadvsx(fp_load_new, 0); | |
32 | } | |
33 | ||
34 | __attribute__((used)) void load_vsx_ckpt(void) | |
35 | { | |
36 | loadvsx(fp_load_ckpt, 0); | |
37 | } | |
38 | ||
39 | __attribute__((used)) void wait_parent(void) | |
40 | { | |
41 | cptr[2] = 1; | |
42 | while (!cptr[1]) | |
43 | asm volatile("" : : : "memory"); | |
44 | } | |
45 | ||
46 | void tm_spd_vsx(void) | |
47 | { | |
48 | unsigned long result, texasr; | |
49 | int ret; | |
50 | ||
51 | cptr = (int *)shmat(shm_id, NULL, 0); | |
52 | ||
53 | trans: | |
54 | cptr[2] = 0; | |
55 | asm __volatile__( | |
56 | "bl load_vsx_ckpt;" | |
57 | ||
58 | "1: ;" | |
59 | "tbegin.;" | |
60 | "beq 2f;" | |
61 | ||
62 | "bl load_vsx_new;" | |
63 | "tsuspend.;" | |
64 | "bl load_vsx;" | |
65 | "bl wait_parent;" | |
66 | "tresume.;" | |
67 | ||
68 | "tend.;" | |
69 | "li 0, 0;" | |
70 | "ori %[res], 0, 0;" | |
71 | "b 3f;" | |
72 | ||
73 | "2: ;" | |
74 | "li 0, 1;" | |
75 | "ori %[res], 0, 0;" | |
76 | "mfspr %[texasr], %[sprn_texasr];" | |
77 | ||
78 | "3: ;" | |
79 | : [res] "=r" (result), [texasr] "=r" (texasr) | |
5249497a | 80 | : [sprn_texasr] "i" (SPRN_TEXASR) |
f36dbfe1 SG |
81 | : "memory", "r0", "r1", "r3", "r4", |
82 | "r7", "r8", "r9", "r10", "r11" | |
a18b55bf AK |
83 | ); |
84 | ||
85 | if (result) { | |
86 | if (!cptr[0]) | |
87 | goto trans; | |
88 | shmdt((void *)cptr); | |
89 | ||
90 | storevsx(fp_store, 0); | |
91 | ret = compare_vsx_vmx(fp_store, fp_load_ckpt_new); | |
92 | if (ret) | |
93 | exit(1); | |
94 | exit(0); | |
95 | } | |
96 | shmdt((void *)cptr); | |
97 | exit(1); | |
98 | } | |
99 | ||
100 | int trace_tm_spd_vsx(pid_t child) | |
101 | { | |
102 | unsigned long vsx[VSX_MAX]; | |
103 | unsigned long vmx[VMX_MAX + 2][2]; | |
104 | ||
105 | FAIL_IF(start_trace(child)); | |
106 | FAIL_IF(show_vsx(child, vsx)); | |
107 | FAIL_IF(validate_vsx(vsx, fp_load)); | |
108 | FAIL_IF(show_vmx(child, vmx)); | |
109 | FAIL_IF(validate_vmx(vmx, fp_load)); | |
110 | FAIL_IF(show_vsx_ckpt(child, vsx)); | |
111 | FAIL_IF(validate_vsx(vsx, fp_load_ckpt)); | |
112 | FAIL_IF(show_vmx_ckpt(child, vmx)); | |
113 | FAIL_IF(validate_vmx(vmx, fp_load_ckpt)); | |
114 | ||
115 | memset(vsx, 0, sizeof(vsx)); | |
116 | memset(vmx, 0, sizeof(vmx)); | |
117 | ||
118 | load_vsx_vmx(fp_load_ckpt_new, vsx, vmx); | |
119 | ||
120 | FAIL_IF(write_vsx_ckpt(child, vsx)); | |
121 | FAIL_IF(write_vmx_ckpt(child, vmx)); | |
122 | ||
123 | pptr[0] = 1; | |
124 | pptr[1] = 1; | |
125 | FAIL_IF(stop_trace(child)); | |
126 | ||
127 | return TEST_PASS; | |
128 | } | |
129 | ||
130 | int ptrace_tm_spd_vsx(void) | |
131 | { | |
132 | pid_t pid; | |
133 | int ret, status, i; | |
134 | ||
135 | SKIP_IF(!have_htm()); | |
136 | shm_id = shmget(IPC_PRIVATE, sizeof(int) * 3, 0777|IPC_CREAT); | |
137 | ||
138 | for (i = 0; i < 128; i++) { | |
139 | fp_load[i] = 1 + rand(); | |
140 | fp_load_new[i] = 1 + 2 * rand(); | |
141 | fp_load_ckpt[i] = 1 + 3 * rand(); | |
142 | fp_load_ckpt_new[i] = 1 + 4 * rand(); | |
143 | } | |
144 | ||
145 | pid = fork(); | |
146 | if (pid < 0) { | |
147 | perror("fork() failed"); | |
148 | return TEST_FAIL; | |
149 | } | |
150 | ||
151 | if (pid == 0) | |
152 | tm_spd_vsx(); | |
153 | ||
154 | if (pid) { | |
155 | pptr = (int *)shmat(shm_id, NULL, 0); | |
156 | while (!pptr[2]) | |
157 | asm volatile("" : : : "memory"); | |
158 | ||
159 | ret = trace_tm_spd_vsx(pid); | |
160 | if (ret) { | |
161 | kill(pid, SIGKILL); | |
162 | shmdt((void *)pptr); | |
163 | shmctl(shm_id, IPC_RMID, NULL); | |
164 | return TEST_FAIL; | |
165 | } | |
166 | ||
167 | shmdt((void *)pptr); | |
168 | ret = wait(&status); | |
169 | shmctl(shm_id, IPC_RMID, NULL); | |
170 | if (ret != pid) { | |
171 | printf("Child's exit status not captured\n"); | |
172 | return TEST_FAIL; | |
173 | } | |
174 | ||
175 | return (WIFEXITED(status) && WEXITSTATUS(status)) ? TEST_FAIL : | |
176 | TEST_PASS; | |
177 | } | |
178 | return TEST_PASS; | |
179 | } | |
180 | ||
181 | int main(int argc, char *argv[]) | |
182 | { | |
183 | return test_harness(ptrace_tm_spd_vsx, "ptrace_tm_spd_vsx"); | |
184 | } |