1 // SPDX-License-Identifier: GPL-2.0-or-later
2 /*
3 * Test the powerpc alignment handler on POWER8/POWER9
4 *
5 * Copyright (C) 2017 IBM Corporation (Michael Neuling, Andrew Donnellan)
6 */
7
8 /*
9 * This selftest exercises the powerpc alignment fault handler.
10 *
11 * We create two sets of source and destination buffers, one in regular memory,
12 * the other cache-inhibited (by default we use /dev/fb0 for this, but an
13 * alterative path for cache-inhibited memory may be provided, e.g. memtrace).
14 *
15 * We initialise the source buffers, then use whichever set of load/store
16 * instructions is under test to copy bytes from the source buffers to the
17 * destination buffers. For the regular buffers, these instructions will
18 * execute normally. For the cache-inhibited buffers, these instructions
19 * will trap and cause an alignment fault, and the alignment fault handler
20 * will emulate the particular instruction under test. We then compare the
21 * destination buffers to ensure that the native and emulated cases give the
22 * same result.
23 *
24 * TODO:
25 * - Any FIXMEs below
26 * - Test VSX regs < 32 and > 32
27 * - Test all loads and stores
28 * - Check update forms do update register
29 * - Test alignment faults over page boundary
30 *
31 * Some old binutils may not support all the instructions.
32 */
33
34
35 #include <sys/mman.h>
36 #include <sys/types.h>
37 #include <sys/stat.h>
38 #include <fcntl.h>
39 #include <unistd.h>
40 #include <stdbool.h>
41 #include <stdio.h>
42 #include <stdlib.h>
43 #include <string.h>
44 #include <assert.h>
45 #include <getopt.h>
46 #include <setjmp.h>
47 #include <signal.h>
48
49 #include "utils.h"
50 #include "instructions.h"
51
52 int bufsize;
53 int debug;
54 int testing;
55 volatile int gotsig;
56 bool prefixes_enabled;
57 char *cipath = "/dev/fb0";
58 long cioffset;
59
sighandler(int sig,siginfo_t * info,void * ctx)60 void sighandler(int sig, siginfo_t *info, void *ctx)
61 {
62 ucontext_t *ucp = ctx;
63
64 if (!testing) {
65 signal(sig, SIG_DFL);
66 kill(0, sig);
67 }
68 gotsig = sig;
69 #ifdef __powerpc64__
70 if (prefixes_enabled) {
71 u32 inst = *(u32 *)ucp->uc_mcontext.gp_regs[PT_NIP];
72 ucp->uc_mcontext.gp_regs[PT_NIP] += ((inst >> 26 == 1) ? 8 : 4);
73 } else {
74 ucp->uc_mcontext.gp_regs[PT_NIP] += 4;
75 }
76 #else
77 ucp->uc_mcontext.uc_regs->gregs[PT_NIP] += 4;
78 #endif
79 }
80
81 #define XFORM(reg, n) " " #reg " ,%"#n",%2 ;"
82 #define DFORM(reg, n) " " #reg " ,0(%"#n") ;"
83
84 #define TEST(name, ld_op, st_op, form, ld_reg, st_reg) \
85 void test_##name(char *s, char *d) \
86 { \
87 asm volatile( \
88 #ld_op form(ld_reg, 0) \
89 #st_op form(st_reg, 1) \
90 :: "r"(s), "r"(d), "r"(0) \
91 : "memory", "vs0", "vs32", "r31"); \
92 } \
93 rc |= do_test(#name, test_##name)
94
95 #define TESTP(name, ld_op, st_op, ld_reg, st_reg) \
96 void test_##name(char *s, char *d) \
97 { \
98 asm volatile( \
99 ld_op(ld_reg, %0, 0, 0) \
100 st_op(st_reg, %1, 0, 0) \
101 :: "r"(s), "r"(d), "r"(0) \
102 : "memory", "vs0", "vs32", "r31"); \
103 } \
104 rc |= do_test(#name, test_##name)
105
106 #define LOAD_VSX_XFORM_TEST(op) TEST(op, op, stxvd2x, XFORM, 32, 32)
107 #define STORE_VSX_XFORM_TEST(op) TEST(op, lxvd2x, op, XFORM, 32, 32)
108 #define LOAD_VSX_DFORM_TEST(op) TEST(op, op, stxv, DFORM, 32, 32)
109 #define STORE_VSX_DFORM_TEST(op) TEST(op, lxv, op, DFORM, 32, 32)
110 #define LOAD_VMX_XFORM_TEST(op) TEST(op, op, stxvd2x, XFORM, 0, 32)
111 #define STORE_VMX_XFORM_TEST(op) TEST(op, lxvd2x, op, XFORM, 32, 0)
112 #define LOAD_VMX_DFORM_TEST(op) TEST(op, op, stxv, DFORM, 0, 32)
113 #define STORE_VMX_DFORM_TEST(op) TEST(op, lxv, op, DFORM, 32, 0)
114
115 #define LOAD_XFORM_TEST(op) TEST(op, op, stdx, XFORM, 31, 31)
116 #define STORE_XFORM_TEST(op) TEST(op, ldx, op, XFORM, 31, 31)
117 #define LOAD_DFORM_TEST(op) TEST(op, op, std, DFORM, 31, 31)
118 #define STORE_DFORM_TEST(op) TEST(op, ld, op, DFORM, 31, 31)
119
120 #define LOAD_FLOAT_DFORM_TEST(op) TEST(op, op, stfd, DFORM, 0, 0)
121 #define STORE_FLOAT_DFORM_TEST(op) TEST(op, lfd, op, DFORM, 0, 0)
122 #define LOAD_FLOAT_XFORM_TEST(op) TEST(op, op, stfdx, XFORM, 0, 0)
123 #define STORE_FLOAT_XFORM_TEST(op) TEST(op, lfdx, op, XFORM, 0, 0)
124
125 #define LOAD_MLS_PREFIX_TEST(op) TESTP(op, op, PSTD, 31, 31)
126 #define STORE_MLS_PREFIX_TEST(op) TESTP(op, PLD, op, 31, 31)
127
128 #define LOAD_8LS_PREFIX_TEST(op) TESTP(op, op, PSTD, 31, 31)
129 #define STORE_8LS_PREFIX_TEST(op) TESTP(op, PLD, op, 31, 31)
130
131 #define LOAD_FLOAT_MLS_PREFIX_TEST(op) TESTP(op, op, PSTFD, 0, 0)
132 #define STORE_FLOAT_MLS_PREFIX_TEST(op) TESTP(op, PLFD, op, 0, 0)
133
134 #define LOAD_VSX_8LS_PREFIX_TEST(op, tail) TESTP(op, op, PSTXV ## tail, 0, 32)
135 #define STORE_VSX_8LS_PREFIX_TEST(op, tail) TESTP(op, PLXV ## tail, op, 32, 0)
136
137 /* FIXME: Unimplemented tests: */
138 // STORE_DFORM_TEST(stq) /* FIXME: need two registers for quad */
139 // STORE_DFORM_TEST(stswi) /* FIXME: string instruction */
140
141 // STORE_XFORM_TEST(stwat) /* AMO can't emulate or run on CI */
142 // STORE_XFORM_TEST(stdat) /* ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ */
143
144
145 /* preload byte by byte */
preload_data(void * dst,int offset,int width)146 void preload_data(void *dst, int offset, int width)
147 {
148 char *c = dst;
149 int i;
150
151 c += offset;
152
153 for (i = 0 ; i < width ; i++)
154 c[i] = i;
155 }
156
test_memcpy(void * dst,void * src,int size,int offset,void (* test_func)(char *,char *))157 int test_memcpy(void *dst, void *src, int size, int offset,
158 void (*test_func)(char *, char *))
159 {
160 char *s, *d;
161
162 s = src;
163 s += offset;
164 d = dst;
165 d += offset;
166
167 assert(size == 16);
168 gotsig = 0;
169 testing = 1;
170
171 test_func(s, d); /* run the actual test */
172
173 testing = 0;
174 if (gotsig) {
175 if (debug)
176 printf(" Got signal %i\n", gotsig);
177 return 1;
178 }
179 return 0;
180 }
181
dumpdata(char * s1,char * s2,int n,char * test_name)182 void dumpdata(char *s1, char *s2, int n, char *test_name)
183 {
184 int i;
185
186 printf(" %s: unexpected result:\n", test_name);
187 printf(" mem:");
188 for (i = 0; i < n; i++)
189 printf(" %02x", s1[i]);
190 printf("\n");
191 printf(" ci: ");
192 for (i = 0; i < n; i++)
193 printf(" %02x", s2[i]);
194 printf("\n");
195 }
196
test_memcmp(void * s1,void * s2,int n,int offset,char * test_name)197 int test_memcmp(void *s1, void *s2, int n, int offset, char *test_name)
198 {
199 char *s1c, *s2c;
200
201 s1c = s1;
202 s1c += offset;
203 s2c = s2;
204 s2c += offset;
205
206 if (memcmp(s1c, s2c, n)) {
207 if (debug) {
208 printf("\n Compare failed. Offset:%i length:%i\n",
209 offset, n);
210 dumpdata(s1c, s2c, n, test_name);
211 }
212 return 1;
213 }
214 return 0;
215 }
216
217 /*
218 * Do two memcpy tests using the same instructions. One cachable
219 * memory and the other doesn't.
220 */
do_test(char * test_name,void (* test_func)(char *,char *))221 int do_test(char *test_name, void (*test_func)(char *, char *))
222 {
223 int offset, width, fd, rc, r;
224 void *mem0, *mem1, *ci0, *ci1;
225
226 printf("\tDoing %s:\t", test_name);
227
228 fd = open(cipath, O_RDWR);
229 if (fd < 0) {
230 printf("\n");
231 perror("Can't open ci file now?");
232 return 1;
233 }
234
235 ci0 = mmap(NULL, bufsize, PROT_WRITE | PROT_READ, MAP_SHARED,
236 fd, cioffset);
237 ci1 = mmap(NULL, bufsize, PROT_WRITE | PROT_READ, MAP_SHARED,
238 fd, cioffset + bufsize);
239
240 if ((ci0 == MAP_FAILED) || (ci1 == MAP_FAILED)) {
241 printf("\n");
242 perror("mmap failed");
243 SKIP_IF(1);
244 }
245
246 rc = posix_memalign(&mem0, bufsize, bufsize);
247 if (rc) {
248 printf("\n");
249 return rc;
250 }
251
252 rc = posix_memalign(&mem1, bufsize, bufsize);
253 if (rc) {
254 printf("\n");
255 free(mem0);
256 return rc;
257 }
258
259 rc = 0;
260 /*
261 * offset = 0 is aligned but tests the workaround for the P9N
262 * DD2.1 vector CI load issue (see 5080332c2c89 "powerpc/64s:
263 * Add workaround for P9 vector CI load issue")
264 */
265 for (offset = 0; offset < 16; offset++) {
266 width = 16; /* vsx == 16 bytes */
267 r = 0;
268
269 /* load pattern into memory byte by byte */
270 preload_data(ci0, offset, width);
271 preload_data(mem0, offset, width); // FIXME: remove??
272 memcpy(ci0, mem0, bufsize);
273 memcpy(ci1, mem1, bufsize); /* initialise output to the same */
274
275 /* sanity check */
276 test_memcmp(mem0, ci0, width, offset, test_name);
277
278 r |= test_memcpy(ci1, ci0, width, offset, test_func);
279 r |= test_memcpy(mem1, mem0, width, offset, test_func);
280 if (r && !debug) {
281 printf("FAILED: Got signal");
282 rc = 1;
283 break;
284 }
285
286 r |= test_memcmp(mem1, ci1, width, offset, test_name);
287 if (r && !debug) {
288 printf("FAILED: Wrong Data");
289 rc = 1;
290 break;
291 }
292 }
293
294 if (rc == 0)
295 printf("PASSED");
296
297 printf("\n");
298
299 munmap(ci0, bufsize);
300 munmap(ci1, bufsize);
301 free(mem0);
302 free(mem1);
303 close(fd);
304
305 return rc;
306 }
307
can_open_cifile(void)308 static bool can_open_cifile(void)
309 {
310 int fd;
311
312 fd = open(cipath, O_RDWR);
313 if (fd < 0)
314 return false;
315
316 close(fd);
317 return true;
318 }
319
test_alignment_handler_vsx_206(void)320 int test_alignment_handler_vsx_206(void)
321 {
322 int rc = 0;
323
324 SKIP_IF(!can_open_cifile());
325 SKIP_IF(!have_hwcap(PPC_FEATURE_ARCH_2_06));
326
327 printf("VSX: 2.06B\n");
328 LOAD_VSX_XFORM_TEST(lxvd2x);
329 LOAD_VSX_XFORM_TEST(lxvw4x);
330 LOAD_VSX_XFORM_TEST(lxsdx);
331 LOAD_VSX_XFORM_TEST(lxvdsx);
332 STORE_VSX_XFORM_TEST(stxvd2x);
333 STORE_VSX_XFORM_TEST(stxvw4x);
334 STORE_VSX_XFORM_TEST(stxsdx);
335 return rc;
336 }
337
test_alignment_handler_vsx_207(void)338 int test_alignment_handler_vsx_207(void)
339 {
340 int rc = 0;
341
342 SKIP_IF(!can_open_cifile());
343 SKIP_IF(!have_hwcap2(PPC_FEATURE2_ARCH_2_07));
344
345 printf("VSX: 2.07B\n");
346 LOAD_VSX_XFORM_TEST(lxsspx);
347 LOAD_VSX_XFORM_TEST(lxsiwax);
348 LOAD_VSX_XFORM_TEST(lxsiwzx);
349 STORE_VSX_XFORM_TEST(stxsspx);
350 STORE_VSX_XFORM_TEST(stxsiwx);
351 return rc;
352 }
353
test_alignment_handler_vsx_300(void)354 int test_alignment_handler_vsx_300(void)
355 {
356 int rc = 0;
357
358 SKIP_IF(!can_open_cifile());
359
360 SKIP_IF(!have_hwcap2(PPC_FEATURE2_ARCH_3_00));
361 printf("VSX: 3.00B\n");
362 LOAD_VMX_DFORM_TEST(lxsd);
363 LOAD_VSX_XFORM_TEST(lxsibzx);
364 LOAD_VSX_XFORM_TEST(lxsihzx);
365 LOAD_VMX_DFORM_TEST(lxssp);
366 LOAD_VSX_DFORM_TEST(lxv);
367 LOAD_VSX_XFORM_TEST(lxvb16x);
368 LOAD_VSX_XFORM_TEST(lxvh8x);
369 LOAD_VSX_XFORM_TEST(lxvx);
370 LOAD_VSX_XFORM_TEST(lxvwsx);
371 LOAD_VSX_XFORM_TEST(lxvl);
372 LOAD_VSX_XFORM_TEST(lxvll);
373 STORE_VMX_DFORM_TEST(stxsd);
374 STORE_VSX_XFORM_TEST(stxsibx);
375 STORE_VSX_XFORM_TEST(stxsihx);
376 STORE_VMX_DFORM_TEST(stxssp);
377 STORE_VSX_DFORM_TEST(stxv);
378 STORE_VSX_XFORM_TEST(stxvb16x);
379 STORE_VSX_XFORM_TEST(stxvh8x);
380 STORE_VSX_XFORM_TEST(stxvx);
381 STORE_VSX_XFORM_TEST(stxvl);
382 STORE_VSX_XFORM_TEST(stxvll);
383 return rc;
384 }
385
test_alignment_handler_vsx_prefix(void)386 int test_alignment_handler_vsx_prefix(void)
387 {
388 int rc = 0;
389
390 SKIP_IF(!can_open_cifile());
391 SKIP_IF(!have_hwcap2(PPC_FEATURE2_ARCH_3_1));
392
393 printf("VSX: PREFIX\n");
394 LOAD_VSX_8LS_PREFIX_TEST(PLXSD, 0);
395 LOAD_VSX_8LS_PREFIX_TEST(PLXSSP, 0);
396 LOAD_VSX_8LS_PREFIX_TEST(PLXV0, 0);
397 LOAD_VSX_8LS_PREFIX_TEST(PLXV1, 1);
398 STORE_VSX_8LS_PREFIX_TEST(PSTXSD, 0);
399 STORE_VSX_8LS_PREFIX_TEST(PSTXSSP, 0);
400 STORE_VSX_8LS_PREFIX_TEST(PSTXV0, 0);
401 STORE_VSX_8LS_PREFIX_TEST(PSTXV1, 1);
402 return rc;
403 }
404
test_alignment_handler_integer(void)405 int test_alignment_handler_integer(void)
406 {
407 int rc = 0;
408
409 SKIP_IF(!can_open_cifile());
410
411 printf("Integer\n");
412 LOAD_DFORM_TEST(lbz);
413 LOAD_DFORM_TEST(lbzu);
414 LOAD_XFORM_TEST(lbzx);
415 LOAD_XFORM_TEST(lbzux);
416 LOAD_DFORM_TEST(lhz);
417 LOAD_DFORM_TEST(lhzu);
418 LOAD_XFORM_TEST(lhzx);
419 LOAD_XFORM_TEST(lhzux);
420 LOAD_DFORM_TEST(lha);
421 LOAD_DFORM_TEST(lhau);
422 LOAD_XFORM_TEST(lhax);
423 LOAD_XFORM_TEST(lhaux);
424 LOAD_XFORM_TEST(lhbrx);
425 LOAD_DFORM_TEST(lwz);
426 LOAD_DFORM_TEST(lwzu);
427 LOAD_XFORM_TEST(lwzx);
428 LOAD_XFORM_TEST(lwzux);
429 LOAD_DFORM_TEST(lwa);
430 LOAD_XFORM_TEST(lwax);
431 LOAD_XFORM_TEST(lwaux);
432 LOAD_XFORM_TEST(lwbrx);
433 LOAD_DFORM_TEST(ld);
434 LOAD_DFORM_TEST(ldu);
435 LOAD_XFORM_TEST(ldx);
436 LOAD_XFORM_TEST(ldux);
437 STORE_DFORM_TEST(stb);
438 STORE_XFORM_TEST(stbx);
439 STORE_DFORM_TEST(stbu);
440 STORE_XFORM_TEST(stbux);
441 STORE_DFORM_TEST(sth);
442 STORE_XFORM_TEST(sthx);
443 STORE_DFORM_TEST(sthu);
444 STORE_XFORM_TEST(sthux);
445 STORE_XFORM_TEST(sthbrx);
446 STORE_DFORM_TEST(stw);
447 STORE_XFORM_TEST(stwx);
448 STORE_DFORM_TEST(stwu);
449 STORE_XFORM_TEST(stwux);
450 STORE_XFORM_TEST(stwbrx);
451 STORE_DFORM_TEST(std);
452 STORE_XFORM_TEST(stdx);
453 STORE_DFORM_TEST(stdu);
454 STORE_XFORM_TEST(stdux);
455
456 #ifdef __BIG_ENDIAN__
457 LOAD_DFORM_TEST(lmw);
458 STORE_DFORM_TEST(stmw);
459 #endif
460
461 return rc;
462 }
463
test_alignment_handler_integer_206(void)464 int test_alignment_handler_integer_206(void)
465 {
466 int rc = 0;
467
468 SKIP_IF(!can_open_cifile());
469 SKIP_IF(!have_hwcap(PPC_FEATURE_ARCH_2_06));
470
471 printf("Integer: 2.06\n");
472
473 LOAD_XFORM_TEST(ldbrx);
474 STORE_XFORM_TEST(stdbrx);
475
476 return rc;
477 }
478
test_alignment_handler_integer_prefix(void)479 int test_alignment_handler_integer_prefix(void)
480 {
481 int rc = 0;
482
483 SKIP_IF(!can_open_cifile());
484 SKIP_IF(!have_hwcap2(PPC_FEATURE2_ARCH_3_1));
485
486 printf("Integer: PREFIX\n");
487 LOAD_MLS_PREFIX_TEST(PLBZ);
488 LOAD_MLS_PREFIX_TEST(PLHZ);
489 LOAD_MLS_PREFIX_TEST(PLHA);
490 LOAD_MLS_PREFIX_TEST(PLWZ);
491 LOAD_8LS_PREFIX_TEST(PLWA);
492 LOAD_8LS_PREFIX_TEST(PLD);
493 STORE_MLS_PREFIX_TEST(PSTB);
494 STORE_MLS_PREFIX_TEST(PSTH);
495 STORE_MLS_PREFIX_TEST(PSTW);
496 STORE_8LS_PREFIX_TEST(PSTD);
497 return rc;
498 }
499
test_alignment_handler_vmx(void)500 int test_alignment_handler_vmx(void)
501 {
502 int rc = 0;
503
504 SKIP_IF(!can_open_cifile());
505 SKIP_IF(!have_hwcap(PPC_FEATURE_HAS_ALTIVEC));
506
507 printf("VMX\n");
508 LOAD_VMX_XFORM_TEST(lvx);
509
510 /*
511 * FIXME: These loads only load part of the register, so our
512 * testing method doesn't work. Also they don't take alignment
513 * faults, so it's kinda pointless anyway
514 *
515 LOAD_VMX_XFORM_TEST(lvebx)
516 LOAD_VMX_XFORM_TEST(lvehx)
517 LOAD_VMX_XFORM_TEST(lvewx)
518 LOAD_VMX_XFORM_TEST(lvxl)
519 */
520 STORE_VMX_XFORM_TEST(stvx);
521 STORE_VMX_XFORM_TEST(stvebx);
522 STORE_VMX_XFORM_TEST(stvehx);
523 STORE_VMX_XFORM_TEST(stvewx);
524 STORE_VMX_XFORM_TEST(stvxl);
525 return rc;
526 }
527
test_alignment_handler_fp(void)528 int test_alignment_handler_fp(void)
529 {
530 int rc = 0;
531
532 SKIP_IF(!can_open_cifile());
533
534 printf("Floating point\n");
535 LOAD_FLOAT_DFORM_TEST(lfd);
536 LOAD_FLOAT_XFORM_TEST(lfdx);
537 LOAD_FLOAT_DFORM_TEST(lfdu);
538 LOAD_FLOAT_XFORM_TEST(lfdux);
539 LOAD_FLOAT_DFORM_TEST(lfs);
540 LOAD_FLOAT_XFORM_TEST(lfsx);
541 LOAD_FLOAT_DFORM_TEST(lfsu);
542 LOAD_FLOAT_XFORM_TEST(lfsux);
543 STORE_FLOAT_DFORM_TEST(stfd);
544 STORE_FLOAT_XFORM_TEST(stfdx);
545 STORE_FLOAT_DFORM_TEST(stfdu);
546 STORE_FLOAT_XFORM_TEST(stfdux);
547 STORE_FLOAT_DFORM_TEST(stfs);
548 STORE_FLOAT_XFORM_TEST(stfsx);
549 STORE_FLOAT_DFORM_TEST(stfsu);
550 STORE_FLOAT_XFORM_TEST(stfsux);
551 STORE_FLOAT_XFORM_TEST(stfiwx);
552
553 return rc;
554 }
555
test_alignment_handler_fp_205(void)556 int test_alignment_handler_fp_205(void)
557 {
558 int rc = 0;
559
560 SKIP_IF(!can_open_cifile());
561 SKIP_IF(!have_hwcap(PPC_FEATURE_ARCH_2_05));
562
563 printf("Floating point: 2.05\n");
564
565 LOAD_FLOAT_DFORM_TEST(lfdp);
566 LOAD_FLOAT_XFORM_TEST(lfdpx);
567 LOAD_FLOAT_XFORM_TEST(lfiwax);
568 STORE_FLOAT_DFORM_TEST(stfdp);
569 STORE_FLOAT_XFORM_TEST(stfdpx);
570
571 return rc;
572 }
573
test_alignment_handler_fp_206(void)574 int test_alignment_handler_fp_206(void)
575 {
576 int rc = 0;
577
578 SKIP_IF(!can_open_cifile());
579 SKIP_IF(!have_hwcap(PPC_FEATURE_ARCH_2_06));
580
581 printf("Floating point: 2.06\n");
582
583 LOAD_FLOAT_XFORM_TEST(lfiwzx);
584
585 return rc;
586 }
587
588
test_alignment_handler_fp_prefix(void)589 int test_alignment_handler_fp_prefix(void)
590 {
591 int rc = 0;
592
593 SKIP_IF(!can_open_cifile());
594 SKIP_IF(!have_hwcap2(PPC_FEATURE2_ARCH_3_1));
595
596 printf("Floating point: PREFIX\n");
597 LOAD_FLOAT_DFORM_TEST(lfs);
598 LOAD_FLOAT_MLS_PREFIX_TEST(PLFS);
599 LOAD_FLOAT_MLS_PREFIX_TEST(PLFD);
600 STORE_FLOAT_MLS_PREFIX_TEST(PSTFS);
601 STORE_FLOAT_MLS_PREFIX_TEST(PSTFD);
602 return rc;
603 }
604
usage(char * prog)605 void usage(char *prog)
606 {
607 printf("Usage: %s [options] [path [offset]]\n", prog);
608 printf(" -d Enable debug error output\n");
609 printf("\n");
610 printf("This test requires a POWER8, POWER9 or POWER10 CPU ");
611 printf("and either a usable framebuffer at /dev/fb0 or ");
612 printf("the path to usable cache inhibited memory and optional ");
613 printf("offset to be provided\n");
614 }
615
main(int argc,char * argv[])616 int main(int argc, char *argv[])
617 {
618
619 struct sigaction sa;
620 int rc = 0;
621 int option = 0;
622
623 while ((option = getopt(argc, argv, "d")) != -1) {
624 switch (option) {
625 case 'd':
626 debug++;
627 break;
628 default:
629 usage(argv[0]);
630 exit(1);
631 }
632 }
633 argc -= optind;
634 argv += optind;
635
636 if (argc > 0)
637 cipath = argv[0];
638 if (argc > 1)
639 cioffset = strtol(argv[1], 0, 0x10);
640
641 bufsize = getpagesize();
642
643 sa.sa_sigaction = sighandler;
644 sigemptyset(&sa.sa_mask);
645 sa.sa_flags = SA_SIGINFO;
646 if (sigaction(SIGSEGV, &sa, NULL) == -1
647 || sigaction(SIGBUS, &sa, NULL) == -1
648 || sigaction(SIGILL, &sa, NULL) == -1) {
649 perror("sigaction");
650 exit(1);
651 }
652
653 prefixes_enabled = have_hwcap2(PPC_FEATURE2_ARCH_3_1);
654
655 rc |= test_harness(test_alignment_handler_vsx_206,
656 "test_alignment_handler_vsx_206");
657 rc |= test_harness(test_alignment_handler_vsx_207,
658 "test_alignment_handler_vsx_207");
659 rc |= test_harness(test_alignment_handler_vsx_300,
660 "test_alignment_handler_vsx_300");
661 rc |= test_harness(test_alignment_handler_vsx_prefix,
662 "test_alignment_handler_vsx_prefix");
663 rc |= test_harness(test_alignment_handler_integer,
664 "test_alignment_handler_integer");
665 rc |= test_harness(test_alignment_handler_integer_206,
666 "test_alignment_handler_integer_206");
667 rc |= test_harness(test_alignment_handler_integer_prefix,
668 "test_alignment_handler_integer_prefix");
669 rc |= test_harness(test_alignment_handler_vmx,
670 "test_alignment_handler_vmx");
671 rc |= test_harness(test_alignment_handler_fp,
672 "test_alignment_handler_fp");
673 rc |= test_harness(test_alignment_handler_fp_205,
674 "test_alignment_handler_fp_205");
675 rc |= test_harness(test_alignment_handler_fp_206,
676 "test_alignment_handler_fp_206");
677 rc |= test_harness(test_alignment_handler_fp_prefix,
678 "test_alignment_handler_fp_prefix");
679 return rc;
680 }
681