Back to home page

OSCL-LXR

 
 

    


0001 // SPDX-License-Identifier: GPL-2.0-or-later
0002 /*
0003  * Test the powerpc alignment handler on POWER8/POWER9
0004  *
0005  * Copyright (C) 2017 IBM Corporation (Michael Neuling, Andrew Donnellan)
0006  */
0007 
0008 /*
0009  * This selftest exercises the powerpc alignment fault handler.
0010  *
0011  * We create two sets of source and destination buffers, one in regular memory,
0012  * the other cache-inhibited (by default we use /dev/fb0 for this, but an
0013  * alterative path for cache-inhibited memory may be provided, e.g. memtrace).
0014  *
0015  * We initialise the source buffers, then use whichever set of load/store
0016  * instructions is under test to copy bytes from the source buffers to the
0017  * destination buffers. For the regular buffers, these instructions will
0018  * execute normally. For the cache-inhibited buffers, these instructions
0019  * will trap and cause an alignment fault, and the alignment fault handler
0020  * will emulate the particular instruction under test. We then compare the
0021  * destination buffers to ensure that the native and emulated cases give the
0022  * same result.
0023  *
0024  * TODO:
0025  *   - Any FIXMEs below
0026  *   - Test VSX regs < 32 and > 32
0027  *   - Test all loads and stores
0028  *   - Check update forms do update register
0029  *   - Test alignment faults over page boundary
0030  *
0031  * Some old binutils may not support all the instructions.
0032  */
0033 
0034 
0035 #include <sys/mman.h>
0036 #include <sys/types.h>
0037 #include <sys/stat.h>
0038 #include <fcntl.h>
0039 #include <unistd.h>
0040 #include <stdbool.h>
0041 #include <stdio.h>
0042 #include <stdlib.h>
0043 #include <string.h>
0044 #include <assert.h>
0045 #include <getopt.h>
0046 #include <setjmp.h>
0047 #include <signal.h>
0048 
0049 #include "utils.h"
0050 #include "instructions.h"
0051 
0052 int bufsize;
0053 int debug;
0054 int testing;
0055 volatile int gotsig;
0056 bool prefixes_enabled;
0057 char *cipath = "/dev/fb0";
0058 long cioffset;
0059 
0060 void sighandler(int sig, siginfo_t *info, void *ctx)
0061 {
0062     ucontext_t *ucp = ctx;
0063 
0064     if (!testing) {
0065         signal(sig, SIG_DFL);
0066         kill(0, sig);
0067     }
0068     gotsig = sig;
0069 #ifdef __powerpc64__
0070     if (prefixes_enabled) {
0071         u32 inst = *(u32 *)ucp->uc_mcontext.gp_regs[PT_NIP];
0072         ucp->uc_mcontext.gp_regs[PT_NIP] += ((inst >> 26 == 1) ? 8 : 4);
0073     } else {
0074         ucp->uc_mcontext.gp_regs[PT_NIP] += 4;
0075     }
0076 #else
0077     ucp->uc_mcontext.uc_regs->gregs[PT_NIP] += 4;
0078 #endif
0079 }
0080 
0081 #define XFORM(reg, n)  " " #reg " ,%"#n",%2 ;"
0082 #define DFORM(reg, n)  " " #reg " ,0(%"#n") ;"
0083 
0084 #define TEST(name, ld_op, st_op, form, ld_reg, st_reg)      \
0085     void test_##name(char *s, char *d)          \
0086     {                           \
0087         asm volatile(                   \
0088             #ld_op form(ld_reg, 0)          \
0089             #st_op form(st_reg, 1)          \
0090             :: "r"(s), "r"(d), "r"(0)       \
0091             : "memory", "vs0", "vs32", "r31");  \
0092     }                           \
0093     rc |= do_test(#name, test_##name)
0094 
0095 #define TESTP(name, ld_op, st_op, ld_reg, st_reg)       \
0096     void test_##name(char *s, char *d)          \
0097     {                           \
0098         asm volatile(                   \
0099             ld_op(ld_reg, %0, 0, 0)         \
0100             st_op(st_reg, %1, 0, 0)         \
0101             :: "r"(s), "r"(d), "r"(0)       \
0102             : "memory", "vs0", "vs32", "r31");  \
0103     }                           \
0104     rc |= do_test(#name, test_##name)
0105 
0106 #define LOAD_VSX_XFORM_TEST(op) TEST(op, op, stxvd2x, XFORM, 32, 32)
0107 #define STORE_VSX_XFORM_TEST(op) TEST(op, lxvd2x, op, XFORM, 32, 32)
0108 #define LOAD_VSX_DFORM_TEST(op) TEST(op, op, stxv, DFORM, 32, 32)
0109 #define STORE_VSX_DFORM_TEST(op) TEST(op, lxv, op, DFORM, 32, 32)
0110 #define LOAD_VMX_XFORM_TEST(op) TEST(op, op, stxvd2x, XFORM, 0, 32)
0111 #define STORE_VMX_XFORM_TEST(op) TEST(op, lxvd2x, op, XFORM, 32, 0)
0112 #define LOAD_VMX_DFORM_TEST(op) TEST(op, op, stxv, DFORM, 0, 32)
0113 #define STORE_VMX_DFORM_TEST(op) TEST(op, lxv, op, DFORM, 32, 0)
0114 
0115 #define LOAD_XFORM_TEST(op) TEST(op, op, stdx, XFORM, 31, 31)
0116 #define STORE_XFORM_TEST(op) TEST(op, ldx, op, XFORM, 31, 31)
0117 #define LOAD_DFORM_TEST(op) TEST(op, op, std, DFORM, 31, 31)
0118 #define STORE_DFORM_TEST(op) TEST(op, ld, op, DFORM, 31, 31)
0119 
0120 #define LOAD_FLOAT_DFORM_TEST(op)  TEST(op, op, stfd, DFORM, 0, 0)
0121 #define STORE_FLOAT_DFORM_TEST(op) TEST(op, lfd, op, DFORM, 0, 0)
0122 #define LOAD_FLOAT_XFORM_TEST(op)  TEST(op, op, stfdx, XFORM, 0, 0)
0123 #define STORE_FLOAT_XFORM_TEST(op) TEST(op, lfdx, op, XFORM, 0, 0)
0124 
0125 #define LOAD_MLS_PREFIX_TEST(op) TESTP(op, op, PSTD, 31, 31)
0126 #define STORE_MLS_PREFIX_TEST(op) TESTP(op, PLD, op, 31, 31)
0127 
0128 #define LOAD_8LS_PREFIX_TEST(op) TESTP(op, op, PSTD, 31, 31)
0129 #define STORE_8LS_PREFIX_TEST(op) TESTP(op, PLD, op, 31, 31)
0130 
0131 #define LOAD_FLOAT_MLS_PREFIX_TEST(op) TESTP(op, op, PSTFD, 0, 0)
0132 #define STORE_FLOAT_MLS_PREFIX_TEST(op) TESTP(op, PLFD, op, 0, 0)
0133 
0134 #define LOAD_VSX_8LS_PREFIX_TEST(op, tail) TESTP(op, op, PSTXV ## tail, 0, 32)
0135 #define STORE_VSX_8LS_PREFIX_TEST(op, tail) TESTP(op, PLXV ## tail, op, 32, 0)
0136 
0137 /* FIXME: Unimplemented tests: */
0138 // STORE_DFORM_TEST(stq)   /* FIXME: need two registers for quad */
0139 // STORE_DFORM_TEST(stswi) /* FIXME: string instruction */
0140 
0141 // STORE_XFORM_TEST(stwat) /* AMO can't emulate or run on CI */
0142 // STORE_XFORM_TEST(stdat) /* ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ */
0143 
0144 
0145 /* preload byte by byte */
0146 void preload_data(void *dst, int offset, int width)
0147 {
0148     char *c = dst;
0149     int i;
0150 
0151     c += offset;
0152 
0153     for (i = 0 ; i < width ; i++)
0154         c[i] = i;
0155 }
0156 
0157 int test_memcpy(void *dst, void *src, int size, int offset,
0158         void (*test_func)(char *, char *))
0159 {
0160     char *s, *d;
0161 
0162     s = src;
0163     s += offset;
0164     d = dst;
0165     d += offset;
0166 
0167     assert(size == 16);
0168     gotsig = 0;
0169     testing = 1;
0170 
0171     test_func(s, d); /* run the actual test */
0172 
0173     testing = 0;
0174     if (gotsig) {
0175         if (debug)
0176             printf("  Got signal %i\n", gotsig);
0177         return 1;
0178     }
0179     return 0;
0180 }
0181 
0182 void dumpdata(char *s1, char *s2, int n, char *test_name)
0183 {
0184     int i;
0185 
0186     printf("  %s: unexpected result:\n", test_name);
0187     printf("    mem:");
0188     for (i = 0; i < n; i++)
0189         printf(" %02x", s1[i]);
0190     printf("\n");
0191     printf("    ci: ");
0192     for (i = 0; i < n; i++)
0193         printf(" %02x", s2[i]);
0194     printf("\n");
0195 }
0196 
0197 int test_memcmp(void *s1, void *s2, int n, int offset, char *test_name)
0198 {
0199     char *s1c, *s2c;
0200 
0201     s1c = s1;
0202     s1c += offset;
0203     s2c = s2;
0204     s2c += offset;
0205 
0206     if (memcmp(s1c, s2c, n)) {
0207         if (debug) {
0208             printf("\n  Compare failed. Offset:%i length:%i\n",
0209                    offset, n);
0210             dumpdata(s1c, s2c, n, test_name);
0211         }
0212         return 1;
0213     }
0214     return 0;
0215 }
0216 
0217 /*
0218  * Do two memcpy tests using the same instructions. One cachable
0219  * memory and the other doesn't.
0220  */
0221 int do_test(char *test_name, void (*test_func)(char *, char *))
0222 {
0223     int offset, width, fd, rc, r;
0224     void *mem0, *mem1, *ci0, *ci1;
0225 
0226     printf("\tDoing %s:\t", test_name);
0227 
0228     fd = open(cipath, O_RDWR);
0229     if (fd < 0) {
0230         printf("\n");
0231         perror("Can't open ci file now?");
0232         return 1;
0233     }
0234 
0235     ci0 = mmap(NULL, bufsize, PROT_WRITE | PROT_READ, MAP_SHARED,
0236            fd, cioffset);
0237     ci1 = mmap(NULL, bufsize, PROT_WRITE | PROT_READ, MAP_SHARED,
0238            fd, cioffset + bufsize);
0239 
0240     if ((ci0 == MAP_FAILED) || (ci1 == MAP_FAILED)) {
0241         printf("\n");
0242         perror("mmap failed");
0243         SKIP_IF(1);
0244     }
0245 
0246     rc = posix_memalign(&mem0, bufsize, bufsize);
0247     if (rc) {
0248         printf("\n");
0249         return rc;
0250     }
0251 
0252     rc = posix_memalign(&mem1, bufsize, bufsize);
0253     if (rc) {
0254         printf("\n");
0255         free(mem0);
0256         return rc;
0257     }
0258 
0259     rc = 0;
0260     /*
0261      * offset = 0 is aligned but tests the workaround for the P9N
0262      * DD2.1 vector CI load issue (see 5080332c2c89 "powerpc/64s:
0263      * Add workaround for P9 vector CI load issue")
0264      */
0265     for (offset = 0; offset < 16; offset++) {
0266         width = 16; /* vsx == 16 bytes */
0267         r = 0;
0268 
0269         /* load pattern into memory byte by byte */
0270         preload_data(ci0, offset, width);
0271         preload_data(mem0, offset, width); // FIXME: remove??
0272         memcpy(ci0, mem0, bufsize);
0273         memcpy(ci1, mem1, bufsize); /* initialise output to the same */
0274 
0275         /* sanity check */
0276         test_memcmp(mem0, ci0, width, offset, test_name);
0277 
0278         r |= test_memcpy(ci1,  ci0,  width, offset, test_func);
0279         r |= test_memcpy(mem1, mem0, width, offset, test_func);
0280         if (r && !debug) {
0281             printf("FAILED: Got signal");
0282             rc = 1;
0283             break;
0284         }
0285 
0286         r |= test_memcmp(mem1, ci1, width, offset, test_name);
0287         if (r && !debug) {
0288             printf("FAILED: Wrong Data");
0289             rc = 1;
0290             break;
0291         }
0292     }
0293 
0294     if (rc == 0)
0295         printf("PASSED");
0296 
0297     printf("\n");
0298 
0299     munmap(ci0, bufsize);
0300     munmap(ci1, bufsize);
0301     free(mem0);
0302     free(mem1);
0303     close(fd);
0304 
0305     return rc;
0306 }
0307 
0308 static bool can_open_cifile(void)
0309 {
0310     int fd;
0311 
0312     fd = open(cipath, O_RDWR);
0313     if (fd < 0)
0314         return false;
0315 
0316     close(fd);
0317     return true;
0318 }
0319 
0320 int test_alignment_handler_vsx_206(void)
0321 {
0322     int rc = 0;
0323 
0324     SKIP_IF(!can_open_cifile());
0325     SKIP_IF(!have_hwcap(PPC_FEATURE_ARCH_2_06));
0326 
0327     printf("VSX: 2.06B\n");
0328     LOAD_VSX_XFORM_TEST(lxvd2x);
0329     LOAD_VSX_XFORM_TEST(lxvw4x);
0330     LOAD_VSX_XFORM_TEST(lxsdx);
0331     LOAD_VSX_XFORM_TEST(lxvdsx);
0332     STORE_VSX_XFORM_TEST(stxvd2x);
0333     STORE_VSX_XFORM_TEST(stxvw4x);
0334     STORE_VSX_XFORM_TEST(stxsdx);
0335     return rc;
0336 }
0337 
0338 int test_alignment_handler_vsx_207(void)
0339 {
0340     int rc = 0;
0341 
0342     SKIP_IF(!can_open_cifile());
0343     SKIP_IF(!have_hwcap2(PPC_FEATURE2_ARCH_2_07));
0344 
0345     printf("VSX: 2.07B\n");
0346     LOAD_VSX_XFORM_TEST(lxsspx);
0347     LOAD_VSX_XFORM_TEST(lxsiwax);
0348     LOAD_VSX_XFORM_TEST(lxsiwzx);
0349     STORE_VSX_XFORM_TEST(stxsspx);
0350     STORE_VSX_XFORM_TEST(stxsiwx);
0351     return rc;
0352 }
0353 
0354 int test_alignment_handler_vsx_300(void)
0355 {
0356     int rc = 0;
0357 
0358     SKIP_IF(!can_open_cifile());
0359 
0360     SKIP_IF(!have_hwcap2(PPC_FEATURE2_ARCH_3_00));
0361     printf("VSX: 3.00B\n");
0362     LOAD_VMX_DFORM_TEST(lxsd);
0363     LOAD_VSX_XFORM_TEST(lxsibzx);
0364     LOAD_VSX_XFORM_TEST(lxsihzx);
0365     LOAD_VMX_DFORM_TEST(lxssp);
0366     LOAD_VSX_DFORM_TEST(lxv);
0367     LOAD_VSX_XFORM_TEST(lxvb16x);
0368     LOAD_VSX_XFORM_TEST(lxvh8x);
0369     LOAD_VSX_XFORM_TEST(lxvx);
0370     LOAD_VSX_XFORM_TEST(lxvwsx);
0371     LOAD_VSX_XFORM_TEST(lxvl);
0372     LOAD_VSX_XFORM_TEST(lxvll);
0373     STORE_VMX_DFORM_TEST(stxsd);
0374     STORE_VSX_XFORM_TEST(stxsibx);
0375     STORE_VSX_XFORM_TEST(stxsihx);
0376     STORE_VMX_DFORM_TEST(stxssp);
0377     STORE_VSX_DFORM_TEST(stxv);
0378     STORE_VSX_XFORM_TEST(stxvb16x);
0379     STORE_VSX_XFORM_TEST(stxvh8x);
0380     STORE_VSX_XFORM_TEST(stxvx);
0381     STORE_VSX_XFORM_TEST(stxvl);
0382     STORE_VSX_XFORM_TEST(stxvll);
0383     return rc;
0384 }
0385 
0386 int test_alignment_handler_vsx_prefix(void)
0387 {
0388     int rc = 0;
0389 
0390     SKIP_IF(!can_open_cifile());
0391     SKIP_IF(!have_hwcap2(PPC_FEATURE2_ARCH_3_1));
0392 
0393     printf("VSX: PREFIX\n");
0394     LOAD_VSX_8LS_PREFIX_TEST(PLXSD, 0);
0395     LOAD_VSX_8LS_PREFIX_TEST(PLXSSP, 0);
0396     LOAD_VSX_8LS_PREFIX_TEST(PLXV0, 0);
0397     LOAD_VSX_8LS_PREFIX_TEST(PLXV1, 1);
0398     STORE_VSX_8LS_PREFIX_TEST(PSTXSD, 0);
0399     STORE_VSX_8LS_PREFIX_TEST(PSTXSSP, 0);
0400     STORE_VSX_8LS_PREFIX_TEST(PSTXV0, 0);
0401     STORE_VSX_8LS_PREFIX_TEST(PSTXV1, 1);
0402     return rc;
0403 }
0404 
0405 int test_alignment_handler_integer(void)
0406 {
0407     int rc = 0;
0408 
0409     SKIP_IF(!can_open_cifile());
0410 
0411     printf("Integer\n");
0412     LOAD_DFORM_TEST(lbz);
0413     LOAD_DFORM_TEST(lbzu);
0414     LOAD_XFORM_TEST(lbzx);
0415     LOAD_XFORM_TEST(lbzux);
0416     LOAD_DFORM_TEST(lhz);
0417     LOAD_DFORM_TEST(lhzu);
0418     LOAD_XFORM_TEST(lhzx);
0419     LOAD_XFORM_TEST(lhzux);
0420     LOAD_DFORM_TEST(lha);
0421     LOAD_DFORM_TEST(lhau);
0422     LOAD_XFORM_TEST(lhax);
0423     LOAD_XFORM_TEST(lhaux);
0424     LOAD_XFORM_TEST(lhbrx);
0425     LOAD_DFORM_TEST(lwz);
0426     LOAD_DFORM_TEST(lwzu);
0427     LOAD_XFORM_TEST(lwzx);
0428     LOAD_XFORM_TEST(lwzux);
0429     LOAD_DFORM_TEST(lwa);
0430     LOAD_XFORM_TEST(lwax);
0431     LOAD_XFORM_TEST(lwaux);
0432     LOAD_XFORM_TEST(lwbrx);
0433     LOAD_DFORM_TEST(ld);
0434     LOAD_DFORM_TEST(ldu);
0435     LOAD_XFORM_TEST(ldx);
0436     LOAD_XFORM_TEST(ldux);
0437     STORE_DFORM_TEST(stb);
0438     STORE_XFORM_TEST(stbx);
0439     STORE_DFORM_TEST(stbu);
0440     STORE_XFORM_TEST(stbux);
0441     STORE_DFORM_TEST(sth);
0442     STORE_XFORM_TEST(sthx);
0443     STORE_DFORM_TEST(sthu);
0444     STORE_XFORM_TEST(sthux);
0445     STORE_XFORM_TEST(sthbrx);
0446     STORE_DFORM_TEST(stw);
0447     STORE_XFORM_TEST(stwx);
0448     STORE_DFORM_TEST(stwu);
0449     STORE_XFORM_TEST(stwux);
0450     STORE_XFORM_TEST(stwbrx);
0451     STORE_DFORM_TEST(std);
0452     STORE_XFORM_TEST(stdx);
0453     STORE_DFORM_TEST(stdu);
0454     STORE_XFORM_TEST(stdux);
0455 
0456 #ifdef __BIG_ENDIAN__
0457     LOAD_DFORM_TEST(lmw);
0458     STORE_DFORM_TEST(stmw);
0459 #endif
0460 
0461     return rc;
0462 }
0463 
0464 int test_alignment_handler_integer_206(void)
0465 {
0466     int rc = 0;
0467 
0468     SKIP_IF(!can_open_cifile());
0469     SKIP_IF(!have_hwcap(PPC_FEATURE_ARCH_2_06));
0470 
0471     printf("Integer: 2.06\n");
0472 
0473     LOAD_XFORM_TEST(ldbrx);
0474     STORE_XFORM_TEST(stdbrx);
0475 
0476     return rc;
0477 }
0478 
0479 int test_alignment_handler_integer_prefix(void)
0480 {
0481     int rc = 0;
0482 
0483     SKIP_IF(!can_open_cifile());
0484     SKIP_IF(!have_hwcap2(PPC_FEATURE2_ARCH_3_1));
0485 
0486     printf("Integer: PREFIX\n");
0487     LOAD_MLS_PREFIX_TEST(PLBZ);
0488     LOAD_MLS_PREFIX_TEST(PLHZ);
0489     LOAD_MLS_PREFIX_TEST(PLHA);
0490     LOAD_MLS_PREFIX_TEST(PLWZ);
0491     LOAD_8LS_PREFIX_TEST(PLWA);
0492     LOAD_8LS_PREFIX_TEST(PLD);
0493     STORE_MLS_PREFIX_TEST(PSTB);
0494     STORE_MLS_PREFIX_TEST(PSTH);
0495     STORE_MLS_PREFIX_TEST(PSTW);
0496     STORE_8LS_PREFIX_TEST(PSTD);
0497     return rc;
0498 }
0499 
0500 int test_alignment_handler_vmx(void)
0501 {
0502     int rc = 0;
0503 
0504     SKIP_IF(!can_open_cifile());
0505     SKIP_IF(!have_hwcap(PPC_FEATURE_HAS_ALTIVEC));
0506 
0507     printf("VMX\n");
0508     LOAD_VMX_XFORM_TEST(lvx);
0509 
0510     /*
0511      * FIXME: These loads only load part of the register, so our
0512      * testing method doesn't work. Also they don't take alignment
0513      * faults, so it's kinda pointless anyway
0514      *
0515      LOAD_VMX_XFORM_TEST(lvebx)
0516      LOAD_VMX_XFORM_TEST(lvehx)
0517      LOAD_VMX_XFORM_TEST(lvewx)
0518      LOAD_VMX_XFORM_TEST(lvxl)
0519     */
0520     STORE_VMX_XFORM_TEST(stvx);
0521     STORE_VMX_XFORM_TEST(stvebx);
0522     STORE_VMX_XFORM_TEST(stvehx);
0523     STORE_VMX_XFORM_TEST(stvewx);
0524     STORE_VMX_XFORM_TEST(stvxl);
0525     return rc;
0526 }
0527 
0528 int test_alignment_handler_fp(void)
0529 {
0530     int rc = 0;
0531 
0532     SKIP_IF(!can_open_cifile());
0533 
0534     printf("Floating point\n");
0535     LOAD_FLOAT_DFORM_TEST(lfd);
0536     LOAD_FLOAT_XFORM_TEST(lfdx);
0537     LOAD_FLOAT_DFORM_TEST(lfdu);
0538     LOAD_FLOAT_XFORM_TEST(lfdux);
0539     LOAD_FLOAT_DFORM_TEST(lfs);
0540     LOAD_FLOAT_XFORM_TEST(lfsx);
0541     LOAD_FLOAT_DFORM_TEST(lfsu);
0542     LOAD_FLOAT_XFORM_TEST(lfsux);
0543     STORE_FLOAT_DFORM_TEST(stfd);
0544     STORE_FLOAT_XFORM_TEST(stfdx);
0545     STORE_FLOAT_DFORM_TEST(stfdu);
0546     STORE_FLOAT_XFORM_TEST(stfdux);
0547     STORE_FLOAT_DFORM_TEST(stfs);
0548     STORE_FLOAT_XFORM_TEST(stfsx);
0549     STORE_FLOAT_DFORM_TEST(stfsu);
0550     STORE_FLOAT_XFORM_TEST(stfsux);
0551     STORE_FLOAT_XFORM_TEST(stfiwx);
0552 
0553     return rc;
0554 }
0555 
0556 int test_alignment_handler_fp_205(void)
0557 {
0558     int rc = 0;
0559 
0560     SKIP_IF(!can_open_cifile());
0561     SKIP_IF(!have_hwcap(PPC_FEATURE_ARCH_2_05));
0562 
0563     printf("Floating point: 2.05\n");
0564 
0565     LOAD_FLOAT_DFORM_TEST(lfdp);
0566     LOAD_FLOAT_XFORM_TEST(lfdpx);
0567     LOAD_FLOAT_XFORM_TEST(lfiwax);
0568     STORE_FLOAT_DFORM_TEST(stfdp);
0569     STORE_FLOAT_XFORM_TEST(stfdpx);
0570 
0571     return rc;
0572 }
0573 
0574 int test_alignment_handler_fp_206(void)
0575 {
0576     int rc = 0;
0577 
0578     SKIP_IF(!can_open_cifile());
0579     SKIP_IF(!have_hwcap(PPC_FEATURE_ARCH_2_06));
0580 
0581     printf("Floating point: 2.06\n");
0582 
0583     LOAD_FLOAT_XFORM_TEST(lfiwzx);
0584 
0585     return rc;
0586 }
0587 
0588 
0589 int test_alignment_handler_fp_prefix(void)
0590 {
0591     int rc = 0;
0592 
0593     SKIP_IF(!can_open_cifile());
0594     SKIP_IF(!have_hwcap2(PPC_FEATURE2_ARCH_3_1));
0595 
0596     printf("Floating point: PREFIX\n");
0597     LOAD_FLOAT_DFORM_TEST(lfs);
0598     LOAD_FLOAT_MLS_PREFIX_TEST(PLFS);
0599     LOAD_FLOAT_MLS_PREFIX_TEST(PLFD);
0600     STORE_FLOAT_MLS_PREFIX_TEST(PSTFS);
0601     STORE_FLOAT_MLS_PREFIX_TEST(PSTFD);
0602     return rc;
0603 }
0604 
0605 void usage(char *prog)
0606 {
0607     printf("Usage: %s [options] [path [offset]]\n", prog);
0608     printf("  -d    Enable debug error output\n");
0609     printf("\n");
0610     printf("This test requires a POWER8, POWER9 or POWER10 CPU ");
0611     printf("and either a usable framebuffer at /dev/fb0 or ");
0612     printf("the path to usable cache inhibited memory and optional ");
0613     printf("offset to be provided\n");
0614 }
0615 
0616 int main(int argc, char *argv[])
0617 {
0618 
0619     struct sigaction sa;
0620     int rc = 0;
0621     int option = 0;
0622 
0623     while ((option = getopt(argc, argv, "d")) != -1) {
0624         switch (option) {
0625         case 'd':
0626             debug++;
0627             break;
0628         default:
0629             usage(argv[0]);
0630             exit(1);
0631         }
0632     }
0633     argc -= optind;
0634     argv += optind;
0635 
0636     if (argc > 0)
0637         cipath = argv[0];
0638     if (argc > 1)
0639         cioffset = strtol(argv[1], 0, 0x10);
0640 
0641     bufsize = getpagesize();
0642 
0643     sa.sa_sigaction = sighandler;
0644     sigemptyset(&sa.sa_mask);
0645     sa.sa_flags = SA_SIGINFO;
0646     if (sigaction(SIGSEGV, &sa, NULL) == -1
0647         || sigaction(SIGBUS, &sa, NULL) == -1
0648         || sigaction(SIGILL, &sa, NULL) == -1) {
0649         perror("sigaction");
0650         exit(1);
0651     }
0652 
0653     prefixes_enabled = have_hwcap2(PPC_FEATURE2_ARCH_3_1);
0654 
0655     rc |= test_harness(test_alignment_handler_vsx_206,
0656                "test_alignment_handler_vsx_206");
0657     rc |= test_harness(test_alignment_handler_vsx_207,
0658                "test_alignment_handler_vsx_207");
0659     rc |= test_harness(test_alignment_handler_vsx_300,
0660                "test_alignment_handler_vsx_300");
0661     rc |= test_harness(test_alignment_handler_vsx_prefix,
0662                "test_alignment_handler_vsx_prefix");
0663     rc |= test_harness(test_alignment_handler_integer,
0664                "test_alignment_handler_integer");
0665     rc |= test_harness(test_alignment_handler_integer_206,
0666                "test_alignment_handler_integer_206");
0667     rc |= test_harness(test_alignment_handler_integer_prefix,
0668                "test_alignment_handler_integer_prefix");
0669     rc |= test_harness(test_alignment_handler_vmx,
0670                "test_alignment_handler_vmx");
0671     rc |= test_harness(test_alignment_handler_fp,
0672                "test_alignment_handler_fp");
0673     rc |= test_harness(test_alignment_handler_fp_205,
0674                "test_alignment_handler_fp_205");
0675     rc |= test_harness(test_alignment_handler_fp_206,
0676                "test_alignment_handler_fp_206");
0677     rc |= test_harness(test_alignment_handler_fp_prefix,
0678                "test_alignment_handler_fp_prefix");
0679     return rc;
0680 }