ARM: kprobes: Fix unreliable MRS instruction tests
authorJon Medhurst (Tixy) <tixy@linaro.org>
Mon, 5 Jan 2015 11:29:40 +0000 (19:29 +0800)
committerJon Medhurst <tixy@linaro.org>
Tue, 13 Jan 2015 16:10:17 +0000 (16:10 +0000)
For the instruction 'mrs Rn, cpsr' the resulting value of Rn can vary due to
external factors we can't control. So get the test code to mask out these
indeterminate bits.

Signed-off-by: Jon Medhurst <tixy@linaro.org>
arch/arm/probes/kprobes/test-arm.c
arch/arm/probes/kprobes/test-core.c
arch/arm/probes/kprobes/test-core.h
arch/arm/probes/kprobes/test-thumb.c

index 9b3b1b4a09391dec7fc5ddba364a01e05c7f2631..e72b07e8cd9accb505a340415c7a673ae6309b13 100644 (file)
@@ -204,9 +204,9 @@ void kprobe_arm_test_cases(void)
 #endif
        TEST_GROUP("Miscellaneous instructions")
 
-       TEST("mrs       r0, cpsr")
-       TEST("mrspl     r7, cpsr")
-       TEST("mrs       r14, cpsr")
+       TEST_RMASKED("mrs       r",0,~PSR_IGNORE_BITS,", cpsr")
+       TEST_RMASKED("mrspl     r",7,~PSR_IGNORE_BITS,", cpsr")
+       TEST_RMASKED("mrs       r",14,~PSR_IGNORE_BITS,", cpsr")
        TEST_UNSUPPORTED(__inst_arm(0xe10ff000) "       @ mrs r15, cpsr")
        TEST_UNSUPPORTED("mrs   r0, spsr")
        TEST_UNSUPPORTED("mrs   lr, spsr")
index 7c5ddd5a6afd48a22c11a189fbb467b6ec40d83a..e495127d757105d06b32d99b5a1bf4d03b3f9153 100644 (file)
@@ -1056,15 +1056,6 @@ static int test_case_run_count;
 static bool test_case_is_thumb;
 static int test_instance;
 
-/*
- * We ignore the state of the imprecise abort disable flag (CPSR.A) because this
- * can change randomly as the kernel doesn't take care to preserve or initialise
- * this across context switches. Also, with Security Extentions, the flag may
- * not be under control of the kernel; for this reason we ignore the state of
- * the FIQ disable flag CPSR.F as well.
- */
-#define PSR_IGNORE_BITS (PSR_A_BIT | PSR_F_BIT)
-
 static unsigned long test_check_cc(int cc, unsigned long cpsr)
 {
        int ret = arm_check_condition(cc << 28, cpsr);
@@ -1271,11 +1262,21 @@ test_case_pre_handler(struct kprobe *p, struct pt_regs *regs)
 static int __kprobes
 test_after_pre_handler(struct kprobe *p, struct pt_regs *regs)
 {
+       struct test_arg *args;
+
        if (container_of(p, struct test_probe, kprobe)->hit == test_instance)
                return 0; /* Already run for this test instance */
 
        result_regs = *regs;
+
+       /* Mask out results which are indeterminate */
        result_regs.ARM_cpsr &= ~PSR_IGNORE_BITS;
+       for (args = current_args; args[0].type != ARG_TYPE_END; ++args)
+               if (args[0].type == ARG_TYPE_REG_MASKED) {
+                       struct test_arg_regptr *arg =
+                               (struct test_arg_regptr *)args;
+                       result_regs.uregs[arg->reg] &= arg->val;
+               }
 
        /* Undo any changes done to SP by the test case */
        regs->ARM_sp = (unsigned long)current_stack;
index 9991754947bc1fd22bcbe101e0d31838d3deb0d1..94285203e9f74421153defc83a92ba65eedab9ea 100644 (file)
@@ -45,10 +45,11 @@ extern int kprobe_test_cc_position;
  *
  */
 
-#define        ARG_TYPE_END    0
-#define        ARG_TYPE_REG    1
-#define        ARG_TYPE_PTR    2
-#define        ARG_TYPE_MEM    3
+#define        ARG_TYPE_END            0
+#define        ARG_TYPE_REG            1
+#define        ARG_TYPE_PTR            2
+#define        ARG_TYPE_MEM            3
+#define        ARG_TYPE_REG_MASKED     4
 
 #define ARG_FLAG_UNSUPPORTED   0x01
 #define ARG_FLAG_SUPPORTED     0x02
@@ -61,7 +62,7 @@ struct test_arg {
 };
 
 struct test_arg_regptr {
-       u8      type;           /* ARG_TYPE_REG or ARG_TYPE_PTR */
+       u8      type;           /* ARG_TYPE_REG or ARG_TYPE_PTR or ARG_TYPE_REG_MASKED */
        u8      reg;
        u8      _padding[2];
        u32     val;
@@ -138,6 +139,12 @@ struct test_arg_end {
        ".short 0                                       \n\t"   \
        ".word  "#val"                                  \n\t"
 
+#define        TEST_ARG_REG_MASKED(reg, val)                           \
+       ".byte  "__stringify(ARG_TYPE_REG_MASKED)"      \n\t"   \
+       ".byte  "#reg"                                  \n\t"   \
+       ".short 0                                       \n\t"   \
+       ".word  "#val"                                  \n\t"
+
 #define        TEST_ARG_END(flags)                                     \
        ".byte  "__stringify(ARG_TYPE_END)"             \n\t"   \
        ".byte  "TEST_ISA flags"                        \n\t"   \
@@ -395,6 +402,22 @@ struct test_arg_end {
        "       "codex"                 \n\t"                                   \
        TESTCASE_END
 
+#define TEST_RMASKED(code1, reg, mask, code2)          \
+       TESTCASE_START(code1 #reg code2)                \
+       TEST_ARG_REG_MASKED(reg, mask)                  \
+       TEST_ARG_END("")                                \
+       TEST_INSTRUCTION(code1 #reg code2)              \
+       TESTCASE_END
+
+/*
+ * We ignore the state of the imprecise abort disable flag (CPSR.A) because this
+ * can change randomly as the kernel doesn't take care to preserve or initialise
+ * this across context switches. Also, with Security Extensions, the flag may
+ * not be under control of the kernel; for this reason we ignore the state of
+ * the FIQ disable flag CPSR.F as well.
+ */
+#define PSR_IGNORE_BITS (PSR_A_BIT | PSR_F_BIT)
+
 
 /*
  * Macros for defining space directives spread over multiple lines.
index e8cf193db1ea3085e9bc42f89634f58ef4dd2531..b683b4517458ce0c899ae4f02b56019d61ffb3f1 100644 (file)
@@ -778,8 +778,8 @@ CONDITION_INSTRUCTIONS(22,
 
        TEST_UNSUPPORTED("subs  pc, lr, #4")
 
-       TEST("mrs       r0, cpsr")
-       TEST("mrs       r14, cpsr")
+       TEST_RMASKED("mrs       r",0,~PSR_IGNORE_BITS,", cpsr")
+       TEST_RMASKED("mrs       r",14,~PSR_IGNORE_BITS,", cpsr")
        TEST_UNSUPPORTED(__inst_thumb32(0xf3ef8d00) "   @ mrs   sp, spsr")
        TEST_UNSUPPORTED(__inst_thumb32(0xf3ef8f00) "   @ mrs   pc, spsr")
        TEST_UNSUPPORTED("mrs   r0, spsr")