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