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