1 // SPDX-License-Identifier: GPL-2.0-or-later
3 * Simple sanity tests for instruction emulation infrastructure.
5 * Copyright IBM Corp. 2016
8 #define pr_fmt(fmt) "emulate_step_test: " fmt
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>
17 #define MAX_SUBTESTS 16
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)
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))
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))
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))
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))
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))
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))
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))
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))
57 static void __init
init_pt_regs(struct pt_regs
*regs
)
59 static unsigned long msr
;
60 static bool msr_cached
;
62 memset(regs
, 0, sizeof(struct pt_regs
));
64 if (likely(msr_cached
)) {
69 asm volatile("mfmsr %0" : "=r"(regs
->msr
));
79 static void __init
show_result(char *mnemonic
, char *result
)
81 pr_info("%-14s : %s\n", mnemonic
, result
);
84 static void __init
show_result_with_descr(char *mnemonic
, char *descr
,
87 pr_info("%-14s : %-50s %s\n", mnemonic
, descr
, result
);
90 static void __init
test_ld(void)
93 unsigned long a
= 0x23;
97 regs
.gpr
[3] = (unsigned long) &a
;
100 stepped
= emulate_step(®s
, ppc_inst(PPC_RAW_LD(5, 3, 0)));
102 if (stepped
== 1 && regs
.gpr
[5] == a
)
103 show_result("ld", "PASS");
105 show_result("ld", "FAIL");
108 static void __init
test_pld(void)
111 unsigned long a
= 0x23;
114 if (!cpu_has_feature(CPU_FTR_ARCH_31
)) {
115 show_result("pld", "SKIP (!CPU_FTR_ARCH_31)");
120 regs
.gpr
[3] = (unsigned long)&a
;
122 /* pld r5, 0(r3), 0 */
123 stepped
= emulate_step(®s
, TEST_PLD(5, 3, 0, 0));
125 if (stepped
== 1 && regs
.gpr
[5] == a
)
126 show_result("pld", "PASS");
128 show_result("pld", "FAIL");
131 static void __init
test_lwz(void)
134 unsigned int a
= 0x4545;
138 regs
.gpr
[3] = (unsigned long) &a
;
141 stepped
= emulate_step(®s
, ppc_inst(PPC_RAW_LWZ(5, 3, 0)));
143 if (stepped
== 1 && regs
.gpr
[5] == a
)
144 show_result("lwz", "PASS");
146 show_result("lwz", "FAIL");
149 static void __init
test_plwz(void)
152 unsigned int a
= 0x4545;
155 if (!cpu_has_feature(CPU_FTR_ARCH_31
)) {
156 show_result("plwz", "SKIP (!CPU_FTR_ARCH_31)");
161 regs
.gpr
[3] = (unsigned long)&a
;
163 /* plwz r5, 0(r3), 0 */
165 stepped
= emulate_step(®s
, TEST_PLWZ(5, 3, 0, 0));
167 if (stepped
== 1 && regs
.gpr
[5] == a
)
168 show_result("plwz", "PASS");
170 show_result("plwz", "FAIL");
173 static void __init
test_lwzx(void)
176 unsigned int a
[3] = {0x0, 0x0, 0x1234};
180 regs
.gpr
[3] = (unsigned long) a
;
182 regs
.gpr
[5] = 0x8765;
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");
189 show_result("lwzx", "FAIL");
192 static void __init
test_std(void)
195 unsigned long a
= 0x1234;
199 regs
.gpr
[3] = (unsigned long) &a
;
200 regs
.gpr
[5] = 0x5678;
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");
207 show_result("std", "FAIL");
210 static void __init
test_pstd(void)
213 unsigned long a
= 0x1234;
216 if (!cpu_has_feature(CPU_FTR_ARCH_31
)) {
217 show_result("pstd", "SKIP (!CPU_FTR_ARCH_31)");
222 regs
.gpr
[3] = (unsigned long)&a
;
223 regs
.gpr
[5] = 0x5678;
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");
230 show_result("pstd", "FAIL");
233 static void __init
test_ldarx_stdcx(void)
236 unsigned long a
= 0x1234;
238 unsigned long cr0_eq
= 0x1 << 29; /* eq bit of CR0 */
241 asm volatile("mfcr %0" : "=r"(regs
.ccr
));
246 regs
.gpr
[3] = (unsigned long) &a
;
248 regs
.gpr
[5] = 0x5678;
250 /* ldarx r5, r3, r4, 0 */
251 stepped
= emulate_step(®s
, ppc_inst(PPC_RAW_LDARX(5, 3, 4, 0)));
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.
258 if (stepped
<= 0 || regs
.gpr
[5] != 0x1234) {
259 show_result("ldarx / stdcx.", "FAIL (ldarx)");
266 regs
.gpr
[5] = 0x9ABC;
268 /* stdcx. r5, r3, r4 */
269 stepped
= emulate_step(®s
, ppc_inst(PPC_RAW_STDCX(5, 3, 4)));
272 * Two possible scenarios that indicates successful emulation
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.
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");
283 show_result("ldarx / stdcx.", "FAIL (stdcx.)");
286 #ifdef CONFIG_PPC_FPU
287 static void __init
test_lfsx_stfsx(void)
305 regs
.gpr
[3] = (unsigned long) &c
.a
;
308 /* lfsx frt10, r3, r4 */
309 stepped
= emulate_step(®s
, ppc_inst(PPC_RAW_LFSX(10, 3, 4)));
312 show_result("lfsx", "PASS");
314 show_result("lfsx", "FAIL");
321 /* stfsx frs10, r3, r4 */
322 stepped
= emulate_step(®s
, ppc_inst(PPC_RAW_STFSX(10, 3, 4)));
324 if (stepped
== 1 && c
.b
== cached_b
)
325 show_result("stfsx", "PASS");
327 show_result("stfsx", "FAIL");
330 static void __init
test_plfs_pstfs(void)
340 if (!cpu_has_feature(CPU_FTR_ARCH_31
)) {
341 show_result("pld", "SKIP (!CPU_FTR_ARCH_31)");
353 regs
.gpr
[3] = (unsigned long)&c
.a
;
355 /* plfs frt10, 0(r3), 0 */
356 stepped
= emulate_step(®s
, TEST_PLFS(10, 3, 0, 0));
359 show_result("plfs", "PASS");
361 show_result("plfs", "FAIL");
368 /* pstfs frs10, 0(r3), 0 */
369 stepped
= emulate_step(®s
, TEST_PSTFS(10, 3, 0, 0));
371 if (stepped
== 1 && c
.b
== cached_b
)
372 show_result("pstfs", "PASS");
374 show_result("pstfs", "FAIL");
377 static void __init
test_lfdx_stfdx(void)
395 regs
.gpr
[3] = (unsigned long) &c
.a
;
398 /* lfdx frt10, r3, r4 */
399 stepped
= emulate_step(®s
, ppc_inst(PPC_RAW_LFDX(10, 3, 4)));
402 show_result("lfdx", "PASS");
404 show_result("lfdx", "FAIL");
411 /* stfdx frs10, r3, r4 */
412 stepped
= emulate_step(®s
, ppc_inst(PPC_RAW_STFDX(10, 3, 4)));
414 if (stepped
== 1 && c
.b
== cached_b
)
415 show_result("stfdx", "PASS");
417 show_result("stfdx", "FAIL");
420 static void __init
test_plfd_pstfd(void)
430 if (!cpu_has_feature(CPU_FTR_ARCH_31
)) {
431 show_result("pld", "SKIP (!CPU_FTR_ARCH_31)");
443 regs
.gpr
[3] = (unsigned long)&c
.a
;
445 /* plfd frt10, 0(r3), 0 */
446 stepped
= emulate_step(®s
, TEST_PLFD(10, 3, 0, 0));
449 show_result("plfd", "PASS");
451 show_result("plfd", "FAIL");
458 /* pstfd frs10, 0(r3), 0 */
459 stepped
= emulate_step(®s
, TEST_PSTFD(10, 3, 0, 0));
461 if (stepped
== 1 && c
.b
== cached_b
)
462 show_result("pstfd", "PASS");
464 show_result("pstfd", "FAIL");
467 static void __init
test_lfsx_stfsx(void)
469 show_result("lfsx", "SKIP (CONFIG_PPC_FPU is not set)");
470 show_result("stfsx", "SKIP (CONFIG_PPC_FPU is not set)");
473 static void __init
test_plfs_pstfs(void)
475 show_result("plfs", "SKIP (CONFIG_PPC_FPU is not set)");
476 show_result("pstfs", "SKIP (CONFIG_PPC_FPU is not set)");
479 static void __init
test_lfdx_stfdx(void)
481 show_result("lfdx", "SKIP (CONFIG_PPC_FPU is not set)");
482 show_result("stfdx", "SKIP (CONFIG_PPC_FPU is not set)");
485 static void __init
test_plfd_pstfd(void)
487 show_result("plfd", "SKIP (CONFIG_PPC_FPU is not set)");
488 show_result("pstfd", "SKIP (CONFIG_PPC_FPU is not set)");
490 #endif /* CONFIG_PPC_FPU */
492 #ifdef CONFIG_ALTIVEC
493 static void __init
test_lvx_stvx(void)
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;
513 regs
.gpr
[3] = (unsigned long) &c
.a
;
516 /* lvx vrt10, r3, r4 */
517 stepped
= emulate_step(®s
, ppc_inst(PPC_RAW_LVX(10, 3, 4)));
520 show_result("lvx", "PASS");
522 show_result("lvx", "FAIL");
532 /* stvx vrs10, r3, r4 */
533 stepped
= emulate_step(®s
, ppc_inst(PPC_RAW_STVX(10, 3, 4)));
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");
539 show_result("stvx", "FAIL");
542 static void __init
test_lvx_stvx(void)
544 show_result("lvx", "SKIP (CONFIG_ALTIVEC is not set)");
545 show_result("stvx", "SKIP (CONFIG_ALTIVEC is not set)");
547 #endif /* CONFIG_ALTIVEC */
550 static void __init
test_lxvd2x_stxvd2x(void)
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;
570 regs
.gpr
[3] = (unsigned long) &c
.a
;
573 /* lxvd2x vsr39, r3, r4 */
574 stepped
= emulate_step(®s
, ppc_inst(PPC_RAW_LXVD2X(39, R3
, R4
)));
576 if (stepped
== 1 && cpu_has_feature(CPU_FTR_VSX
)) {
577 show_result("lxvd2x", "PASS");
579 if (!cpu_has_feature(CPU_FTR_VSX
))
580 show_result("lxvd2x", "PASS (!CPU_FTR_VSX)");
582 show_result("lxvd2x", "FAIL");
593 /* stxvd2x vsr39, r3, r4 */
594 stepped
= emulate_step(®s
, ppc_inst(PPC_RAW_STXVD2X(39, R3
, R4
)));
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");
601 if (!cpu_has_feature(CPU_FTR_VSX
))
602 show_result("stxvd2x", "PASS (!CPU_FTR_VSX)");
604 show_result("stxvd2x", "FAIL");
608 static void __init
test_lxvd2x_stxvd2x(void)
610 show_result("lxvd2x", "SKIP (CONFIG_VSX is not set)");
611 show_result("stxvd2x", "SKIP (CONFIG_VSX is not set)");
613 #endif /* CONFIG_VSX */
616 static void __init
test_lxvp_stxvp(void)
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)");
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;
645 regs
.gpr
[4] = (unsigned long)&c
[0].a
;
650 * let TX=1 Tp=1 RA=4 DQ=0
652 stepped
= emulate_step(®s
, ppc_inst(PPC_RAW_LXVP(34, 4, 0)));
654 if (stepped
== 1 && cpu_has_feature(CPU_FTR_VSX
)) {
655 show_result("lxvp", "PASS");
657 if (!cpu_has_feature(CPU_FTR_VSX
))
658 show_result("lxvp", "PASS (!CPU_FTR_VSX)");
660 show_result("lxvp", "FAIL");
665 c
[0].b
[0] = 21379463;
677 * let SX=1 Sp=1 RA=4 DQ=0
679 stepped
= emulate_step(®s
, ppc_inst(PPC_RAW_STXVP(34, 4, 0)));
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");
688 if (!cpu_has_feature(CPU_FTR_VSX
))
689 show_result("stxvp", "PASS (!CPU_FTR_VSX)");
691 show_result("stxvp", "FAIL");
695 static void __init
test_lxvp_stxvp(void)
697 show_result("lxvp", "SKIP (CONFIG_VSX is not set)");
698 show_result("stxvp", "SKIP (CONFIG_VSX is not set)");
700 #endif /* CONFIG_VSX */
703 static void __init
test_lxvpx_stxvpx(void)
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)");
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;
732 regs
.gpr
[3] = (unsigned long)&c
[0].a
;
738 * let TX=1 Tp=1 RA=3 RB=4
740 stepped
= emulate_step(®s
, ppc_inst(PPC_RAW_LXVPX(34, 3, 4)));
742 if (stepped
== 1 && cpu_has_feature(CPU_FTR_VSX
)) {
743 show_result("lxvpx", "PASS");
745 if (!cpu_has_feature(CPU_FTR_VSX
))
746 show_result("lxvpx", "PASS (!CPU_FTR_VSX)");
748 show_result("lxvpx", "FAIL");
753 c
[0].b
[0] = 21379463;
765 * let SX=1 Sp=1 RA=3 RB=4
767 stepped
= emulate_step(®s
, ppc_inst(PPC_RAW_STXVPX(34, 3, 4)));
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");
776 if (!cpu_has_feature(CPU_FTR_VSX
))
777 show_result("stxvpx", "PASS (!CPU_FTR_VSX)");
779 show_result("stxvpx", "FAIL");
783 static void __init
test_lxvpx_stxvpx(void)
785 show_result("lxvpx", "SKIP (CONFIG_VSX is not set)");
786 show_result("stxvpx", "SKIP (CONFIG_VSX is not set)");
788 #endif /* CONFIG_VSX */
791 static void __init
test_plxvp_pstxvp(void)
793 struct ppc_inst instr
;
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)");
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;
820 regs
.gpr
[3] = (unsigned long)&c
[0].a
;
825 * let RA=3 R=0 D=d0||d1=0 R=0 Tp=1 TX=1
827 instr
= ppc_inst_prefix(PPC_RAW_PLXVP(34, 0, 3, 0) >> 32,
828 PPC_RAW_PLXVP(34, 0, 3, 0) & 0xffffffff);
830 stepped
= emulate_step(®s
, instr
);
831 if (stepped
== 1 && cpu_has_feature(CPU_FTR_VSX
)) {
832 show_result("plxvp", "PASS");
834 if (!cpu_has_feature(CPU_FTR_VSX
))
835 show_result("plxvp", "PASS (!CPU_FTR_VSX)");
837 show_result("plxvp", "FAIL");
842 c
[0].b
[0] = 21379463;
854 * let RA=3 D=d0||d1=0 R=0 Sp=1 SX=1
856 instr
= ppc_inst_prefix(PPC_RAW_PSTXVP(34, 0, 3, 0) >> 32,
857 PPC_RAW_PSTXVP(34, 0, 3, 0) & 0xffffffff);
859 stepped
= emulate_step(®s
, instr
);
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");
868 if (!cpu_has_feature(CPU_FTR_VSX
))
869 show_result("pstxvp", "PASS (!CPU_FTR_VSX)");
871 show_result("pstxvp", "FAIL");
875 static void __init
test_plxvp_pstxvp(void)
877 show_result("plxvp", "SKIP (CONFIG_VSX is not set)");
878 show_result("pstxvp", "SKIP (CONFIG_VSX is not set)");
880 #endif /* CONFIG_VSX */
882 static void __init
run_tests_load_store(void)
897 test_lxvd2x_stxvd2x();
903 struct compute_test
{
905 unsigned long cpu_feature
;
909 struct ppc_inst instr
;
911 } subtests
[MAX_SUBTESTS
+ 1];
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)
919 static struct compute_test compute_tests
[] = {
924 .descr
= "R0 = LONG_MAX",
925 .instr
= ppc_inst(PPC_INST_NOP
),
936 .descr
= "RA = LONG_MIN, RB = LONG_MIN",
937 .instr
= ppc_inst(PPC_RAW_ADD(20, 21, 22)),
944 .descr
= "RA = LONG_MIN, RB = LONG_MAX",
945 .instr
= ppc_inst(PPC_RAW_ADD(20, 21, 22)),
952 .descr
= "RA = LONG_MAX, RB = LONG_MAX",
953 .instr
= ppc_inst(PPC_RAW_ADD(20, 21, 22)),
960 .descr
= "RA = ULONG_MAX, RB = ULONG_MAX",
961 .instr
= ppc_inst(PPC_RAW_ADD(20, 21, 22)),
963 .gpr
[21] = ULONG_MAX
,
964 .gpr
[22] = ULONG_MAX
,
968 .descr
= "RA = ULONG_MAX, RB = 0x1",
969 .instr
= ppc_inst(PPC_RAW_ADD(20, 21, 22)),
971 .gpr
[21] = ULONG_MAX
,
976 .descr
= "RA = INT_MIN, RB = INT_MIN",
977 .instr
= ppc_inst(PPC_RAW_ADD(20, 21, 22)),
984 .descr
= "RA = INT_MIN, RB = INT_MAX",
985 .instr
= ppc_inst(PPC_RAW_ADD(20, 21, 22)),
992 .descr
= "RA = INT_MAX, RB = INT_MAX",
993 .instr
= ppc_inst(PPC_RAW_ADD(20, 21, 22)),
1000 .descr
= "RA = UINT_MAX, RB = UINT_MAX",
1001 .instr
= ppc_inst(PPC_RAW_ADD(20, 21, 22)),
1003 .gpr
[21] = UINT_MAX
,
1004 .gpr
[22] = UINT_MAX
,
1008 .descr
= "RA = UINT_MAX, RB = 0x1",
1009 .instr
= ppc_inst(PPC_RAW_ADD(20, 21, 22)),
1011 .gpr
[21] = UINT_MAX
,
1021 .descr
= "RA = LONG_MIN, RB = LONG_MIN",
1022 .flags
= IGNORE_CCR
,
1023 .instr
= ppc_inst(PPC_RAW_ADD_DOT(20, 21, 22)),
1025 .gpr
[21] = LONG_MIN
,
1026 .gpr
[22] = LONG_MIN
,
1030 .descr
= "RA = LONG_MIN, RB = LONG_MAX",
1031 .instr
= ppc_inst(PPC_RAW_ADD_DOT(20, 21, 22)),
1033 .gpr
[21] = LONG_MIN
,
1034 .gpr
[22] = LONG_MAX
,
1038 .descr
= "RA = LONG_MAX, RB = LONG_MAX",
1039 .flags
= IGNORE_CCR
,
1040 .instr
= ppc_inst(PPC_RAW_ADD_DOT(20, 21, 22)),
1042 .gpr
[21] = LONG_MAX
,
1043 .gpr
[22] = LONG_MAX
,
1047 .descr
= "RA = ULONG_MAX, RB = ULONG_MAX",
1048 .instr
= ppc_inst(PPC_RAW_ADD_DOT(20, 21, 22)),
1050 .gpr
[21] = ULONG_MAX
,
1051 .gpr
[22] = ULONG_MAX
,
1055 .descr
= "RA = ULONG_MAX, RB = 0x1",
1056 .instr
= ppc_inst(PPC_RAW_ADD_DOT(20, 21, 22)),
1058 .gpr
[21] = ULONG_MAX
,
1063 .descr
= "RA = INT_MIN, RB = INT_MIN",
1064 .instr
= ppc_inst(PPC_RAW_ADD_DOT(20, 21, 22)),
1071 .descr
= "RA = INT_MIN, RB = INT_MAX",
1072 .instr
= ppc_inst(PPC_RAW_ADD_DOT(20, 21, 22)),
1079 .descr
= "RA = INT_MAX, RB = INT_MAX",
1080 .instr
= ppc_inst(PPC_RAW_ADD_DOT(20, 21, 22)),
1087 .descr
= "RA = UINT_MAX, RB = UINT_MAX",
1088 .instr
= ppc_inst(PPC_RAW_ADD_DOT(20, 21, 22)),
1090 .gpr
[21] = UINT_MAX
,
1091 .gpr
[22] = UINT_MAX
,
1095 .descr
= "RA = UINT_MAX, RB = 0x1",
1096 .instr
= ppc_inst(PPC_RAW_ADD_DOT(20, 21, 22)),
1098 .gpr
[21] = UINT_MAX
,
1108 .descr
= "RA = LONG_MIN, RB = LONG_MIN",
1109 .instr
= ppc_inst(PPC_RAW_ADDC(20, 21, 22)),
1111 .gpr
[21] = LONG_MIN
,
1112 .gpr
[22] = LONG_MIN
,
1116 .descr
= "RA = LONG_MIN, RB = LONG_MAX",
1117 .instr
= ppc_inst(PPC_RAW_ADDC(20, 21, 22)),
1119 .gpr
[21] = LONG_MIN
,
1120 .gpr
[22] = LONG_MAX
,
1124 .descr
= "RA = LONG_MAX, RB = LONG_MAX",
1125 .instr
= ppc_inst(PPC_RAW_ADDC(20, 21, 22)),
1127 .gpr
[21] = LONG_MAX
,
1128 .gpr
[22] = LONG_MAX
,
1132 .descr
= "RA = ULONG_MAX, RB = ULONG_MAX",
1133 .instr
= ppc_inst(PPC_RAW_ADDC(20, 21, 22)),
1135 .gpr
[21] = ULONG_MAX
,
1136 .gpr
[22] = ULONG_MAX
,
1140 .descr
= "RA = ULONG_MAX, RB = 0x1",
1141 .instr
= ppc_inst(PPC_RAW_ADDC(20, 21, 22)),
1143 .gpr
[21] = ULONG_MAX
,
1148 .descr
= "RA = INT_MIN, RB = INT_MIN",
1149 .instr
= ppc_inst(PPC_RAW_ADDC(20, 21, 22)),
1156 .descr
= "RA = INT_MIN, RB = INT_MAX",
1157 .instr
= ppc_inst(PPC_RAW_ADDC(20, 21, 22)),
1164 .descr
= "RA = INT_MAX, RB = INT_MAX",
1165 .instr
= ppc_inst(PPC_RAW_ADDC(20, 21, 22)),
1172 .descr
= "RA = UINT_MAX, RB = UINT_MAX",
1173 .instr
= ppc_inst(PPC_RAW_ADDC(20, 21, 22)),
1175 .gpr
[21] = UINT_MAX
,
1176 .gpr
[22] = UINT_MAX
,
1180 .descr
= "RA = UINT_MAX, RB = 0x1",
1181 .instr
= ppc_inst(PPC_RAW_ADDC(20, 21, 22)),
1183 .gpr
[21] = UINT_MAX
,
1188 .descr
= "RA = LONG_MIN | INT_MIN, RB = LONG_MIN | INT_MIN",
1189 .instr
= ppc_inst(PPC_RAW_ADDC(20, 21, 22)),
1191 .gpr
[21] = LONG_MIN
| (uint
)INT_MIN
,
1192 .gpr
[22] = LONG_MIN
| (uint
)INT_MIN
,
1198 .mnemonic
= "addc.",
1201 .descr
= "RA = LONG_MIN, RB = LONG_MIN",
1202 .flags
= IGNORE_CCR
,
1203 .instr
= ppc_inst(PPC_RAW_ADDC_DOT(20, 21, 22)),
1205 .gpr
[21] = LONG_MIN
,
1206 .gpr
[22] = LONG_MIN
,
1210 .descr
= "RA = LONG_MIN, RB = LONG_MAX",
1211 .instr
= ppc_inst(PPC_RAW_ADDC_DOT(20, 21, 22)),
1213 .gpr
[21] = LONG_MIN
,
1214 .gpr
[22] = LONG_MAX
,
1218 .descr
= "RA = LONG_MAX, RB = LONG_MAX",
1219 .flags
= IGNORE_CCR
,
1220 .instr
= ppc_inst(PPC_RAW_ADDC_DOT(20, 21, 22)),
1222 .gpr
[21] = LONG_MAX
,
1223 .gpr
[22] = LONG_MAX
,
1227 .descr
= "RA = ULONG_MAX, RB = ULONG_MAX",
1228 .instr
= ppc_inst(PPC_RAW_ADDC_DOT(20, 21, 22)),
1230 .gpr
[21] = ULONG_MAX
,
1231 .gpr
[22] = ULONG_MAX
,
1235 .descr
= "RA = ULONG_MAX, RB = 0x1",
1236 .instr
= ppc_inst(PPC_RAW_ADDC_DOT(20, 21, 22)),
1238 .gpr
[21] = ULONG_MAX
,
1243 .descr
= "RA = INT_MIN, RB = INT_MIN",
1244 .instr
= ppc_inst(PPC_RAW_ADDC_DOT(20, 21, 22)),
1251 .descr
= "RA = INT_MIN, RB = INT_MAX",
1252 .instr
= ppc_inst(PPC_RAW_ADDC_DOT(20, 21, 22)),
1259 .descr
= "RA = INT_MAX, RB = INT_MAX",
1260 .instr
= ppc_inst(PPC_RAW_ADDC_DOT(20, 21, 22)),
1267 .descr
= "RA = UINT_MAX, RB = UINT_MAX",
1268 .instr
= ppc_inst(PPC_RAW_ADDC_DOT(20, 21, 22)),
1270 .gpr
[21] = UINT_MAX
,
1271 .gpr
[22] = UINT_MAX
,
1275 .descr
= "RA = UINT_MAX, RB = 0x1",
1276 .instr
= ppc_inst(PPC_RAW_ADDC_DOT(20, 21, 22)),
1278 .gpr
[21] = UINT_MAX
,
1283 .descr
= "RA = LONG_MIN | INT_MIN, RB = LONG_MIN | INT_MIN",
1284 .instr
= ppc_inst(PPC_RAW_ADDC_DOT(20, 21, 22)),
1286 .gpr
[21] = LONG_MIN
| (uint
)INT_MIN
,
1287 .gpr
[22] = LONG_MIN
| (uint
)INT_MIN
,
1293 .mnemonic
= "divde",
1296 .descr
= "RA = LONG_MIN, RB = LONG_MIN",
1297 .instr
= ppc_inst(PPC_RAW_DIVDE(20, 21, 22)),
1299 .gpr
[21] = LONG_MIN
,
1300 .gpr
[22] = LONG_MIN
,
1304 .descr
= "RA = 1L, RB = 0",
1305 .instr
= ppc_inst(PPC_RAW_DIVDE(20, 21, 22)),
1306 .flags
= IGNORE_GPR(20),
1313 .descr
= "RA = LONG_MIN, RB = LONG_MAX",
1314 .instr
= ppc_inst(PPC_RAW_DIVDE(20, 21, 22)),
1316 .gpr
[21] = LONG_MIN
,
1317 .gpr
[22] = LONG_MAX
,
1323 .mnemonic
= "divde.",
1326 .descr
= "RA = LONG_MIN, RB = LONG_MIN",
1327 .instr
= ppc_inst(PPC_RAW_DIVDE_DOT(20, 21, 22)),
1329 .gpr
[21] = LONG_MIN
,
1330 .gpr
[22] = LONG_MIN
,
1334 .descr
= "RA = 1L, RB = 0",
1335 .instr
= ppc_inst(PPC_RAW_DIVDE_DOT(20, 21, 22)),
1336 .flags
= IGNORE_GPR(20),
1343 .descr
= "RA = LONG_MIN, RB = LONG_MAX",
1344 .instr
= ppc_inst(PPC_RAW_DIVDE_DOT(20, 21, 22)),
1346 .gpr
[21] = LONG_MIN
,
1347 .gpr
[22] = LONG_MAX
,
1353 .mnemonic
= "divdeu",
1356 .descr
= "RA = LONG_MIN, RB = LONG_MIN",
1357 .instr
= ppc_inst(PPC_RAW_DIVDEU(20, 21, 22)),
1358 .flags
= IGNORE_GPR(20),
1360 .gpr
[21] = LONG_MIN
,
1361 .gpr
[22] = LONG_MIN
,
1365 .descr
= "RA = 1L, RB = 0",
1366 .instr
= ppc_inst(PPC_RAW_DIVDEU(20, 21, 22)),
1367 .flags
= IGNORE_GPR(20),
1374 .descr
= "RA = LONG_MIN, RB = LONG_MAX",
1375 .instr
= ppc_inst(PPC_RAW_DIVDEU(20, 21, 22)),
1377 .gpr
[21] = LONG_MIN
,
1378 .gpr
[22] = LONG_MAX
,
1382 .descr
= "RA = LONG_MAX - 1, RB = LONG_MAX",
1383 .instr
= ppc_inst(PPC_RAW_DIVDEU(20, 21, 22)),
1385 .gpr
[21] = LONG_MAX
- 1,
1386 .gpr
[22] = LONG_MAX
,
1390 .descr
= "RA = LONG_MIN + 1, RB = LONG_MIN",
1391 .instr
= ppc_inst(PPC_RAW_DIVDEU(20, 21, 22)),
1392 .flags
= IGNORE_GPR(20),
1394 .gpr
[21] = LONG_MIN
+ 1,
1395 .gpr
[22] = LONG_MIN
,
1401 .mnemonic
= "divdeu.",
1404 .descr
= "RA = LONG_MIN, RB = LONG_MIN",
1405 .instr
= ppc_inst(PPC_RAW_DIVDEU_DOT(20, 21, 22)),
1406 .flags
= IGNORE_GPR(20),
1408 .gpr
[21] = LONG_MIN
,
1409 .gpr
[22] = LONG_MIN
,
1413 .descr
= "RA = 1L, RB = 0",
1414 .instr
= ppc_inst(PPC_RAW_DIVDEU_DOT(20, 21, 22)),
1415 .flags
= IGNORE_GPR(20),
1422 .descr
= "RA = LONG_MIN, RB = LONG_MAX",
1423 .instr
= ppc_inst(PPC_RAW_DIVDEU_DOT(20, 21, 22)),
1425 .gpr
[21] = LONG_MIN
,
1426 .gpr
[22] = LONG_MAX
,
1430 .descr
= "RA = LONG_MAX - 1, RB = LONG_MAX",
1431 .instr
= ppc_inst(PPC_RAW_DIVDEU_DOT(20, 21, 22)),
1433 .gpr
[21] = LONG_MAX
- 1,
1434 .gpr
[22] = LONG_MAX
,
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),
1442 .gpr
[21] = LONG_MIN
+ 1,
1443 .gpr
[22] = LONG_MIN
,
1449 .mnemonic
= "paddi",
1450 .cpu_feature
= CPU_FTR_ARCH_31
,
1453 .descr
= "RA = LONG_MIN, SI = SI_MIN, R = 0",
1454 .instr
= TEST_PADDI(21, 22, SI_MIN
, 0),
1457 .gpr
[22] = LONG_MIN
,
1461 .descr
= "RA = LONG_MIN, SI = SI_MAX, R = 0",
1462 .instr
= TEST_PADDI(21, 22, SI_MAX
, 0),
1465 .gpr
[22] = LONG_MIN
,
1469 .descr
= "RA = LONG_MAX, SI = SI_MAX, R = 0",
1470 .instr
= TEST_PADDI(21, 22, SI_MAX
, 0),
1473 .gpr
[22] = LONG_MAX
,
1477 .descr
= "RA = ULONG_MAX, SI = SI_UMAX, R = 0",
1478 .instr
= TEST_PADDI(21, 22, SI_UMAX
, 0),
1481 .gpr
[22] = ULONG_MAX
,
1485 .descr
= "RA = ULONG_MAX, SI = 0x1, R = 0",
1486 .instr
= TEST_PADDI(21, 22, 0x1, 0),
1489 .gpr
[22] = ULONG_MAX
,
1493 .descr
= "RA = INT_MIN, SI = SI_MIN, R = 0",
1494 .instr
= TEST_PADDI(21, 22, SI_MIN
, 0),
1501 .descr
= "RA = INT_MIN, SI = SI_MAX, R = 0",
1502 .instr
= TEST_PADDI(21, 22, SI_MAX
, 0),
1509 .descr
= "RA = INT_MAX, SI = SI_MAX, R = 0",
1510 .instr
= TEST_PADDI(21, 22, SI_MAX
, 0),
1517 .descr
= "RA = UINT_MAX, SI = 0x1, R = 0",
1518 .instr
= TEST_PADDI(21, 22, 0x1, 0),
1521 .gpr
[22] = UINT_MAX
,
1525 .descr
= "RA = UINT_MAX, SI = SI_MAX, R = 0",
1526 .instr
= TEST_PADDI(21, 22, SI_MAX
, 0),
1529 .gpr
[22] = UINT_MAX
,
1533 .descr
= "RA is r0, SI = SI_MIN, R = 0",
1534 .instr
= TEST_PADDI(21, 0, SI_MIN
, 0),
1540 .descr
= "RA = 0, SI = SI_MIN, R = 0",
1541 .instr
= TEST_PADDI(21, 22, SI_MIN
, 0),
1548 .descr
= "RA is r0, SI = 0, R = 1",
1549 .instr
= TEST_PADDI(21, 0, 0, 1),
1555 .descr
= "RA is r0, SI = SI_MIN, R = 1",
1556 .instr
= TEST_PADDI(21, 0, SI_MIN
, 1),
1561 /* Invalid instruction form with R = 1 and RA != 0 */
1563 .descr
= "RA = R22(0), SI = 0, R = 1",
1564 .instr
= TEST_PADDI(21, 22, 0, 1),
1565 .flags
= NEGATIVE_TEST
,
1575 static int __init
emulate_compute_instr(struct pt_regs
*regs
,
1576 struct ppc_inst instr
,
1580 struct instruction_op op
;
1582 if (!regs
|| !ppc_inst_val(instr
))
1585 regs
->nip
= patch_site_addr(&patch__exec_instr
);
1587 analysed
= analyse_instr(&op
, regs
, instr
);
1588 if (analysed
!= 1 || GETTYPE(op
.type
) != COMPUTE
) {
1591 pr_info("emulation failed, instruction = %s\n", ppc_inst_as_str(instr
));
1594 if (analysed
== 1 && negative
)
1595 pr_info("negative test failed, instruction = %s\n", ppc_inst_as_str(instr
));
1597 emulate_update_regs(regs
, &op
);
1601 static int __init
execute_compute_instr(struct pt_regs
*regs
,
1602 struct ppc_inst instr
)
1604 extern int exec_instr(struct pt_regs
*regs
);
1606 if (!regs
|| !ppc_inst_val(instr
))
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
));
1619 #define gpr_mismatch(gprn, exp, got) \
1620 pr_info("GPR%u mismatch, exp = 0x%016lx, got = 0x%016lx\n", \
1623 #define reg_mismatch(name, exp, got) \
1624 pr_info("%s mismatch, exp = 0x%016lx, got = 0x%016lx\n", \
1627 static void __init
run_tests_compute(void)
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
;
1636 for (i
= 0; i
< ARRAY_SIZE(compute_tests
); i
++) {
1637 test
= &compute_tests
[i
];
1639 if (test
->cpu_feature
&& !early_cpu_has_feature(test
->cpu_feature
)) {
1640 show_result(test
->mnemonic
, "SKIP (!CPU_FTR)");
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
;
1653 memcpy(&exp
, regs
, sizeof(struct pt_regs
));
1654 memcpy(&got
, regs
, sizeof(struct pt_regs
));
1657 * Set a compatible MSR value explicitly to ensure
1658 * that XER and CR bits are updated appropriately
1660 exp
.msr
= MSR_KERNEL
;
1661 got
.msr
= MSR_KERNEL
;
1663 rc
= emulate_compute_instr(&got
, instr
, negative
) != 0;
1665 /* skip executing instruction */
1668 } else if (rc
|| execute_compute_instr(&exp
, instr
)) {
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
]) {
1678 gpr_mismatch(k
, exp
.gpr
[k
], got
.gpr
[k
]);
1682 /* Verify LR value */
1683 if (exp
.link
!= got
.link
) {
1685 reg_mismatch("LR", exp
.link
, got
.link
);
1688 /* Verify XER value */
1689 if (!ignore_xer
&& exp
.xer
!= got
.xer
) {
1691 reg_mismatch("XER", exp
.xer
, got
.xer
);
1694 /* Verify CR value */
1695 if (!ignore_ccr
&& exp
.ccr
!= got
.ccr
) {
1697 reg_mismatch("CR", exp
.ccr
, got
.ccr
);
1701 show_result_with_descr(test
->mnemonic
,
1702 test
->subtests
[j
].descr
,
1703 passed
? "PASS" : "FAIL");
1708 static int __init
test_emulate_step(void)
1710 printk(KERN_INFO
"Running instruction emulation self-tests ...\n");
1711 run_tests_load_store();
1712 run_tests_compute();
1716 late_initcall(test_emulate_step
);