diff options
author | Jon Medhurst <tixy@yxit.co.uk> | 2011-04-18 03:53:57 -0400 |
---|---|---|
committer | Nicolas Pitre <nicolas.pitre@linaro.org> | 2011-04-28 23:40:59 -0400 |
commit | 41713d1396312a027ec02abc4767041627c178ef (patch) | |
tree | 778fedcc66cf4e15ca1e0eeb8502715bd84d021d | |
parent | f0aeb8bff0fe9de50e1e4093ef86ff8f17a9b1b0 (diff) |
ARM: kprobes: Fix emulation of PLD instructions
The PLD instructions wasn't being decoded correctly and the emulation
code wasn't adjusting PC correctly.
As the PLD instruction is only a performance hint we emulate it as a
simple nop, and we can broaden the instruction decoding to take into
account newer PLI and PLDW instructions.
Signed-off-by: Jon Medhurst <tixy@yxit.co.uk>
Signed-off-by: Nicolas Pitre <nicolas.pitre@linaro.org>
-rw-r--r-- | arch/arm/kernel/kprobes-decode.c | 21 |
1 files changed, 8 insertions, 13 deletions
diff --git a/arch/arm/kernel/kprobes-decode.c b/arch/arm/kernel/kprobes-decode.c index b81fbfb33151..bddf8d0f3dc1 100644 --- a/arch/arm/kernel/kprobes-decode.c +++ b/arch/arm/kernel/kprobes-decode.c | |||
@@ -657,14 +657,8 @@ static void __kprobes emulate_none(struct kprobe *p, struct pt_regs *regs) | |||
657 | insnslot_0arg_rflags(regs->ARM_cpsr, i_fn); | 657 | insnslot_0arg_rflags(regs->ARM_cpsr, i_fn); |
658 | } | 658 | } |
659 | 659 | ||
660 | static void __kprobes emulate_rn16(struct kprobe *p, struct pt_regs *regs) | 660 | static void __kprobes emulate_nop(struct kprobe *p, struct pt_regs *regs) |
661 | { | 661 | { |
662 | insn_1arg_fn_t *i_fn = (insn_1arg_fn_t *)&p->ainsn.insn[0]; | ||
663 | kprobe_opcode_t insn = p->opcode; | ||
664 | int rn = (insn >> 16) & 0xf; | ||
665 | long rnv = regs->uregs[rn]; | ||
666 | |||
667 | insnslot_1arg_rflags(rnv, regs->ARM_cpsr, i_fn); | ||
668 | } | 662 | } |
669 | 663 | ||
670 | static void __kprobes emulate_rd12rm0(struct kprobe *p, struct pt_regs *regs) | 664 | static void __kprobes emulate_rd12rm0(struct kprobe *p, struct pt_regs *regs) |
@@ -941,12 +935,13 @@ space_1111(kprobe_opcode_t insn, struct arch_specific_insn *asi) | |||
941 | (insn & 0xfe5f0f00) == 0xf84d0500) | 935 | (insn & 0xfe5f0f00) == 0xf84d0500) |
942 | return INSN_REJECTED; | 936 | return INSN_REJECTED; |
943 | 937 | ||
944 | /* PLD : 1111 01x1 x101 xxxx xxxx xxxx xxxx xxxx : */ | 938 | /* memory hint : 1111 0100 x001 xxxx xxxx xxxx xxxx xxxx : */ |
945 | if ((insn & 0xfd700000) == 0xf4500000) { | 939 | /* PLDI : 1111 0100 x101 xxxx xxxx xxxx xxxx xxxx : */ |
946 | insn &= 0xfff0ffff; /* Rn = r0 */ | 940 | /* PLDW : 1111 0101 x001 xxxx xxxx xxxx xxxx xxxx : */ |
947 | asi->insn[0] = insn; | 941 | /* PLD : 1111 0101 x101 xxxx xxxx xxxx xxxx xxxx : */ |
948 | asi->insn_handler = emulate_rn16; | 942 | if ((insn & 0xfe300000) == 0xf4100000) { |
949 | return INSN_GOOD; | 943 | asi->insn_handler = emulate_nop; |
944 | return INSN_GOOD_NO_SLOT; | ||
950 | } | 945 | } |
951 | 946 | ||
952 | /* BLX(1) : 1111 101x xxxx xxxx xxxx xxxx xxxx xxxx : */ | 947 | /* BLX(1) : 1111 101x xxxx xxxx xxxx xxxx xxxx xxxx : */ |