hc
2023-12-08 01573e231f18eb2d99162747186f59511f56b64d
kernel/tools/testing/selftests/powerpc/alignment/alignment_handler.c
....@@ -1,19 +1,25 @@
1
+// SPDX-License-Identifier: GPL-2.0-or-later
12 /*
23 * Test the powerpc alignment handler on POWER8/POWER9
34 *
45 * Copyright (C) 2017 IBM Corporation (Michael Neuling, Andrew Donnellan)
5
- *
6
- * This program is free software; you can redistribute it and/or
7
- * modify it under the terms of the GNU General Public License
8
- * as published by the Free Software Foundation; either version
9
- * 2 of the License, or (at your option) any later version.
106 */
117
128 /*
139 * This selftest exercises the powerpc alignment fault handler.
1410 *
1511 * We create two sets of source and destination buffers, one in regular memory,
16
- * the other cache-inhibited (we use /dev/fb0 for this).
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
1723 *
1824 * We initialise the source buffers, then use whichever set of load/store
1925 * instructions is under test to copy bytes from the source buffers to the
....@@ -49,14 +55,16 @@
4955 #include <setjmp.h>
5056 #include <signal.h>
5157
52
-#include <asm/cputable.h>
53
-
5458 #include "utils.h"
59
+#include "instructions.h"
5560
5661 int bufsize;
5762 int debug;
5863 int testing;
5964 volatile int gotsig;
65
+bool prefixes_enabled;
66
+char *cipath = "/dev/fb0";
67
+long cioffset;
6068
6169 void sighandler(int sig, siginfo_t *info, void *ctx)
6270 {
....@@ -68,7 +76,12 @@
6876 }
6977 gotsig = sig;
7078 #ifdef __powerpc64__
71
- ucp->uc_mcontext.gp_regs[PT_NIP] += 4;
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
+ }
7285 #else
7386 ucp->uc_mcontext.uc_regs->gregs[PT_NIP] += 4;
7487 #endif
....@@ -83,6 +96,17 @@
8396 asm volatile( \
8497 #ld_op form(ld_reg, 0) \
8598 #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) \
86110 :: "r"(s), "r"(d), "r"(0) \
87111 : "memory", "vs0", "vs32", "r31"); \
88112 } \
....@@ -107,6 +131,17 @@
107131 #define LOAD_FLOAT_XFORM_TEST(op) TEST(op, op, stfdx, XFORM, 0, 0)
108132 #define STORE_FLOAT_XFORM_TEST(op) TEST(op, lfdx, op, XFORM, 0, 0)
109133
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)
110145
111146 /* FIXME: Unimplemented tests: */
112147 // STORE_DFORM_TEST(stq) /* FIXME: need two registers for quad */
....@@ -199,17 +234,18 @@
199234
200235 printf("\tDoing %s:\t", test_name);
201236
202
- fd = open("/dev/fb0", O_RDWR);
237
+ fd = open(cipath, O_RDWR);
203238 if (fd < 0) {
204239 printf("\n");
205
- perror("Can't open /dev/fb0 now?");
240
+ perror("Can't open ci file now?");
206241 return 1;
207242 }
208243
209
- ci0 = mmap(NULL, bufsize, PROT_WRITE, MAP_SHARED,
210
- fd, 0x0);
211
- ci1 = mmap(NULL, bufsize, PROT_WRITE, MAP_SHARED,
212
- fd, bufsize);
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
+
213249 if ((ci0 == MAP_FAILED) || (ci1 == MAP_FAILED)) {
214250 printf("\n");
215251 perror("mmap failed");
....@@ -230,8 +266,12 @@
230266 }
231267
232268 rc = 0;
233
- /* offset = 0 no alignment fault, so skip */
234
- for (offset = 1; offset < 16; offset++) {
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++) {
235275 width = 16; /* vsx == 16 bytes */
236276 r = 0;
237277
....@@ -274,11 +314,11 @@
274314 return rc;
275315 }
276316
277
-static bool can_open_fb0(void)
317
+static bool can_open_cifile(void)
278318 {
279319 int fd;
280320
281
- fd = open("/dev/fb0", O_RDWR);
321
+ fd = open(cipath, O_RDWR);
282322 if (fd < 0)
283323 return false;
284324
....@@ -290,7 +330,7 @@
290330 {
291331 int rc = 0;
292332
293
- SKIP_IF(!can_open_fb0());
333
+ SKIP_IF(!can_open_cifile());
294334 SKIP_IF(!have_hwcap(PPC_FEATURE_ARCH_2_06));
295335
296336 printf("VSX: 2.06B\n");
....@@ -308,7 +348,7 @@
308348 {
309349 int rc = 0;
310350
311
- SKIP_IF(!can_open_fb0());
351
+ SKIP_IF(!can_open_cifile());
312352 SKIP_IF(!have_hwcap2(PPC_FEATURE2_ARCH_2_07));
313353
314354 printf("VSX: 2.07B\n");
....@@ -324,7 +364,7 @@
324364 {
325365 int rc = 0;
326366
327
- SKIP_IF(!can_open_fb0());
367
+ SKIP_IF(!can_open_cifile());
328368
329369 SKIP_IF(!have_hwcap2(PPC_FEATURE2_ARCH_3_00));
330370 printf("VSX: 3.00B\n");
....@@ -352,11 +392,30 @@
352392 return rc;
353393 }
354394
395
+int 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
+
355414 int test_alignment_handler_integer(void)
356415 {
357416 int rc = 0;
358417
359
- SKIP_IF(!can_open_fb0());
418
+ SKIP_IF(!can_open_cifile());
360419
361420 printf("Integer\n");
362421 LOAD_DFORM_TEST(lbz);
....@@ -415,7 +474,7 @@
415474 {
416475 int rc = 0;
417476
418
- SKIP_IF(!can_open_fb0());
477
+ SKIP_IF(!can_open_cifile());
419478 SKIP_IF(!have_hwcap(PPC_FEATURE_ARCH_2_06));
420479
421480 printf("Integer: 2.06\n");
....@@ -426,11 +485,32 @@
426485 return rc;
427486 }
428487
488
+int 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
+
429509 int test_alignment_handler_vmx(void)
430510 {
431511 int rc = 0;
432512
433
- SKIP_IF(!can_open_fb0());
513
+ SKIP_IF(!can_open_cifile());
434514 SKIP_IF(!have_hwcap(PPC_FEATURE_HAS_ALTIVEC));
435515
436516 printf("VMX\n");
....@@ -458,7 +538,7 @@
458538 {
459539 int rc = 0;
460540
461
- SKIP_IF(!can_open_fb0());
541
+ SKIP_IF(!can_open_cifile());
462542
463543 printf("Floating point\n");
464544 LOAD_FLOAT_DFORM_TEST(lfd);
....@@ -486,7 +566,7 @@
486566 {
487567 int rc = 0;
488568
489
- SKIP_IF(!can_open_fb0());
569
+ SKIP_IF(!can_open_cifile());
490570 SKIP_IF(!have_hwcap(PPC_FEATURE_ARCH_2_05));
491571
492572 printf("Floating point: 2.05\n");
....@@ -504,7 +584,7 @@
504584 {
505585 int rc = 0;
506586
507
- SKIP_IF(!can_open_fb0());
587
+ SKIP_IF(!can_open_cifile());
508588 SKIP_IF(!have_hwcap(PPC_FEATURE_ARCH_2_06));
509589
510590 printf("Floating point: 2.06\n");
....@@ -514,13 +594,32 @@
514594 return rc;
515595 }
516596
597
+
598
+int 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
+
517614 void usage(char *prog)
518615 {
519
- printf("Usage: %s [options]\n", prog);
616
+ printf("Usage: %s [options] [path [offset]]\n", prog);
520617 printf(" -d Enable debug error output\n");
521618 printf("\n");
522
- printf("This test requires a POWER8 or POWER9 CPU and a usable ");
523
- printf("framebuffer at /dev/fb0.\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");
524623 }
525624
526625 int main(int argc, char *argv[])
....@@ -540,6 +639,13 @@
540639 exit(1);
541640 }
542641 }
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);
543649
544650 bufsize = getpagesize();
545651
....@@ -553,16 +659,22 @@
553659 exit(1);
554660 }
555661
662
+ prefixes_enabled = have_hwcap2(PPC_FEATURE2_ARCH_3_1);
663
+
556664 rc |= test_harness(test_alignment_handler_vsx_206,
557665 "test_alignment_handler_vsx_206");
558666 rc |= test_harness(test_alignment_handler_vsx_207,
559667 "test_alignment_handler_vsx_207");
560668 rc |= test_harness(test_alignment_handler_vsx_300,
561669 "test_alignment_handler_vsx_300");
670
+ rc |= test_harness(test_alignment_handler_vsx_prefix,
671
+ "test_alignment_handler_vsx_prefix");
562672 rc |= test_harness(test_alignment_handler_integer,
563673 "test_alignment_handler_integer");
564674 rc |= test_harness(test_alignment_handler_integer_206,
565675 "test_alignment_handler_integer_206");
676
+ rc |= test_harness(test_alignment_handler_integer_prefix,
677
+ "test_alignment_handler_integer_prefix");
566678 rc |= test_harness(test_alignment_handler_vmx,
567679 "test_alignment_handler_vmx");
568680 rc |= test_harness(test_alignment_handler_fp,
....@@ -571,5 +683,7 @@
571683 "test_alignment_handler_fp_205");
572684 rc |= test_harness(test_alignment_handler_fp_206,
573685 "test_alignment_handler_fp_206");
686
+ rc |= test_harness(test_alignment_handler_fp_prefix,
687
+ "test_alignment_handler_fp_prefix");
574688 return rc;
575689 }