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 "utils.h"
  59#include "instructions.h"
  60
  61int bufsize;
  62int debug;
  63int testing;
  64volatile int gotsig;
  65bool prefixes_enabled;
  66char *cipath = "/dev/fb0";
  67long cioffset;
  68
  69void 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 */
 155void 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
 166int 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
 191void 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
 206int 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 */
 230int 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
 317static 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
 329int 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
 347int 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
 363int 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
 395int 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
 414int 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
 473int 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
 488int 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
 509int 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
 537int 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
 565int 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
 583int 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
 598int 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
 614void 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
 625int 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