1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
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 <asm/cputable.h>
59
60#include "utils.h"
61#include "instructions.h"
62
63int bufsize;
64int debug;
65int testing;
66volatile int gotsig;
67char *cipath = "/dev/fb0";
68long cioffset;
69
70void sighandler(int sig, siginfo_t *info, void *ctx)
71{
72 ucontext_t *ucp = ctx;
73
74 if (!testing) {
75 signal(sig, SIG_DFL);
76 kill(0, sig);
77 }
78 gotsig = sig;
79#ifdef __powerpc64__
80 ucp->uc_mcontext.gp_regs[PT_NIP] += 4;
81#else
82 ucp->uc_mcontext.uc_regs->gregs[PT_NIP] += 4;
83#endif
84}
85
86#define XFORM(reg, n) " " #reg " ,%"#n",%2 ;"
87#define DFORM(reg, n) " " #reg " ,0(%"#n") ;"
88
89#define TEST(name, ld_op, st_op, form, ld_reg, st_reg) \
90 void test_##name(char *s, char *d) \
91 { \
92 asm volatile( \
93 #ld_op form(ld_reg, 0) \
94 #st_op form(st_reg, 1) \
95 :: "r"(s), "r"(d), "r"(0) \
96 : "memory", "vs0", "vs32", "r31"); \
97 } \
98 rc |= do_test(#name, test_##name)
99
100#define TESTP(name, ld_op, st_op, ld_reg, st_reg) \
101 void test_##name(char *s, char *d) \
102 { \
103 asm volatile( \
104 ld_op(ld_reg, %0, 0, 0) \
105 st_op(st_reg, %1, 0, 0) \
106 :: "r"(s), "r"(d), "r"(0) \
107 : "memory", "vs0", "vs32", "r31"); \
108 } \
109 rc |= do_test(#name, test_##name)
110
111#define LOAD_VSX_XFORM_TEST(op) TEST(op, op, stxvd2x, XFORM, 32, 32)
112#define STORE_VSX_XFORM_TEST(op) TEST(op, lxvd2x, op, XFORM, 32, 32)
113#define LOAD_VSX_DFORM_TEST(op) TEST(op, op, stxv, DFORM, 32, 32)
114#define STORE_VSX_DFORM_TEST(op) TEST(op, lxv, op, DFORM, 32, 32)
115#define LOAD_VMX_XFORM_TEST(op) TEST(op, op, stxvd2x, XFORM, 0, 32)
116#define STORE_VMX_XFORM_TEST(op) TEST(op, lxvd2x, op, XFORM, 32, 0)
117#define LOAD_VMX_DFORM_TEST(op) TEST(op, op, stxv, DFORM, 0, 32)
118#define STORE_VMX_DFORM_TEST(op) TEST(op, lxv, op, DFORM, 32, 0)
119
120#define LOAD_XFORM_TEST(op) TEST(op, op, stdx, XFORM, 31, 31)
121#define STORE_XFORM_TEST(op) TEST(op, ldx, op, XFORM, 31, 31)
122#define LOAD_DFORM_TEST(op) TEST(op, op, std, DFORM, 31, 31)
123#define STORE_DFORM_TEST(op) TEST(op, ld, op, DFORM, 31, 31)
124
125#define LOAD_FLOAT_DFORM_TEST(op) TEST(op, op, stfd, DFORM, 0, 0)
126#define STORE_FLOAT_DFORM_TEST(op) TEST(op, lfd, op, DFORM, 0, 0)
127#define LOAD_FLOAT_XFORM_TEST(op) TEST(op, op, stfdx, XFORM, 0, 0)
128#define STORE_FLOAT_XFORM_TEST(op) TEST(op, lfdx, op, XFORM, 0, 0)
129
130#define LOAD_MLS_PREFIX_TEST(op) TESTP(op, op, PSTD, 31, 31)
131#define STORE_MLS_PREFIX_TEST(op) TESTP(op, PLD, op, 31, 31)
132
133#define LOAD_8LS_PREFIX_TEST(op) TESTP(op, op, PSTD, 31, 31)
134#define STORE_8LS_PREFIX_TEST(op) TESTP(op, PLD, op, 31, 31)
135
136#define LOAD_FLOAT_MLS_PREFIX_TEST(op) TESTP(op, op, PSTFD, 0, 0)
137#define STORE_FLOAT_MLS_PREFIX_TEST(op) TESTP(op, PLFD, op, 0, 0)
138
139#define LOAD_VSX_8LS_PREFIX_TEST(op, tail) TESTP(op, op, PSTXV ## tail, 0, 32)
140#define STORE_VSX_8LS_PREFIX_TEST(op, tail) TESTP(op, PLXV ## tail, op, 32, 0)
141
142
143
144
145
146
147
148
149
150
151void preload_data(void *dst, int offset, int width)
152{
153 char *c = dst;
154 int i;
155
156 c += offset;
157
158 for (i = 0 ; i < width ; i++)
159 c[i] = i;
160}
161
162int test_memcpy(void *dst, void *src, int size, int offset,
163 void (*test_func)(char *, char *))
164{
165 char *s, *d;
166
167 s = src;
168 s += offset;
169 d = dst;
170 d += offset;
171
172 assert(size == 16);
173 gotsig = 0;
174 testing = 1;
175
176 test_func(s, d);
177
178 testing = 0;
179 if (gotsig) {
180 if (debug)
181 printf(" Got signal %i\n", gotsig);
182 return 1;
183 }
184 return 0;
185}
186
187void dumpdata(char *s1, char *s2, int n, char *test_name)
188{
189 int i;
190
191 printf(" %s: unexpected result:\n", test_name);
192 printf(" mem:");
193 for (i = 0; i < n; i++)
194 printf(" %02x", s1[i]);
195 printf("\n");
196 printf(" ci: ");
197 for (i = 0; i < n; i++)
198 printf(" %02x", s2[i]);
199 printf("\n");
200}
201
202int test_memcmp(void *s1, void *s2, int n, int offset, char *test_name)
203{
204 char *s1c, *s2c;
205
206 s1c = s1;
207 s1c += offset;
208 s2c = s2;
209 s2c += offset;
210
211 if (memcmp(s1c, s2c, n)) {
212 if (debug) {
213 printf("\n Compare failed. Offset:%i length:%i\n",
214 offset, n);
215 dumpdata(s1c, s2c, n, test_name);
216 }
217 return 1;
218 }
219 return 0;
220}
221
222
223
224
225
226int do_test(char *test_name, void (*test_func)(char *, char *))
227{
228 int offset, width, fd, rc, r;
229 void *mem0, *mem1, *ci0, *ci1;
230
231 printf("\tDoing %s:\t", test_name);
232
233 fd = open(cipath, O_RDWR);
234 if (fd < 0) {
235 printf("\n");
236 perror("Can't open ci file now?");
237 return 1;
238 }
239
240 ci0 = mmap(NULL, bufsize, PROT_WRITE | PROT_READ, MAP_SHARED,
241 fd, cioffset);
242 ci1 = mmap(NULL, bufsize, PROT_WRITE | PROT_READ, MAP_SHARED,
243 fd, cioffset + bufsize);
244
245 if ((ci0 == MAP_FAILED) || (ci1 == MAP_FAILED)) {
246 printf("\n");
247 perror("mmap failed");
248 SKIP_IF(1);
249 }
250
251 rc = posix_memalign(&mem0, bufsize, bufsize);
252 if (rc) {
253 printf("\n");
254 return rc;
255 }
256
257 rc = posix_memalign(&mem1, bufsize, bufsize);
258 if (rc) {
259 printf("\n");
260 free(mem0);
261 return rc;
262 }
263
264 rc = 0;
265
266 for (offset = 1; offset < 16; offset++) {
267 width = 16;
268 r = 0;
269
270
271 preload_data(ci0, offset, width);
272 preload_data(mem0, offset, width);
273 memcpy(ci0, mem0, bufsize);
274 memcpy(ci1, mem1, bufsize);
275
276
277 test_memcmp(mem0, ci0, width, offset, test_name);
278
279 r |= test_memcpy(ci1, ci0, width, offset, test_func);
280 r |= test_memcpy(mem1, mem0, width, offset, test_func);
281 if (r && !debug) {
282 printf("FAILED: Got signal");
283 rc = 1;
284 break;
285 }
286
287 r |= test_memcmp(mem1, ci1, width, offset, test_name);
288 if (r && !debug) {
289 printf("FAILED: Wrong Data");
290 rc = 1;
291 break;
292 }
293 }
294
295 if (rc == 0)
296 printf("PASSED");
297
298 printf("\n");
299
300 munmap(ci0, bufsize);
301 munmap(ci1, bufsize);
302 free(mem0);
303 free(mem1);
304 close(fd);
305
306 return rc;
307}
308
309static bool can_open_cifile(void)
310{
311 int fd;
312
313 fd = open(cipath, O_RDWR);
314 if (fd < 0)
315 return false;
316
317 close(fd);
318 return true;
319}
320
321int test_alignment_handler_vsx_206(void)
322{
323 int rc = 0;
324
325 SKIP_IF(!can_open_cifile());
326 SKIP_IF(!have_hwcap(PPC_FEATURE_ARCH_2_06));
327
328 printf("VSX: 2.06B\n");
329 LOAD_VSX_XFORM_TEST(lxvd2x);
330 LOAD_VSX_XFORM_TEST(lxvw4x);
331 LOAD_VSX_XFORM_TEST(lxsdx);
332 LOAD_VSX_XFORM_TEST(lxvdsx);
333 STORE_VSX_XFORM_TEST(stxvd2x);
334 STORE_VSX_XFORM_TEST(stxvw4x);
335 STORE_VSX_XFORM_TEST(stxsdx);
336 return rc;
337}
338
339int test_alignment_handler_vsx_207(void)
340{
341 int rc = 0;
342
343 SKIP_IF(!can_open_cifile());
344 SKIP_IF(!have_hwcap2(PPC_FEATURE2_ARCH_2_07));
345
346 printf("VSX: 2.07B\n");
347 LOAD_VSX_XFORM_TEST(lxsspx);
348 LOAD_VSX_XFORM_TEST(lxsiwax);
349 LOAD_VSX_XFORM_TEST(lxsiwzx);
350 STORE_VSX_XFORM_TEST(stxsspx);
351 STORE_VSX_XFORM_TEST(stxsiwx);
352 return rc;
353}
354
355int test_alignment_handler_vsx_300(void)
356{
357 int rc = 0;
358
359 SKIP_IF(!can_open_cifile());
360
361 SKIP_IF(!have_hwcap2(PPC_FEATURE2_ARCH_3_00));
362 printf("VSX: 3.00B\n");
363 LOAD_VMX_DFORM_TEST(lxsd);
364 LOAD_VSX_XFORM_TEST(lxsibzx);
365 LOAD_VSX_XFORM_TEST(lxsihzx);
366 LOAD_VMX_DFORM_TEST(lxssp);
367 LOAD_VSX_DFORM_TEST(lxv);
368 LOAD_VSX_XFORM_TEST(lxvb16x);
369 LOAD_VSX_XFORM_TEST(lxvh8x);
370 LOAD_VSX_XFORM_TEST(lxvx);
371 LOAD_VSX_XFORM_TEST(lxvwsx);
372 LOAD_VSX_XFORM_TEST(lxvl);
373 LOAD_VSX_XFORM_TEST(lxvll);
374 STORE_VMX_DFORM_TEST(stxsd);
375 STORE_VSX_XFORM_TEST(stxsibx);
376 STORE_VSX_XFORM_TEST(stxsihx);
377 STORE_VMX_DFORM_TEST(stxssp);
378 STORE_VSX_DFORM_TEST(stxv);
379 STORE_VSX_XFORM_TEST(stxvb16x);
380 STORE_VSX_XFORM_TEST(stxvh8x);
381 STORE_VSX_XFORM_TEST(stxvx);
382 STORE_VSX_XFORM_TEST(stxvl);
383 STORE_VSX_XFORM_TEST(stxvll);
384 return rc;
385}
386
387int test_alignment_handler_vsx_prefix(void)
388{
389 int rc = 0;
390
391 SKIP_IF(!can_open_cifile());
392 SKIP_IF(!have_hwcap2(PPC_FEATURE2_ARCH_3_1));
393
394 printf("VSX: PREFIX\n");
395 LOAD_VSX_8LS_PREFIX_TEST(PLXSD, 0);
396 LOAD_VSX_8LS_PREFIX_TEST(PLXSSP, 0);
397 LOAD_VSX_8LS_PREFIX_TEST(PLXV0, 0);
398 LOAD_VSX_8LS_PREFIX_TEST(PLXV1, 1);
399 STORE_VSX_8LS_PREFIX_TEST(PSTXSD, 0);
400 STORE_VSX_8LS_PREFIX_TEST(PSTXSSP, 0);
401 STORE_VSX_8LS_PREFIX_TEST(PSTXV0, 0);
402 STORE_VSX_8LS_PREFIX_TEST(PSTXV1, 1);
403 return rc;
404}
405
406int test_alignment_handler_integer(void)
407{
408 int rc = 0;
409
410 SKIP_IF(!can_open_cifile());
411
412 printf("Integer\n");
413 LOAD_DFORM_TEST(lbz);
414 LOAD_DFORM_TEST(lbzu);
415 LOAD_XFORM_TEST(lbzx);
416 LOAD_XFORM_TEST(lbzux);
417 LOAD_DFORM_TEST(lhz);
418 LOAD_DFORM_TEST(lhzu);
419 LOAD_XFORM_TEST(lhzx);
420 LOAD_XFORM_TEST(lhzux);
421 LOAD_DFORM_TEST(lha);
422 LOAD_DFORM_TEST(lhau);
423 LOAD_XFORM_TEST(lhax);
424 LOAD_XFORM_TEST(lhaux);
425 LOAD_XFORM_TEST(lhbrx);
426 LOAD_DFORM_TEST(lwz);
427 LOAD_DFORM_TEST(lwzu);
428 LOAD_XFORM_TEST(lwzx);
429 LOAD_XFORM_TEST(lwzux);
430 LOAD_DFORM_TEST(lwa);
431 LOAD_XFORM_TEST(lwax);
432 LOAD_XFORM_TEST(lwaux);
433 LOAD_XFORM_TEST(lwbrx);
434 LOAD_DFORM_TEST(ld);
435 LOAD_DFORM_TEST(ldu);
436 LOAD_XFORM_TEST(ldx);
437 LOAD_XFORM_TEST(ldux);
438 LOAD_DFORM_TEST(lmw);
439 STORE_DFORM_TEST(stb);
440 STORE_XFORM_TEST(stbx);
441 STORE_DFORM_TEST(stbu);
442 STORE_XFORM_TEST(stbux);
443 STORE_DFORM_TEST(sth);
444 STORE_XFORM_TEST(sthx);
445 STORE_DFORM_TEST(sthu);
446 STORE_XFORM_TEST(sthux);
447 STORE_XFORM_TEST(sthbrx);
448 STORE_DFORM_TEST(stw);
449 STORE_XFORM_TEST(stwx);
450 STORE_DFORM_TEST(stwu);
451 STORE_XFORM_TEST(stwux);
452 STORE_XFORM_TEST(stwbrx);
453 STORE_DFORM_TEST(std);
454 STORE_XFORM_TEST(stdx);
455 STORE_DFORM_TEST(stdu);
456 STORE_XFORM_TEST(stdux);
457 STORE_DFORM_TEST(stmw);
458
459 return rc;
460}
461
462int test_alignment_handler_integer_206(void)
463{
464 int rc = 0;
465
466 SKIP_IF(!can_open_cifile());
467 SKIP_IF(!have_hwcap(PPC_FEATURE_ARCH_2_06));
468
469 printf("Integer: 2.06\n");
470
471 LOAD_XFORM_TEST(ldbrx);
472 STORE_XFORM_TEST(stdbrx);
473
474 return rc;
475}
476
477int test_alignment_handler_integer_prefix(void)
478{
479 int rc = 0;
480
481 SKIP_IF(!can_open_cifile());
482 SKIP_IF(!have_hwcap2(PPC_FEATURE2_ARCH_3_1));
483
484 printf("Integer: PREFIX\n");
485 LOAD_MLS_PREFIX_TEST(PLBZ);
486 LOAD_MLS_PREFIX_TEST(PLHZ);
487 LOAD_MLS_PREFIX_TEST(PLHA);
488 LOAD_MLS_PREFIX_TEST(PLWZ);
489 LOAD_8LS_PREFIX_TEST(PLWA);
490 LOAD_8LS_PREFIX_TEST(PLD);
491 STORE_MLS_PREFIX_TEST(PSTB);
492 STORE_MLS_PREFIX_TEST(PSTH);
493 STORE_MLS_PREFIX_TEST(PSTW);
494 STORE_8LS_PREFIX_TEST(PSTD);
495 return rc;
496}
497
498int test_alignment_handler_vmx(void)
499{
500 int rc = 0;
501
502 SKIP_IF(!can_open_cifile());
503 SKIP_IF(!have_hwcap(PPC_FEATURE_HAS_ALTIVEC));
504
505 printf("VMX\n");
506 LOAD_VMX_XFORM_TEST(lvx);
507
508
509
510
511
512
513
514
515
516
517
518 STORE_VMX_XFORM_TEST(stvx);
519 STORE_VMX_XFORM_TEST(stvebx);
520 STORE_VMX_XFORM_TEST(stvehx);
521 STORE_VMX_XFORM_TEST(stvewx);
522 STORE_VMX_XFORM_TEST(stvxl);
523 return rc;
524}
525
526int test_alignment_handler_fp(void)
527{
528 int rc = 0;
529
530 SKIP_IF(!can_open_cifile());
531
532 printf("Floating point\n");
533 LOAD_FLOAT_DFORM_TEST(lfd);
534 LOAD_FLOAT_XFORM_TEST(lfdx);
535 LOAD_FLOAT_DFORM_TEST(lfdu);
536 LOAD_FLOAT_XFORM_TEST(lfdux);
537 LOAD_FLOAT_DFORM_TEST(lfs);
538 LOAD_FLOAT_XFORM_TEST(lfsx);
539 LOAD_FLOAT_DFORM_TEST(lfsu);
540 LOAD_FLOAT_XFORM_TEST(lfsux);
541 STORE_FLOAT_DFORM_TEST(stfd);
542 STORE_FLOAT_XFORM_TEST(stfdx);
543 STORE_FLOAT_DFORM_TEST(stfdu);
544 STORE_FLOAT_XFORM_TEST(stfdux);
545 STORE_FLOAT_DFORM_TEST(stfs);
546 STORE_FLOAT_XFORM_TEST(stfsx);
547 STORE_FLOAT_DFORM_TEST(stfsu);
548 STORE_FLOAT_XFORM_TEST(stfsux);
549 STORE_FLOAT_XFORM_TEST(stfiwx);
550
551 return rc;
552}
553
554int test_alignment_handler_fp_205(void)
555{
556 int rc = 0;
557
558 SKIP_IF(!can_open_cifile());
559 SKIP_IF(!have_hwcap(PPC_FEATURE_ARCH_2_05));
560
561 printf("Floating point: 2.05\n");
562
563 LOAD_FLOAT_DFORM_TEST(lfdp);
564 LOAD_FLOAT_XFORM_TEST(lfdpx);
565 LOAD_FLOAT_XFORM_TEST(lfiwax);
566 STORE_FLOAT_DFORM_TEST(stfdp);
567 STORE_FLOAT_XFORM_TEST(stfdpx);
568
569 return rc;
570}
571
572int test_alignment_handler_fp_206(void)
573{
574 int rc = 0;
575
576 SKIP_IF(!can_open_cifile());
577 SKIP_IF(!have_hwcap(PPC_FEATURE_ARCH_2_06));
578
579 printf("Floating point: 2.06\n");
580
581 LOAD_FLOAT_XFORM_TEST(lfiwzx);
582
583 return rc;
584}
585
586
587int test_alignment_handler_fp_prefix(void)
588{
589 int rc = 0;
590
591 SKIP_IF(!can_open_cifile());
592 SKIP_IF(!have_hwcap2(PPC_FEATURE2_ARCH_3_1));
593
594 printf("Floating point: PREFIX\n");
595 LOAD_FLOAT_DFORM_TEST(lfs);
596 LOAD_FLOAT_MLS_PREFIX_TEST(PLFS);
597 LOAD_FLOAT_MLS_PREFIX_TEST(PLFD);
598 STORE_FLOAT_MLS_PREFIX_TEST(PSTFS);
599 STORE_FLOAT_MLS_PREFIX_TEST(PSTFD);
600 return rc;
601}
602
603void usage(char *prog)
604{
605 printf("Usage: %s [options] [path [offset]]\n", prog);
606 printf(" -d Enable debug error output\n");
607 printf("\n");
608 printf("This test requires a POWER8, POWER9 or POWER10 CPU ");
609 printf("and either a usable framebuffer at /dev/fb0 or ");
610 printf("the path to usable cache inhibited memory and optional ");
611 printf("offset to be provided\n");
612}
613
614int main(int argc, char *argv[])
615{
616
617 struct sigaction sa;
618 int rc = 0;
619 int option = 0;
620
621 while ((option = getopt(argc, argv, "d")) != -1) {
622 switch (option) {
623 case 'd':
624 debug++;
625 break;
626 default:
627 usage(argv[0]);
628 exit(1);
629 }
630 }
631 argc -= optind;
632 argv += optind;
633
634 if (argc > 0)
635 cipath = argv[0];
636 if (argc > 1)
637 cioffset = strtol(argv[1], 0, 0x10);
638
639 bufsize = getpagesize();
640
641 sa.sa_sigaction = sighandler;
642 sigemptyset(&sa.sa_mask);
643 sa.sa_flags = SA_SIGINFO;
644 if (sigaction(SIGSEGV, &sa, NULL) == -1
645 || sigaction(SIGBUS, &sa, NULL) == -1
646 || sigaction(SIGILL, &sa, NULL) == -1) {
647 perror("sigaction");
648 exit(1);
649 }
650
651 rc |= test_harness(test_alignment_handler_vsx_206,
652 "test_alignment_handler_vsx_206");
653 rc |= test_harness(test_alignment_handler_vsx_207,
654 "test_alignment_handler_vsx_207");
655 rc |= test_harness(test_alignment_handler_vsx_300,
656 "test_alignment_handler_vsx_300");
657 rc |= test_harness(test_alignment_handler_vsx_prefix,
658 "test_alignment_handler_vsx_prefix");
659 rc |= test_harness(test_alignment_handler_integer,
660 "test_alignment_handler_integer");
661 rc |= test_harness(test_alignment_handler_integer_206,
662 "test_alignment_handler_integer_206");
663 rc |= test_harness(test_alignment_handler_integer_prefix,
664 "test_alignment_handler_integer_prefix");
665 rc |= test_harness(test_alignment_handler_vmx,
666 "test_alignment_handler_vmx");
667 rc |= test_harness(test_alignment_handler_fp,
668 "test_alignment_handler_fp");
669 rc |= test_harness(test_alignment_handler_fp_205,
670 "test_alignment_handler_fp_205");
671 rc |= test_harness(test_alignment_handler_fp_206,
672 "test_alignment_handler_fp_206");
673 rc |= test_harness(test_alignment_handler_fp_prefix,
674 "test_alignment_handler_fp_prefix");
675 return rc;
676}
677