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 (we use /dev/fb0 for this).
14 * We initialise the source buffers, then use whichever set of load/store
15 * instructions is under test to copy bytes from the source buffers to the
16 * destination buffers. For the regular buffers, these instructions will
17 * execute normally. For the cache-inhibited buffers, these instructions
18 * will trap and cause an alignment fault, and the alignment fault handler
19 * will emulate the particular instruction under test. We then compare the
20 * destination buffers to ensure that the native and emulated cases give the
25 * - Test VSX regs < 32 and > 32
26 * - Test all loads and stores
27 * - Check update forms do update register
28 * - Test alignment faults over page boundary
30 * Some old binutils may not support all the instructions.
35 #include <sys/types.h>
48 #include <asm/cputable.h>
57 void sighandler(int sig
, siginfo_t
*info
, void *ctx
)
59 ucontext_t
*ucp
= ctx
;
67 ucp
->uc_mcontext
.gp_regs
[PT_NIP
] += 4;
69 ucp
->uc_mcontext
.uc_regs
->gregs
[PT_NIP
] += 4;
73 #define XFORM(reg, n) " " #reg " ,%"#n",%2 ;"
74 #define DFORM(reg, n) " " #reg " ,0(%"#n") ;"
76 #define TEST(name, ld_op, st_op, form, ld_reg, st_reg) \
77 void test_##name(char *s, char *d) \
80 #ld_op form(ld_reg, 0) \
81 #st_op form(st_reg, 1) \
82 :: "r"(s), "r"(d), "r"(0) \
83 : "memory", "vs0", "vs32", "r31"); \
85 rc |= do_test(#name, test_##name)
87 #define LOAD_VSX_XFORM_TEST(op) TEST(op, op, stxvd2x, XFORM, 32, 32)
88 #define STORE_VSX_XFORM_TEST(op) TEST(op, lxvd2x, op, XFORM, 32, 32)
89 #define LOAD_VSX_DFORM_TEST(op) TEST(op, op, stxv, DFORM, 32, 32)
90 #define STORE_VSX_DFORM_TEST(op) TEST(op, lxv, op, DFORM, 32, 32)
91 #define LOAD_VMX_XFORM_TEST(op) TEST(op, op, stxvd2x, XFORM, 0, 32)
92 #define STORE_VMX_XFORM_TEST(op) TEST(op, lxvd2x, op, XFORM, 32, 0)
93 #define LOAD_VMX_DFORM_TEST(op) TEST(op, op, stxv, DFORM, 0, 32)
94 #define STORE_VMX_DFORM_TEST(op) TEST(op, lxv, op, DFORM, 32, 0)
96 #define LOAD_XFORM_TEST(op) TEST(op, op, stdx, XFORM, 31, 31)
97 #define STORE_XFORM_TEST(op) TEST(op, ldx, op, XFORM, 31, 31)
98 #define LOAD_DFORM_TEST(op) TEST(op, op, std, DFORM, 31, 31)
99 #define STORE_DFORM_TEST(op) TEST(op, ld, op, DFORM, 31, 31)
101 #define LOAD_FLOAT_DFORM_TEST(op) TEST(op, op, stfd, DFORM, 0, 0)
102 #define STORE_FLOAT_DFORM_TEST(op) TEST(op, lfd, op, DFORM, 0, 0)
103 #define LOAD_FLOAT_XFORM_TEST(op) TEST(op, op, stfdx, XFORM, 0, 0)
104 #define STORE_FLOAT_XFORM_TEST(op) TEST(op, lfdx, op, XFORM, 0, 0)
107 /* FIXME: Unimplemented tests: */
108 // STORE_DFORM_TEST(stq) /* FIXME: need two registers for quad */
109 // STORE_DFORM_TEST(stswi) /* FIXME: string instruction */
111 // STORE_XFORM_TEST(stwat) /* AMO can't emulate or run on CI */
112 // STORE_XFORM_TEST(stdat) /* ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ */
115 /* preload byte by byte */
116 void preload_data(void *dst
, int offset
, int width
)
123 for (i
= 0 ; i
< width
; i
++)
127 int test_memcpy(void *dst
, void *src
, int size
, int offset
,
128 void (*test_func
)(char *, char *))
141 test_func(s
, d
); /* run the actual test */
146 printf(" Got signal %i\n", gotsig
);
152 void dumpdata(char *s1
, char *s2
, int n
, char *test_name
)
156 printf(" %s: unexpected result:\n", test_name
);
158 for (i
= 0; i
< n
; i
++)
159 printf(" %02x", s1
[i
]);
162 for (i
= 0; i
< n
; i
++)
163 printf(" %02x", s2
[i
]);
167 int test_memcmp(void *s1
, void *s2
, int n
, int offset
, char *test_name
)
176 if (memcmp(s1c
, s2c
, n
)) {
178 printf("\n Compare failed. Offset:%i length:%i\n",
180 dumpdata(s1c
, s2c
, n
, test_name
);
188 * Do two memcpy tests using the same instructions. One cachable
189 * memory and the other doesn't.
191 int do_test(char *test_name
, void (*test_func
)(char *, char *))
193 int offset
, width
, fd
, rc
, r
;
194 void *mem0
, *mem1
, *ci0
, *ci1
;
196 printf("\tDoing %s:\t", test_name
);
198 fd
= open("/dev/fb0", O_RDWR
);
201 perror("Can't open /dev/fb0 now?");
205 ci0
= mmap(NULL
, bufsize
, PROT_WRITE
, MAP_SHARED
,
207 ci1
= mmap(NULL
, bufsize
, PROT_WRITE
, MAP_SHARED
,
209 if ((ci0
== MAP_FAILED
) || (ci1
== MAP_FAILED
)) {
211 perror("mmap failed");
215 rc
= posix_memalign(&mem0
, bufsize
, bufsize
);
221 rc
= posix_memalign(&mem1
, bufsize
, bufsize
);
229 /* offset = 0 no alignment fault, so skip */
230 for (offset
= 1; offset
< 16; offset
++) {
231 width
= 16; /* vsx == 16 bytes */
234 /* load pattern into memory byte by byte */
235 preload_data(ci0
, offset
, width
);
236 preload_data(mem0
, offset
, width
); // FIXME: remove??
237 memcpy(ci0
, mem0
, bufsize
);
238 memcpy(ci1
, mem1
, bufsize
); /* initialise output to the same */
241 test_memcmp(mem0
, ci0
, width
, offset
, test_name
);
243 r
|= test_memcpy(ci1
, ci0
, width
, offset
, test_func
);
244 r
|= test_memcpy(mem1
, mem0
, width
, offset
, test_func
);
246 printf("FAILED: Got signal");
251 r
|= test_memcmp(mem1
, ci1
, width
, offset
, test_name
);
253 printf("FAILED: Wrong Data");
264 munmap(ci0
, bufsize
);
265 munmap(ci1
, bufsize
);
273 static bool can_open_fb0(void)
277 fd
= open("/dev/fb0", O_RDWR
);
285 int test_alignment_handler_vsx_206(void)
289 SKIP_IF(!can_open_fb0());
290 SKIP_IF(!have_hwcap(PPC_FEATURE_ARCH_2_06
));
292 printf("VSX: 2.06B\n");
293 LOAD_VSX_XFORM_TEST(lxvd2x
);
294 LOAD_VSX_XFORM_TEST(lxvw4x
);
295 LOAD_VSX_XFORM_TEST(lxsdx
);
296 LOAD_VSX_XFORM_TEST(lxvdsx
);
297 STORE_VSX_XFORM_TEST(stxvd2x
);
298 STORE_VSX_XFORM_TEST(stxvw4x
);
299 STORE_VSX_XFORM_TEST(stxsdx
);
303 int test_alignment_handler_vsx_207(void)
307 SKIP_IF(!can_open_fb0());
308 SKIP_IF(!have_hwcap2(PPC_FEATURE2_ARCH_2_07
));
310 printf("VSX: 2.07B\n");
311 LOAD_VSX_XFORM_TEST(lxsspx
);
312 LOAD_VSX_XFORM_TEST(lxsiwax
);
313 LOAD_VSX_XFORM_TEST(lxsiwzx
);
314 STORE_VSX_XFORM_TEST(stxsspx
);
315 STORE_VSX_XFORM_TEST(stxsiwx
);
319 int test_alignment_handler_vsx_300(void)
323 SKIP_IF(!can_open_fb0());
325 SKIP_IF(!have_hwcap2(PPC_FEATURE2_ARCH_3_00
));
326 printf("VSX: 3.00B\n");
327 LOAD_VMX_DFORM_TEST(lxsd
);
328 LOAD_VSX_XFORM_TEST(lxsibzx
);
329 LOAD_VSX_XFORM_TEST(lxsihzx
);
330 LOAD_VMX_DFORM_TEST(lxssp
);
331 LOAD_VSX_DFORM_TEST(lxv
);
332 LOAD_VSX_XFORM_TEST(lxvb16x
);
333 LOAD_VSX_XFORM_TEST(lxvh8x
);
334 LOAD_VSX_XFORM_TEST(lxvx
);
335 LOAD_VSX_XFORM_TEST(lxvwsx
);
336 LOAD_VSX_XFORM_TEST(lxvl
);
337 LOAD_VSX_XFORM_TEST(lxvll
);
338 STORE_VMX_DFORM_TEST(stxsd
);
339 STORE_VSX_XFORM_TEST(stxsibx
);
340 STORE_VSX_XFORM_TEST(stxsihx
);
341 STORE_VMX_DFORM_TEST(stxssp
);
342 STORE_VSX_DFORM_TEST(stxv
);
343 STORE_VSX_XFORM_TEST(stxvb16x
);
344 STORE_VSX_XFORM_TEST(stxvh8x
);
345 STORE_VSX_XFORM_TEST(stxvx
);
346 STORE_VSX_XFORM_TEST(stxvl
);
347 STORE_VSX_XFORM_TEST(stxvll
);
351 int test_alignment_handler_integer(void)
355 SKIP_IF(!can_open_fb0());
358 LOAD_DFORM_TEST(lbz
);
359 LOAD_DFORM_TEST(lbzu
);
360 LOAD_XFORM_TEST(lbzx
);
361 LOAD_XFORM_TEST(lbzux
);
362 LOAD_DFORM_TEST(lhz
);
363 LOAD_DFORM_TEST(lhzu
);
364 LOAD_XFORM_TEST(lhzx
);
365 LOAD_XFORM_TEST(lhzux
);
366 LOAD_DFORM_TEST(lha
);
367 LOAD_DFORM_TEST(lhau
);
368 LOAD_XFORM_TEST(lhax
);
369 LOAD_XFORM_TEST(lhaux
);
370 LOAD_XFORM_TEST(lhbrx
);
371 LOAD_DFORM_TEST(lwz
);
372 LOAD_DFORM_TEST(lwzu
);
373 LOAD_XFORM_TEST(lwzx
);
374 LOAD_XFORM_TEST(lwzux
);
375 LOAD_DFORM_TEST(lwa
);
376 LOAD_XFORM_TEST(lwax
);
377 LOAD_XFORM_TEST(lwaux
);
378 LOAD_XFORM_TEST(lwbrx
);
380 LOAD_DFORM_TEST(ldu
);
381 LOAD_XFORM_TEST(ldx
);
382 LOAD_XFORM_TEST(ldux
);
383 LOAD_DFORM_TEST(lmw
);
384 STORE_DFORM_TEST(stb
);
385 STORE_XFORM_TEST(stbx
);
386 STORE_DFORM_TEST(stbu
);
387 STORE_XFORM_TEST(stbux
);
388 STORE_DFORM_TEST(sth
);
389 STORE_XFORM_TEST(sthx
);
390 STORE_DFORM_TEST(sthu
);
391 STORE_XFORM_TEST(sthux
);
392 STORE_XFORM_TEST(sthbrx
);
393 STORE_DFORM_TEST(stw
);
394 STORE_XFORM_TEST(stwx
);
395 STORE_DFORM_TEST(stwu
);
396 STORE_XFORM_TEST(stwux
);
397 STORE_XFORM_TEST(stwbrx
);
398 STORE_DFORM_TEST(std
);
399 STORE_XFORM_TEST(stdx
);
400 STORE_DFORM_TEST(stdu
);
401 STORE_XFORM_TEST(stdux
);
402 STORE_DFORM_TEST(stmw
);
407 int test_alignment_handler_integer_206(void)
411 SKIP_IF(!can_open_fb0());
412 SKIP_IF(!have_hwcap(PPC_FEATURE_ARCH_2_06
));
414 printf("Integer: 2.06\n");
416 LOAD_XFORM_TEST(ldbrx
);
417 STORE_XFORM_TEST(stdbrx
);
422 int test_alignment_handler_vmx(void)
426 SKIP_IF(!can_open_fb0());
427 SKIP_IF(!have_hwcap(PPC_FEATURE_HAS_ALTIVEC
));
430 LOAD_VMX_XFORM_TEST(lvx
);
433 * FIXME: These loads only load part of the register, so our
434 * testing method doesn't work. Also they don't take alignment
435 * faults, so it's kinda pointless anyway
437 LOAD_VMX_XFORM_TEST(lvebx)
438 LOAD_VMX_XFORM_TEST(lvehx)
439 LOAD_VMX_XFORM_TEST(lvewx)
440 LOAD_VMX_XFORM_TEST(lvxl)
442 STORE_VMX_XFORM_TEST(stvx
);
443 STORE_VMX_XFORM_TEST(stvebx
);
444 STORE_VMX_XFORM_TEST(stvehx
);
445 STORE_VMX_XFORM_TEST(stvewx
);
446 STORE_VMX_XFORM_TEST(stvxl
);
450 int test_alignment_handler_fp(void)
454 SKIP_IF(!can_open_fb0());
456 printf("Floating point\n");
457 LOAD_FLOAT_DFORM_TEST(lfd
);
458 LOAD_FLOAT_XFORM_TEST(lfdx
);
459 LOAD_FLOAT_DFORM_TEST(lfdu
);
460 LOAD_FLOAT_XFORM_TEST(lfdux
);
461 LOAD_FLOAT_DFORM_TEST(lfs
);
462 LOAD_FLOAT_XFORM_TEST(lfsx
);
463 LOAD_FLOAT_DFORM_TEST(lfsu
);
464 LOAD_FLOAT_XFORM_TEST(lfsux
);
465 STORE_FLOAT_DFORM_TEST(stfd
);
466 STORE_FLOAT_XFORM_TEST(stfdx
);
467 STORE_FLOAT_DFORM_TEST(stfdu
);
468 STORE_FLOAT_XFORM_TEST(stfdux
);
469 STORE_FLOAT_DFORM_TEST(stfs
);
470 STORE_FLOAT_XFORM_TEST(stfsx
);
471 STORE_FLOAT_DFORM_TEST(stfsu
);
472 STORE_FLOAT_XFORM_TEST(stfsux
);
473 STORE_FLOAT_XFORM_TEST(stfiwx
);
478 int test_alignment_handler_fp_205(void)
482 SKIP_IF(!can_open_fb0());
483 SKIP_IF(!have_hwcap(PPC_FEATURE_ARCH_2_05
));
485 printf("Floating point: 2.05\n");
487 LOAD_FLOAT_DFORM_TEST(lfdp
);
488 LOAD_FLOAT_XFORM_TEST(lfdpx
);
489 LOAD_FLOAT_XFORM_TEST(lfiwax
);
490 STORE_FLOAT_DFORM_TEST(stfdp
);
491 STORE_FLOAT_XFORM_TEST(stfdpx
);
496 int test_alignment_handler_fp_206(void)
500 SKIP_IF(!can_open_fb0());
501 SKIP_IF(!have_hwcap(PPC_FEATURE_ARCH_2_06
));
503 printf("Floating point: 2.06\n");
505 LOAD_FLOAT_XFORM_TEST(lfiwzx
);
510 void usage(char *prog
)
512 printf("Usage: %s [options]\n", prog
);
513 printf(" -d Enable debug error output\n");
515 printf("This test requires a POWER8 or POWER9 CPU and a usable ");
516 printf("framebuffer at /dev/fb0.\n");
519 int main(int argc
, char *argv
[])
526 while ((option
= getopt(argc
, argv
, "d")) != -1) {
537 bufsize
= getpagesize();
539 sa
.sa_sigaction
= sighandler
;
540 sigemptyset(&sa
.sa_mask
);
541 sa
.sa_flags
= SA_SIGINFO
;
542 if (sigaction(SIGSEGV
, &sa
, NULL
) == -1
543 || sigaction(SIGBUS
, &sa
, NULL
) == -1
544 || sigaction(SIGILL
, &sa
, NULL
) == -1) {
549 rc
|= test_harness(test_alignment_handler_vsx_206
,
550 "test_alignment_handler_vsx_206");
551 rc
|= test_harness(test_alignment_handler_vsx_207
,
552 "test_alignment_handler_vsx_207");
553 rc
|= test_harness(test_alignment_handler_vsx_300
,
554 "test_alignment_handler_vsx_300");
555 rc
|= test_harness(test_alignment_handler_integer
,
556 "test_alignment_handler_integer");
557 rc
|= test_harness(test_alignment_handler_integer_206
,
558 "test_alignment_handler_integer_206");
559 rc
|= test_harness(test_alignment_handler_vmx
,
560 "test_alignment_handler_vmx");
561 rc
|= test_harness(test_alignment_handler_fp
,
562 "test_alignment_handler_fp");
563 rc
|= test_harness(test_alignment_handler_fp_205
,
564 "test_alignment_handler_fp_205");
565 rc
|= test_harness(test_alignment_handler_fp_206
,
566 "test_alignment_handler_fp_206");