diff options
author | Leif Lindholm <leif.lindholm@arm.com> | 2011-12-12 19:45:24 +0100 |
---|---|---|
committer | Russell King <rmk+kernel@arm.linux.org.uk> | 2011-12-13 08:52:03 +0000 |
commit | c245dcd326fb9f8cca4b396796f0d2e54171b5c9 (patch) | |
tree | 4c7d4f696a6912a64d5acd4f01ca42d453722b86 /arch | |
parent | e7f626db83689f55089717a6d771c57afe1adc1a (diff) |
ARM: 7208/1: Add condition code checking to SWP emulation handler.
This patch fixes two separate issues with the SWP emulation handler:
1: Certain processors implementing ARMv7-A can (legally) take an
undef exception even when the condition code would have meant that
the instruction should not have been executed.
2: Opcodes with all flags set (condition code = 0xf) have been reused
in recent, and not-so-recent, versions of the ARM architecture to
implement unconditional extensions to the instruction set. The
existing code would still have processed any undefs triggered by
executing an opcode with such a value.
This patch uses the new generic ARM instruction set condition code
checks to implement proper handling of these situations.
Signed-off-by: Leif Lindholm <leif.lindholm@arm.com>
Reviewed-by: Will Deacon <will.deacon@arm.com>
Signed-off-by: Russell King <rmk+kernel@arm.linux.org.uk>
Diffstat (limited to 'arch')
-rw-r--r-- | arch/arm/kernel/swp_emulate.c | 16 |
1 files changed, 16 insertions, 0 deletions
diff --git a/arch/arm/kernel/swp_emulate.c b/arch/arm/kernel/swp_emulate.c index 5f452f8fde0..df745188f5d 100644 --- a/arch/arm/kernel/swp_emulate.c +++ b/arch/arm/kernel/swp_emulate.c @@ -25,6 +25,7 @@ #include <linux/syscalls.h> #include <linux/perf_event.h> +#include <asm/opcodes.h> #include <asm/traps.h> #include <asm/uaccess.h> @@ -185,6 +186,21 @@ static int swp_handler(struct pt_regs *regs, unsigned int instr) perf_sw_event(PERF_COUNT_SW_EMULATION_FAULTS, 1, regs, regs->ARM_pc); + res = arm_check_condition(instr, regs->ARM_cpsr); + switch (res) { + case ARM_OPCODE_CONDTEST_PASS: + break; + case ARM_OPCODE_CONDTEST_FAIL: + /* Condition failed - return to next instruction */ + regs->ARM_pc += 4; + return 0; + case ARM_OPCODE_CONDTEST_UNCOND: + /* If unconditional encoding - not a SWP, undef */ + return -EFAULT; + default: + return -EINVAL; + } + if (current->pid != previous_pid) { pr_debug("\"%s\" (%ld) uses deprecated SWP{B} instruction\n", current->comm, (unsigned long)current->pid); |