cachepc-linux

Fork of AMDESE/linux with modifications for CachePC side-channel attack
git clone https://git.sinitax.com/sinitax/cachepc-linux
Log | Files | Refs | README | LICENSE | sfeed.txt

alignment_handler.c (16437B)


      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}