1 // SPDX-License-Identifier: GPL-2.0-or-later
3 * Test the powerpc alignment handler on POWER8/POWER9
5 * Copyright (C) 2017 IBM Corporation (Michael Neuling, Andrew Donnellan)
9 * This selftest exercises the powerpc alignment fault handler.
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).
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
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
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
40 * Some old binutils may not support all the instructions.
45 #include <sys/types.h>
59 #include "instructions.h"
65 bool prefixes_enabled
;
66 char *cipath
= "/dev/fb0";
69 void sighandler(int sig
, siginfo_t
*info
, void *ctx
)
71 ucontext_t
*ucp
= ctx
;
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);
83 ucp
->uc_mcontext
.gp_regs
[PT_NIP
] += 4;
86 ucp
->uc_mcontext
.uc_regs
->gregs
[PT_NIP
] += 4;
90 #define XFORM(reg, n) " " #reg " ,%"#n",%2 ;"
91 #define DFORM(reg, n) " " #reg " ,0(%"#n") ;"
93 #define TEST(name, ld_op, st_op, form, ld_reg, st_reg) \
94 void test_##name(char *s, char *d) \
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"); \
102 rc |= do_test(#name, test_##name)
104 #define TESTP(name, ld_op, st_op, ld_reg, st_reg) \
105 void test_##name(char *s, char *d) \
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"); \
113 rc |= do_test(#name, test_##name)
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)
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)
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)
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)
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)
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)
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)
146 /* FIXME: Unimplemented tests: */
147 // STORE_DFORM_TEST(stq) /* FIXME: need two registers for quad */
148 // STORE_DFORM_TEST(stswi) /* FIXME: string instruction */
150 // STORE_XFORM_TEST(stwat) /* AMO can't emulate or run on CI */
151 // STORE_XFORM_TEST(stdat) /* ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ */
154 /* preload byte by byte */
155 void preload_data(void *dst
, int offset
, int width
)
162 for (i
= 0 ; i
< width
; i
++)
166 int test_memcpy(void *dst
, void *src
, int size
, int offset
,
167 void (*test_func
)(char *, char *))
180 test_func(s
, d
); /* run the actual test */
185 printf(" Got signal %i\n", gotsig
);
191 void dumpdata(char *s1
, char *s2
, int n
, char *test_name
)
195 printf(" %s: unexpected result:\n", test_name
);
197 for (i
= 0; i
< n
; i
++)
198 printf(" %02x", s1
[i
]);
201 for (i
= 0; i
< n
; i
++)
202 printf(" %02x", s2
[i
]);
206 int test_memcmp(void *s1
, void *s2
, int n
, int offset
, char *test_name
)
215 if (memcmp(s1c
, s2c
, n
)) {
217 printf("\n Compare failed. Offset:%i length:%i\n",
219 dumpdata(s1c
, s2c
, n
, test_name
);
227 * Do two memcpy tests using the same instructions. One cachable
228 * memory and the other doesn't.
230 int do_test(char *test_name
, void (*test_func
)(char *, char *))
232 int offset
, width
, fd
, rc
, r
;
233 void *mem0
, *mem1
, *ci0
, *ci1
;
235 printf("\tDoing %s:\t", test_name
);
237 fd
= open(cipath
, O_RDWR
);
240 perror("Can't open ci file now?");
244 ci0
= mmap(NULL
, bufsize
, PROT_WRITE
| PROT_READ
, MAP_SHARED
,
246 ci1
= mmap(NULL
, bufsize
, PROT_WRITE
| PROT_READ
, MAP_SHARED
,
247 fd
, cioffset
+ bufsize
);
249 if ((ci0
== MAP_FAILED
) || (ci1
== MAP_FAILED
)) {
251 perror("mmap failed");
255 rc
= posix_memalign(&mem0
, bufsize
, bufsize
);
261 rc
= posix_memalign(&mem1
, bufsize
, bufsize
);
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")
274 for (offset
= 0; offset
< 16; offset
++) {
275 width
= 16; /* vsx == 16 bytes */
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 */
285 test_memcmp(mem0
, ci0
, width
, offset
, test_name
);
287 r
|= test_memcpy(ci1
, ci0
, width
, offset
, test_func
);
288 r
|= test_memcpy(mem1
, mem0
, width
, offset
, test_func
);
290 printf("FAILED: Got signal");
295 r
|= test_memcmp(mem1
, ci1
, width
, offset
, test_name
);
297 printf("FAILED: Wrong Data");
308 munmap(ci0
, bufsize
);
309 munmap(ci1
, bufsize
);
317 static bool can_open_cifile(void)
321 fd
= open(cipath
, O_RDWR
);
329 int test_alignment_handler_vsx_206(void)
333 SKIP_IF(!can_open_cifile());
334 SKIP_IF(!have_hwcap(PPC_FEATURE_ARCH_2_06
));
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
);
347 int test_alignment_handler_vsx_207(void)
351 SKIP_IF(!can_open_cifile());
352 SKIP_IF(!have_hwcap2(PPC_FEATURE2_ARCH_2_07
));
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
);
363 int test_alignment_handler_vsx_300(void)
367 SKIP_IF(!can_open_cifile());
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
);
395 int test_alignment_handler_vsx_prefix(void)
399 SKIP_IF(!can_open_cifile());
400 SKIP_IF(!have_hwcap2(PPC_FEATURE2_ARCH_3_1
));
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);
414 int test_alignment_handler_integer(void)
418 SKIP_IF(!can_open_cifile());
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
);
443 LOAD_DFORM_TEST(ldu
);
444 LOAD_XFORM_TEST(ldx
);
445 LOAD_XFORM_TEST(ldux
);
446 LOAD_DFORM_TEST(lmw
);
447 STORE_DFORM_TEST(stb
);
448 STORE_XFORM_TEST(stbx
);
449 STORE_DFORM_TEST(stbu
);
450 STORE_XFORM_TEST(stbux
);
451 STORE_DFORM_TEST(sth
);
452 STORE_XFORM_TEST(sthx
);
453 STORE_DFORM_TEST(sthu
);
454 STORE_XFORM_TEST(sthux
);
455 STORE_XFORM_TEST(sthbrx
);
456 STORE_DFORM_TEST(stw
);
457 STORE_XFORM_TEST(stwx
);
458 STORE_DFORM_TEST(stwu
);
459 STORE_XFORM_TEST(stwux
);
460 STORE_XFORM_TEST(stwbrx
);
461 STORE_DFORM_TEST(std
);
462 STORE_XFORM_TEST(stdx
);
463 STORE_DFORM_TEST(stdu
);
464 STORE_XFORM_TEST(stdux
);
465 STORE_DFORM_TEST(stmw
);
470 int test_alignment_handler_integer_206(void)
474 SKIP_IF(!can_open_cifile());
475 SKIP_IF(!have_hwcap(PPC_FEATURE_ARCH_2_06
));
477 printf("Integer: 2.06\n");
479 LOAD_XFORM_TEST(ldbrx
);
480 STORE_XFORM_TEST(stdbrx
);
485 int test_alignment_handler_integer_prefix(void)
489 SKIP_IF(!can_open_cifile());
490 SKIP_IF(!have_hwcap2(PPC_FEATURE2_ARCH_3_1
));
492 printf("Integer: PREFIX\n");
493 LOAD_MLS_PREFIX_TEST(PLBZ
);
494 LOAD_MLS_PREFIX_TEST(PLHZ
);
495 LOAD_MLS_PREFIX_TEST(PLHA
);
496 LOAD_MLS_PREFIX_TEST(PLWZ
);
497 LOAD_8LS_PREFIX_TEST(PLWA
);
498 LOAD_8LS_PREFIX_TEST(PLD
);
499 STORE_MLS_PREFIX_TEST(PSTB
);
500 STORE_MLS_PREFIX_TEST(PSTH
);
501 STORE_MLS_PREFIX_TEST(PSTW
);
502 STORE_8LS_PREFIX_TEST(PSTD
);
506 int test_alignment_handler_vmx(void)
510 SKIP_IF(!can_open_cifile());
511 SKIP_IF(!have_hwcap(PPC_FEATURE_HAS_ALTIVEC
));
514 LOAD_VMX_XFORM_TEST(lvx
);
517 * FIXME: These loads only load part of the register, so our
518 * testing method doesn't work. Also they don't take alignment
519 * faults, so it's kinda pointless anyway
521 LOAD_VMX_XFORM_TEST(lvebx)
522 LOAD_VMX_XFORM_TEST(lvehx)
523 LOAD_VMX_XFORM_TEST(lvewx)
524 LOAD_VMX_XFORM_TEST(lvxl)
526 STORE_VMX_XFORM_TEST(stvx
);
527 STORE_VMX_XFORM_TEST(stvebx
);
528 STORE_VMX_XFORM_TEST(stvehx
);
529 STORE_VMX_XFORM_TEST(stvewx
);
530 STORE_VMX_XFORM_TEST(stvxl
);
534 int test_alignment_handler_fp(void)
538 SKIP_IF(!can_open_cifile());
540 printf("Floating point\n");
541 LOAD_FLOAT_DFORM_TEST(lfd
);
542 LOAD_FLOAT_XFORM_TEST(lfdx
);
543 LOAD_FLOAT_DFORM_TEST(lfdu
);
544 LOAD_FLOAT_XFORM_TEST(lfdux
);
545 LOAD_FLOAT_DFORM_TEST(lfs
);
546 LOAD_FLOAT_XFORM_TEST(lfsx
);
547 LOAD_FLOAT_DFORM_TEST(lfsu
);
548 LOAD_FLOAT_XFORM_TEST(lfsux
);
549 STORE_FLOAT_DFORM_TEST(stfd
);
550 STORE_FLOAT_XFORM_TEST(stfdx
);
551 STORE_FLOAT_DFORM_TEST(stfdu
);
552 STORE_FLOAT_XFORM_TEST(stfdux
);
553 STORE_FLOAT_DFORM_TEST(stfs
);
554 STORE_FLOAT_XFORM_TEST(stfsx
);
555 STORE_FLOAT_DFORM_TEST(stfsu
);
556 STORE_FLOAT_XFORM_TEST(stfsux
);
557 STORE_FLOAT_XFORM_TEST(stfiwx
);
562 int test_alignment_handler_fp_205(void)
566 SKIP_IF(!can_open_cifile());
567 SKIP_IF(!have_hwcap(PPC_FEATURE_ARCH_2_05
));
569 printf("Floating point: 2.05\n");
571 LOAD_FLOAT_DFORM_TEST(lfdp
);
572 LOAD_FLOAT_XFORM_TEST(lfdpx
);
573 LOAD_FLOAT_XFORM_TEST(lfiwax
);
574 STORE_FLOAT_DFORM_TEST(stfdp
);
575 STORE_FLOAT_XFORM_TEST(stfdpx
);
580 int test_alignment_handler_fp_206(void)
584 SKIP_IF(!can_open_cifile());
585 SKIP_IF(!have_hwcap(PPC_FEATURE_ARCH_2_06
));
587 printf("Floating point: 2.06\n");
589 LOAD_FLOAT_XFORM_TEST(lfiwzx
);
595 int test_alignment_handler_fp_prefix(void)
599 SKIP_IF(!can_open_cifile());
600 SKIP_IF(!have_hwcap2(PPC_FEATURE2_ARCH_3_1
));
602 printf("Floating point: PREFIX\n");
603 LOAD_FLOAT_DFORM_TEST(lfs
);
604 LOAD_FLOAT_MLS_PREFIX_TEST(PLFS
);
605 LOAD_FLOAT_MLS_PREFIX_TEST(PLFD
);
606 STORE_FLOAT_MLS_PREFIX_TEST(PSTFS
);
607 STORE_FLOAT_MLS_PREFIX_TEST(PSTFD
);
611 void usage(char *prog
)
613 printf("Usage: %s [options] [path [offset]]\n", prog
);
614 printf(" -d Enable debug error output\n");
616 printf("This test requires a POWER8, POWER9 or POWER10 CPU ");
617 printf("and either a usable framebuffer at /dev/fb0 or ");
618 printf("the path to usable cache inhibited memory and optional ");
619 printf("offset to be provided\n");
622 int main(int argc
, char *argv
[])
629 while ((option
= getopt(argc
, argv
, "d")) != -1) {
645 cioffset
= strtol(argv
[1], 0, 0x10);
647 bufsize
= getpagesize();
649 sa
.sa_sigaction
= sighandler
;
650 sigemptyset(&sa
.sa_mask
);
651 sa
.sa_flags
= SA_SIGINFO
;
652 if (sigaction(SIGSEGV
, &sa
, NULL
) == -1
653 || sigaction(SIGBUS
, &sa
, NULL
) == -1
654 || sigaction(SIGILL
, &sa
, NULL
) == -1) {
659 prefixes_enabled
= have_hwcap2(PPC_FEATURE2_ARCH_3_1
);
661 rc
|= test_harness(test_alignment_handler_vsx_206
,
662 "test_alignment_handler_vsx_206");
663 rc
|= test_harness(test_alignment_handler_vsx_207
,
664 "test_alignment_handler_vsx_207");
665 rc
|= test_harness(test_alignment_handler_vsx_300
,
666 "test_alignment_handler_vsx_300");
667 rc
|= test_harness(test_alignment_handler_vsx_prefix
,
668 "test_alignment_handler_vsx_prefix");
669 rc
|= test_harness(test_alignment_handler_integer
,
670 "test_alignment_handler_integer");
671 rc
|= test_harness(test_alignment_handler_integer_206
,
672 "test_alignment_handler_integer_206");
673 rc
|= test_harness(test_alignment_handler_integer_prefix
,
674 "test_alignment_handler_integer_prefix");
675 rc
|= test_harness(test_alignment_handler_vmx
,
676 "test_alignment_handler_vmx");
677 rc
|= test_harness(test_alignment_handler_fp
,
678 "test_alignment_handler_fp");
679 rc
|= test_harness(test_alignment_handler_fp_205
,
680 "test_alignment_handler_fp_205");
681 rc
|= test_harness(test_alignment_handler_fp_206
,
682 "test_alignment_handler_fp_206");
683 rc
|= test_harness(test_alignment_handler_fp_prefix
,
684 "test_alignment_handler_fp_prefix");