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/text-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))
56 static void __init
init_pt_regs(struct pt_regs
*regs
)
58 static unsigned long msr
;
59 static bool msr_cached
;
61 memset(regs
, 0, sizeof(struct pt_regs
));
63 if (likely(msr_cached
)) {
68 asm volatile("mfmsr %0" : "=r"(regs
->msr
));
78 static void __init
show_result(char *mnemonic
, char *result
)
80 pr_info("%-14s : %s\n", mnemonic
, result
);
83 static void __init
show_result_with_descr(char *mnemonic
, char *descr
,
86 pr_info("%-14s : %-50s %s\n", mnemonic
, descr
, result
);
89 static void __init
test_ld(void)
92 unsigned long a
= 0x23;
96 regs
.gpr
[3] = (unsigned long) &a
;
99 stepped
= emulate_step(®s
, ppc_inst(PPC_RAW_LD(5, 3, 0)));
101 if (stepped
== 1 && regs
.gpr
[5] == a
)
102 show_result("ld", "PASS");
104 show_result("ld", "FAIL");
107 static void __init
test_pld(void)
110 unsigned long a
= 0x23;
113 if (!cpu_has_feature(CPU_FTR_ARCH_31
)) {
114 show_result("pld", "SKIP (!CPU_FTR_ARCH_31)");
119 regs
.gpr
[3] = (unsigned long)&a
;
121 /* pld r5, 0(r3), 0 */
122 stepped
= emulate_step(®s
, TEST_PLD(5, 3, 0, 0));
124 if (stepped
== 1 && regs
.gpr
[5] == a
)
125 show_result("pld", "PASS");
127 show_result("pld", "FAIL");
130 static void __init
test_lwz(void)
133 unsigned int a
= 0x4545;
137 regs
.gpr
[3] = (unsigned long) &a
;
140 stepped
= emulate_step(®s
, ppc_inst(PPC_RAW_LWZ(5, 3, 0)));
142 if (stepped
== 1 && regs
.gpr
[5] == a
)
143 show_result("lwz", "PASS");
145 show_result("lwz", "FAIL");
148 static void __init
test_plwz(void)
151 unsigned int a
= 0x4545;
154 if (!cpu_has_feature(CPU_FTR_ARCH_31
)) {
155 show_result("plwz", "SKIP (!CPU_FTR_ARCH_31)");
160 regs
.gpr
[3] = (unsigned long)&a
;
162 /* plwz r5, 0(r3), 0 */
164 stepped
= emulate_step(®s
, TEST_PLWZ(5, 3, 0, 0));
166 if (stepped
== 1 && regs
.gpr
[5] == a
)
167 show_result("plwz", "PASS");
169 show_result("plwz", "FAIL");
172 static void __init
test_lwzx(void)
175 unsigned int a
[3] = {0x0, 0x0, 0x1234};
179 regs
.gpr
[3] = (unsigned long) a
;
181 regs
.gpr
[5] = 0x8765;
183 /* lwzx r5, r3, r4 */
184 stepped
= emulate_step(®s
, ppc_inst(PPC_RAW_LWZX(5, 3, 4)));
185 if (stepped
== 1 && regs
.gpr
[5] == a
[2])
186 show_result("lwzx", "PASS");
188 show_result("lwzx", "FAIL");
191 static void __init
test_std(void)
194 unsigned long a
= 0x1234;
198 regs
.gpr
[3] = (unsigned long) &a
;
199 regs
.gpr
[5] = 0x5678;
202 stepped
= emulate_step(®s
, ppc_inst(PPC_RAW_STD(5, 3, 0)));
203 if (stepped
== 1 && regs
.gpr
[5] == a
)
204 show_result("std", "PASS");
206 show_result("std", "FAIL");
209 static void __init
test_pstd(void)
212 unsigned long a
= 0x1234;
215 if (!cpu_has_feature(CPU_FTR_ARCH_31
)) {
216 show_result("pstd", "SKIP (!CPU_FTR_ARCH_31)");
221 regs
.gpr
[3] = (unsigned long)&a
;
222 regs
.gpr
[5] = 0x5678;
224 /* pstd r5, 0(r3), 0 */
225 stepped
= emulate_step(®s
, TEST_PSTD(5, 3, 0, 0));
226 if (stepped
== 1 || regs
.gpr
[5] == a
)
227 show_result("pstd", "PASS");
229 show_result("pstd", "FAIL");
232 static void __init
test_ldarx_stdcx(void)
235 unsigned long a
= 0x1234;
237 unsigned long cr0_eq
= 0x1 << 29; /* eq bit of CR0 */
240 asm volatile("mfcr %0" : "=r"(regs
.ccr
));
245 regs
.gpr
[3] = (unsigned long) &a
;
247 regs
.gpr
[5] = 0x5678;
249 /* ldarx r5, r3, r4, 0 */
250 stepped
= emulate_step(®s
, ppc_inst(PPC_RAW_LDARX(5, 3, 4, 0)));
253 * Don't touch 'a' here. Touching 'a' can do Load/store
254 * of 'a' which result in failure of subsequent stdcx.
255 * Instead, use hardcoded value for comparison.
257 if (stepped
<= 0 || regs
.gpr
[5] != 0x1234) {
258 show_result("ldarx / stdcx.", "FAIL (ldarx)");
265 regs
.gpr
[5] = 0x9ABC;
267 /* stdcx. r5, r3, r4 */
268 stepped
= emulate_step(®s
, ppc_inst(PPC_RAW_STDCX(5, 3, 4)));
271 * Two possible scenarios that indicates successful emulation
273 * 1. Reservation is active and store is performed. In this
274 * case cr0.eq bit will be set to 1.
275 * 2. Reservation is not active and store is not performed.
276 * In this case cr0.eq bit will be set to 0.
278 if (stepped
== 1 && ((regs
.gpr
[5] == a
&& (regs
.ccr
& cr0_eq
))
279 || (regs
.gpr
[5] != a
&& !(regs
.ccr
& cr0_eq
))))
280 show_result("ldarx / stdcx.", "PASS");
282 show_result("ldarx / stdcx.", "FAIL (stdcx.)");
285 #ifdef CONFIG_PPC_FPU
286 static void __init
test_lfsx_stfsx(void)
304 regs
.gpr
[3] = (unsigned long) &c
.a
;
307 /* lfsx frt10, r3, r4 */
308 stepped
= emulate_step(®s
, ppc_inst(PPC_RAW_LFSX(10, 3, 4)));
311 show_result("lfsx", "PASS");
313 show_result("lfsx", "FAIL");
320 /* stfsx frs10, r3, r4 */
321 stepped
= emulate_step(®s
, ppc_inst(PPC_RAW_STFSX(10, 3, 4)));
323 if (stepped
== 1 && c
.b
== cached_b
)
324 show_result("stfsx", "PASS");
326 show_result("stfsx", "FAIL");
329 static void __init
test_plfs_pstfs(void)
339 if (!cpu_has_feature(CPU_FTR_ARCH_31
)) {
340 show_result("pld", "SKIP (!CPU_FTR_ARCH_31)");
352 regs
.gpr
[3] = (unsigned long)&c
.a
;
354 /* plfs frt10, 0(r3), 0 */
355 stepped
= emulate_step(®s
, TEST_PLFS(10, 3, 0, 0));
358 show_result("plfs", "PASS");
360 show_result("plfs", "FAIL");
367 /* pstfs frs10, 0(r3), 0 */
368 stepped
= emulate_step(®s
, TEST_PSTFS(10, 3, 0, 0));
370 if (stepped
== 1 && c
.b
== cached_b
)
371 show_result("pstfs", "PASS");
373 show_result("pstfs", "FAIL");
376 static void __init
test_lfdx_stfdx(void)
394 regs
.gpr
[3] = (unsigned long) &c
.a
;
397 /* lfdx frt10, r3, r4 */
398 stepped
= emulate_step(®s
, ppc_inst(PPC_RAW_LFDX(10, 3, 4)));
401 show_result("lfdx", "PASS");
403 show_result("lfdx", "FAIL");
410 /* stfdx frs10, r3, r4 */
411 stepped
= emulate_step(®s
, ppc_inst(PPC_RAW_STFDX(10, 3, 4)));
413 if (stepped
== 1 && c
.b
== cached_b
)
414 show_result("stfdx", "PASS");
416 show_result("stfdx", "FAIL");
419 static void __init
test_plfd_pstfd(void)
429 if (!cpu_has_feature(CPU_FTR_ARCH_31
)) {
430 show_result("pld", "SKIP (!CPU_FTR_ARCH_31)");
442 regs
.gpr
[3] = (unsigned long)&c
.a
;
444 /* plfd frt10, 0(r3), 0 */
445 stepped
= emulate_step(®s
, TEST_PLFD(10, 3, 0, 0));
448 show_result("plfd", "PASS");
450 show_result("plfd", "FAIL");
457 /* pstfd frs10, 0(r3), 0 */
458 stepped
= emulate_step(®s
, TEST_PSTFD(10, 3, 0, 0));
460 if (stepped
== 1 && c
.b
== cached_b
)
461 show_result("pstfd", "PASS");
463 show_result("pstfd", "FAIL");
466 static void __init
test_lfsx_stfsx(void)
468 show_result("lfsx", "SKIP (CONFIG_PPC_FPU is not set)");
469 show_result("stfsx", "SKIP (CONFIG_PPC_FPU is not set)");
472 static void __init
test_plfs_pstfs(void)
474 show_result("plfs", "SKIP (CONFIG_PPC_FPU is not set)");
475 show_result("pstfs", "SKIP (CONFIG_PPC_FPU is not set)");
478 static void __init
test_lfdx_stfdx(void)
480 show_result("lfdx", "SKIP (CONFIG_PPC_FPU is not set)");
481 show_result("stfdx", "SKIP (CONFIG_PPC_FPU is not set)");
484 static void __init
test_plfd_pstfd(void)
486 show_result("plfd", "SKIP (CONFIG_PPC_FPU is not set)");
487 show_result("pstfd", "SKIP (CONFIG_PPC_FPU is not set)");
489 #endif /* CONFIG_PPC_FPU */
491 #ifdef CONFIG_ALTIVEC
492 static void __init
test_lvx_stvx(void)
507 cached_b
[0] = c
.b
[0] = 923745;
508 cached_b
[1] = c
.b
[1] = 2139478;
509 cached_b
[2] = c
.b
[2] = 9012;
510 cached_b
[3] = c
.b
[3] = 982134;
512 regs
.gpr
[3] = (unsigned long) &c
.a
;
515 /* lvx vrt10, r3, r4 */
516 stepped
= emulate_step(®s
, ppc_inst(PPC_RAW_LVX(10, 3, 4)));
519 show_result("lvx", "PASS");
521 show_result("lvx", "FAIL");
531 /* stvx vrs10, r3, r4 */
532 stepped
= emulate_step(®s
, ppc_inst(PPC_RAW_STVX(10, 3, 4)));
534 if (stepped
== 1 && cached_b
[0] == c
.b
[0] && cached_b
[1] == c
.b
[1] &&
535 cached_b
[2] == c
.b
[2] && cached_b
[3] == c
.b
[3])
536 show_result("stvx", "PASS");
538 show_result("stvx", "FAIL");
541 static void __init
test_lvx_stvx(void)
543 show_result("lvx", "SKIP (CONFIG_ALTIVEC is not set)");
544 show_result("stvx", "SKIP (CONFIG_ALTIVEC is not set)");
546 #endif /* CONFIG_ALTIVEC */
549 static void __init
test_lxvd2x_stxvd2x(void)
564 cached_b
[0] = c
.b
[0] = 18233;
565 cached_b
[1] = c
.b
[1] = 34863571;
566 cached_b
[2] = c
.b
[2] = 834;
567 cached_b
[3] = c
.b
[3] = 6138911;
569 regs
.gpr
[3] = (unsigned long) &c
.a
;
572 /* lxvd2x vsr39, r3, r4 */
573 stepped
= emulate_step(®s
, ppc_inst(PPC_RAW_LXVD2X(39, R3
, R4
)));
575 if (stepped
== 1 && cpu_has_feature(CPU_FTR_VSX
)) {
576 show_result("lxvd2x", "PASS");
578 if (!cpu_has_feature(CPU_FTR_VSX
))
579 show_result("lxvd2x", "PASS (!CPU_FTR_VSX)");
581 show_result("lxvd2x", "FAIL");
592 /* stxvd2x vsr39, r3, r4 */
593 stepped
= emulate_step(®s
, ppc_inst(PPC_RAW_STXVD2X(39, R3
, R4
)));
595 if (stepped
== 1 && cached_b
[0] == c
.b
[0] && cached_b
[1] == c
.b
[1] &&
596 cached_b
[2] == c
.b
[2] && cached_b
[3] == c
.b
[3] &&
597 cpu_has_feature(CPU_FTR_VSX
)) {
598 show_result("stxvd2x", "PASS");
600 if (!cpu_has_feature(CPU_FTR_VSX
))
601 show_result("stxvd2x", "PASS (!CPU_FTR_VSX)");
603 show_result("stxvd2x", "FAIL");
607 static void __init
test_lxvd2x_stxvd2x(void)
609 show_result("lxvd2x", "SKIP (CONFIG_VSX is not set)");
610 show_result("stxvd2x", "SKIP (CONFIG_VSX is not set)");
612 #endif /* CONFIG_VSX */
615 static void __init
test_lxvp_stxvp(void)
625 if (!cpu_has_feature(CPU_FTR_ARCH_31
)) {
626 show_result("lxvp", "SKIP (!CPU_FTR_ARCH_31)");
627 show_result("stxvp", "SKIP (!CPU_FTR_ARCH_31)");
635 cached_b
[0] = c
[0].b
[0] = 18233;
636 cached_b
[1] = c
[0].b
[1] = 34863571;
637 cached_b
[2] = c
[0].b
[2] = 834;
638 cached_b
[3] = c
[0].b
[3] = 6138911;
639 cached_b
[4] = c
[1].b
[0] = 1234;
640 cached_b
[5] = c
[1].b
[1] = 5678;
641 cached_b
[6] = c
[1].b
[2] = 91011;
642 cached_b
[7] = c
[1].b
[3] = 121314;
644 regs
.gpr
[4] = (unsigned long)&c
[0].a
;
649 * let TX=1 Tp=1 RA=4 DQ=0
651 stepped
= emulate_step(®s
, ppc_inst(PPC_RAW_LXVP(34, 4, 0)));
653 if (stepped
== 1 && cpu_has_feature(CPU_FTR_VSX
)) {
654 show_result("lxvp", "PASS");
656 if (!cpu_has_feature(CPU_FTR_VSX
))
657 show_result("lxvp", "PASS (!CPU_FTR_VSX)");
659 show_result("lxvp", "FAIL");
664 c
[0].b
[0] = 21379463;
676 * let SX=1 Sp=1 RA=4 DQ=0
678 stepped
= emulate_step(®s
, ppc_inst(PPC_RAW_STXVP(34, 4, 0)));
680 if (stepped
== 1 && cached_b
[0] == c
[0].b
[0] && cached_b
[1] == c
[0].b
[1] &&
681 cached_b
[2] == c
[0].b
[2] && cached_b
[3] == c
[0].b
[3] &&
682 cached_b
[4] == c
[1].b
[0] && cached_b
[5] == c
[1].b
[1] &&
683 cached_b
[6] == c
[1].b
[2] && cached_b
[7] == c
[1].b
[3] &&
684 cpu_has_feature(CPU_FTR_VSX
)) {
685 show_result("stxvp", "PASS");
687 if (!cpu_has_feature(CPU_FTR_VSX
))
688 show_result("stxvp", "PASS (!CPU_FTR_VSX)");
690 show_result("stxvp", "FAIL");
694 static void __init
test_lxvp_stxvp(void)
696 show_result("lxvp", "SKIP (CONFIG_VSX is not set)");
697 show_result("stxvp", "SKIP (CONFIG_VSX is not set)");
699 #endif /* CONFIG_VSX */
702 static void __init
test_lxvpx_stxvpx(void)
712 if (!cpu_has_feature(CPU_FTR_ARCH_31
)) {
713 show_result("lxvpx", "SKIP (!CPU_FTR_ARCH_31)");
714 show_result("stxvpx", "SKIP (!CPU_FTR_ARCH_31)");
722 cached_b
[0] = c
[0].b
[0] = 18233;
723 cached_b
[1] = c
[0].b
[1] = 34863571;
724 cached_b
[2] = c
[0].b
[2] = 834;
725 cached_b
[3] = c
[0].b
[3] = 6138911;
726 cached_b
[4] = c
[1].b
[0] = 1234;
727 cached_b
[5] = c
[1].b
[1] = 5678;
728 cached_b
[6] = c
[1].b
[2] = 91011;
729 cached_b
[7] = c
[1].b
[3] = 121314;
731 regs
.gpr
[3] = (unsigned long)&c
[0].a
;
737 * let TX=1 Tp=1 RA=3 RB=4
739 stepped
= emulate_step(®s
, ppc_inst(PPC_RAW_LXVPX(34, 3, 4)));
741 if (stepped
== 1 && cpu_has_feature(CPU_FTR_VSX
)) {
742 show_result("lxvpx", "PASS");
744 if (!cpu_has_feature(CPU_FTR_VSX
))
745 show_result("lxvpx", "PASS (!CPU_FTR_VSX)");
747 show_result("lxvpx", "FAIL");
752 c
[0].b
[0] = 21379463;
764 * let SX=1 Sp=1 RA=3 RB=4
766 stepped
= emulate_step(®s
, ppc_inst(PPC_RAW_STXVPX(34, 3, 4)));
768 if (stepped
== 1 && cached_b
[0] == c
[0].b
[0] && cached_b
[1] == c
[0].b
[1] &&
769 cached_b
[2] == c
[0].b
[2] && cached_b
[3] == c
[0].b
[3] &&
770 cached_b
[4] == c
[1].b
[0] && cached_b
[5] == c
[1].b
[1] &&
771 cached_b
[6] == c
[1].b
[2] && cached_b
[7] == c
[1].b
[3] &&
772 cpu_has_feature(CPU_FTR_VSX
)) {
773 show_result("stxvpx", "PASS");
775 if (!cpu_has_feature(CPU_FTR_VSX
))
776 show_result("stxvpx", "PASS (!CPU_FTR_VSX)");
778 show_result("stxvpx", "FAIL");
782 static void __init
test_lxvpx_stxvpx(void)
784 show_result("lxvpx", "SKIP (CONFIG_VSX is not set)");
785 show_result("stxvpx", "SKIP (CONFIG_VSX is not set)");
787 #endif /* CONFIG_VSX */
790 static void __init
test_plxvp_pstxvp(void)
801 if (!cpu_has_feature(CPU_FTR_ARCH_31
)) {
802 show_result("plxvp", "SKIP (!CPU_FTR_ARCH_31)");
803 show_result("pstxvp", "SKIP (!CPU_FTR_ARCH_31)");
809 cached_b
[0] = c
[0].b
[0] = 18233;
810 cached_b
[1] = c
[0].b
[1] = 34863571;
811 cached_b
[2] = c
[0].b
[2] = 834;
812 cached_b
[3] = c
[0].b
[3] = 6138911;
813 cached_b
[4] = c
[1].b
[0] = 1234;
814 cached_b
[5] = c
[1].b
[1] = 5678;
815 cached_b
[6] = c
[1].b
[2] = 91011;
816 cached_b
[7] = c
[1].b
[3] = 121314;
819 regs
.gpr
[3] = (unsigned long)&c
[0].a
;
824 * let RA=3 R=0 D=d0||d1=0 R=0 Tp=1 TX=1
826 instr
= ppc_inst_prefix(PPC_RAW_PLXVP_P(34, 0, 3, 0), PPC_RAW_PLXVP_S(34, 0, 3, 0));
828 stepped
= emulate_step(®s
, instr
);
829 if (stepped
== 1 && cpu_has_feature(CPU_FTR_VSX
)) {
830 show_result("plxvp", "PASS");
832 if (!cpu_has_feature(CPU_FTR_VSX
))
833 show_result("plxvp", "PASS (!CPU_FTR_VSX)");
835 show_result("plxvp", "FAIL");
840 c
[0].b
[0] = 21379463;
852 * let RA=3 D=d0||d1=0 R=0 Sp=1 SX=1
854 instr
= ppc_inst_prefix(PPC_RAW_PSTXVP_P(34, 0, 3, 0), PPC_RAW_PSTXVP_S(34, 0, 3, 0));
856 stepped
= emulate_step(®s
, instr
);
858 if (stepped
== 1 && cached_b
[0] == c
[0].b
[0] && cached_b
[1] == c
[0].b
[1] &&
859 cached_b
[2] == c
[0].b
[2] && cached_b
[3] == c
[0].b
[3] &&
860 cached_b
[4] == c
[1].b
[0] && cached_b
[5] == c
[1].b
[1] &&
861 cached_b
[6] == c
[1].b
[2] && cached_b
[7] == c
[1].b
[3] &&
862 cpu_has_feature(CPU_FTR_VSX
)) {
863 show_result("pstxvp", "PASS");
865 if (!cpu_has_feature(CPU_FTR_VSX
))
866 show_result("pstxvp", "PASS (!CPU_FTR_VSX)");
868 show_result("pstxvp", "FAIL");
872 static void __init
test_plxvp_pstxvp(void)
874 show_result("plxvp", "SKIP (CONFIG_VSX is not set)");
875 show_result("pstxvp", "SKIP (CONFIG_VSX is not set)");
877 #endif /* CONFIG_VSX */
879 static void __init
run_tests_load_store(void)
894 test_lxvd2x_stxvd2x();
900 struct compute_test
{
902 unsigned long cpu_feature
;
908 } subtests
[MAX_SUBTESTS
+ 1];
911 /* Extreme values for si0||si1 (the MLS:D-form 34 bit immediate field) */
912 #define SI_MIN BIT(33)
913 #define SI_MAX (BIT(33) - 1)
914 #define SI_UMAX (BIT(34) - 1)
916 static struct compute_test compute_tests
[] = {
921 .descr
= "R0 = LONG_MAX",
922 .instr
= ppc_inst(PPC_RAW_NOP()),
931 .cpu_feature
= CPU_FTR_ARCH_300
,
934 .descr
= "BFA = 1, CR = GT",
935 .instr
= ppc_inst(PPC_RAW_SETB(20, 1)),
941 .descr
= "BFA = 4, CR = LT",
942 .instr
= ppc_inst(PPC_RAW_SETB(20, 4)),
948 .descr
= "BFA = 5, CR = EQ",
949 .instr
= ppc_inst(PPC_RAW_SETB(20, 5)),
960 .descr
= "RA = LONG_MIN, RB = LONG_MIN",
961 .instr
= ppc_inst(PPC_RAW_ADD(20, 21, 22)),
968 .descr
= "RA = LONG_MIN, RB = LONG_MAX",
969 .instr
= ppc_inst(PPC_RAW_ADD(20, 21, 22)),
976 .descr
= "RA = LONG_MAX, RB = LONG_MAX",
977 .instr
= ppc_inst(PPC_RAW_ADD(20, 21, 22)),
984 .descr
= "RA = ULONG_MAX, RB = ULONG_MAX",
985 .instr
= ppc_inst(PPC_RAW_ADD(20, 21, 22)),
987 .gpr
[21] = ULONG_MAX
,
988 .gpr
[22] = ULONG_MAX
,
992 .descr
= "RA = ULONG_MAX, RB = 0x1",
993 .instr
= ppc_inst(PPC_RAW_ADD(20, 21, 22)),
995 .gpr
[21] = ULONG_MAX
,
1000 .descr
= "RA = INT_MIN, RB = INT_MIN",
1001 .instr
= ppc_inst(PPC_RAW_ADD(20, 21, 22)),
1008 .descr
= "RA = INT_MIN, RB = INT_MAX",
1009 .instr
= ppc_inst(PPC_RAW_ADD(20, 21, 22)),
1016 .descr
= "RA = INT_MAX, RB = INT_MAX",
1017 .instr
= ppc_inst(PPC_RAW_ADD(20, 21, 22)),
1024 .descr
= "RA = UINT_MAX, RB = UINT_MAX",
1025 .instr
= ppc_inst(PPC_RAW_ADD(20, 21, 22)),
1027 .gpr
[21] = UINT_MAX
,
1028 .gpr
[22] = UINT_MAX
,
1032 .descr
= "RA = UINT_MAX, RB = 0x1",
1033 .instr
= ppc_inst(PPC_RAW_ADD(20, 21, 22)),
1035 .gpr
[21] = UINT_MAX
,
1045 .descr
= "RA = LONG_MIN, RB = LONG_MIN",
1046 .flags
= IGNORE_CCR
,
1047 .instr
= ppc_inst(PPC_RAW_ADD_DOT(20, 21, 22)),
1049 .gpr
[21] = LONG_MIN
,
1050 .gpr
[22] = LONG_MIN
,
1054 .descr
= "RA = LONG_MIN, RB = LONG_MAX",
1055 .instr
= ppc_inst(PPC_RAW_ADD_DOT(20, 21, 22)),
1057 .gpr
[21] = LONG_MIN
,
1058 .gpr
[22] = LONG_MAX
,
1062 .descr
= "RA = LONG_MAX, RB = LONG_MAX",
1063 .flags
= IGNORE_CCR
,
1064 .instr
= ppc_inst(PPC_RAW_ADD_DOT(20, 21, 22)),
1066 .gpr
[21] = LONG_MAX
,
1067 .gpr
[22] = LONG_MAX
,
1071 .descr
= "RA = ULONG_MAX, RB = ULONG_MAX",
1072 .instr
= ppc_inst(PPC_RAW_ADD_DOT(20, 21, 22)),
1074 .gpr
[21] = ULONG_MAX
,
1075 .gpr
[22] = ULONG_MAX
,
1079 .descr
= "RA = ULONG_MAX, RB = 0x1",
1080 .instr
= ppc_inst(PPC_RAW_ADD_DOT(20, 21, 22)),
1082 .gpr
[21] = ULONG_MAX
,
1087 .descr
= "RA = INT_MIN, RB = INT_MIN",
1088 .instr
= ppc_inst(PPC_RAW_ADD_DOT(20, 21, 22)),
1095 .descr
= "RA = INT_MIN, RB = INT_MAX",
1096 .instr
= ppc_inst(PPC_RAW_ADD_DOT(20, 21, 22)),
1103 .descr
= "RA = INT_MAX, RB = INT_MAX",
1104 .instr
= ppc_inst(PPC_RAW_ADD_DOT(20, 21, 22)),
1111 .descr
= "RA = UINT_MAX, RB = UINT_MAX",
1112 .instr
= ppc_inst(PPC_RAW_ADD_DOT(20, 21, 22)),
1114 .gpr
[21] = UINT_MAX
,
1115 .gpr
[22] = UINT_MAX
,
1119 .descr
= "RA = UINT_MAX, RB = 0x1",
1120 .instr
= ppc_inst(PPC_RAW_ADD_DOT(20, 21, 22)),
1122 .gpr
[21] = UINT_MAX
,
1132 .descr
= "RA = LONG_MIN, RB = LONG_MIN",
1133 .instr
= ppc_inst(PPC_RAW_ADDC(20, 21, 22)),
1135 .gpr
[21] = LONG_MIN
,
1136 .gpr
[22] = LONG_MIN
,
1140 .descr
= "RA = LONG_MIN, RB = LONG_MAX",
1141 .instr
= ppc_inst(PPC_RAW_ADDC(20, 21, 22)),
1143 .gpr
[21] = LONG_MIN
,
1144 .gpr
[22] = LONG_MAX
,
1148 .descr
= "RA = LONG_MAX, RB = LONG_MAX",
1149 .instr
= ppc_inst(PPC_RAW_ADDC(20, 21, 22)),
1151 .gpr
[21] = LONG_MAX
,
1152 .gpr
[22] = LONG_MAX
,
1156 .descr
= "RA = ULONG_MAX, RB = ULONG_MAX",
1157 .instr
= ppc_inst(PPC_RAW_ADDC(20, 21, 22)),
1159 .gpr
[21] = ULONG_MAX
,
1160 .gpr
[22] = ULONG_MAX
,
1164 .descr
= "RA = ULONG_MAX, RB = 0x1",
1165 .instr
= ppc_inst(PPC_RAW_ADDC(20, 21, 22)),
1167 .gpr
[21] = ULONG_MAX
,
1172 .descr
= "RA = INT_MIN, RB = INT_MIN",
1173 .instr
= ppc_inst(PPC_RAW_ADDC(20, 21, 22)),
1180 .descr
= "RA = INT_MIN, RB = INT_MAX",
1181 .instr
= ppc_inst(PPC_RAW_ADDC(20, 21, 22)),
1188 .descr
= "RA = INT_MAX, RB = INT_MAX",
1189 .instr
= ppc_inst(PPC_RAW_ADDC(20, 21, 22)),
1196 .descr
= "RA = UINT_MAX, RB = UINT_MAX",
1197 .instr
= ppc_inst(PPC_RAW_ADDC(20, 21, 22)),
1199 .gpr
[21] = UINT_MAX
,
1200 .gpr
[22] = UINT_MAX
,
1204 .descr
= "RA = UINT_MAX, RB = 0x1",
1205 .instr
= ppc_inst(PPC_RAW_ADDC(20, 21, 22)),
1207 .gpr
[21] = UINT_MAX
,
1212 .descr
= "RA = LONG_MIN | INT_MIN, RB = LONG_MIN | INT_MIN",
1213 .instr
= ppc_inst(PPC_RAW_ADDC(20, 21, 22)),
1215 .gpr
[21] = LONG_MIN
| (uint
)INT_MIN
,
1216 .gpr
[22] = LONG_MIN
| (uint
)INT_MIN
,
1222 .mnemonic
= "addc.",
1225 .descr
= "RA = LONG_MIN, RB = LONG_MIN",
1226 .flags
= IGNORE_CCR
,
1227 .instr
= ppc_inst(PPC_RAW_ADDC_DOT(20, 21, 22)),
1229 .gpr
[21] = LONG_MIN
,
1230 .gpr
[22] = LONG_MIN
,
1234 .descr
= "RA = LONG_MIN, RB = LONG_MAX",
1235 .instr
= ppc_inst(PPC_RAW_ADDC_DOT(20, 21, 22)),
1237 .gpr
[21] = LONG_MIN
,
1238 .gpr
[22] = LONG_MAX
,
1242 .descr
= "RA = LONG_MAX, RB = LONG_MAX",
1243 .flags
= IGNORE_CCR
,
1244 .instr
= ppc_inst(PPC_RAW_ADDC_DOT(20, 21, 22)),
1246 .gpr
[21] = LONG_MAX
,
1247 .gpr
[22] = LONG_MAX
,
1251 .descr
= "RA = ULONG_MAX, RB = ULONG_MAX",
1252 .instr
= ppc_inst(PPC_RAW_ADDC_DOT(20, 21, 22)),
1254 .gpr
[21] = ULONG_MAX
,
1255 .gpr
[22] = ULONG_MAX
,
1259 .descr
= "RA = ULONG_MAX, RB = 0x1",
1260 .instr
= ppc_inst(PPC_RAW_ADDC_DOT(20, 21, 22)),
1262 .gpr
[21] = ULONG_MAX
,
1267 .descr
= "RA = INT_MIN, RB = INT_MIN",
1268 .instr
= ppc_inst(PPC_RAW_ADDC_DOT(20, 21, 22)),
1275 .descr
= "RA = INT_MIN, RB = INT_MAX",
1276 .instr
= ppc_inst(PPC_RAW_ADDC_DOT(20, 21, 22)),
1283 .descr
= "RA = INT_MAX, RB = INT_MAX",
1284 .instr
= ppc_inst(PPC_RAW_ADDC_DOT(20, 21, 22)),
1291 .descr
= "RA = UINT_MAX, RB = UINT_MAX",
1292 .instr
= ppc_inst(PPC_RAW_ADDC_DOT(20, 21, 22)),
1294 .gpr
[21] = UINT_MAX
,
1295 .gpr
[22] = UINT_MAX
,
1299 .descr
= "RA = UINT_MAX, RB = 0x1",
1300 .instr
= ppc_inst(PPC_RAW_ADDC_DOT(20, 21, 22)),
1302 .gpr
[21] = UINT_MAX
,
1307 .descr
= "RA = LONG_MIN | INT_MIN, RB = LONG_MIN | INT_MIN",
1308 .instr
= ppc_inst(PPC_RAW_ADDC_DOT(20, 21, 22)),
1310 .gpr
[21] = LONG_MIN
| (uint
)INT_MIN
,
1311 .gpr
[22] = LONG_MIN
| (uint
)INT_MIN
,
1317 .mnemonic
= "divde",
1320 .descr
= "RA = LONG_MIN, RB = LONG_MIN",
1321 .instr
= ppc_inst(PPC_RAW_DIVDE(20, 21, 22)),
1323 .gpr
[21] = LONG_MIN
,
1324 .gpr
[22] = LONG_MIN
,
1328 .descr
= "RA = 1L, RB = 0",
1329 .instr
= ppc_inst(PPC_RAW_DIVDE(20, 21, 22)),
1330 .flags
= IGNORE_GPR(20),
1337 .descr
= "RA = LONG_MIN, RB = LONG_MAX",
1338 .instr
= ppc_inst(PPC_RAW_DIVDE(20, 21, 22)),
1340 .gpr
[21] = LONG_MIN
,
1341 .gpr
[22] = LONG_MAX
,
1347 .mnemonic
= "divde.",
1350 .descr
= "RA = LONG_MIN, RB = LONG_MIN",
1351 .instr
= ppc_inst(PPC_RAW_DIVDE_DOT(20, 21, 22)),
1353 .gpr
[21] = LONG_MIN
,
1354 .gpr
[22] = LONG_MIN
,
1358 .descr
= "RA = 1L, RB = 0",
1359 .instr
= ppc_inst(PPC_RAW_DIVDE_DOT(20, 21, 22)),
1360 .flags
= IGNORE_GPR(20),
1367 .descr
= "RA = LONG_MIN, RB = LONG_MAX",
1368 .instr
= ppc_inst(PPC_RAW_DIVDE_DOT(20, 21, 22)),
1370 .gpr
[21] = LONG_MIN
,
1371 .gpr
[22] = LONG_MAX
,
1377 .mnemonic
= "divdeu",
1380 .descr
= "RA = LONG_MIN, RB = LONG_MIN",
1381 .instr
= ppc_inst(PPC_RAW_DIVDEU(20, 21, 22)),
1382 .flags
= IGNORE_GPR(20),
1384 .gpr
[21] = LONG_MIN
,
1385 .gpr
[22] = LONG_MIN
,
1389 .descr
= "RA = 1L, RB = 0",
1390 .instr
= ppc_inst(PPC_RAW_DIVDEU(20, 21, 22)),
1391 .flags
= IGNORE_GPR(20),
1398 .descr
= "RA = LONG_MIN, RB = LONG_MAX",
1399 .instr
= ppc_inst(PPC_RAW_DIVDEU(20, 21, 22)),
1401 .gpr
[21] = LONG_MIN
,
1402 .gpr
[22] = LONG_MAX
,
1406 .descr
= "RA = LONG_MAX - 1, RB = LONG_MAX",
1407 .instr
= ppc_inst(PPC_RAW_DIVDEU(20, 21, 22)),
1409 .gpr
[21] = LONG_MAX
- 1,
1410 .gpr
[22] = LONG_MAX
,
1414 .descr
= "RA = LONG_MIN + 1, RB = LONG_MIN",
1415 .instr
= ppc_inst(PPC_RAW_DIVDEU(20, 21, 22)),
1416 .flags
= IGNORE_GPR(20),
1418 .gpr
[21] = LONG_MIN
+ 1,
1419 .gpr
[22] = LONG_MIN
,
1425 .mnemonic
= "divdeu.",
1428 .descr
= "RA = LONG_MIN, RB = LONG_MIN",
1429 .instr
= ppc_inst(PPC_RAW_DIVDEU_DOT(20, 21, 22)),
1430 .flags
= IGNORE_GPR(20),
1432 .gpr
[21] = LONG_MIN
,
1433 .gpr
[22] = LONG_MIN
,
1437 .descr
= "RA = 1L, RB = 0",
1438 .instr
= ppc_inst(PPC_RAW_DIVDEU_DOT(20, 21, 22)),
1439 .flags
= IGNORE_GPR(20),
1446 .descr
= "RA = LONG_MIN, RB = LONG_MAX",
1447 .instr
= ppc_inst(PPC_RAW_DIVDEU_DOT(20, 21, 22)),
1449 .gpr
[21] = LONG_MIN
,
1450 .gpr
[22] = LONG_MAX
,
1454 .descr
= "RA = LONG_MAX - 1, RB = LONG_MAX",
1455 .instr
= ppc_inst(PPC_RAW_DIVDEU_DOT(20, 21, 22)),
1457 .gpr
[21] = LONG_MAX
- 1,
1458 .gpr
[22] = LONG_MAX
,
1462 .descr
= "RA = LONG_MIN + 1, RB = LONG_MIN",
1463 .instr
= ppc_inst(PPC_RAW_DIVDEU_DOT(20, 21, 22)),
1464 .flags
= IGNORE_GPR(20),
1466 .gpr
[21] = LONG_MIN
+ 1,
1467 .gpr
[22] = LONG_MIN
,
1473 .mnemonic
= "paddi",
1474 .cpu_feature
= CPU_FTR_ARCH_31
,
1477 .descr
= "RA = LONG_MIN, SI = SI_MIN, R = 0",
1478 .instr
= TEST_PADDI(21, 22, SI_MIN
, 0),
1481 .gpr
[22] = LONG_MIN
,
1485 .descr
= "RA = LONG_MIN, SI = SI_MAX, R = 0",
1486 .instr
= TEST_PADDI(21, 22, SI_MAX
, 0),
1489 .gpr
[22] = LONG_MIN
,
1493 .descr
= "RA = LONG_MAX, SI = SI_MAX, R = 0",
1494 .instr
= TEST_PADDI(21, 22, SI_MAX
, 0),
1497 .gpr
[22] = LONG_MAX
,
1501 .descr
= "RA = ULONG_MAX, SI = SI_UMAX, R = 0",
1502 .instr
= TEST_PADDI(21, 22, SI_UMAX
, 0),
1505 .gpr
[22] = ULONG_MAX
,
1509 .descr
= "RA = ULONG_MAX, SI = 0x1, R = 0",
1510 .instr
= TEST_PADDI(21, 22, 0x1, 0),
1513 .gpr
[22] = ULONG_MAX
,
1517 .descr
= "RA = INT_MIN, SI = SI_MIN, R = 0",
1518 .instr
= TEST_PADDI(21, 22, SI_MIN
, 0),
1525 .descr
= "RA = INT_MIN, SI = SI_MAX, R = 0",
1526 .instr
= TEST_PADDI(21, 22, SI_MAX
, 0),
1533 .descr
= "RA = INT_MAX, SI = SI_MAX, R = 0",
1534 .instr
= TEST_PADDI(21, 22, SI_MAX
, 0),
1541 .descr
= "RA = UINT_MAX, SI = 0x1, R = 0",
1542 .instr
= TEST_PADDI(21, 22, 0x1, 0),
1545 .gpr
[22] = UINT_MAX
,
1549 .descr
= "RA = UINT_MAX, SI = SI_MAX, R = 0",
1550 .instr
= TEST_PADDI(21, 22, SI_MAX
, 0),
1553 .gpr
[22] = UINT_MAX
,
1557 .descr
= "RA is r0, SI = SI_MIN, R = 0",
1558 .instr
= TEST_PADDI(21, 0, SI_MIN
, 0),
1564 .descr
= "RA = 0, SI = SI_MIN, R = 0",
1565 .instr
= TEST_PADDI(21, 22, SI_MIN
, 0),
1572 .descr
= "RA is r0, SI = 0, R = 1",
1573 .instr
= TEST_PADDI(21, 0, 0, 1),
1579 .descr
= "RA is r0, SI = SI_MIN, R = 1",
1580 .instr
= TEST_PADDI(21, 0, SI_MIN
, 1),
1585 /* Invalid instruction form with R = 1 and RA != 0 */
1587 .descr
= "RA = R22(0), SI = 0, R = 1",
1588 .instr
= TEST_PADDI(21, 22, 0, 1),
1589 .flags
= NEGATIVE_TEST
,
1599 static int __init
emulate_compute_instr(struct pt_regs
*regs
,
1604 struct instruction_op op
;
1606 if (!regs
|| !ppc_inst_val(instr
))
1609 /* This is not a return frame regs */
1610 regs
->nip
= patch_site_addr(&patch__exec_instr
);
1612 analysed
= analyse_instr(&op
, regs
, instr
);
1613 if (analysed
!= 1 || GETTYPE(op
.type
) != COMPUTE
) {
1616 pr_info("emulation failed, instruction = %08lx\n", ppc_inst_as_ulong(instr
));
1619 if (analysed
== 1 && negative
)
1620 pr_info("negative test failed, instruction = %08lx\n", ppc_inst_as_ulong(instr
));
1622 emulate_update_regs(regs
, &op
);
1626 static int __init
execute_compute_instr(struct pt_regs
*regs
,
1629 extern int exec_instr(struct pt_regs
*regs
);
1631 if (!regs
|| !ppc_inst_val(instr
))
1634 /* Patch the NOP with the actual instruction */
1635 patch_instruction_site(&patch__exec_instr
, instr
);
1636 if (exec_instr(regs
)) {
1637 pr_info("execution failed, instruction = %08lx\n", ppc_inst_as_ulong(instr
));
1644 #define gpr_mismatch(gprn, exp, got) \
1645 pr_info("GPR%u mismatch, exp = 0x%016lx, got = 0x%016lx\n", \
1648 #define reg_mismatch(name, exp, got) \
1649 pr_info("%s mismatch, exp = 0x%016lx, got = 0x%016lx\n", \
1652 static void __init
run_tests_compute(void)
1654 unsigned long flags
;
1655 struct compute_test
*test
;
1656 struct pt_regs
*regs
, exp
, got
;
1657 unsigned int i
, j
, k
;
1659 bool ignore_gpr
, ignore_xer
, ignore_ccr
, passed
, rc
, negative
;
1661 for (i
= 0; i
< ARRAY_SIZE(compute_tests
); i
++) {
1662 test
= &compute_tests
[i
];
1664 if (test
->cpu_feature
&& !early_cpu_has_feature(test
->cpu_feature
)) {
1665 show_result(test
->mnemonic
, "SKIP (!CPU_FTR)");
1669 for (j
= 0; j
< MAX_SUBTESTS
&& test
->subtests
[j
].descr
; j
++) {
1670 instr
= test
->subtests
[j
].instr
;
1671 flags
= test
->subtests
[j
].flags
;
1672 regs
= &test
->subtests
[j
].regs
;
1673 negative
= flags
& NEGATIVE_TEST
;
1674 ignore_xer
= flags
& IGNORE_XER
;
1675 ignore_ccr
= flags
& IGNORE_CCR
;
1678 memcpy(&exp
, regs
, sizeof(struct pt_regs
));
1679 memcpy(&got
, regs
, sizeof(struct pt_regs
));
1682 * Set a compatible MSR value explicitly to ensure
1683 * that XER and CR bits are updated appropriately
1685 exp
.msr
= MSR_KERNEL
;
1686 got
.msr
= MSR_KERNEL
;
1688 rc
= emulate_compute_instr(&got
, instr
, negative
) != 0;
1690 /* skip executing instruction */
1693 } else if (rc
|| execute_compute_instr(&exp
, instr
)) {
1698 /* Verify GPR values */
1699 for (k
= 0; k
< 32; k
++) {
1700 ignore_gpr
= flags
& IGNORE_GPR(k
);
1701 if (!ignore_gpr
&& exp
.gpr
[k
] != got
.gpr
[k
]) {
1703 gpr_mismatch(k
, exp
.gpr
[k
], got
.gpr
[k
]);
1707 /* Verify LR value */
1708 if (exp
.link
!= got
.link
) {
1710 reg_mismatch("LR", exp
.link
, got
.link
);
1713 /* Verify XER value */
1714 if (!ignore_xer
&& exp
.xer
!= got
.xer
) {
1716 reg_mismatch("XER", exp
.xer
, got
.xer
);
1719 /* Verify CR value */
1720 if (!ignore_ccr
&& exp
.ccr
!= got
.ccr
) {
1722 reg_mismatch("CR", exp
.ccr
, got
.ccr
);
1726 show_result_with_descr(test
->mnemonic
,
1727 test
->subtests
[j
].descr
,
1728 passed
? "PASS" : "FAIL");
1733 static int __init
test_emulate_step(void)
1735 printk(KERN_INFO
"Running instruction emulation self-tests ...\n");
1736 run_tests_load_store();
1737 run_tests_compute();
1741 late_initcall(test_emulate_step
);