This source file includes following definitions.
- expecting_failure
- is_failure
- tm_una_ping
- tm_una_pong
- test_fp_vec
- tm_unavailable_test
- main
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17 #define _GNU_SOURCE
18 #include <error.h>
19 #include <stdio.h>
20 #include <stdlib.h>
21 #include <unistd.h>
22 #include <inttypes.h>
23 #include <stdbool.h>
24 #include <pthread.h>
25 #include <sched.h>
26
27 #include "tm.h"
28
29 #define DEBUG 0
30
31
32 #define FP_UNA_EXCEPTION 0
33 #define VEC_UNA_EXCEPTION 1
34 #define VSX_UNA_EXCEPTION 2
35
36 #define NUM_EXCEPTIONS 3
37 #define err_at_line(status, errnum, format, ...) \
38 error_at_line(status, errnum, __FILE__, __LINE__, format ##__VA_ARGS__)
39
40 #define pr_warn(code, format, ...) err_at_line(0, code, format, ##__VA_ARGS__)
41 #define pr_err(code, format, ...) err_at_line(1, code, format, ##__VA_ARGS__)
42
43 struct Flags {
44 int touch_fp;
45 int touch_vec;
46 int result;
47 int exception;
48 } flags;
49
50 bool expecting_failure(void)
51 {
52 if (flags.touch_fp && flags.exception == FP_UNA_EXCEPTION)
53 return false;
54
55 if (flags.touch_vec && flags.exception == VEC_UNA_EXCEPTION)
56 return false;
57
58
59
60
61
62
63
64
65 if ((flags.touch_fp && flags.touch_vec) &&
66 flags.exception == VSX_UNA_EXCEPTION)
67 return false;
68
69 return true;
70 }
71
72
73 bool is_failure(uint64_t condition_reg)
74 {
75
76
77
78
79
80 return ((condition_reg >> 28) & 0xa) == 0xa;
81 }
82
83 void *tm_una_ping(void *input)
84 {
85
86
87
88
89
90 uint64_t high_vs0 = 0x5555555555555555;
91 uint64_t low_vs0 = 0xffffffffffffffff;
92 uint64_t high_vs32 = 0x5555555555555555;
93 uint64_t low_vs32 = 0xffffffffffffffff;
94
95
96 uint64_t counter = 0x1ff000000;
97
98
99
100
101
102 uint64_t cr_ = 0;
103
104
105
106
107
108 if (DEBUG)
109 sleep(1);
110
111 printf("If MSR.FP=%d MSR.VEC=%d: ", flags.touch_fp, flags.touch_vec);
112
113 if (flags.exception != FP_UNA_EXCEPTION &&
114 flags.exception != VEC_UNA_EXCEPTION &&
115 flags.exception != VSX_UNA_EXCEPTION) {
116 printf("No valid exception specified to test.\n");
117 return NULL;
118 }
119
120 asm (
121
122 " mtvsrd 33, %[high_vs0] ;"
123 " mtvsrd 34, %[low_vs0] ;"
124
125
126
127
128
129 " xxmrghd 0, 33, 34 ;"
130
131
132
133
134
135 " xxmrghd 32, 33, 34 ;"
136
137
138
139
140
141 " mtctr %[counter] ;"
142
143
144 "1: bdnz 1b ;"
145
146
147
148
149
150
151 " cmpldi %[touch_fp], 0 ;"
152 " beq no_fp ;"
153 " fadd 10, 10, 10 ;"
154 "no_fp: ;"
155
156
157
158
159
160
161 " cmpldi %[touch_vec], 0 ;"
162 " beq no_vec ;"
163 " vaddcuw 10, 10, 10 ;"
164 "no_vec: ;"
165
166
167
168
169
170
171 " tbegin. ;"
172 " beq trans_fail ;"
173
174
175 " cmpldi %[exception], %[ex_fp] ;"
176 " bne 1f ;"
177 " fadd 10, 10, 10 ;"
178 " b done ;"
179
180
181 "1: cmpldi %[exception], %[ex_vec] ;"
182 " bne 2f ;"
183 " vaddcuw 10, 10, 10 ;"
184 " b done ;"
185
186
187
188
189
190
191
192 "2: xxmrghd 10, 10, 10 ;"
193
194 "done: tend. ;"
195
196 "trans_fail: ;"
197
198
199 " mfvsrd %[high_vs0], 0 ;"
200 " xxsldwi 3, 0, 0, 2 ;"
201 " mfvsrd %[low_vs0], 3 ;"
202 " mfvsrd %[high_vs32], 32 ;"
203 " xxsldwi 3, 32, 32, 2 ;"
204 " mfvsrd %[low_vs32], 3 ;"
205
206
207 " mfcr %[cr_] ;"
208
209 : [high_vs0] "+r" (high_vs0),
210 [low_vs0] "+r" (low_vs0),
211 [high_vs32] "=r" (high_vs32),
212 [low_vs32] "=r" (low_vs32),
213 [cr_] "+r" (cr_)
214 : [touch_fp] "r" (flags.touch_fp),
215 [touch_vec] "r" (flags.touch_vec),
216 [exception] "r" (flags.exception),
217 [ex_fp] "i" (FP_UNA_EXCEPTION),
218 [ex_vec] "i" (VEC_UNA_EXCEPTION),
219 [ex_vsx] "i" (VSX_UNA_EXCEPTION),
220 [counter] "r" (counter)
221
222 : "cr0", "ctr", "v10", "vs0", "vs10", "vs3", "vs32", "vs33",
223 "vs34", "fr10"
224
225 );
226
227
228
229
230
231
232 if (expecting_failure() && !is_failure(cr_)) {
233 printf("\n\tExpecting the transaction to fail, %s",
234 "but it didn't\n\t");
235 flags.result++;
236 }
237
238
239 if (!expecting_failure() && is_failure(cr_) &&
240 !failure_is_reschedule()) {
241 printf("\n\tUnexpected transaction failure 0x%02lx\n\t",
242 failure_code());
243 return (void *) -1;
244 }
245
246
247
248
249
250
251 if (is_failure(cr_) && !failure_is_unavailable() &&
252 !failure_is_reschedule()) {
253 printf("\n\tUnexpected failure cause 0x%02lx\n\t",
254 failure_code());
255 return (void *) -1;
256 }
257
258
259 if (DEBUG)
260 printf("CR0: 0x%1lx ", cr_ >> 28);
261
262
263 if (high_vs0 != 0x5555555555555555 || low_vs0 != 0xFFFFFFFFFFFFFFFF) {
264 printf("FP corrupted!");
265 printf(" high = %#16" PRIx64 " low = %#16" PRIx64 " ",
266 high_vs0, low_vs0);
267 flags.result++;
268 } else
269 printf("FP ok ");
270
271
272 if (high_vs32 != 0x5555555555555555 || low_vs32 != 0xFFFFFFFFFFFFFFFF) {
273 printf("VEC corrupted!");
274 printf(" high = %#16" PRIx64 " low = %#16" PRIx64,
275 high_vs32, low_vs32);
276 flags.result++;
277 } else
278 printf("VEC ok");
279
280 putchar('\n');
281
282 return NULL;
283 }
284
285
286 void *tm_una_pong(void *not_used)
287 {
288
289 if (DEBUG)
290 sleep(1);
291
292
293 while (1)
294 sched_yield();
295 }
296
297
298 void test_fp_vec(int fp, int vec, pthread_attr_t *attr)
299 {
300 int retries = 2;
301 void *ret_value;
302 pthread_t t0;
303
304 flags.touch_fp = fp;
305 flags.touch_vec = vec;
306
307
308
309
310
311
312
313
314 do {
315 int rc;
316
317
318 rc = pthread_create(&t0, attr, tm_una_ping, (void *) &flags);
319 if (rc)
320 pr_err(rc, "pthread_create()");
321 rc = pthread_setname_np(t0, "tm_una_ping");
322 if (rc)
323 pr_warn(rc, "pthread_setname_np");
324 rc = pthread_join(t0, &ret_value);
325 if (rc)
326 pr_err(rc, "pthread_join");
327
328 retries--;
329 } while (ret_value != NULL && retries);
330
331 if (!retries) {
332 flags.result = 1;
333 if (DEBUG)
334 printf("All transactions failed unexpectedly\n");
335
336 }
337 }
338
339 int tm_unavailable_test(void)
340 {
341 int rc, exception;
342 pthread_t t1;
343 pthread_attr_t attr;
344 cpu_set_t cpuset;
345
346 SKIP_IF(!have_htm());
347
348
349 CPU_ZERO(&cpuset);
350 CPU_SET(0, &cpuset);
351
352
353 rc = pthread_attr_init(&attr);
354 if (rc)
355 pr_err(rc, "pthread_attr_init()");
356
357
358 rc = pthread_attr_setaffinity_np(&attr, sizeof(cpu_set_t), &cpuset);
359 if (rc)
360 pr_err(rc, "pthread_attr_setaffinity_np()");
361
362 rc = pthread_create(&t1, &attr , tm_una_pong, NULL);
363 if (rc)
364 pr_err(rc, "pthread_create()");
365
366
367 rc = pthread_setname_np(t1, "tm_una_pong");
368 if (rc)
369 pr_warn(rc, "pthread_create()");
370
371 flags.result = 0;
372
373 for (exception = 0; exception < NUM_EXCEPTIONS; exception++) {
374 printf("Checking if FP/VEC registers are sane after");
375
376 if (exception == FP_UNA_EXCEPTION)
377 printf(" a FP unavailable exception...\n");
378
379 else if (exception == VEC_UNA_EXCEPTION)
380 printf(" a VEC unavailable exception...\n");
381
382 else
383 printf(" a VSX unavailable exception...\n");
384
385 flags.exception = exception;
386
387 test_fp_vec(0, 0, &attr);
388 test_fp_vec(1, 0, &attr);
389 test_fp_vec(0, 1, &attr);
390 test_fp_vec(1, 1, &attr);
391
392 }
393
394 if (flags.result > 0) {
395 printf("result: failed!\n");
396 exit(1);
397 } else {
398 printf("result: success\n");
399 exit(0);
400 }
401 }
402
403 int main(int argc, char **argv)
404 {
405 test_harness_set_timeout(220);
406 return test_harness(tm_unavailable_test, "tm_unavailable_test");
407 }