xref: /openbmc/linux/tools/testing/selftests/powerpc/alignment/alignment_handler.c (revision 8be98d2f2a0a262f8bf8a0bc1fdf522b3c7aab17)
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  
52  int bufsize;
53  int debug;
54  int testing;
55  volatile int gotsig;
56  bool prefixes_enabled;
57  char *cipath = "/dev/fb0";
58  long cioffset;
59  
sighandler(int sig,siginfo_t * info,void * ctx)60  void 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 */
preload_data(void * dst,int offset,int width)146  void 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  
test_memcpy(void * dst,void * src,int size,int offset,void (* test_func)(char *,char *))157  int 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  
dumpdata(char * s1,char * s2,int n,char * test_name)182  void 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  
test_memcmp(void * s1,void * s2,int n,int offset,char * test_name)197  int 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   */
do_test(char * test_name,void (* test_func)(char *,char *))221  int 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  
can_open_cifile(void)308  static 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  
test_alignment_handler_vsx_206(void)320  int 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  
test_alignment_handler_vsx_207(void)338  int 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  
test_alignment_handler_vsx_300(void)354  int 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  
test_alignment_handler_vsx_prefix(void)386  int 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  
test_alignment_handler_integer(void)405  int 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  
test_alignment_handler_integer_206(void)464  int 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  
test_alignment_handler_integer_prefix(void)479  int 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  
test_alignment_handler_vmx(void)500  int 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  
test_alignment_handler_fp(void)528  int 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  
test_alignment_handler_fp_205(void)556  int 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  
test_alignment_handler_fp_206(void)574  int 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  
test_alignment_handler_fp_prefix(void)589  int 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  
usage(char * prog)605  void 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  
main(int argc,char * argv[])616  int 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