summaryrefslogtreecommitdiffstats
path: root/arch/arm/kernel/kprobes-arm.c
diff options
context:
space:
mode:
authorJon Medhurst <tixy@yxit.co.uk>2011-07-07 08:57:22 +0100
committerTixy <tixy@medhuaa1.miniserver.com>2011-07-13 17:32:45 +0000
commit235a4ce79feb8d5351f9164981bc57d5e29f974b (patch)
treec3dd0e698781faf592b2b01880103cf0d57d8a92 /arch/arm/kernel/kprobes-arm.c
parent263e368a2f1f960db07d7524a4a3e7df951f1f72 (diff)
downloadop-kernel-dev-235a4ce79feb8d5351f9164981bc57d5e29f974b.zip
op-kernel-dev-235a4ce79feb8d5351f9164981bc57d5e29f974b.tar.gz
ARM: kprobes: Add common decoding function for LDM and STM
The encoding of these instructions is substantially the same for both ARM and Thumb, so we can have common decoding and simulation functions. This patch moves the simulation functions from kprobes-arm.c to kprobes-common.c. It also adds a new simulation function (simulate_ldm1_pc) for the case where we load into PC because this may need to interwork. The instruction decoding is done by a custom function (kprobe_decode_ldmstm) rather than just relying on decoding table entries because we will later be adding optimisation code. Signed-off-by: Jon Medhurst <tixy@yxit.co.uk> Acked-by: Nicolas Pitre <nicolas.pitre@linaro.org>
Diffstat (limited to 'arch/arm/kernel/kprobes-arm.c')
-rw-r--r--arch/arm/kernel/kprobes-arm.c58
1 files changed, 7 insertions, 51 deletions
diff --git a/arch/arm/kernel/kprobes-arm.c b/arch/arm/kernel/kprobes-arm.c
index a1143e8..c6f2c69 100644
--- a/arch/arm/kernel/kprobes-arm.c
+++ b/arch/arm/kernel/kprobes-arm.c
@@ -437,54 +437,6 @@ static void __kprobes simulate_mrs(struct kprobe *p, struct pt_regs *regs)
regs->uregs[rd] = regs->ARM_cpsr & mask;
}
-static void __kprobes simulate_ldm1stm1(struct kprobe *p, struct pt_regs *regs)
-{
- kprobe_opcode_t insn = p->opcode;
- int rn = (insn >> 16) & 0xf;
- int lbit = insn & (1 << 20);
- int wbit = insn & (1 << 21);
- int ubit = insn & (1 << 23);
- int pbit = insn & (1 << 24);
- long *addr = (long *)regs->uregs[rn];
- int reg_bit_vector;
- int reg_count;
-
- reg_count = 0;
- reg_bit_vector = insn & 0xffff;
- while (reg_bit_vector) {
- reg_bit_vector &= (reg_bit_vector - 1);
- ++reg_count;
- }
-
- if (!ubit)
- addr -= reg_count;
- addr += (!pbit == !ubit);
-
- reg_bit_vector = insn & 0xffff;
- while (reg_bit_vector) {
- int reg = __ffs(reg_bit_vector);
- reg_bit_vector &= (reg_bit_vector - 1);
- if (lbit)
- regs->uregs[reg] = *addr++;
- else
- *addr++ = regs->uregs[reg];
- }
-
- if (wbit) {
- if (!ubit)
- addr -= reg_count;
- addr -= (!pbit == !ubit);
- regs->uregs[rn] = (long)addr;
- }
-}
-
-static void __kprobes simulate_stm1_pc(struct kprobe *p, struct pt_regs *regs)
-{
- regs->ARM_pc = (long)p->addr + str_pc_offset;
- simulate_ldm1stm1(p, regs);
- regs->ARM_pc = (long)p->addr + 4;
-}
-
static void __kprobes simulate_mov_ipsp(struct kprobe *p, struct pt_regs *regs)
{
regs->uregs[12] = regs->uregs[13];
@@ -1463,9 +1415,13 @@ space_cccc_100x(kprobe_opcode_t insn, struct arch_specific_insn *asi)
/* LDM(1) : cccc 100x x0x1 xxxx xxxx xxxx xxxx xxxx */
/* STM(1) : cccc 100x x0x0 xxxx xxxx xxxx xxxx xxxx */
- asi->insn_handler = ((insn & 0x108000) == 0x008000) ? /* STM & R15 */
- simulate_stm1_pc : simulate_ldm1stm1;
- return INSN_GOOD_NO_SLOT;
+
+ /*
+ * Make the instruction unconditional because the new emulation
+ * functions don't bother to setup the PSR context.
+ */
+ insn = (insn | 0xe0000000) & ~0x10000000;
+ return kprobe_decode_ldmstm(insn, asi);
}
static enum kprobe_insn __kprobes
OpenPOWER on IntegriCloud