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/sstep.h>
12 #include <asm/ppc-opcode.h>
13 #include <asm/code-patching.h>
15 #define IMM_L(i) ((uintptr_t)(i) & 0xffff)
18 * Defined with TEST_ prefix so it does not conflict with other
21 #define TEST_LD(r, base, i) (PPC_INST_LD | ___PPC_RT(r) | \
22 ___PPC_RA(base) | IMM_L(i))
23 #define TEST_LWZ(r, base, i) (PPC_INST_LWZ | ___PPC_RT(r) | \
24 ___PPC_RA(base) | IMM_L(i))
25 #define TEST_LWZX(t, a, b) (PPC_INST_LWZX | ___PPC_RT(t) | \
26 ___PPC_RA(a) | ___PPC_RB(b))
27 #define TEST_STD(r, base, i) (PPC_INST_STD | ___PPC_RS(r) | \
28 ___PPC_RA(base) | ((i) & 0xfffc))
29 #define TEST_LDARX(t, a, b, eh) (PPC_INST_LDARX | ___PPC_RT(t) | \
30 ___PPC_RA(a) | ___PPC_RB(b) | \
32 #define TEST_STDCX(s, a, b) (PPC_INST_STDCX | ___PPC_RS(s) | \
33 ___PPC_RA(a) | ___PPC_RB(b))
34 #define TEST_LFSX(t, a, b) (PPC_INST_LFSX | ___PPC_RT(t) | \
35 ___PPC_RA(a) | ___PPC_RB(b))
36 #define TEST_STFSX(s, a, b) (PPC_INST_STFSX | ___PPC_RS(s) | \
37 ___PPC_RA(a) | ___PPC_RB(b))
38 #define TEST_LFDX(t, a, b) (PPC_INST_LFDX | ___PPC_RT(t) | \
39 ___PPC_RA(a) | ___PPC_RB(b))
40 #define TEST_STFDX(s, a, b) (PPC_INST_STFDX | ___PPC_RS(s) | \
41 ___PPC_RA(a) | ___PPC_RB(b))
42 #define TEST_LVX(t, a, b) (PPC_INST_LVX | ___PPC_RT(t) | \
43 ___PPC_RA(a) | ___PPC_RB(b))
44 #define TEST_STVX(s, a, b) (PPC_INST_STVX | ___PPC_RS(s) | \
45 ___PPC_RA(a) | ___PPC_RB(b))
46 #define TEST_LXVD2X(s, a, b) (PPC_INST_LXVD2X | VSX_XX1((s), R##a, R##b))
47 #define TEST_STXVD2X(s, a, b) (PPC_INST_STXVD2X | VSX_XX1((s), R##a, R##b))
48 #define TEST_ADD(t, a, b) (PPC_INST_ADD | ___PPC_RT(t) | \
49 ___PPC_RA(a) | ___PPC_RB(b))
50 #define TEST_ADD_DOT(t, a, b) (PPC_INST_ADD | ___PPC_RT(t) | \
51 ___PPC_RA(a) | ___PPC_RB(b) | 0x1)
52 #define TEST_ADDC(t, a, b) (PPC_INST_ADDC | ___PPC_RT(t) | \
53 ___PPC_RA(a) | ___PPC_RB(b))
54 #define TEST_ADDC_DOT(t, a, b) (PPC_INST_ADDC | ___PPC_RT(t) | \
55 ___PPC_RA(a) | ___PPC_RB(b) | 0x1)
57 #define MAX_SUBTESTS 16
59 #define IGNORE_GPR(n) (0x1UL << (n))
60 #define IGNORE_XER (0x1UL << 32)
61 #define IGNORE_CCR (0x1UL << 33)
63 static void __init
init_pt_regs(struct pt_regs
*regs
)
65 static unsigned long msr
;
66 static bool msr_cached
;
68 memset(regs
, 0, sizeof(struct pt_regs
));
70 if (likely(msr_cached
)) {
75 asm volatile("mfmsr %0" : "=r"(regs
->msr
));
85 static void __init
show_result(char *mnemonic
, char *result
)
87 pr_info("%-14s : %s\n", mnemonic
, result
);
90 static void __init
show_result_with_descr(char *mnemonic
, char *descr
,
93 pr_info("%-14s : %-50s %s\n", mnemonic
, descr
, result
);
96 static void __init
test_ld(void)
99 unsigned long a
= 0x23;
103 regs
.gpr
[3] = (unsigned long) &a
;
106 stepped
= emulate_step(®s
, TEST_LD(5, 3, 0));
108 if (stepped
== 1 && regs
.gpr
[5] == a
)
109 show_result("ld", "PASS");
111 show_result("ld", "FAIL");
114 static void __init
test_lwz(void)
117 unsigned int a
= 0x4545;
121 regs
.gpr
[3] = (unsigned long) &a
;
124 stepped
= emulate_step(®s
, TEST_LWZ(5, 3, 0));
126 if (stepped
== 1 && regs
.gpr
[5] == a
)
127 show_result("lwz", "PASS");
129 show_result("lwz", "FAIL");
132 static void __init
test_lwzx(void)
135 unsigned int a
[3] = {0x0, 0x0, 0x1234};
139 regs
.gpr
[3] = (unsigned long) a
;
141 regs
.gpr
[5] = 0x8765;
143 /* lwzx r5, r3, r4 */
144 stepped
= emulate_step(®s
, TEST_LWZX(5, 3, 4));
145 if (stepped
== 1 && regs
.gpr
[5] == a
[2])
146 show_result("lwzx", "PASS");
148 show_result("lwzx", "FAIL");
151 static void __init
test_std(void)
154 unsigned long a
= 0x1234;
158 regs
.gpr
[3] = (unsigned long) &a
;
159 regs
.gpr
[5] = 0x5678;
162 stepped
= emulate_step(®s
, TEST_STD(5, 3, 0));
163 if (stepped
== 1 || regs
.gpr
[5] == a
)
164 show_result("std", "PASS");
166 show_result("std", "FAIL");
169 static void __init
test_ldarx_stdcx(void)
172 unsigned long a
= 0x1234;
174 unsigned long cr0_eq
= 0x1 << 29; /* eq bit of CR0 */
177 asm volatile("mfcr %0" : "=r"(regs
.ccr
));
182 regs
.gpr
[3] = (unsigned long) &a
;
184 regs
.gpr
[5] = 0x5678;
186 /* ldarx r5, r3, r4, 0 */
187 stepped
= emulate_step(®s
, TEST_LDARX(5, 3, 4, 0));
190 * Don't touch 'a' here. Touching 'a' can do Load/store
191 * of 'a' which result in failure of subsequent stdcx.
192 * Instead, use hardcoded value for comparison.
194 if (stepped
<= 0 || regs
.gpr
[5] != 0x1234) {
195 show_result("ldarx / stdcx.", "FAIL (ldarx)");
202 regs
.gpr
[5] = 0x9ABC;
204 /* stdcx. r5, r3, r4 */
205 stepped
= emulate_step(®s
, TEST_STDCX(5, 3, 4));
208 * Two possible scenarios that indicates successful emulation
210 * 1. Reservation is active and store is performed. In this
211 * case cr0.eq bit will be set to 1.
212 * 2. Reservation is not active and store is not performed.
213 * In this case cr0.eq bit will be set to 0.
215 if (stepped
== 1 && ((regs
.gpr
[5] == a
&& (regs
.ccr
& cr0_eq
))
216 || (regs
.gpr
[5] != a
&& !(regs
.ccr
& cr0_eq
))))
217 show_result("ldarx / stdcx.", "PASS");
219 show_result("ldarx / stdcx.", "FAIL (stdcx.)");
222 #ifdef CONFIG_PPC_FPU
223 static void __init
test_lfsx_stfsx(void)
241 regs
.gpr
[3] = (unsigned long) &c
.a
;
244 /* lfsx frt10, r3, r4 */
245 stepped
= emulate_step(®s
, TEST_LFSX(10, 3, 4));
248 show_result("lfsx", "PASS");
250 show_result("lfsx", "FAIL");
257 /* stfsx frs10, r3, r4 */
258 stepped
= emulate_step(®s
, TEST_STFSX(10, 3, 4));
260 if (stepped
== 1 && c
.b
== cached_b
)
261 show_result("stfsx", "PASS");
263 show_result("stfsx", "FAIL");
266 static void __init
test_lfdx_stfdx(void)
284 regs
.gpr
[3] = (unsigned long) &c
.a
;
287 /* lfdx frt10, r3, r4 */
288 stepped
= emulate_step(®s
, TEST_LFDX(10, 3, 4));
291 show_result("lfdx", "PASS");
293 show_result("lfdx", "FAIL");
300 /* stfdx frs10, r3, r4 */
301 stepped
= emulate_step(®s
, TEST_STFDX(10, 3, 4));
303 if (stepped
== 1 && c
.b
== cached_b
)
304 show_result("stfdx", "PASS");
306 show_result("stfdx", "FAIL");
309 static void __init
test_lfsx_stfsx(void)
311 show_result("lfsx", "SKIP (CONFIG_PPC_FPU is not set)");
312 show_result("stfsx", "SKIP (CONFIG_PPC_FPU is not set)");
315 static void __init
test_lfdx_stfdx(void)
317 show_result("lfdx", "SKIP (CONFIG_PPC_FPU is not set)");
318 show_result("stfdx", "SKIP (CONFIG_PPC_FPU is not set)");
320 #endif /* CONFIG_PPC_FPU */
322 #ifdef CONFIG_ALTIVEC
323 static void __init
test_lvx_stvx(void)
338 cached_b
[0] = c
.b
[0] = 923745;
339 cached_b
[1] = c
.b
[1] = 2139478;
340 cached_b
[2] = c
.b
[2] = 9012;
341 cached_b
[3] = c
.b
[3] = 982134;
343 regs
.gpr
[3] = (unsigned long) &c
.a
;
346 /* lvx vrt10, r3, r4 */
347 stepped
= emulate_step(®s
, TEST_LVX(10, 3, 4));
350 show_result("lvx", "PASS");
352 show_result("lvx", "FAIL");
362 /* stvx vrs10, r3, r4 */
363 stepped
= emulate_step(®s
, TEST_STVX(10, 3, 4));
365 if (stepped
== 1 && cached_b
[0] == c
.b
[0] && cached_b
[1] == c
.b
[1] &&
366 cached_b
[2] == c
.b
[2] && cached_b
[3] == c
.b
[3])
367 show_result("stvx", "PASS");
369 show_result("stvx", "FAIL");
372 static void __init
test_lvx_stvx(void)
374 show_result("lvx", "SKIP (CONFIG_ALTIVEC is not set)");
375 show_result("stvx", "SKIP (CONFIG_ALTIVEC is not set)");
377 #endif /* CONFIG_ALTIVEC */
380 static void __init
test_lxvd2x_stxvd2x(void)
395 cached_b
[0] = c
.b
[0] = 18233;
396 cached_b
[1] = c
.b
[1] = 34863571;
397 cached_b
[2] = c
.b
[2] = 834;
398 cached_b
[3] = c
.b
[3] = 6138911;
400 regs
.gpr
[3] = (unsigned long) &c
.a
;
403 /* lxvd2x vsr39, r3, r4 */
404 stepped
= emulate_step(®s
, TEST_LXVD2X(39, 3, 4));
406 if (stepped
== 1 && cpu_has_feature(CPU_FTR_VSX
)) {
407 show_result("lxvd2x", "PASS");
409 if (!cpu_has_feature(CPU_FTR_VSX
))
410 show_result("lxvd2x", "PASS (!CPU_FTR_VSX)");
412 show_result("lxvd2x", "FAIL");
423 /* stxvd2x vsr39, r3, r4 */
424 stepped
= emulate_step(®s
, TEST_STXVD2X(39, 3, 4));
426 if (stepped
== 1 && cached_b
[0] == c
.b
[0] && cached_b
[1] == c
.b
[1] &&
427 cached_b
[2] == c
.b
[2] && cached_b
[3] == c
.b
[3] &&
428 cpu_has_feature(CPU_FTR_VSX
)) {
429 show_result("stxvd2x", "PASS");
431 if (!cpu_has_feature(CPU_FTR_VSX
))
432 show_result("stxvd2x", "PASS (!CPU_FTR_VSX)");
434 show_result("stxvd2x", "FAIL");
438 static void __init
test_lxvd2x_stxvd2x(void)
440 show_result("lxvd2x", "SKIP (CONFIG_VSX is not set)");
441 show_result("stxvd2x", "SKIP (CONFIG_VSX is not set)");
443 #endif /* CONFIG_VSX */
445 static void __init
run_tests_load_store(void)
455 test_lxvd2x_stxvd2x();
458 struct compute_test
{
465 } subtests
[MAX_SUBTESTS
+ 1];
468 static struct compute_test compute_tests
[] = {
473 .descr
= "R0 = LONG_MAX",
474 .instr
= PPC_INST_NOP
,
485 .descr
= "RA = LONG_MIN, RB = LONG_MIN",
486 .instr
= TEST_ADD(20, 21, 22),
493 .descr
= "RA = LONG_MIN, RB = LONG_MAX",
494 .instr
= TEST_ADD(20, 21, 22),
501 .descr
= "RA = LONG_MAX, RB = LONG_MAX",
502 .instr
= TEST_ADD(20, 21, 22),
509 .descr
= "RA = ULONG_MAX, RB = ULONG_MAX",
510 .instr
= TEST_ADD(20, 21, 22),
512 .gpr
[21] = ULONG_MAX
,
513 .gpr
[22] = ULONG_MAX
,
517 .descr
= "RA = ULONG_MAX, RB = 0x1",
518 .instr
= TEST_ADD(20, 21, 22),
520 .gpr
[21] = ULONG_MAX
,
525 .descr
= "RA = INT_MIN, RB = INT_MIN",
526 .instr
= TEST_ADD(20, 21, 22),
533 .descr
= "RA = INT_MIN, RB = INT_MAX",
534 .instr
= TEST_ADD(20, 21, 22),
541 .descr
= "RA = INT_MAX, RB = INT_MAX",
542 .instr
= TEST_ADD(20, 21, 22),
549 .descr
= "RA = UINT_MAX, RB = UINT_MAX",
550 .instr
= TEST_ADD(20, 21, 22),
557 .descr
= "RA = UINT_MAX, RB = 0x1",
558 .instr
= TEST_ADD(20, 21, 22),
570 .descr
= "RA = LONG_MIN, RB = LONG_MIN",
572 .instr
= TEST_ADD_DOT(20, 21, 22),
579 .descr
= "RA = LONG_MIN, RB = LONG_MAX",
580 .instr
= TEST_ADD_DOT(20, 21, 22),
587 .descr
= "RA = LONG_MAX, RB = LONG_MAX",
589 .instr
= TEST_ADD_DOT(20, 21, 22),
596 .descr
= "RA = ULONG_MAX, RB = ULONG_MAX",
597 .instr
= TEST_ADD_DOT(20, 21, 22),
599 .gpr
[21] = ULONG_MAX
,
600 .gpr
[22] = ULONG_MAX
,
604 .descr
= "RA = ULONG_MAX, RB = 0x1",
605 .instr
= TEST_ADD_DOT(20, 21, 22),
607 .gpr
[21] = ULONG_MAX
,
612 .descr
= "RA = INT_MIN, RB = INT_MIN",
613 .instr
= TEST_ADD_DOT(20, 21, 22),
620 .descr
= "RA = INT_MIN, RB = INT_MAX",
621 .instr
= TEST_ADD_DOT(20, 21, 22),
628 .descr
= "RA = INT_MAX, RB = INT_MAX",
629 .instr
= TEST_ADD_DOT(20, 21, 22),
636 .descr
= "RA = UINT_MAX, RB = UINT_MAX",
637 .instr
= TEST_ADD_DOT(20, 21, 22),
644 .descr
= "RA = UINT_MAX, RB = 0x1",
645 .instr
= TEST_ADD_DOT(20, 21, 22),
657 .descr
= "RA = LONG_MIN, RB = LONG_MIN",
658 .instr
= TEST_ADDC(20, 21, 22),
665 .descr
= "RA = LONG_MIN, RB = LONG_MAX",
666 .instr
= TEST_ADDC(20, 21, 22),
673 .descr
= "RA = LONG_MAX, RB = LONG_MAX",
674 .instr
= TEST_ADDC(20, 21, 22),
681 .descr
= "RA = ULONG_MAX, RB = ULONG_MAX",
682 .instr
= TEST_ADDC(20, 21, 22),
684 .gpr
[21] = ULONG_MAX
,
685 .gpr
[22] = ULONG_MAX
,
689 .descr
= "RA = ULONG_MAX, RB = 0x1",
690 .instr
= TEST_ADDC(20, 21, 22),
692 .gpr
[21] = ULONG_MAX
,
697 .descr
= "RA = INT_MIN, RB = INT_MIN",
698 .instr
= TEST_ADDC(20, 21, 22),
705 .descr
= "RA = INT_MIN, RB = INT_MAX",
706 .instr
= TEST_ADDC(20, 21, 22),
713 .descr
= "RA = INT_MAX, RB = INT_MAX",
714 .instr
= TEST_ADDC(20, 21, 22),
721 .descr
= "RA = UINT_MAX, RB = UINT_MAX",
722 .instr
= TEST_ADDC(20, 21, 22),
729 .descr
= "RA = UINT_MAX, RB = 0x1",
730 .instr
= TEST_ADDC(20, 21, 22),
737 .descr
= "RA = LONG_MIN | INT_MIN, RB = LONG_MIN | INT_MIN",
738 .instr
= TEST_ADDC(20, 21, 22),
740 .gpr
[21] = LONG_MIN
| (uint
)INT_MIN
,
741 .gpr
[22] = LONG_MIN
| (uint
)INT_MIN
,
750 .descr
= "RA = LONG_MIN, RB = LONG_MIN",
752 .instr
= TEST_ADDC_DOT(20, 21, 22),
759 .descr
= "RA = LONG_MIN, RB = LONG_MAX",
760 .instr
= TEST_ADDC_DOT(20, 21, 22),
767 .descr
= "RA = LONG_MAX, RB = LONG_MAX",
769 .instr
= TEST_ADDC_DOT(20, 21, 22),
776 .descr
= "RA = ULONG_MAX, RB = ULONG_MAX",
777 .instr
= TEST_ADDC_DOT(20, 21, 22),
779 .gpr
[21] = ULONG_MAX
,
780 .gpr
[22] = ULONG_MAX
,
784 .descr
= "RA = ULONG_MAX, RB = 0x1",
785 .instr
= TEST_ADDC_DOT(20, 21, 22),
787 .gpr
[21] = ULONG_MAX
,
792 .descr
= "RA = INT_MIN, RB = INT_MIN",
793 .instr
= TEST_ADDC_DOT(20, 21, 22),
800 .descr
= "RA = INT_MIN, RB = INT_MAX",
801 .instr
= TEST_ADDC_DOT(20, 21, 22),
808 .descr
= "RA = INT_MAX, RB = INT_MAX",
809 .instr
= TEST_ADDC_DOT(20, 21, 22),
816 .descr
= "RA = UINT_MAX, RB = UINT_MAX",
817 .instr
= TEST_ADDC_DOT(20, 21, 22),
824 .descr
= "RA = UINT_MAX, RB = 0x1",
825 .instr
= TEST_ADDC_DOT(20, 21, 22),
832 .descr
= "RA = LONG_MIN | INT_MIN, RB = LONG_MIN | INT_MIN",
833 .instr
= TEST_ADDC_DOT(20, 21, 22),
835 .gpr
[21] = LONG_MIN
| (uint
)INT_MIN
,
836 .gpr
[22] = LONG_MIN
| (uint
)INT_MIN
,
843 static int __init
emulate_compute_instr(struct pt_regs
*regs
,
846 struct instruction_op op
;
851 if (analyse_instr(&op
, regs
, instr
) != 1 ||
852 GETTYPE(op
.type
) != COMPUTE
) {
853 pr_info("emulation failed, instruction = 0x%08x\n", instr
);
857 emulate_update_regs(regs
, &op
);
861 static int __init
execute_compute_instr(struct pt_regs
*regs
,
864 extern int exec_instr(struct pt_regs
*regs
);
865 extern s32 patch__exec_instr
;
870 /* Patch the NOP with the actual instruction */
871 patch_instruction_site(&patch__exec_instr
, instr
);
872 if (exec_instr(regs
)) {
873 pr_info("execution failed, instruction = 0x%08x\n", instr
);
880 #define gpr_mismatch(gprn, exp, got) \
881 pr_info("GPR%u mismatch, exp = 0x%016lx, got = 0x%016lx\n", \
884 #define reg_mismatch(name, exp, got) \
885 pr_info("%s mismatch, exp = 0x%016lx, got = 0x%016lx\n", \
888 static void __init
run_tests_compute(void)
891 struct compute_test
*test
;
892 struct pt_regs
*regs
, exp
, got
;
893 unsigned int i
, j
, k
, instr
;
894 bool ignore_gpr
, ignore_xer
, ignore_ccr
, passed
;
896 for (i
= 0; i
< ARRAY_SIZE(compute_tests
); i
++) {
897 test
= &compute_tests
[i
];
899 for (j
= 0; j
< MAX_SUBTESTS
&& test
->subtests
[j
].descr
; j
++) {
900 instr
= test
->subtests
[j
].instr
;
901 flags
= test
->subtests
[j
].flags
;
902 regs
= &test
->subtests
[j
].regs
;
903 ignore_xer
= flags
& IGNORE_XER
;
904 ignore_ccr
= flags
& IGNORE_CCR
;
907 memcpy(&exp
, regs
, sizeof(struct pt_regs
));
908 memcpy(&got
, regs
, sizeof(struct pt_regs
));
911 * Set a compatible MSR value explicitly to ensure
912 * that XER and CR bits are updated appropriately
914 exp
.msr
= MSR_KERNEL
;
915 got
.msr
= MSR_KERNEL
;
917 if (emulate_compute_instr(&got
, instr
) ||
918 execute_compute_instr(&exp
, instr
)) {
923 /* Verify GPR values */
924 for (k
= 0; k
< 32; k
++) {
925 ignore_gpr
= flags
& IGNORE_GPR(k
);
926 if (!ignore_gpr
&& exp
.gpr
[k
] != got
.gpr
[k
]) {
928 gpr_mismatch(k
, exp
.gpr
[k
], got
.gpr
[k
]);
932 /* Verify LR value */
933 if (exp
.link
!= got
.link
) {
935 reg_mismatch("LR", exp
.link
, got
.link
);
938 /* Verify XER value */
939 if (!ignore_xer
&& exp
.xer
!= got
.xer
) {
941 reg_mismatch("XER", exp
.xer
, got
.xer
);
944 /* Verify CR value */
945 if (!ignore_ccr
&& exp
.ccr
!= got
.ccr
) {
947 reg_mismatch("CR", exp
.ccr
, got
.ccr
);
951 show_result_with_descr(test
->mnemonic
,
952 test
->subtests
[j
].descr
,
953 passed
? "PASS" : "FAIL");
958 static int __init
test_emulate_step(void)
960 printk(KERN_INFO
"Running instruction emulation self-tests ...\n");
961 run_tests_load_store();
966 late_initcall(test_emulate_step
);