diff options
author | Jon Medhurst (Tixy) <tixy@linaro.org> | 2015-01-05 06:29:40 -0500 |
---|---|---|
committer | Jon Medhurst <tixy@linaro.org> | 2015-01-13 11:10:17 -0500 |
commit | 4cd872d973c7e1ce6a41e36db9d9352152da32d4 (patch) | |
tree | 9418dd882418266bcbd60e0d7d757615b02ac6d0 | |
parent | 0dc016dbd820260b8ea74337980735b8c88d4ef2 (diff) |
ARM: kprobes: Fix unreliable MRS instruction tests
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>
-rw-r--r-- | arch/arm/probes/kprobes/test-arm.c | 6 | ||||
-rw-r--r-- | arch/arm/probes/kprobes/test-core.c | 19 | ||||
-rw-r--r-- | arch/arm/probes/kprobes/test-core.h | 33 | ||||
-rw-r--r-- | arch/arm/probes/kprobes/test-thumb.c | 4 |
4 files changed, 43 insertions, 19 deletions
diff --git a/arch/arm/probes/kprobes/test-arm.c b/arch/arm/probes/kprobes/test-arm.c index 9b3b1b4a0939..e72b07e8cd9a 100644 --- a/arch/arm/probes/kprobes/test-arm.c +++ b/arch/arm/probes/kprobes/test-arm.c | |||
@@ -204,9 +204,9 @@ void kprobe_arm_test_cases(void) | |||
204 | #endif | 204 | #endif |
205 | TEST_GROUP("Miscellaneous instructions") | 205 | TEST_GROUP("Miscellaneous instructions") |
206 | 206 | ||
207 | TEST("mrs r0, cpsr") | 207 | TEST_RMASKED("mrs r",0,~PSR_IGNORE_BITS,", cpsr") |
208 | TEST("mrspl r7, cpsr") | 208 | TEST_RMASKED("mrspl r",7,~PSR_IGNORE_BITS,", cpsr") |
209 | TEST("mrs r14, cpsr") | 209 | TEST_RMASKED("mrs r",14,~PSR_IGNORE_BITS,", cpsr") |
210 | TEST_UNSUPPORTED(__inst_arm(0xe10ff000) " @ mrs r15, cpsr") | 210 | TEST_UNSUPPORTED(__inst_arm(0xe10ff000) " @ mrs r15, cpsr") |
211 | TEST_UNSUPPORTED("mrs r0, spsr") | 211 | TEST_UNSUPPORTED("mrs r0, spsr") |
212 | TEST_UNSUPPORTED("mrs lr, spsr") | 212 | TEST_UNSUPPORTED("mrs lr, spsr") |
diff --git a/arch/arm/probes/kprobes/test-core.c b/arch/arm/probes/kprobes/test-core.c index 7c5ddd5a6afd..e495127d7571 100644 --- a/arch/arm/probes/kprobes/test-core.c +++ b/arch/arm/probes/kprobes/test-core.c | |||
@@ -1056,15 +1056,6 @@ static int test_case_run_count; | |||
1056 | static bool test_case_is_thumb; | 1056 | static bool test_case_is_thumb; |
1057 | static int test_instance; | 1057 | static int test_instance; |
1058 | 1058 | ||
1059 | /* | ||
1060 | * We ignore the state of the imprecise abort disable flag (CPSR.A) because this | ||
1061 | * can change randomly as the kernel doesn't take care to preserve or initialise | ||
1062 | * this across context switches. Also, with Security Extentions, the flag may | ||
1063 | * not be under control of the kernel; for this reason we ignore the state of | ||
1064 | * the FIQ disable flag CPSR.F as well. | ||
1065 | */ | ||
1066 | #define PSR_IGNORE_BITS (PSR_A_BIT | PSR_F_BIT) | ||
1067 | |||
1068 | static unsigned long test_check_cc(int cc, unsigned long cpsr) | 1059 | static unsigned long test_check_cc(int cc, unsigned long cpsr) |
1069 | { | 1060 | { |
1070 | int ret = arm_check_condition(cc << 28, cpsr); | 1061 | int ret = arm_check_condition(cc << 28, cpsr); |
@@ -1271,11 +1262,21 @@ test_case_pre_handler(struct kprobe *p, struct pt_regs *regs) | |||
1271 | static int __kprobes | 1262 | static int __kprobes |
1272 | test_after_pre_handler(struct kprobe *p, struct pt_regs *regs) | 1263 | test_after_pre_handler(struct kprobe *p, struct pt_regs *regs) |
1273 | { | 1264 | { |
1265 | struct test_arg *args; | ||
1266 | |||
1274 | if (container_of(p, struct test_probe, kprobe)->hit == test_instance) | 1267 | if (container_of(p, struct test_probe, kprobe)->hit == test_instance) |
1275 | return 0; /* Already run for this test instance */ | 1268 | return 0; /* Already run for this test instance */ |
1276 | 1269 | ||
1277 | result_regs = *regs; | 1270 | result_regs = *regs; |
1271 | |||
1272 | /* Mask out results which are indeterminate */ | ||
1278 | result_regs.ARM_cpsr &= ~PSR_IGNORE_BITS; | 1273 | result_regs.ARM_cpsr &= ~PSR_IGNORE_BITS; |
1274 | for (args = current_args; args[0].type != ARG_TYPE_END; ++args) | ||
1275 | if (args[0].type == ARG_TYPE_REG_MASKED) { | ||
1276 | struct test_arg_regptr *arg = | ||
1277 | (struct test_arg_regptr *)args; | ||
1278 | result_regs.uregs[arg->reg] &= arg->val; | ||
1279 | } | ||
1279 | 1280 | ||
1280 | /* Undo any changes done to SP by the test case */ | 1281 | /* Undo any changes done to SP by the test case */ |
1281 | regs->ARM_sp = (unsigned long)current_stack; | 1282 | regs->ARM_sp = (unsigned long)current_stack; |
diff --git a/arch/arm/probes/kprobes/test-core.h b/arch/arm/probes/kprobes/test-core.h index 9991754947bc..94285203e9f7 100644 --- a/arch/arm/probes/kprobes/test-core.h +++ b/arch/arm/probes/kprobes/test-core.h | |||
@@ -45,10 +45,11 @@ extern int kprobe_test_cc_position; | |||
45 | * | 45 | * |
46 | */ | 46 | */ |
47 | 47 | ||
48 | #define ARG_TYPE_END 0 | 48 | #define ARG_TYPE_END 0 |
49 | #define ARG_TYPE_REG 1 | 49 | #define ARG_TYPE_REG 1 |
50 | #define ARG_TYPE_PTR 2 | 50 | #define ARG_TYPE_PTR 2 |
51 | #define ARG_TYPE_MEM 3 | 51 | #define ARG_TYPE_MEM 3 |
52 | #define ARG_TYPE_REG_MASKED 4 | ||
52 | 53 | ||
53 | #define ARG_FLAG_UNSUPPORTED 0x01 | 54 | #define ARG_FLAG_UNSUPPORTED 0x01 |
54 | #define ARG_FLAG_SUPPORTED 0x02 | 55 | #define ARG_FLAG_SUPPORTED 0x02 |
@@ -61,7 +62,7 @@ struct test_arg { | |||
61 | }; | 62 | }; |
62 | 63 | ||
63 | struct test_arg_regptr { | 64 | struct test_arg_regptr { |
64 | u8 type; /* ARG_TYPE_REG or ARG_TYPE_PTR */ | 65 | u8 type; /* ARG_TYPE_REG or ARG_TYPE_PTR or ARG_TYPE_REG_MASKED */ |
65 | u8 reg; | 66 | u8 reg; |
66 | u8 _padding[2]; | 67 | u8 _padding[2]; |
67 | u32 val; | 68 | u32 val; |
@@ -138,6 +139,12 @@ struct test_arg_end { | |||
138 | ".short 0 \n\t" \ | 139 | ".short 0 \n\t" \ |
139 | ".word "#val" \n\t" | 140 | ".word "#val" \n\t" |
140 | 141 | ||
142 | #define TEST_ARG_REG_MASKED(reg, val) \ | ||
143 | ".byte "__stringify(ARG_TYPE_REG_MASKED)" \n\t" \ | ||
144 | ".byte "#reg" \n\t" \ | ||
145 | ".short 0 \n\t" \ | ||
146 | ".word "#val" \n\t" | ||
147 | |||
141 | #define TEST_ARG_END(flags) \ | 148 | #define TEST_ARG_END(flags) \ |
142 | ".byte "__stringify(ARG_TYPE_END)" \n\t" \ | 149 | ".byte "__stringify(ARG_TYPE_END)" \n\t" \ |
143 | ".byte "TEST_ISA flags" \n\t" \ | 150 | ".byte "TEST_ISA flags" \n\t" \ |
@@ -395,6 +402,22 @@ struct test_arg_end { | |||
395 | " "codex" \n\t" \ | 402 | " "codex" \n\t" \ |
396 | TESTCASE_END | 403 | TESTCASE_END |
397 | 404 | ||
405 | #define TEST_RMASKED(code1, reg, mask, code2) \ | ||
406 | TESTCASE_START(code1 #reg code2) \ | ||
407 | TEST_ARG_REG_MASKED(reg, mask) \ | ||
408 | TEST_ARG_END("") \ | ||
409 | TEST_INSTRUCTION(code1 #reg code2) \ | ||
410 | TESTCASE_END | ||
411 | |||
412 | /* | ||
413 | * We ignore the state of the imprecise abort disable flag (CPSR.A) because this | ||
414 | * can change randomly as the kernel doesn't take care to preserve or initialise | ||
415 | * this across context switches. Also, with Security Extensions, the flag may | ||
416 | * not be under control of the kernel; for this reason we ignore the state of | ||
417 | * the FIQ disable flag CPSR.F as well. | ||
418 | */ | ||
419 | #define PSR_IGNORE_BITS (PSR_A_BIT | PSR_F_BIT) | ||
420 | |||
398 | 421 | ||
399 | /* | 422 | /* |
400 | * Macros for defining space directives spread over multiple lines. | 423 | * Macros for defining space directives spread over multiple lines. |
diff --git a/arch/arm/probes/kprobes/test-thumb.c b/arch/arm/probes/kprobes/test-thumb.c index e8cf193db1ea..b683b4517458 100644 --- a/arch/arm/probes/kprobes/test-thumb.c +++ b/arch/arm/probes/kprobes/test-thumb.c | |||
@@ -778,8 +778,8 @@ CONDITION_INSTRUCTIONS(22, | |||
778 | 778 | ||
779 | TEST_UNSUPPORTED("subs pc, lr, #4") | 779 | TEST_UNSUPPORTED("subs pc, lr, #4") |
780 | 780 | ||
781 | TEST("mrs r0, cpsr") | 781 | TEST_RMASKED("mrs r",0,~PSR_IGNORE_BITS,", cpsr") |
782 | TEST("mrs r14, cpsr") | 782 | TEST_RMASKED("mrs r",14,~PSR_IGNORE_BITS,", cpsr") |
783 | TEST_UNSUPPORTED(__inst_thumb32(0xf3ef8d00) " @ mrs sp, spsr") | 783 | TEST_UNSUPPORTED(__inst_thumb32(0xf3ef8d00) " @ mrs sp, spsr") |
784 | TEST_UNSUPPORTED(__inst_thumb32(0xf3ef8f00) " @ mrs pc, spsr") | 784 | TEST_UNSUPPORTED(__inst_thumb32(0xf3ef8f00) " @ mrs pc, spsr") |
785 | TEST_UNSUPPORTED("mrs r0, spsr") | 785 | TEST_UNSUPPORTED("mrs r0, spsr") |