Linux kernel mirror (for testing)
git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git
kernel
os
linux
1// SPDX-License-Identifier: GPL-2.0-or-later
2/*
3 * Simple sanity tests for instruction emulation infrastructure.
4 *
5 * Copyright IBM Corp. 2016
6 */
7
8#define pr_fmt(fmt) "emulate_step_test: " fmt
9
10#include <linux/ptrace.h>
11#include <asm/cpu_has_feature.h>
12#include <asm/sstep.h>
13#include <asm/ppc-opcode.h>
14#include <asm/code-patching.h>
15#include <asm/inst.h>
16
17#define MAX_SUBTESTS 16
18
19#define IGNORE_GPR(n) (0x1UL << (n))
20#define IGNORE_XER (0x1UL << 32)
21#define IGNORE_CCR (0x1UL << 33)
22#define NEGATIVE_TEST (0x1UL << 63)
23
24#define TEST_PLD(r, base, i, pr) \
25 ppc_inst_prefix(PPC_PREFIX_8LS | __PPC_PRFX_R(pr) | IMM_H(i), \
26 PPC_INST_PLD | ___PPC_RT(r) | ___PPC_RA(base) | IMM_L(i))
27
28#define TEST_PLWZ(r, base, i, pr) \
29 ppc_inst_prefix(PPC_PREFIX_MLS | __PPC_PRFX_R(pr) | IMM_H(i), \
30 PPC_RAW_LWZ(r, base, i))
31
32#define TEST_PSTD(r, base, i, pr) \
33 ppc_inst_prefix(PPC_PREFIX_8LS | __PPC_PRFX_R(pr) | IMM_H(i), \
34 PPC_INST_PSTD | ___PPC_RT(r) | ___PPC_RA(base) | IMM_L(i))
35
36#define TEST_PLFS(r, base, i, pr) \
37 ppc_inst_prefix(PPC_PREFIX_MLS | __PPC_PRFX_R(pr) | IMM_H(i), \
38 PPC_INST_LFS | ___PPC_RT(r) | ___PPC_RA(base) | IMM_L(i))
39
40#define TEST_PSTFS(r, base, i, pr) \
41 ppc_inst_prefix(PPC_PREFIX_MLS | __PPC_PRFX_R(pr) | IMM_H(i), \
42 PPC_INST_STFS | ___PPC_RT(r) | ___PPC_RA(base) | IMM_L(i))
43
44#define TEST_PLFD(r, base, i, pr) \
45 ppc_inst_prefix(PPC_PREFIX_MLS | __PPC_PRFX_R(pr) | IMM_H(i), \
46 PPC_INST_LFD | ___PPC_RT(r) | ___PPC_RA(base) | IMM_L(i))
47
48#define TEST_PSTFD(r, base, i, pr) \
49 ppc_inst_prefix(PPC_PREFIX_MLS | __PPC_PRFX_R(pr) | IMM_H(i), \
50 PPC_INST_STFD | ___PPC_RT(r) | ___PPC_RA(base) | IMM_L(i))
51
52#define TEST_PADDI(t, a, i, pr) \
53 ppc_inst_prefix(PPC_PREFIX_MLS | __PPC_PRFX_R(pr) | IMM_H(i), \
54 PPC_RAW_ADDI(t, a, i))
55
56
57static void __init init_pt_regs(struct pt_regs *regs)
58{
59 static unsigned long msr;
60 static bool msr_cached;
61
62 memset(regs, 0, sizeof(struct pt_regs));
63
64 if (likely(msr_cached)) {
65 regs->msr = msr;
66 return;
67 }
68
69 asm volatile("mfmsr %0" : "=r"(regs->msr));
70
71 regs->msr |= MSR_FP;
72 regs->msr |= MSR_VEC;
73 regs->msr |= MSR_VSX;
74
75 msr = regs->msr;
76 msr_cached = true;
77}
78
79static void __init show_result(char *mnemonic, char *result)
80{
81 pr_info("%-14s : %s\n", mnemonic, result);
82}
83
84static void __init show_result_with_descr(char *mnemonic, char *descr,
85 char *result)
86{
87 pr_info("%-14s : %-50s %s\n", mnemonic, descr, result);
88}
89
90static void __init test_ld(void)
91{
92 struct pt_regs regs;
93 unsigned long a = 0x23;
94 int stepped = -1;
95
96 init_pt_regs(®s);
97 regs.gpr[3] = (unsigned long) &a;
98
99 /* ld r5, 0(r3) */
100 stepped = emulate_step(®s, ppc_inst(PPC_RAW_LD(5, 3, 0)));
101
102 if (stepped == 1 && regs.gpr[5] == a)
103 show_result("ld", "PASS");
104 else
105 show_result("ld", "FAIL");
106}
107
108static void __init test_pld(void)
109{
110 struct pt_regs regs;
111 unsigned long a = 0x23;
112 int stepped = -1;
113
114 if (!cpu_has_feature(CPU_FTR_ARCH_31)) {
115 show_result("pld", "SKIP (!CPU_FTR_ARCH_31)");
116 return;
117 }
118
119 init_pt_regs(®s);
120 regs.gpr[3] = (unsigned long)&a;
121
122 /* pld r5, 0(r3), 0 */
123 stepped = emulate_step(®s, TEST_PLD(5, 3, 0, 0));
124
125 if (stepped == 1 && regs.gpr[5] == a)
126 show_result("pld", "PASS");
127 else
128 show_result("pld", "FAIL");
129}
130
131static void __init test_lwz(void)
132{
133 struct pt_regs regs;
134 unsigned int a = 0x4545;
135 int stepped = -1;
136
137 init_pt_regs(®s);
138 regs.gpr[3] = (unsigned long) &a;
139
140 /* lwz r5, 0(r3) */
141 stepped = emulate_step(®s, ppc_inst(PPC_RAW_LWZ(5, 3, 0)));
142
143 if (stepped == 1 && regs.gpr[5] == a)
144 show_result("lwz", "PASS");
145 else
146 show_result("lwz", "FAIL");
147}
148
149static void __init test_plwz(void)
150{
151 struct pt_regs regs;
152 unsigned int a = 0x4545;
153 int stepped = -1;
154
155 if (!cpu_has_feature(CPU_FTR_ARCH_31)) {
156 show_result("plwz", "SKIP (!CPU_FTR_ARCH_31)");
157 return;
158 }
159
160 init_pt_regs(®s);
161 regs.gpr[3] = (unsigned long)&a;
162
163 /* plwz r5, 0(r3), 0 */
164
165 stepped = emulate_step(®s, TEST_PLWZ(5, 3, 0, 0));
166
167 if (stepped == 1 && regs.gpr[5] == a)
168 show_result("plwz", "PASS");
169 else
170 show_result("plwz", "FAIL");
171}
172
173static void __init test_lwzx(void)
174{
175 struct pt_regs regs;
176 unsigned int a[3] = {0x0, 0x0, 0x1234};
177 int stepped = -1;
178
179 init_pt_regs(®s);
180 regs.gpr[3] = (unsigned long) a;
181 regs.gpr[4] = 8;
182 regs.gpr[5] = 0x8765;
183
184 /* lwzx r5, r3, r4 */
185 stepped = emulate_step(®s, ppc_inst(PPC_RAW_LWZX(5, 3, 4)));
186 if (stepped == 1 && regs.gpr[5] == a[2])
187 show_result("lwzx", "PASS");
188 else
189 show_result("lwzx", "FAIL");
190}
191
192static void __init test_std(void)
193{
194 struct pt_regs regs;
195 unsigned long a = 0x1234;
196 int stepped = -1;
197
198 init_pt_regs(®s);
199 regs.gpr[3] = (unsigned long) &a;
200 regs.gpr[5] = 0x5678;
201
202 /* std r5, 0(r3) */
203 stepped = emulate_step(®s, ppc_inst(PPC_RAW_STD(5, 3, 0)));
204 if (stepped == 1 && regs.gpr[5] == a)
205 show_result("std", "PASS");
206 else
207 show_result("std", "FAIL");
208}
209
210static void __init test_pstd(void)
211{
212 struct pt_regs regs;
213 unsigned long a = 0x1234;
214 int stepped = -1;
215
216 if (!cpu_has_feature(CPU_FTR_ARCH_31)) {
217 show_result("pstd", "SKIP (!CPU_FTR_ARCH_31)");
218 return;
219 }
220
221 init_pt_regs(®s);
222 regs.gpr[3] = (unsigned long)&a;
223 regs.gpr[5] = 0x5678;
224
225 /* pstd r5, 0(r3), 0 */
226 stepped = emulate_step(®s, TEST_PSTD(5, 3, 0, 0));
227 if (stepped == 1 || regs.gpr[5] == a)
228 show_result("pstd", "PASS");
229 else
230 show_result("pstd", "FAIL");
231}
232
233static void __init test_ldarx_stdcx(void)
234{
235 struct pt_regs regs;
236 unsigned long a = 0x1234;
237 int stepped = -1;
238 unsigned long cr0_eq = 0x1 << 29; /* eq bit of CR0 */
239
240 init_pt_regs(®s);
241 asm volatile("mfcr %0" : "=r"(regs.ccr));
242
243
244 /*** ldarx ***/
245
246 regs.gpr[3] = (unsigned long) &a;
247 regs.gpr[4] = 0;
248 regs.gpr[5] = 0x5678;
249
250 /* ldarx r5, r3, r4, 0 */
251 stepped = emulate_step(®s, ppc_inst(PPC_RAW_LDARX(5, 3, 4, 0)));
252
253 /*
254 * Don't touch 'a' here. Touching 'a' can do Load/store
255 * of 'a' which result in failure of subsequent stdcx.
256 * Instead, use hardcoded value for comparison.
257 */
258 if (stepped <= 0 || regs.gpr[5] != 0x1234) {
259 show_result("ldarx / stdcx.", "FAIL (ldarx)");
260 return;
261 }
262
263
264 /*** stdcx. ***/
265
266 regs.gpr[5] = 0x9ABC;
267
268 /* stdcx. r5, r3, r4 */
269 stepped = emulate_step(®s, ppc_inst(PPC_RAW_STDCX(5, 3, 4)));
270
271 /*
272 * Two possible scenarios that indicates successful emulation
273 * of stdcx. :
274 * 1. Reservation is active and store is performed. In this
275 * case cr0.eq bit will be set to 1.
276 * 2. Reservation is not active and store is not performed.
277 * In this case cr0.eq bit will be set to 0.
278 */
279 if (stepped == 1 && ((regs.gpr[5] == a && (regs.ccr & cr0_eq))
280 || (regs.gpr[5] != a && !(regs.ccr & cr0_eq))))
281 show_result("ldarx / stdcx.", "PASS");
282 else
283 show_result("ldarx / stdcx.", "FAIL (stdcx.)");
284}
285
286#ifdef CONFIG_PPC_FPU
287static void __init test_lfsx_stfsx(void)
288{
289 struct pt_regs regs;
290 union {
291 float a;
292 int b;
293 } c;
294 int cached_b;
295 int stepped = -1;
296
297 init_pt_regs(®s);
298
299
300 /*** lfsx ***/
301
302 c.a = 123.45;
303 cached_b = c.b;
304
305 regs.gpr[3] = (unsigned long) &c.a;
306 regs.gpr[4] = 0;
307
308 /* lfsx frt10, r3, r4 */
309 stepped = emulate_step(®s, ppc_inst(PPC_RAW_LFSX(10, 3, 4)));
310
311 if (stepped == 1)
312 show_result("lfsx", "PASS");
313 else
314 show_result("lfsx", "FAIL");
315
316
317 /*** stfsx ***/
318
319 c.a = 678.91;
320
321 /* stfsx frs10, r3, r4 */
322 stepped = emulate_step(®s, ppc_inst(PPC_RAW_STFSX(10, 3, 4)));
323
324 if (stepped == 1 && c.b == cached_b)
325 show_result("stfsx", "PASS");
326 else
327 show_result("stfsx", "FAIL");
328}
329
330static void __init test_plfs_pstfs(void)
331{
332 struct pt_regs regs;
333 union {
334 float a;
335 int b;
336 } c;
337 int cached_b;
338 int stepped = -1;
339
340 if (!cpu_has_feature(CPU_FTR_ARCH_31)) {
341 show_result("pld", "SKIP (!CPU_FTR_ARCH_31)");
342 return;
343 }
344
345 init_pt_regs(®s);
346
347
348 /*** plfs ***/
349
350 c.a = 123.45;
351 cached_b = c.b;
352
353 regs.gpr[3] = (unsigned long)&c.a;
354
355 /* plfs frt10, 0(r3), 0 */
356 stepped = emulate_step(®s, TEST_PLFS(10, 3, 0, 0));
357
358 if (stepped == 1)
359 show_result("plfs", "PASS");
360 else
361 show_result("plfs", "FAIL");
362
363
364 /*** pstfs ***/
365
366 c.a = 678.91;
367
368 /* pstfs frs10, 0(r3), 0 */
369 stepped = emulate_step(®s, TEST_PSTFS(10, 3, 0, 0));
370
371 if (stepped == 1 && c.b == cached_b)
372 show_result("pstfs", "PASS");
373 else
374 show_result("pstfs", "FAIL");
375}
376
377static void __init test_lfdx_stfdx(void)
378{
379 struct pt_regs regs;
380 union {
381 double a;
382 long b;
383 } c;
384 long cached_b;
385 int stepped = -1;
386
387 init_pt_regs(®s);
388
389
390 /*** lfdx ***/
391
392 c.a = 123456.78;
393 cached_b = c.b;
394
395 regs.gpr[3] = (unsigned long) &c.a;
396 regs.gpr[4] = 0;
397
398 /* lfdx frt10, r3, r4 */
399 stepped = emulate_step(®s, ppc_inst(PPC_RAW_LFDX(10, 3, 4)));
400
401 if (stepped == 1)
402 show_result("lfdx", "PASS");
403 else
404 show_result("lfdx", "FAIL");
405
406
407 /*** stfdx ***/
408
409 c.a = 987654.32;
410
411 /* stfdx frs10, r3, r4 */
412 stepped = emulate_step(®s, ppc_inst(PPC_RAW_STFDX(10, 3, 4)));
413
414 if (stepped == 1 && c.b == cached_b)
415 show_result("stfdx", "PASS");
416 else
417 show_result("stfdx", "FAIL");
418}
419
420static void __init test_plfd_pstfd(void)
421{
422 struct pt_regs regs;
423 union {
424 double a;
425 long b;
426 } c;
427 long cached_b;
428 int stepped = -1;
429
430 if (!cpu_has_feature(CPU_FTR_ARCH_31)) {
431 show_result("pld", "SKIP (!CPU_FTR_ARCH_31)");
432 return;
433 }
434
435 init_pt_regs(®s);
436
437
438 /*** plfd ***/
439
440 c.a = 123456.78;
441 cached_b = c.b;
442
443 regs.gpr[3] = (unsigned long)&c.a;
444
445 /* plfd frt10, 0(r3), 0 */
446 stepped = emulate_step(®s, TEST_PLFD(10, 3, 0, 0));
447
448 if (stepped == 1)
449 show_result("plfd", "PASS");
450 else
451 show_result("plfd", "FAIL");
452
453
454 /*** pstfd ***/
455
456 c.a = 987654.32;
457
458 /* pstfd frs10, 0(r3), 0 */
459 stepped = emulate_step(®s, TEST_PSTFD(10, 3, 0, 0));
460
461 if (stepped == 1 && c.b == cached_b)
462 show_result("pstfd", "PASS");
463 else
464 show_result("pstfd", "FAIL");
465}
466#else
467static void __init test_lfsx_stfsx(void)
468{
469 show_result("lfsx", "SKIP (CONFIG_PPC_FPU is not set)");
470 show_result("stfsx", "SKIP (CONFIG_PPC_FPU is not set)");
471}
472
473static void __init test_plfs_pstfs(void)
474{
475 show_result("plfs", "SKIP (CONFIG_PPC_FPU is not set)");
476 show_result("pstfs", "SKIP (CONFIG_PPC_FPU is not set)");
477}
478
479static void __init test_lfdx_stfdx(void)
480{
481 show_result("lfdx", "SKIP (CONFIG_PPC_FPU is not set)");
482 show_result("stfdx", "SKIP (CONFIG_PPC_FPU is not set)");
483}
484
485static void __init test_plfd_pstfd(void)
486{
487 show_result("plfd", "SKIP (CONFIG_PPC_FPU is not set)");
488 show_result("pstfd", "SKIP (CONFIG_PPC_FPU is not set)");
489}
490#endif /* CONFIG_PPC_FPU */
491
492#ifdef CONFIG_ALTIVEC
493static void __init test_lvx_stvx(void)
494{
495 struct pt_regs regs;
496 union {
497 vector128 a;
498 u32 b[4];
499 } c;
500 u32 cached_b[4];
501 int stepped = -1;
502
503 init_pt_regs(®s);
504
505
506 /*** lvx ***/
507
508 cached_b[0] = c.b[0] = 923745;
509 cached_b[1] = c.b[1] = 2139478;
510 cached_b[2] = c.b[2] = 9012;
511 cached_b[3] = c.b[3] = 982134;
512
513 regs.gpr[3] = (unsigned long) &c.a;
514 regs.gpr[4] = 0;
515
516 /* lvx vrt10, r3, r4 */
517 stepped = emulate_step(®s, ppc_inst(PPC_RAW_LVX(10, 3, 4)));
518
519 if (stepped == 1)
520 show_result("lvx", "PASS");
521 else
522 show_result("lvx", "FAIL");
523
524
525 /*** stvx ***/
526
527 c.b[0] = 4987513;
528 c.b[1] = 84313948;
529 c.b[2] = 71;
530 c.b[3] = 498532;
531
532 /* stvx vrs10, r3, r4 */
533 stepped = emulate_step(®s, ppc_inst(PPC_RAW_STVX(10, 3, 4)));
534
535 if (stepped == 1 && cached_b[0] == c.b[0] && cached_b[1] == c.b[1] &&
536 cached_b[2] == c.b[2] && cached_b[3] == c.b[3])
537 show_result("stvx", "PASS");
538 else
539 show_result("stvx", "FAIL");
540}
541#else
542static void __init test_lvx_stvx(void)
543{
544 show_result("lvx", "SKIP (CONFIG_ALTIVEC is not set)");
545 show_result("stvx", "SKIP (CONFIG_ALTIVEC is not set)");
546}
547#endif /* CONFIG_ALTIVEC */
548
549#ifdef CONFIG_VSX
550static void __init test_lxvd2x_stxvd2x(void)
551{
552 struct pt_regs regs;
553 union {
554 vector128 a;
555 u32 b[4];
556 } c;
557 u32 cached_b[4];
558 int stepped = -1;
559
560 init_pt_regs(®s);
561
562
563 /*** lxvd2x ***/
564
565 cached_b[0] = c.b[0] = 18233;
566 cached_b[1] = c.b[1] = 34863571;
567 cached_b[2] = c.b[2] = 834;
568 cached_b[3] = c.b[3] = 6138911;
569
570 regs.gpr[3] = (unsigned long) &c.a;
571 regs.gpr[4] = 0;
572
573 /* lxvd2x vsr39, r3, r4 */
574 stepped = emulate_step(®s, ppc_inst(PPC_RAW_LXVD2X(39, R3, R4)));
575
576 if (stepped == 1 && cpu_has_feature(CPU_FTR_VSX)) {
577 show_result("lxvd2x", "PASS");
578 } else {
579 if (!cpu_has_feature(CPU_FTR_VSX))
580 show_result("lxvd2x", "PASS (!CPU_FTR_VSX)");
581 else
582 show_result("lxvd2x", "FAIL");
583 }
584
585
586 /*** stxvd2x ***/
587
588 c.b[0] = 21379463;
589 c.b[1] = 87;
590 c.b[2] = 374234;
591 c.b[3] = 4;
592
593 /* stxvd2x vsr39, r3, r4 */
594 stepped = emulate_step(®s, ppc_inst(PPC_RAW_STXVD2X(39, R3, R4)));
595
596 if (stepped == 1 && cached_b[0] == c.b[0] && cached_b[1] == c.b[1] &&
597 cached_b[2] == c.b[2] && cached_b[3] == c.b[3] &&
598 cpu_has_feature(CPU_FTR_VSX)) {
599 show_result("stxvd2x", "PASS");
600 } else {
601 if (!cpu_has_feature(CPU_FTR_VSX))
602 show_result("stxvd2x", "PASS (!CPU_FTR_VSX)");
603 else
604 show_result("stxvd2x", "FAIL");
605 }
606}
607#else
608static void __init test_lxvd2x_stxvd2x(void)
609{
610 show_result("lxvd2x", "SKIP (CONFIG_VSX is not set)");
611 show_result("stxvd2x", "SKIP (CONFIG_VSX is not set)");
612}
613#endif /* CONFIG_VSX */
614
615#ifdef CONFIG_VSX
616static void __init test_lxvp_stxvp(void)
617{
618 struct pt_regs regs;
619 union {
620 vector128 a;
621 u32 b[4];
622 } c[2];
623 u32 cached_b[8];
624 int stepped = -1;
625
626 if (!cpu_has_feature(CPU_FTR_ARCH_31)) {
627 show_result("lxvp", "SKIP (!CPU_FTR_ARCH_31)");
628 show_result("stxvp", "SKIP (!CPU_FTR_ARCH_31)");
629 return;
630 }
631
632 init_pt_regs(®s);
633
634 /*** lxvp ***/
635
636 cached_b[0] = c[0].b[0] = 18233;
637 cached_b[1] = c[0].b[1] = 34863571;
638 cached_b[2] = c[0].b[2] = 834;
639 cached_b[3] = c[0].b[3] = 6138911;
640 cached_b[4] = c[1].b[0] = 1234;
641 cached_b[5] = c[1].b[1] = 5678;
642 cached_b[6] = c[1].b[2] = 91011;
643 cached_b[7] = c[1].b[3] = 121314;
644
645 regs.gpr[4] = (unsigned long)&c[0].a;
646
647 /*
648 * lxvp XTp,DQ(RA)
649 * XTp = 32xTX + 2xTp
650 * let TX=1 Tp=1 RA=4 DQ=0
651 */
652 stepped = emulate_step(®s, ppc_inst(PPC_RAW_LXVP(34, 4, 0)));
653
654 if (stepped == 1 && cpu_has_feature(CPU_FTR_VSX)) {
655 show_result("lxvp", "PASS");
656 } else {
657 if (!cpu_has_feature(CPU_FTR_VSX))
658 show_result("lxvp", "PASS (!CPU_FTR_VSX)");
659 else
660 show_result("lxvp", "FAIL");
661 }
662
663 /*** stxvp ***/
664
665 c[0].b[0] = 21379463;
666 c[0].b[1] = 87;
667 c[0].b[2] = 374234;
668 c[0].b[3] = 4;
669 c[1].b[0] = 90;
670 c[1].b[1] = 122;
671 c[1].b[2] = 555;
672 c[1].b[3] = 32144;
673
674 /*
675 * stxvp XSp,DQ(RA)
676 * XSp = 32xSX + 2xSp
677 * let SX=1 Sp=1 RA=4 DQ=0
678 */
679 stepped = emulate_step(®s, ppc_inst(PPC_RAW_STXVP(34, 4, 0)));
680
681 if (stepped == 1 && cached_b[0] == c[0].b[0] && cached_b[1] == c[0].b[1] &&
682 cached_b[2] == c[0].b[2] && cached_b[3] == c[0].b[3] &&
683 cached_b[4] == c[1].b[0] && cached_b[5] == c[1].b[1] &&
684 cached_b[6] == c[1].b[2] && cached_b[7] == c[1].b[3] &&
685 cpu_has_feature(CPU_FTR_VSX)) {
686 show_result("stxvp", "PASS");
687 } else {
688 if (!cpu_has_feature(CPU_FTR_VSX))
689 show_result("stxvp", "PASS (!CPU_FTR_VSX)");
690 else
691 show_result("stxvp", "FAIL");
692 }
693}
694#else
695static void __init test_lxvp_stxvp(void)
696{
697 show_result("lxvp", "SKIP (CONFIG_VSX is not set)");
698 show_result("stxvp", "SKIP (CONFIG_VSX is not set)");
699}
700#endif /* CONFIG_VSX */
701
702#ifdef CONFIG_VSX
703static void __init test_lxvpx_stxvpx(void)
704{
705 struct pt_regs regs;
706 union {
707 vector128 a;
708 u32 b[4];
709 } c[2];
710 u32 cached_b[8];
711 int stepped = -1;
712
713 if (!cpu_has_feature(CPU_FTR_ARCH_31)) {
714 show_result("lxvpx", "SKIP (!CPU_FTR_ARCH_31)");
715 show_result("stxvpx", "SKIP (!CPU_FTR_ARCH_31)");
716 return;
717 }
718
719 init_pt_regs(®s);
720
721 /*** lxvpx ***/
722
723 cached_b[0] = c[0].b[0] = 18233;
724 cached_b[1] = c[0].b[1] = 34863571;
725 cached_b[2] = c[0].b[2] = 834;
726 cached_b[3] = c[0].b[3] = 6138911;
727 cached_b[4] = c[1].b[0] = 1234;
728 cached_b[5] = c[1].b[1] = 5678;
729 cached_b[6] = c[1].b[2] = 91011;
730 cached_b[7] = c[1].b[3] = 121314;
731
732 regs.gpr[3] = (unsigned long)&c[0].a;
733 regs.gpr[4] = 0;
734
735 /*
736 * lxvpx XTp,RA,RB
737 * XTp = 32xTX + 2xTp
738 * let TX=1 Tp=1 RA=3 RB=4
739 */
740 stepped = emulate_step(®s, ppc_inst(PPC_RAW_LXVPX(34, 3, 4)));
741
742 if (stepped == 1 && cpu_has_feature(CPU_FTR_VSX)) {
743 show_result("lxvpx", "PASS");
744 } else {
745 if (!cpu_has_feature(CPU_FTR_VSX))
746 show_result("lxvpx", "PASS (!CPU_FTR_VSX)");
747 else
748 show_result("lxvpx", "FAIL");
749 }
750
751 /*** stxvpx ***/
752
753 c[0].b[0] = 21379463;
754 c[0].b[1] = 87;
755 c[0].b[2] = 374234;
756 c[0].b[3] = 4;
757 c[1].b[0] = 90;
758 c[1].b[1] = 122;
759 c[1].b[2] = 555;
760 c[1].b[3] = 32144;
761
762 /*
763 * stxvpx XSp,RA,RB
764 * XSp = 32xSX + 2xSp
765 * let SX=1 Sp=1 RA=3 RB=4
766 */
767 stepped = emulate_step(®s, ppc_inst(PPC_RAW_STXVPX(34, 3, 4)));
768
769 if (stepped == 1 && cached_b[0] == c[0].b[0] && cached_b[1] == c[0].b[1] &&
770 cached_b[2] == c[0].b[2] && cached_b[3] == c[0].b[3] &&
771 cached_b[4] == c[1].b[0] && cached_b[5] == c[1].b[1] &&
772 cached_b[6] == c[1].b[2] && cached_b[7] == c[1].b[3] &&
773 cpu_has_feature(CPU_FTR_VSX)) {
774 show_result("stxvpx", "PASS");
775 } else {
776 if (!cpu_has_feature(CPU_FTR_VSX))
777 show_result("stxvpx", "PASS (!CPU_FTR_VSX)");
778 else
779 show_result("stxvpx", "FAIL");
780 }
781}
782#else
783static void __init test_lxvpx_stxvpx(void)
784{
785 show_result("lxvpx", "SKIP (CONFIG_VSX is not set)");
786 show_result("stxvpx", "SKIP (CONFIG_VSX is not set)");
787}
788#endif /* CONFIG_VSX */
789
790#ifdef CONFIG_VSX
791static void __init test_plxvp_pstxvp(void)
792{
793 struct ppc_inst instr;
794 struct pt_regs regs;
795 union {
796 vector128 a;
797 u32 b[4];
798 } c[2];
799 u32 cached_b[8];
800 int stepped = -1;
801
802 if (!cpu_has_feature(CPU_FTR_ARCH_31)) {
803 show_result("plxvp", "SKIP (!CPU_FTR_ARCH_31)");
804 show_result("pstxvp", "SKIP (!CPU_FTR_ARCH_31)");
805 return;
806 }
807
808 /*** plxvp ***/
809
810 cached_b[0] = c[0].b[0] = 18233;
811 cached_b[1] = c[0].b[1] = 34863571;
812 cached_b[2] = c[0].b[2] = 834;
813 cached_b[3] = c[0].b[3] = 6138911;
814 cached_b[4] = c[1].b[0] = 1234;
815 cached_b[5] = c[1].b[1] = 5678;
816 cached_b[6] = c[1].b[2] = 91011;
817 cached_b[7] = c[1].b[3] = 121314;
818
819 init_pt_regs(®s);
820 regs.gpr[3] = (unsigned long)&c[0].a;
821
822 /*
823 * plxvp XTp,D(RA),R
824 * XTp = 32xTX + 2xTp
825 * let RA=3 R=0 D=d0||d1=0 R=0 Tp=1 TX=1
826 */
827 instr = ppc_inst_prefix(PPC_RAW_PLXVP(34, 0, 3, 0) >> 32,
828 PPC_RAW_PLXVP(34, 0, 3, 0) & 0xffffffff);
829
830 stepped = emulate_step(®s, instr);
831 if (stepped == 1 && cpu_has_feature(CPU_FTR_VSX)) {
832 show_result("plxvp", "PASS");
833 } else {
834 if (!cpu_has_feature(CPU_FTR_VSX))
835 show_result("plxvp", "PASS (!CPU_FTR_VSX)");
836 else
837 show_result("plxvp", "FAIL");
838 }
839
840 /*** pstxvp ***/
841
842 c[0].b[0] = 21379463;
843 c[0].b[1] = 87;
844 c[0].b[2] = 374234;
845 c[0].b[3] = 4;
846 c[1].b[0] = 90;
847 c[1].b[1] = 122;
848 c[1].b[2] = 555;
849 c[1].b[3] = 32144;
850
851 /*
852 * pstxvp XSp,D(RA),R
853 * XSp = 32xSX + 2xSp
854 * let RA=3 D=d0||d1=0 R=0 Sp=1 SX=1
855 */
856 instr = ppc_inst_prefix(PPC_RAW_PSTXVP(34, 0, 3, 0) >> 32,
857 PPC_RAW_PSTXVP(34, 0, 3, 0) & 0xffffffff);
858
859 stepped = emulate_step(®s, instr);
860
861 if (stepped == 1 && cached_b[0] == c[0].b[0] && cached_b[1] == c[0].b[1] &&
862 cached_b[2] == c[0].b[2] && cached_b[3] == c[0].b[3] &&
863 cached_b[4] == c[1].b[0] && cached_b[5] == c[1].b[1] &&
864 cached_b[6] == c[1].b[2] && cached_b[7] == c[1].b[3] &&
865 cpu_has_feature(CPU_FTR_VSX)) {
866 show_result("pstxvp", "PASS");
867 } else {
868 if (!cpu_has_feature(CPU_FTR_VSX))
869 show_result("pstxvp", "PASS (!CPU_FTR_VSX)");
870 else
871 show_result("pstxvp", "FAIL");
872 }
873}
874#else
875static void __init test_plxvp_pstxvp(void)
876{
877 show_result("plxvp", "SKIP (CONFIG_VSX is not set)");
878 show_result("pstxvp", "SKIP (CONFIG_VSX is not set)");
879}
880#endif /* CONFIG_VSX */
881
882static void __init run_tests_load_store(void)
883{
884 test_ld();
885 test_pld();
886 test_lwz();
887 test_plwz();
888 test_lwzx();
889 test_std();
890 test_pstd();
891 test_ldarx_stdcx();
892 test_lfsx_stfsx();
893 test_plfs_pstfs();
894 test_lfdx_stfdx();
895 test_plfd_pstfd();
896 test_lvx_stvx();
897 test_lxvd2x_stxvd2x();
898 test_lxvp_stxvp();
899 test_lxvpx_stxvpx();
900 test_plxvp_pstxvp();
901}
902
903struct compute_test {
904 char *mnemonic;
905 unsigned long cpu_feature;
906 struct {
907 char *descr;
908 unsigned long flags;
909 struct ppc_inst instr;
910 struct pt_regs regs;
911 } subtests[MAX_SUBTESTS + 1];
912};
913
914/* Extreme values for si0||si1 (the MLS:D-form 34 bit immediate field) */
915#define SI_MIN BIT(33)
916#define SI_MAX (BIT(33) - 1)
917#define SI_UMAX (BIT(34) - 1)
918
919static struct compute_test compute_tests[] = {
920 {
921 .mnemonic = "nop",
922 .subtests = {
923 {
924 .descr = "R0 = LONG_MAX",
925 .instr = ppc_inst(PPC_INST_NOP),
926 .regs = {
927 .gpr[0] = LONG_MAX,
928 }
929 }
930 }
931 },
932 {
933 .mnemonic = "add",
934 .subtests = {
935 {
936 .descr = "RA = LONG_MIN, RB = LONG_MIN",
937 .instr = ppc_inst(PPC_RAW_ADD(20, 21, 22)),
938 .regs = {
939 .gpr[21] = LONG_MIN,
940 .gpr[22] = LONG_MIN,
941 }
942 },
943 {
944 .descr = "RA = LONG_MIN, RB = LONG_MAX",
945 .instr = ppc_inst(PPC_RAW_ADD(20, 21, 22)),
946 .regs = {
947 .gpr[21] = LONG_MIN,
948 .gpr[22] = LONG_MAX,
949 }
950 },
951 {
952 .descr = "RA = LONG_MAX, RB = LONG_MAX",
953 .instr = ppc_inst(PPC_RAW_ADD(20, 21, 22)),
954 .regs = {
955 .gpr[21] = LONG_MAX,
956 .gpr[22] = LONG_MAX,
957 }
958 },
959 {
960 .descr = "RA = ULONG_MAX, RB = ULONG_MAX",
961 .instr = ppc_inst(PPC_RAW_ADD(20, 21, 22)),
962 .regs = {
963 .gpr[21] = ULONG_MAX,
964 .gpr[22] = ULONG_MAX,
965 }
966 },
967 {
968 .descr = "RA = ULONG_MAX, RB = 0x1",
969 .instr = ppc_inst(PPC_RAW_ADD(20, 21, 22)),
970 .regs = {
971 .gpr[21] = ULONG_MAX,
972 .gpr[22] = 0x1,
973 }
974 },
975 {
976 .descr = "RA = INT_MIN, RB = INT_MIN",
977 .instr = ppc_inst(PPC_RAW_ADD(20, 21, 22)),
978 .regs = {
979 .gpr[21] = INT_MIN,
980 .gpr[22] = INT_MIN,
981 }
982 },
983 {
984 .descr = "RA = INT_MIN, RB = INT_MAX",
985 .instr = ppc_inst(PPC_RAW_ADD(20, 21, 22)),
986 .regs = {
987 .gpr[21] = INT_MIN,
988 .gpr[22] = INT_MAX,
989 }
990 },
991 {
992 .descr = "RA = INT_MAX, RB = INT_MAX",
993 .instr = ppc_inst(PPC_RAW_ADD(20, 21, 22)),
994 .regs = {
995 .gpr[21] = INT_MAX,
996 .gpr[22] = INT_MAX,
997 }
998 },
999 {
1000 .descr = "RA = UINT_MAX, RB = UINT_MAX",
1001 .instr = ppc_inst(PPC_RAW_ADD(20, 21, 22)),
1002 .regs = {
1003 .gpr[21] = UINT_MAX,
1004 .gpr[22] = UINT_MAX,
1005 }
1006 },
1007 {
1008 .descr = "RA = UINT_MAX, RB = 0x1",
1009 .instr = ppc_inst(PPC_RAW_ADD(20, 21, 22)),
1010 .regs = {
1011 .gpr[21] = UINT_MAX,
1012 .gpr[22] = 0x1,
1013 }
1014 }
1015 }
1016 },
1017 {
1018 .mnemonic = "add.",
1019 .subtests = {
1020 {
1021 .descr = "RA = LONG_MIN, RB = LONG_MIN",
1022 .flags = IGNORE_CCR,
1023 .instr = ppc_inst(PPC_RAW_ADD_DOT(20, 21, 22)),
1024 .regs = {
1025 .gpr[21] = LONG_MIN,
1026 .gpr[22] = LONG_MIN,
1027 }
1028 },
1029 {
1030 .descr = "RA = LONG_MIN, RB = LONG_MAX",
1031 .instr = ppc_inst(PPC_RAW_ADD_DOT(20, 21, 22)),
1032 .regs = {
1033 .gpr[21] = LONG_MIN,
1034 .gpr[22] = LONG_MAX,
1035 }
1036 },
1037 {
1038 .descr = "RA = LONG_MAX, RB = LONG_MAX",
1039 .flags = IGNORE_CCR,
1040 .instr = ppc_inst(PPC_RAW_ADD_DOT(20, 21, 22)),
1041 .regs = {
1042 .gpr[21] = LONG_MAX,
1043 .gpr[22] = LONG_MAX,
1044 }
1045 },
1046 {
1047 .descr = "RA = ULONG_MAX, RB = ULONG_MAX",
1048 .instr = ppc_inst(PPC_RAW_ADD_DOT(20, 21, 22)),
1049 .regs = {
1050 .gpr[21] = ULONG_MAX,
1051 .gpr[22] = ULONG_MAX,
1052 }
1053 },
1054 {
1055 .descr = "RA = ULONG_MAX, RB = 0x1",
1056 .instr = ppc_inst(PPC_RAW_ADD_DOT(20, 21, 22)),
1057 .regs = {
1058 .gpr[21] = ULONG_MAX,
1059 .gpr[22] = 0x1,
1060 }
1061 },
1062 {
1063 .descr = "RA = INT_MIN, RB = INT_MIN",
1064 .instr = ppc_inst(PPC_RAW_ADD_DOT(20, 21, 22)),
1065 .regs = {
1066 .gpr[21] = INT_MIN,
1067 .gpr[22] = INT_MIN,
1068 }
1069 },
1070 {
1071 .descr = "RA = INT_MIN, RB = INT_MAX",
1072 .instr = ppc_inst(PPC_RAW_ADD_DOT(20, 21, 22)),
1073 .regs = {
1074 .gpr[21] = INT_MIN,
1075 .gpr[22] = INT_MAX,
1076 }
1077 },
1078 {
1079 .descr = "RA = INT_MAX, RB = INT_MAX",
1080 .instr = ppc_inst(PPC_RAW_ADD_DOT(20, 21, 22)),
1081 .regs = {
1082 .gpr[21] = INT_MAX,
1083 .gpr[22] = INT_MAX,
1084 }
1085 },
1086 {
1087 .descr = "RA = UINT_MAX, RB = UINT_MAX",
1088 .instr = ppc_inst(PPC_RAW_ADD_DOT(20, 21, 22)),
1089 .regs = {
1090 .gpr[21] = UINT_MAX,
1091 .gpr[22] = UINT_MAX,
1092 }
1093 },
1094 {
1095 .descr = "RA = UINT_MAX, RB = 0x1",
1096 .instr = ppc_inst(PPC_RAW_ADD_DOT(20, 21, 22)),
1097 .regs = {
1098 .gpr[21] = UINT_MAX,
1099 .gpr[22] = 0x1,
1100 }
1101 }
1102 }
1103 },
1104 {
1105 .mnemonic = "addc",
1106 .subtests = {
1107 {
1108 .descr = "RA = LONG_MIN, RB = LONG_MIN",
1109 .instr = ppc_inst(PPC_RAW_ADDC(20, 21, 22)),
1110 .regs = {
1111 .gpr[21] = LONG_MIN,
1112 .gpr[22] = LONG_MIN,
1113 }
1114 },
1115 {
1116 .descr = "RA = LONG_MIN, RB = LONG_MAX",
1117 .instr = ppc_inst(PPC_RAW_ADDC(20, 21, 22)),
1118 .regs = {
1119 .gpr[21] = LONG_MIN,
1120 .gpr[22] = LONG_MAX,
1121 }
1122 },
1123 {
1124 .descr = "RA = LONG_MAX, RB = LONG_MAX",
1125 .instr = ppc_inst(PPC_RAW_ADDC(20, 21, 22)),
1126 .regs = {
1127 .gpr[21] = LONG_MAX,
1128 .gpr[22] = LONG_MAX,
1129 }
1130 },
1131 {
1132 .descr = "RA = ULONG_MAX, RB = ULONG_MAX",
1133 .instr = ppc_inst(PPC_RAW_ADDC(20, 21, 22)),
1134 .regs = {
1135 .gpr[21] = ULONG_MAX,
1136 .gpr[22] = ULONG_MAX,
1137 }
1138 },
1139 {
1140 .descr = "RA = ULONG_MAX, RB = 0x1",
1141 .instr = ppc_inst(PPC_RAW_ADDC(20, 21, 22)),
1142 .regs = {
1143 .gpr[21] = ULONG_MAX,
1144 .gpr[22] = 0x1,
1145 }
1146 },
1147 {
1148 .descr = "RA = INT_MIN, RB = INT_MIN",
1149 .instr = ppc_inst(PPC_RAW_ADDC(20, 21, 22)),
1150 .regs = {
1151 .gpr[21] = INT_MIN,
1152 .gpr[22] = INT_MIN,
1153 }
1154 },
1155 {
1156 .descr = "RA = INT_MIN, RB = INT_MAX",
1157 .instr = ppc_inst(PPC_RAW_ADDC(20, 21, 22)),
1158 .regs = {
1159 .gpr[21] = INT_MIN,
1160 .gpr[22] = INT_MAX,
1161 }
1162 },
1163 {
1164 .descr = "RA = INT_MAX, RB = INT_MAX",
1165 .instr = ppc_inst(PPC_RAW_ADDC(20, 21, 22)),
1166 .regs = {
1167 .gpr[21] = INT_MAX,
1168 .gpr[22] = INT_MAX,
1169 }
1170 },
1171 {
1172 .descr = "RA = UINT_MAX, RB = UINT_MAX",
1173 .instr = ppc_inst(PPC_RAW_ADDC(20, 21, 22)),
1174 .regs = {
1175 .gpr[21] = UINT_MAX,
1176 .gpr[22] = UINT_MAX,
1177 }
1178 },
1179 {
1180 .descr = "RA = UINT_MAX, RB = 0x1",
1181 .instr = ppc_inst(PPC_RAW_ADDC(20, 21, 22)),
1182 .regs = {
1183 .gpr[21] = UINT_MAX,
1184 .gpr[22] = 0x1,
1185 }
1186 },
1187 {
1188 .descr = "RA = LONG_MIN | INT_MIN, RB = LONG_MIN | INT_MIN",
1189 .instr = ppc_inst(PPC_RAW_ADDC(20, 21, 22)),
1190 .regs = {
1191 .gpr[21] = LONG_MIN | (uint)INT_MIN,
1192 .gpr[22] = LONG_MIN | (uint)INT_MIN,
1193 }
1194 }
1195 }
1196 },
1197 {
1198 .mnemonic = "addc.",
1199 .subtests = {
1200 {
1201 .descr = "RA = LONG_MIN, RB = LONG_MIN",
1202 .flags = IGNORE_CCR,
1203 .instr = ppc_inst(PPC_RAW_ADDC_DOT(20, 21, 22)),
1204 .regs = {
1205 .gpr[21] = LONG_MIN,
1206 .gpr[22] = LONG_MIN,
1207 }
1208 },
1209 {
1210 .descr = "RA = LONG_MIN, RB = LONG_MAX",
1211 .instr = ppc_inst(PPC_RAW_ADDC_DOT(20, 21, 22)),
1212 .regs = {
1213 .gpr[21] = LONG_MIN,
1214 .gpr[22] = LONG_MAX,
1215 }
1216 },
1217 {
1218 .descr = "RA = LONG_MAX, RB = LONG_MAX",
1219 .flags = IGNORE_CCR,
1220 .instr = ppc_inst(PPC_RAW_ADDC_DOT(20, 21, 22)),
1221 .regs = {
1222 .gpr[21] = LONG_MAX,
1223 .gpr[22] = LONG_MAX,
1224 }
1225 },
1226 {
1227 .descr = "RA = ULONG_MAX, RB = ULONG_MAX",
1228 .instr = ppc_inst(PPC_RAW_ADDC_DOT(20, 21, 22)),
1229 .regs = {
1230 .gpr[21] = ULONG_MAX,
1231 .gpr[22] = ULONG_MAX,
1232 }
1233 },
1234 {
1235 .descr = "RA = ULONG_MAX, RB = 0x1",
1236 .instr = ppc_inst(PPC_RAW_ADDC_DOT(20, 21, 22)),
1237 .regs = {
1238 .gpr[21] = ULONG_MAX,
1239 .gpr[22] = 0x1,
1240 }
1241 },
1242 {
1243 .descr = "RA = INT_MIN, RB = INT_MIN",
1244 .instr = ppc_inst(PPC_RAW_ADDC_DOT(20, 21, 22)),
1245 .regs = {
1246 .gpr[21] = INT_MIN,
1247 .gpr[22] = INT_MIN,
1248 }
1249 },
1250 {
1251 .descr = "RA = INT_MIN, RB = INT_MAX",
1252 .instr = ppc_inst(PPC_RAW_ADDC_DOT(20, 21, 22)),
1253 .regs = {
1254 .gpr[21] = INT_MIN,
1255 .gpr[22] = INT_MAX,
1256 }
1257 },
1258 {
1259 .descr = "RA = INT_MAX, RB = INT_MAX",
1260 .instr = ppc_inst(PPC_RAW_ADDC_DOT(20, 21, 22)),
1261 .regs = {
1262 .gpr[21] = INT_MAX,
1263 .gpr[22] = INT_MAX,
1264 }
1265 },
1266 {
1267 .descr = "RA = UINT_MAX, RB = UINT_MAX",
1268 .instr = ppc_inst(PPC_RAW_ADDC_DOT(20, 21, 22)),
1269 .regs = {
1270 .gpr[21] = UINT_MAX,
1271 .gpr[22] = UINT_MAX,
1272 }
1273 },
1274 {
1275 .descr = "RA = UINT_MAX, RB = 0x1",
1276 .instr = ppc_inst(PPC_RAW_ADDC_DOT(20, 21, 22)),
1277 .regs = {
1278 .gpr[21] = UINT_MAX,
1279 .gpr[22] = 0x1,
1280 }
1281 },
1282 {
1283 .descr = "RA = LONG_MIN | INT_MIN, RB = LONG_MIN | INT_MIN",
1284 .instr = ppc_inst(PPC_RAW_ADDC_DOT(20, 21, 22)),
1285 .regs = {
1286 .gpr[21] = LONG_MIN | (uint)INT_MIN,
1287 .gpr[22] = LONG_MIN | (uint)INT_MIN,
1288 }
1289 }
1290 }
1291 },
1292 {
1293 .mnemonic = "divde",
1294 .subtests = {
1295 {
1296 .descr = "RA = LONG_MIN, RB = LONG_MIN",
1297 .instr = ppc_inst(PPC_RAW_DIVDE(20, 21, 22)),
1298 .regs = {
1299 .gpr[21] = LONG_MIN,
1300 .gpr[22] = LONG_MIN,
1301 }
1302 },
1303 {
1304 .descr = "RA = 1L, RB = 0",
1305 .instr = ppc_inst(PPC_RAW_DIVDE(20, 21, 22)),
1306 .flags = IGNORE_GPR(20),
1307 .regs = {
1308 .gpr[21] = 1L,
1309 .gpr[22] = 0,
1310 }
1311 },
1312 {
1313 .descr = "RA = LONG_MIN, RB = LONG_MAX",
1314 .instr = ppc_inst(PPC_RAW_DIVDE(20, 21, 22)),
1315 .regs = {
1316 .gpr[21] = LONG_MIN,
1317 .gpr[22] = LONG_MAX,
1318 }
1319 }
1320 }
1321 },
1322 {
1323 .mnemonic = "divde.",
1324 .subtests = {
1325 {
1326 .descr = "RA = LONG_MIN, RB = LONG_MIN",
1327 .instr = ppc_inst(PPC_RAW_DIVDE_DOT(20, 21, 22)),
1328 .regs = {
1329 .gpr[21] = LONG_MIN,
1330 .gpr[22] = LONG_MIN,
1331 }
1332 },
1333 {
1334 .descr = "RA = 1L, RB = 0",
1335 .instr = ppc_inst(PPC_RAW_DIVDE_DOT(20, 21, 22)),
1336 .flags = IGNORE_GPR(20),
1337 .regs = {
1338 .gpr[21] = 1L,
1339 .gpr[22] = 0,
1340 }
1341 },
1342 {
1343 .descr = "RA = LONG_MIN, RB = LONG_MAX",
1344 .instr = ppc_inst(PPC_RAW_DIVDE_DOT(20, 21, 22)),
1345 .regs = {
1346 .gpr[21] = LONG_MIN,
1347 .gpr[22] = LONG_MAX,
1348 }
1349 }
1350 }
1351 },
1352 {
1353 .mnemonic = "divdeu",
1354 .subtests = {
1355 {
1356 .descr = "RA = LONG_MIN, RB = LONG_MIN",
1357 .instr = ppc_inst(PPC_RAW_DIVDEU(20, 21, 22)),
1358 .flags = IGNORE_GPR(20),
1359 .regs = {
1360 .gpr[21] = LONG_MIN,
1361 .gpr[22] = LONG_MIN,
1362 }
1363 },
1364 {
1365 .descr = "RA = 1L, RB = 0",
1366 .instr = ppc_inst(PPC_RAW_DIVDEU(20, 21, 22)),
1367 .flags = IGNORE_GPR(20),
1368 .regs = {
1369 .gpr[21] = 1L,
1370 .gpr[22] = 0,
1371 }
1372 },
1373 {
1374 .descr = "RA = LONG_MIN, RB = LONG_MAX",
1375 .instr = ppc_inst(PPC_RAW_DIVDEU(20, 21, 22)),
1376 .regs = {
1377 .gpr[21] = LONG_MIN,
1378 .gpr[22] = LONG_MAX,
1379 }
1380 },
1381 {
1382 .descr = "RA = LONG_MAX - 1, RB = LONG_MAX",
1383 .instr = ppc_inst(PPC_RAW_DIVDEU(20, 21, 22)),
1384 .regs = {
1385 .gpr[21] = LONG_MAX - 1,
1386 .gpr[22] = LONG_MAX,
1387 }
1388 },
1389 {
1390 .descr = "RA = LONG_MIN + 1, RB = LONG_MIN",
1391 .instr = ppc_inst(PPC_RAW_DIVDEU(20, 21, 22)),
1392 .flags = IGNORE_GPR(20),
1393 .regs = {
1394 .gpr[21] = LONG_MIN + 1,
1395 .gpr[22] = LONG_MIN,
1396 }
1397 }
1398 }
1399 },
1400 {
1401 .mnemonic = "divdeu.",
1402 .subtests = {
1403 {
1404 .descr = "RA = LONG_MIN, RB = LONG_MIN",
1405 .instr = ppc_inst(PPC_RAW_DIVDEU_DOT(20, 21, 22)),
1406 .flags = IGNORE_GPR(20),
1407 .regs = {
1408 .gpr[21] = LONG_MIN,
1409 .gpr[22] = LONG_MIN,
1410 }
1411 },
1412 {
1413 .descr = "RA = 1L, RB = 0",
1414 .instr = ppc_inst(PPC_RAW_DIVDEU_DOT(20, 21, 22)),
1415 .flags = IGNORE_GPR(20),
1416 .regs = {
1417 .gpr[21] = 1L,
1418 .gpr[22] = 0,
1419 }
1420 },
1421 {
1422 .descr = "RA = LONG_MIN, RB = LONG_MAX",
1423 .instr = ppc_inst(PPC_RAW_DIVDEU_DOT(20, 21, 22)),
1424 .regs = {
1425 .gpr[21] = LONG_MIN,
1426 .gpr[22] = LONG_MAX,
1427 }
1428 },
1429 {
1430 .descr = "RA = LONG_MAX - 1, RB = LONG_MAX",
1431 .instr = ppc_inst(PPC_RAW_DIVDEU_DOT(20, 21, 22)),
1432 .regs = {
1433 .gpr[21] = LONG_MAX - 1,
1434 .gpr[22] = LONG_MAX,
1435 }
1436 },
1437 {
1438 .descr = "RA = LONG_MIN + 1, RB = LONG_MIN",
1439 .instr = ppc_inst(PPC_RAW_DIVDEU_DOT(20, 21, 22)),
1440 .flags = IGNORE_GPR(20),
1441 .regs = {
1442 .gpr[21] = LONG_MIN + 1,
1443 .gpr[22] = LONG_MIN,
1444 }
1445 }
1446 }
1447 },
1448 {
1449 .mnemonic = "paddi",
1450 .cpu_feature = CPU_FTR_ARCH_31,
1451 .subtests = {
1452 {
1453 .descr = "RA = LONG_MIN, SI = SI_MIN, R = 0",
1454 .instr = TEST_PADDI(21, 22, SI_MIN, 0),
1455 .regs = {
1456 .gpr[21] = 0,
1457 .gpr[22] = LONG_MIN,
1458 }
1459 },
1460 {
1461 .descr = "RA = LONG_MIN, SI = SI_MAX, R = 0",
1462 .instr = TEST_PADDI(21, 22, SI_MAX, 0),
1463 .regs = {
1464 .gpr[21] = 0,
1465 .gpr[22] = LONG_MIN,
1466 }
1467 },
1468 {
1469 .descr = "RA = LONG_MAX, SI = SI_MAX, R = 0",
1470 .instr = TEST_PADDI(21, 22, SI_MAX, 0),
1471 .regs = {
1472 .gpr[21] = 0,
1473 .gpr[22] = LONG_MAX,
1474 }
1475 },
1476 {
1477 .descr = "RA = ULONG_MAX, SI = SI_UMAX, R = 0",
1478 .instr = TEST_PADDI(21, 22, SI_UMAX, 0),
1479 .regs = {
1480 .gpr[21] = 0,
1481 .gpr[22] = ULONG_MAX,
1482 }
1483 },
1484 {
1485 .descr = "RA = ULONG_MAX, SI = 0x1, R = 0",
1486 .instr = TEST_PADDI(21, 22, 0x1, 0),
1487 .regs = {
1488 .gpr[21] = 0,
1489 .gpr[22] = ULONG_MAX,
1490 }
1491 },
1492 {
1493 .descr = "RA = INT_MIN, SI = SI_MIN, R = 0",
1494 .instr = TEST_PADDI(21, 22, SI_MIN, 0),
1495 .regs = {
1496 .gpr[21] = 0,
1497 .gpr[22] = INT_MIN,
1498 }
1499 },
1500 {
1501 .descr = "RA = INT_MIN, SI = SI_MAX, R = 0",
1502 .instr = TEST_PADDI(21, 22, SI_MAX, 0),
1503 .regs = {
1504 .gpr[21] = 0,
1505 .gpr[22] = INT_MIN,
1506 }
1507 },
1508 {
1509 .descr = "RA = INT_MAX, SI = SI_MAX, R = 0",
1510 .instr = TEST_PADDI(21, 22, SI_MAX, 0),
1511 .regs = {
1512 .gpr[21] = 0,
1513 .gpr[22] = INT_MAX,
1514 }
1515 },
1516 {
1517 .descr = "RA = UINT_MAX, SI = 0x1, R = 0",
1518 .instr = TEST_PADDI(21, 22, 0x1, 0),
1519 .regs = {
1520 .gpr[21] = 0,
1521 .gpr[22] = UINT_MAX,
1522 }
1523 },
1524 {
1525 .descr = "RA = UINT_MAX, SI = SI_MAX, R = 0",
1526 .instr = TEST_PADDI(21, 22, SI_MAX, 0),
1527 .regs = {
1528 .gpr[21] = 0,
1529 .gpr[22] = UINT_MAX,
1530 }
1531 },
1532 {
1533 .descr = "RA is r0, SI = SI_MIN, R = 0",
1534 .instr = TEST_PADDI(21, 0, SI_MIN, 0),
1535 .regs = {
1536 .gpr[21] = 0x0,
1537 }
1538 },
1539 {
1540 .descr = "RA = 0, SI = SI_MIN, R = 0",
1541 .instr = TEST_PADDI(21, 22, SI_MIN, 0),
1542 .regs = {
1543 .gpr[21] = 0x0,
1544 .gpr[22] = 0x0,
1545 }
1546 },
1547 {
1548 .descr = "RA is r0, SI = 0, R = 1",
1549 .instr = TEST_PADDI(21, 0, 0, 1),
1550 .regs = {
1551 .gpr[21] = 0,
1552 }
1553 },
1554 {
1555 .descr = "RA is r0, SI = SI_MIN, R = 1",
1556 .instr = TEST_PADDI(21, 0, SI_MIN, 1),
1557 .regs = {
1558 .gpr[21] = 0,
1559 }
1560 },
1561 /* Invalid instruction form with R = 1 and RA != 0 */
1562 {
1563 .descr = "RA = R22(0), SI = 0, R = 1",
1564 .instr = TEST_PADDI(21, 22, 0, 1),
1565 .flags = NEGATIVE_TEST,
1566 .regs = {
1567 .gpr[21] = 0,
1568 .gpr[22] = 0,
1569 }
1570 }
1571 }
1572 }
1573};
1574
1575static int __init emulate_compute_instr(struct pt_regs *regs,
1576 struct ppc_inst instr,
1577 bool negative)
1578{
1579 int analysed;
1580 struct instruction_op op;
1581
1582 if (!regs || !ppc_inst_val(instr))
1583 return -EINVAL;
1584
1585 regs->nip = patch_site_addr(&patch__exec_instr);
1586
1587 analysed = analyse_instr(&op, regs, instr);
1588 if (analysed != 1 || GETTYPE(op.type) != COMPUTE) {
1589 if (negative)
1590 return -EFAULT;
1591 pr_info("emulation failed, instruction = %s\n", ppc_inst_as_str(instr));
1592 return -EFAULT;
1593 }
1594 if (analysed == 1 && negative)
1595 pr_info("negative test failed, instruction = %s\n", ppc_inst_as_str(instr));
1596 if (!negative)
1597 emulate_update_regs(regs, &op);
1598 return 0;
1599}
1600
1601static int __init execute_compute_instr(struct pt_regs *regs,
1602 struct ppc_inst instr)
1603{
1604 extern int exec_instr(struct pt_regs *regs);
1605
1606 if (!regs || !ppc_inst_val(instr))
1607 return -EINVAL;
1608
1609 /* Patch the NOP with the actual instruction */
1610 patch_instruction_site(&patch__exec_instr, instr);
1611 if (exec_instr(regs)) {
1612 pr_info("execution failed, instruction = %s\n", ppc_inst_as_str(instr));
1613 return -EFAULT;
1614 }
1615
1616 return 0;
1617}
1618
1619#define gpr_mismatch(gprn, exp, got) \
1620 pr_info("GPR%u mismatch, exp = 0x%016lx, got = 0x%016lx\n", \
1621 gprn, exp, got)
1622
1623#define reg_mismatch(name, exp, got) \
1624 pr_info("%s mismatch, exp = 0x%016lx, got = 0x%016lx\n", \
1625 name, exp, got)
1626
1627static void __init run_tests_compute(void)
1628{
1629 unsigned long flags;
1630 struct compute_test *test;
1631 struct pt_regs *regs, exp, got;
1632 unsigned int i, j, k;
1633 struct ppc_inst instr;
1634 bool ignore_gpr, ignore_xer, ignore_ccr, passed, rc, negative;
1635
1636 for (i = 0; i < ARRAY_SIZE(compute_tests); i++) {
1637 test = &compute_tests[i];
1638
1639 if (test->cpu_feature && !early_cpu_has_feature(test->cpu_feature)) {
1640 show_result(test->mnemonic, "SKIP (!CPU_FTR)");
1641 continue;
1642 }
1643
1644 for (j = 0; j < MAX_SUBTESTS && test->subtests[j].descr; j++) {
1645 instr = test->subtests[j].instr;
1646 flags = test->subtests[j].flags;
1647 regs = &test->subtests[j].regs;
1648 negative = flags & NEGATIVE_TEST;
1649 ignore_xer = flags & IGNORE_XER;
1650 ignore_ccr = flags & IGNORE_CCR;
1651 passed = true;
1652
1653 memcpy(&exp, regs, sizeof(struct pt_regs));
1654 memcpy(&got, regs, sizeof(struct pt_regs));
1655
1656 /*
1657 * Set a compatible MSR value explicitly to ensure
1658 * that XER and CR bits are updated appropriately
1659 */
1660 exp.msr = MSR_KERNEL;
1661 got.msr = MSR_KERNEL;
1662
1663 rc = emulate_compute_instr(&got, instr, negative) != 0;
1664 if (negative) {
1665 /* skip executing instruction */
1666 passed = rc;
1667 goto print;
1668 } else if (rc || execute_compute_instr(&exp, instr)) {
1669 passed = false;
1670 goto print;
1671 }
1672
1673 /* Verify GPR values */
1674 for (k = 0; k < 32; k++) {
1675 ignore_gpr = flags & IGNORE_GPR(k);
1676 if (!ignore_gpr && exp.gpr[k] != got.gpr[k]) {
1677 passed = false;
1678 gpr_mismatch(k, exp.gpr[k], got.gpr[k]);
1679 }
1680 }
1681
1682 /* Verify LR value */
1683 if (exp.link != got.link) {
1684 passed = false;
1685 reg_mismatch("LR", exp.link, got.link);
1686 }
1687
1688 /* Verify XER value */
1689 if (!ignore_xer && exp.xer != got.xer) {
1690 passed = false;
1691 reg_mismatch("XER", exp.xer, got.xer);
1692 }
1693
1694 /* Verify CR value */
1695 if (!ignore_ccr && exp.ccr != got.ccr) {
1696 passed = false;
1697 reg_mismatch("CR", exp.ccr, got.ccr);
1698 }
1699
1700print:
1701 show_result_with_descr(test->mnemonic,
1702 test->subtests[j].descr,
1703 passed ? "PASS" : "FAIL");
1704 }
1705 }
1706}
1707
1708static int __init test_emulate_step(void)
1709{
1710 printk(KERN_INFO "Running instruction emulation self-tests ...\n");
1711 run_tests_load_store();
1712 run_tests_compute();
1713
1714 return 0;
1715}
1716late_initcall(test_emulate_step);