2 * Simple sanity tests for instruction emulation infrastructure.
4 * Copyright IBM Corp. 2016
6 * This program is free software; you can redistribute it and/or modify
7 * it under the terms of the GNU General Public License as published by
8 * the Free Software Foundation; either version 2 of the License, or
9 * (at your option) any later version.
12 #define pr_fmt(fmt) "emulate_step_test: " fmt
14 #include <linux/ptrace.h>
15 #include <asm/sstep.h>
16 #include <asm/ppc-opcode.h>
17 #include <asm/code-patching.h>
19 #define IMM_L(i) ((uintptr_t)(i) & 0xffff)
22 * Defined with TEST_ prefix so it does not conflict with other
25 #define TEST_LD(r, base, i) (PPC_INST_LD | ___PPC_RT(r) | \
26 ___PPC_RA(base) | IMM_L(i))
27 #define TEST_LWZ(r, base, i) (PPC_INST_LWZ | ___PPC_RT(r) | \
28 ___PPC_RA(base) | IMM_L(i))
29 #define TEST_LWZX(t, a, b) (PPC_INST_LWZX | ___PPC_RT(t) | \
30 ___PPC_RA(a) | ___PPC_RB(b))
31 #define TEST_STD(r, base, i) (PPC_INST_STD | ___PPC_RS(r) | \
32 ___PPC_RA(base) | ((i) & 0xfffc))
33 #define TEST_LDARX(t, a, b, eh) (PPC_INST_LDARX | ___PPC_RT(t) | \
34 ___PPC_RA(a) | ___PPC_RB(b) | \
36 #define TEST_STDCX(s, a, b) (PPC_INST_STDCX | ___PPC_RS(s) | \
37 ___PPC_RA(a) | ___PPC_RB(b))
38 #define TEST_LFSX(t, a, b) (PPC_INST_LFSX | ___PPC_RT(t) | \
39 ___PPC_RA(a) | ___PPC_RB(b))
40 #define TEST_STFSX(s, a, b) (PPC_INST_STFSX | ___PPC_RS(s) | \
41 ___PPC_RA(a) | ___PPC_RB(b))
42 #define TEST_LFDX(t, a, b) (PPC_INST_LFDX | ___PPC_RT(t) | \
43 ___PPC_RA(a) | ___PPC_RB(b))
44 #define TEST_STFDX(s, a, b) (PPC_INST_STFDX | ___PPC_RS(s) | \
45 ___PPC_RA(a) | ___PPC_RB(b))
46 #define TEST_LVX(t, a, b) (PPC_INST_LVX | ___PPC_RT(t) | \
47 ___PPC_RA(a) | ___PPC_RB(b))
48 #define TEST_STVX(s, a, b) (PPC_INST_STVX | ___PPC_RS(s) | \
49 ___PPC_RA(a) | ___PPC_RB(b))
50 #define TEST_LXVD2X(s, a, b) (PPC_INST_LXVD2X | VSX_XX1((s), R##a, R##b))
51 #define TEST_STXVD2X(s, a, b) (PPC_INST_STXVD2X | VSX_XX1((s), R##a, R##b))
52 #define TEST_ADD(t, a, b) (PPC_INST_ADD | ___PPC_RT(t) | \
53 ___PPC_RA(a) | ___PPC_RB(b))
54 #define TEST_ADD_DOT(t, a, b) (PPC_INST_ADD | ___PPC_RT(t) | \
55 ___PPC_RA(a) | ___PPC_RB(b) | 0x1)
56 #define TEST_ADDC(t, a, b) (PPC_INST_ADDC | ___PPC_RT(t) | \
57 ___PPC_RA(a) | ___PPC_RB(b))
58 #define TEST_ADDC_DOT(t, a, b) (PPC_INST_ADDC | ___PPC_RT(t) | \
59 ___PPC_RA(a) | ___PPC_RB(b) | 0x1)
61 #define MAX_SUBTESTS 16
63 #define IGNORE_GPR(n) (0x1UL << (n))
64 #define IGNORE_XER (0x1UL << 32)
65 #define IGNORE_CCR (0x1UL << 33)
67 static void __init init_pt_regs(struct pt_regs *regs)
69 static unsigned long msr;
70 static bool msr_cached;
72 memset(regs, 0, sizeof(struct pt_regs));
74 if (likely(msr_cached)) {
79 asm volatile("mfmsr %0" : "=r"(regs->msr));
89 static void __init show_result(char *mnemonic, char *result)
91 pr_info("%-14s : %s\n", mnemonic, result);
94 static void __init show_result_with_descr(char *mnemonic, char *descr,
97 pr_info("%-14s : %-50s %s\n", mnemonic, descr, result);
100 static void __init test_ld(void)
103 unsigned long a = 0x23;
107 regs.gpr[3] = (unsigned long) &a;
110 stepped = emulate_step(®s, TEST_LD(5, 3, 0));
112 if (stepped == 1 && regs.gpr[5] == a)
113 show_result("ld", "PASS");
115 show_result("ld", "FAIL");
118 static void __init test_lwz(void)
121 unsigned int a = 0x4545;
125 regs.gpr[3] = (unsigned long) &a;
128 stepped = emulate_step(®s, TEST_LWZ(5, 3, 0));
130 if (stepped == 1 && regs.gpr[5] == a)
131 show_result("lwz", "PASS");
133 show_result("lwz", "FAIL");
136 static void __init test_lwzx(void)
139 unsigned int a[3] = {0x0, 0x0, 0x1234};
143 regs.gpr[3] = (unsigned long) a;
145 regs.gpr[5] = 0x8765;
147 /* lwzx r5, r3, r4 */
148 stepped = emulate_step(®s, TEST_LWZX(5, 3, 4));
149 if (stepped == 1 && regs.gpr[5] == a[2])
150 show_result("lwzx", "PASS");
152 show_result("lwzx", "FAIL");
155 static void __init test_std(void)
158 unsigned long a = 0x1234;
162 regs.gpr[3] = (unsigned long) &a;
163 regs.gpr[5] = 0x5678;
166 stepped = emulate_step(®s, TEST_STD(5, 3, 0));
167 if (stepped == 1 || regs.gpr[5] == a)
168 show_result("std", "PASS");
170 show_result("std", "FAIL");
173 static void __init test_ldarx_stdcx(void)
176 unsigned long a = 0x1234;
178 unsigned long cr0_eq = 0x1 << 29; /* eq bit of CR0 */
181 asm volatile("mfcr %0" : "=r"(regs.ccr));
186 regs.gpr[3] = (unsigned long) &a;
188 regs.gpr[5] = 0x5678;
190 /* ldarx r5, r3, r4, 0 */
191 stepped = emulate_step(®s, TEST_LDARX(5, 3, 4, 0));
194 * Don't touch 'a' here. Touching 'a' can do Load/store
195 * of 'a' which result in failure of subsequent stdcx.
196 * Instead, use hardcoded value for comparison.
198 if (stepped <= 0 || regs.gpr[5] != 0x1234) {
199 show_result("ldarx / stdcx.", "FAIL (ldarx)");
206 regs.gpr[5] = 0x9ABC;
208 /* stdcx. r5, r3, r4 */
209 stepped = emulate_step(®s, TEST_STDCX(5, 3, 4));
212 * Two possible scenarios that indicates successful emulation
214 * 1. Reservation is active and store is performed. In this
215 * case cr0.eq bit will be set to 1.
216 * 2. Reservation is not active and store is not performed.
217 * In this case cr0.eq bit will be set to 0.
219 if (stepped == 1 && ((regs.gpr[5] == a && (regs.ccr & cr0_eq))
220 || (regs.gpr[5] != a && !(regs.ccr & cr0_eq))))
221 show_result("ldarx / stdcx.", "PASS");
223 show_result("ldarx / stdcx.", "FAIL (stdcx.)");
226 #ifdef CONFIG_PPC_FPU
227 static void __init test_lfsx_stfsx(void)
245 regs.gpr[3] = (unsigned long) &c.a;
248 /* lfsx frt10, r3, r4 */
249 stepped = emulate_step(®s, TEST_LFSX(10, 3, 4));
252 show_result("lfsx", "PASS");
254 show_result("lfsx", "FAIL");
261 /* stfsx frs10, r3, r4 */
262 stepped = emulate_step(®s, TEST_STFSX(10, 3, 4));
264 if (stepped == 1 && c.b == cached_b)
265 show_result("stfsx", "PASS");
267 show_result("stfsx", "FAIL");
270 static void __init test_lfdx_stfdx(void)
288 regs.gpr[3] = (unsigned long) &c.a;
291 /* lfdx frt10, r3, r4 */
292 stepped = emulate_step(®s, TEST_LFDX(10, 3, 4));
295 show_result("lfdx", "PASS");
297 show_result("lfdx", "FAIL");
304 /* stfdx frs10, r3, r4 */
305 stepped = emulate_step(®s, TEST_STFDX(10, 3, 4));
307 if (stepped == 1 && c.b == cached_b)
308 show_result("stfdx", "PASS");
310 show_result("stfdx", "FAIL");
313 static void __init test_lfsx_stfsx(void)
315 show_result("lfsx", "SKIP (CONFIG_PPC_FPU is not set)");
316 show_result("stfsx", "SKIP (CONFIG_PPC_FPU is not set)");
319 static void __init test_lfdx_stfdx(void)
321 show_result("lfdx", "SKIP (CONFIG_PPC_FPU is not set)");
322 show_result("stfdx", "SKIP (CONFIG_PPC_FPU is not set)");
324 #endif /* CONFIG_PPC_FPU */
326 #ifdef CONFIG_ALTIVEC
327 static void __init test_lvx_stvx(void)
342 cached_b[0] = c.b[0] = 923745;
343 cached_b[1] = c.b[1] = 2139478;
344 cached_b[2] = c.b[2] = 9012;
345 cached_b[3] = c.b[3] = 982134;
347 regs.gpr[3] = (unsigned long) &c.a;
350 /* lvx vrt10, r3, r4 */
351 stepped = emulate_step(®s, TEST_LVX(10, 3, 4));
354 show_result("lvx", "PASS");
356 show_result("lvx", "FAIL");
366 /* stvx vrs10, r3, r4 */
367 stepped = emulate_step(®s, TEST_STVX(10, 3, 4));
369 if (stepped == 1 && cached_b[0] == c.b[0] && cached_b[1] == c.b[1] &&
370 cached_b[2] == c.b[2] && cached_b[3] == c.b[3])
371 show_result("stvx", "PASS");
373 show_result("stvx", "FAIL");
376 static void __init test_lvx_stvx(void)
378 show_result("lvx", "SKIP (CONFIG_ALTIVEC is not set)");
379 show_result("stvx", "SKIP (CONFIG_ALTIVEC is not set)");
381 #endif /* CONFIG_ALTIVEC */
384 static void __init test_lxvd2x_stxvd2x(void)
399 cached_b[0] = c.b[0] = 18233;
400 cached_b[1] = c.b[1] = 34863571;
401 cached_b[2] = c.b[2] = 834;
402 cached_b[3] = c.b[3] = 6138911;
404 regs.gpr[3] = (unsigned long) &c.a;
407 /* lxvd2x vsr39, r3, r4 */
408 stepped = emulate_step(®s, TEST_LXVD2X(39, 3, 4));
410 if (stepped == 1 && cpu_has_feature(CPU_FTR_VSX)) {
411 show_result("lxvd2x", "PASS");
413 if (!cpu_has_feature(CPU_FTR_VSX))
414 show_result("lxvd2x", "PASS (!CPU_FTR_VSX)");
416 show_result("lxvd2x", "FAIL");
427 /* stxvd2x vsr39, r3, r4 */
428 stepped = emulate_step(®s, TEST_STXVD2X(39, 3, 4));
430 if (stepped == 1 && cached_b[0] == c.b[0] && cached_b[1] == c.b[1] &&
431 cached_b[2] == c.b[2] && cached_b[3] == c.b[3] &&
432 cpu_has_feature(CPU_FTR_VSX)) {
433 show_result("stxvd2x", "PASS");
435 if (!cpu_has_feature(CPU_FTR_VSX))
436 show_result("stxvd2x", "PASS (!CPU_FTR_VSX)");
438 show_result("stxvd2x", "FAIL");
442 static void __init test_lxvd2x_stxvd2x(void)
444 show_result("lxvd2x", "SKIP (CONFIG_VSX is not set)");
445 show_result("stxvd2x", "SKIP (CONFIG_VSX is not set)");
447 #endif /* CONFIG_VSX */
449 static void __init run_tests_load_store(void)
459 test_lxvd2x_stxvd2x();
462 struct compute_test {
469 } subtests[MAX_SUBTESTS + 1];
472 static struct compute_test compute_tests[] = {
477 .descr = "R0 = LONG_MAX",
478 .instr = PPC_INST_NOP,
489 .descr = "RA = LONG_MIN, RB = LONG_MIN",
490 .instr = TEST_ADD(20, 21, 22),
497 .descr = "RA = LONG_MIN, RB = LONG_MAX",
498 .instr = TEST_ADD(20, 21, 22),
505 .descr = "RA = LONG_MAX, RB = LONG_MAX",
506 .instr = TEST_ADD(20, 21, 22),
513 .descr = "RA = ULONG_MAX, RB = ULONG_MAX",
514 .instr = TEST_ADD(20, 21, 22),
516 .gpr[21] = ULONG_MAX,
517 .gpr[22] = ULONG_MAX,
521 .descr = "RA = ULONG_MAX, RB = 0x1",
522 .instr = TEST_ADD(20, 21, 22),
524 .gpr[21] = ULONG_MAX,
529 .descr = "RA = INT_MIN, RB = INT_MIN",
530 .instr = TEST_ADD(20, 21, 22),
537 .descr = "RA = INT_MIN, RB = INT_MAX",
538 .instr = TEST_ADD(20, 21, 22),
545 .descr = "RA = INT_MAX, RB = INT_MAX",
546 .instr = TEST_ADD(20, 21, 22),
553 .descr = "RA = UINT_MAX, RB = UINT_MAX",
554 .instr = TEST_ADD(20, 21, 22),
561 .descr = "RA = UINT_MAX, RB = 0x1",
562 .instr = TEST_ADD(20, 21, 22),
574 .descr = "RA = LONG_MIN, RB = LONG_MIN",
576 .instr = TEST_ADD_DOT(20, 21, 22),
583 .descr = "RA = LONG_MIN, RB = LONG_MAX",
584 .instr = TEST_ADD_DOT(20, 21, 22),
591 .descr = "RA = LONG_MAX, RB = LONG_MAX",
593 .instr = TEST_ADD_DOT(20, 21, 22),
600 .descr = "RA = ULONG_MAX, RB = ULONG_MAX",
601 .instr = TEST_ADD_DOT(20, 21, 22),
603 .gpr[21] = ULONG_MAX,
604 .gpr[22] = ULONG_MAX,
608 .descr = "RA = ULONG_MAX, RB = 0x1",
609 .instr = TEST_ADD_DOT(20, 21, 22),
611 .gpr[21] = ULONG_MAX,
616 .descr = "RA = INT_MIN, RB = INT_MIN",
617 .instr = TEST_ADD_DOT(20, 21, 22),
624 .descr = "RA = INT_MIN, RB = INT_MAX",
625 .instr = TEST_ADD_DOT(20, 21, 22),
632 .descr = "RA = INT_MAX, RB = INT_MAX",
633 .instr = TEST_ADD_DOT(20, 21, 22),
640 .descr = "RA = UINT_MAX, RB = UINT_MAX",
641 .instr = TEST_ADD_DOT(20, 21, 22),
648 .descr = "RA = UINT_MAX, RB = 0x1",
649 .instr = TEST_ADD_DOT(20, 21, 22),
661 .descr = "RA = LONG_MIN, RB = LONG_MIN",
662 .instr = TEST_ADDC(20, 21, 22),
669 .descr = "RA = LONG_MIN, RB = LONG_MAX",
670 .instr = TEST_ADDC(20, 21, 22),
677 .descr = "RA = LONG_MAX, RB = LONG_MAX",
678 .instr = TEST_ADDC(20, 21, 22),
685 .descr = "RA = ULONG_MAX, RB = ULONG_MAX",
686 .instr = TEST_ADDC(20, 21, 22),
688 .gpr[21] = ULONG_MAX,
689 .gpr[22] = ULONG_MAX,
693 .descr = "RA = ULONG_MAX, RB = 0x1",
694 .instr = TEST_ADDC(20, 21, 22),
696 .gpr[21] = ULONG_MAX,
701 .descr = "RA = INT_MIN, RB = INT_MIN",
702 .instr = TEST_ADDC(20, 21, 22),
709 .descr = "RA = INT_MIN, RB = INT_MAX",
710 .instr = TEST_ADDC(20, 21, 22),
717 .descr = "RA = INT_MAX, RB = INT_MAX",
718 .instr = TEST_ADDC(20, 21, 22),
725 .descr = "RA = UINT_MAX, RB = UINT_MAX",
726 .instr = TEST_ADDC(20, 21, 22),
733 .descr = "RA = UINT_MAX, RB = 0x1",
734 .instr = TEST_ADDC(20, 21, 22),
741 .descr = "RA = LONG_MIN | INT_MIN, RB = LONG_MIN | INT_MIN",
742 .instr = TEST_ADDC(20, 21, 22),
744 .gpr[21] = LONG_MIN | (uint)INT_MIN,
745 .gpr[22] = LONG_MIN | (uint)INT_MIN,
754 .descr = "RA = LONG_MIN, RB = LONG_MIN",
756 .instr = TEST_ADDC_DOT(20, 21, 22),
763 .descr = "RA = LONG_MIN, RB = LONG_MAX",
764 .instr = TEST_ADDC_DOT(20, 21, 22),
771 .descr = "RA = LONG_MAX, RB = LONG_MAX",
773 .instr = TEST_ADDC_DOT(20, 21, 22),
780 .descr = "RA = ULONG_MAX, RB = ULONG_MAX",
781 .instr = TEST_ADDC_DOT(20, 21, 22),
783 .gpr[21] = ULONG_MAX,
784 .gpr[22] = ULONG_MAX,
788 .descr = "RA = ULONG_MAX, RB = 0x1",
789 .instr = TEST_ADDC_DOT(20, 21, 22),
791 .gpr[21] = ULONG_MAX,
796 .descr = "RA = INT_MIN, RB = INT_MIN",
797 .instr = TEST_ADDC_DOT(20, 21, 22),
804 .descr = "RA = INT_MIN, RB = INT_MAX",
805 .instr = TEST_ADDC_DOT(20, 21, 22),
812 .descr = "RA = INT_MAX, RB = INT_MAX",
813 .instr = TEST_ADDC_DOT(20, 21, 22),
820 .descr = "RA = UINT_MAX, RB = UINT_MAX",
821 .instr = TEST_ADDC_DOT(20, 21, 22),
828 .descr = "RA = UINT_MAX, RB = 0x1",
829 .instr = TEST_ADDC_DOT(20, 21, 22),
836 .descr = "RA = LONG_MIN | INT_MIN, RB = LONG_MIN | INT_MIN",
837 .instr = TEST_ADDC_DOT(20, 21, 22),
839 .gpr[21] = LONG_MIN | (uint)INT_MIN,
840 .gpr[22] = LONG_MIN | (uint)INT_MIN,
847 static int __init emulate_compute_instr(struct pt_regs *regs,
850 struct instruction_op op;
855 if (analyse_instr(&op, regs, instr) != 1 ||
856 GETTYPE(op.type) != COMPUTE) {
857 pr_info("emulation failed, instruction = 0x%08x\n", instr);
861 emulate_update_regs(regs, &op);
865 static int __init execute_compute_instr(struct pt_regs *regs,
868 extern int exec_instr(struct pt_regs *regs);
869 extern s32 patch__exec_instr;
874 /* Patch the NOP with the actual instruction */
875 patch_instruction_site(&patch__exec_instr, instr);
876 if (exec_instr(regs)) {
877 pr_info("execution failed, instruction = 0x%08x\n", instr);
884 #define gpr_mismatch(gprn, exp, got) \
885 pr_info("GPR%u mismatch, exp = 0x%016lx, got = 0x%016lx\n", \
888 #define reg_mismatch(name, exp, got) \
889 pr_info("%s mismatch, exp = 0x%016lx, got = 0x%016lx\n", \
892 static void __init run_tests_compute(void)
895 struct compute_test *test;
896 struct pt_regs *regs, exp, got;
897 unsigned int i, j, k, instr;
898 bool ignore_gpr, ignore_xer, ignore_ccr, passed;
900 for (i = 0; i < ARRAY_SIZE(compute_tests); i++) {
901 test = &compute_tests[i];
903 for (j = 0; j < MAX_SUBTESTS && test->subtests[j].descr; j++) {
904 instr = test->subtests[j].instr;
905 flags = test->subtests[j].flags;
906 regs = &test->subtests[j].regs;
907 ignore_xer = flags & IGNORE_XER;
908 ignore_ccr = flags & IGNORE_CCR;
911 memcpy(&exp, regs, sizeof(struct pt_regs));
912 memcpy(&got, regs, sizeof(struct pt_regs));
915 * Set a compatible MSR value explicitly to ensure
916 * that XER and CR bits are updated appropriately
918 exp.msr = MSR_KERNEL;
919 got.msr = MSR_KERNEL;
921 if (emulate_compute_instr(&got, instr) ||
922 execute_compute_instr(&exp, instr)) {
927 /* Verify GPR values */
928 for (k = 0; k < 32; k++) {
929 ignore_gpr = flags & IGNORE_GPR(k);
930 if (!ignore_gpr && exp.gpr[k] != got.gpr[k]) {
932 gpr_mismatch(k, exp.gpr[k], got.gpr[k]);
936 /* Verify LR value */
937 if (exp.link != got.link) {
939 reg_mismatch("LR", exp.link, got.link);
942 /* Verify XER value */
943 if (!ignore_xer && exp.xer != got.xer) {
945 reg_mismatch("XER", exp.xer, got.xer);
948 /* Verify CR value */
949 if (!ignore_ccr && exp.ccr != got.ccr) {
951 reg_mismatch("CR", exp.ccr, got.ccr);
955 show_result_with_descr(test->mnemonic,
956 test->subtests[j].descr,
957 passed ? "PASS" : "FAIL");
962 static int __init test_emulate_step(void)
964 printk(KERN_INFO "Running instruction emulation self-tests ...\n");
965 run_tests_load_store();
970 late_initcall(test_emulate_step);