linux/tools/testing/selftests/powerpc/alignment/alignment_handler.c
<<
>>
Prefs
   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
  52int bufsize;
  53int debug;
  54int testing;
  55volatile int gotsig;
  56bool prefixes_enabled;
  57char *cipath = "/dev/fb0";
  58long cioffset;
  59
  60void 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 */
 146void 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
 157int 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
 182void 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
 197int 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 */
 221int 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
 308static 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
 320int 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
 338int 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
 354int 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
 386int 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
 405int 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
 464int 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
 479int 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
 500int 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
 528int 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
 556int 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
 574int 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
 589int 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
 605void 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
 616int 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