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 } 690