summaryrefslogtreecommitdiffstats
path: root/arch/arm/kernel
diff options
context:
space:
mode:
authorWang Nan <wangnan0@huawei.com>2015-01-09 10:19:49 +0800
committerJon Medhurst <tixy@linaro.org>2015-01-09 09:36:50 +0000
commitfca08f326ae0423f03b097ff54de432fe77b95d0 (patch)
tree40d680c04ec5ec613c0b8bb9ec9ff8b5821bc237 /arch/arm/kernel
parentb1940cd21c0f4abdce101253e860feff547291b0 (diff)
ARM: probes: move all probe code to dedicate directory
In discussion on LKML (https://lkml.org/lkml/2014/11/28/158), Russell King suggests to move all probe related code to arch/arm/probes. This patch does the work. Due to dependency on 'arch/arm/kernel/patch.h', this patch also moves patch.h to 'arch/arm/include/asm/patch.h', and related '#include' directives are also midified to '#include <asm/patch.h>'. Following is an overview of this patch: ./arch/arm/kernel/ ./arch/arm/probes/ |-- Makefile |-- Makefile |-- probes-arm.c ==> |-- decode-arm.c |-- probes-arm.h ==> |-- decode-arm.h |-- probes-thumb.c ==> |-- decode-thumb.c |-- probes-thumb.h ==> |-- decode-thumb.h |-- probes.c ==> |-- decode.c |-- probes.h ==> |-- decode.h | |-- kprobes | | |-- Makefile |-- kprobes-arm.c ==> | |-- actions-arm.c |-- kprobes-common.c ==> | |-- actions-common.c |-- kprobes-thumb.c ==> | |-- actions-thumb.c |-- kprobes.c ==> | |-- core.c |-- kprobes.h ==> | |-- core.h |-- kprobes-test-arm.c ==> | |-- test-arm.c |-- kprobes-test.c ==> | |-- test-core.c |-- kprobes-test.h ==> | |-- test-core.h |-- kprobes-test-thumb.c ==> | `-- test-thumb.c | `-- uprobes | |-- Makefile |-- uprobes-arm.c ==> |-- actions-arm.c |-- uprobes.c ==> |-- core.c |-- uprobes.h ==> `-- core.h | `-- patch.h ==> arch/arm/include/asm/patch.h Signed-off-by: Wang Nan <wangnan0@huawei.com> Acked-by: Masami Hiramatsu <masami.hiramatsu.pt@hitachi.com> Signed-off-by: Jon Medhurst <tixy@linaro.org>
Diffstat (limited to 'arch/arm/kernel')
-rw-r--r--arch/arm/kernel/Makefile16
-rw-r--r--arch/arm/kernel/jump_label.c2
-rw-r--r--arch/arm/kernel/kgdb.c3
-rw-r--r--arch/arm/kernel/kprobes-arm.c343
-rw-r--r--arch/arm/kernel/kprobes-common.c171
-rw-r--r--arch/arm/kernel/kprobes-test-arm.c1346
-rw-r--r--arch/arm/kernel/kprobes-test-thumb.c1188
-rw-r--r--arch/arm/kernel/kprobes-test.c1713
-rw-r--r--arch/arm/kernel/kprobes-test.h435
-rw-r--r--arch/arm/kernel/kprobes-thumb.c666
-rw-r--r--arch/arm/kernel/kprobes.c628
-rw-r--r--arch/arm/kernel/kprobes.h52
-rw-r--r--arch/arm/kernel/patch.c3
-rw-r--r--arch/arm/kernel/patch.h17
-rw-r--r--arch/arm/kernel/probes-arm.c734
-rw-r--r--arch/arm/kernel/probes-arm.h73
-rw-r--r--arch/arm/kernel/probes-thumb.c882
-rw-r--r--arch/arm/kernel/probes-thumb.h97
-rw-r--r--arch/arm/kernel/probes.c456
-rw-r--r--arch/arm/kernel/probes.h407
-rw-r--r--arch/arm/kernel/uprobes-arm.c234
-rw-r--r--arch/arm/kernel/uprobes.c230
-rw-r--r--arch/arm/kernel/uprobes.h35
23 files changed, 5 insertions, 9726 deletions
diff --git a/arch/arm/kernel/Makefile b/arch/arm/kernel/Makefile
index fb2b71ebe3f2..9c51a433e025 100644
--- a/arch/arm/kernel/Makefile
+++ b/arch/arm/kernel/Makefile
@@ -51,20 +51,8 @@ obj-$(CONFIG_DYNAMIC_FTRACE) += ftrace.o insn.o
obj-$(CONFIG_FUNCTION_GRAPH_TRACER) += ftrace.o insn.o
obj-$(CONFIG_JUMP_LABEL) += jump_label.o insn.o patch.o
obj-$(CONFIG_KEXEC) += machine_kexec.o relocate_kernel.o
-obj-$(CONFIG_UPROBES) += probes.o probes-arm.o uprobes.o uprobes-arm.o
-obj-$(CONFIG_KPROBES) += probes.o kprobes.o kprobes-common.o patch.o
-ifdef CONFIG_THUMB2_KERNEL
-obj-$(CONFIG_KPROBES) += kprobes-thumb.o probes-thumb.o
-else
-obj-$(CONFIG_KPROBES) += kprobes-arm.o probes-arm.o
-endif
-obj-$(CONFIG_ARM_KPROBES_TEST) += test-kprobes.o
-test-kprobes-objs := kprobes-test.o
-ifdef CONFIG_THUMB2_KERNEL
-test-kprobes-objs += kprobes-test-thumb.o
-else
-test-kprobes-objs += kprobes-test-arm.o
-endif
+# Main staffs in KPROBES are in arch/arm/probes/ .
+obj-$(CONFIG_KPROBES) += patch.o
obj-$(CONFIG_OABI_COMPAT) += sys_oabi-compat.o
obj-$(CONFIG_ARM_THUMBEE) += thumbee.o
obj-$(CONFIG_KGDB) += kgdb.o patch.o
diff --git a/arch/arm/kernel/jump_label.c b/arch/arm/kernel/jump_label.c
index afeeb9ea6f43..d8da075959bf 100644
--- a/arch/arm/kernel/jump_label.c
+++ b/arch/arm/kernel/jump_label.c
@@ -1,8 +1,8 @@
#include <linux/kernel.h>
#include <linux/jump_label.h>
+#include <asm/patch.h>
#include "insn.h"
-#include "patch.h"
#ifdef HAVE_JUMP_LABEL
diff --git a/arch/arm/kernel/kgdb.c b/arch/arm/kernel/kgdb.c
index 07db2f8a1b45..a6ad93c9bce3 100644
--- a/arch/arm/kernel/kgdb.c
+++ b/arch/arm/kernel/kgdb.c
@@ -14,10 +14,9 @@
#include <linux/kgdb.h>
#include <linux/uaccess.h>
+#include <asm/patch.h>
#include <asm/traps.h>
-#include "patch.h"
-
struct dbg_reg_def_t dbg_reg_def[DBG_MAX_REG_NUM] =
{
{ "r0", 4, offsetof(struct pt_regs, ARM_r0)},
diff --git a/arch/arm/kernel/kprobes-arm.c b/arch/arm/kernel/kprobes-arm.c
deleted file mode 100644
index ac300c60d656..000000000000
--- a/arch/arm/kernel/kprobes-arm.c
+++ /dev/null
@@ -1,343 +0,0 @@
-/*
- * arch/arm/kernel/kprobes-decode.c
- *
- * Copyright (C) 2006, 2007 Motorola Inc.
- *
- * This program is free software; you can redistribute it and/or modify
- * it under the terms of the GNU General Public License version 2 as
- * published by the Free Software Foundation.
- *
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
- * General Public License for more details.
- */
-
-/*
- * We do not have hardware single-stepping on ARM, This
- * effort is further complicated by the ARM not having a
- * "next PC" register. Instructions that change the PC
- * can't be safely single-stepped in a MP environment, so
- * we have a lot of work to do:
- *
- * In the prepare phase:
- * *) If it is an instruction that does anything
- * with the CPU mode, we reject it for a kprobe.
- * (This is out of laziness rather than need. The
- * instructions could be simulated.)
- *
- * *) Otherwise, decode the instruction rewriting its
- * registers to take fixed, ordered registers and
- * setting a handler for it to run the instruction.
- *
- * In the execution phase by an instruction's handler:
- *
- * *) If the PC is written to by the instruction, the
- * instruction must be fully simulated in software.
- *
- * *) Otherwise, a modified form of the instruction is
- * directly executed. Its handler calls the
- * instruction in insn[0]. In insn[1] is a
- * "mov pc, lr" to return.
- *
- * Before calling, load up the reordered registers
- * from the original instruction's registers. If one
- * of the original input registers is the PC, compute
- * and adjust the appropriate input register.
- *
- * After call completes, copy the output registers to
- * the original instruction's original registers.
- *
- * We don't use a real breakpoint instruction since that
- * would have us in the kernel go from SVC mode to SVC
- * mode losing the link register. Instead we use an
- * undefined instruction. To simplify processing, the
- * undefined instruction used for kprobes must be reserved
- * exclusively for kprobes use.
- *
- * TODO: ifdef out some instruction decoding based on architecture.
- */
-
-#include <linux/kernel.h>
-#include <linux/kprobes.h>
-#include <linux/ptrace.h>
-
-#include "kprobes.h"
-#include "probes-arm.h"
-
-#if __LINUX_ARM_ARCH__ >= 6
-#define BLX(reg) "blx "reg" \n\t"
-#else
-#define BLX(reg) "mov lr, pc \n\t" \
- "mov pc, "reg" \n\t"
-#endif
-
-static void __kprobes
-emulate_ldrdstrd(probes_opcode_t insn,
- struct arch_probes_insn *asi, struct pt_regs *regs)
-{
- unsigned long pc = regs->ARM_pc + 4;
- int rt = (insn >> 12) & 0xf;
- int rn = (insn >> 16) & 0xf;
- int rm = insn & 0xf;
-
- register unsigned long rtv asm("r0") = regs->uregs[rt];
- register unsigned long rt2v asm("r1") = regs->uregs[rt+1];
- register unsigned long rnv asm("r2") = (rn == 15) ? pc
- : regs->uregs[rn];
- register unsigned long rmv asm("r3") = regs->uregs[rm];
-
- __asm__ __volatile__ (
- BLX("%[fn]")
- : "=r" (rtv), "=r" (rt2v), "=r" (rnv)
- : "0" (rtv), "1" (rt2v), "2" (rnv), "r" (rmv),
- [fn] "r" (asi->insn_fn)
- : "lr", "memory", "cc"
- );
-
- regs->uregs[rt] = rtv;
- regs->uregs[rt+1] = rt2v;
- if (is_writeback(insn))
- regs->uregs[rn] = rnv;
-}
-
-static void __kprobes
-emulate_ldr(probes_opcode_t insn,
- struct arch_probes_insn *asi, struct pt_regs *regs)
-{
- unsigned long pc = regs->ARM_pc + 4;
- int rt = (insn >> 12) & 0xf;
- int rn = (insn >> 16) & 0xf;
- int rm = insn & 0xf;
-
- register unsigned long rtv asm("r0");
- register unsigned long rnv asm("r2") = (rn == 15) ? pc
- : regs->uregs[rn];
- register unsigned long rmv asm("r3") = regs->uregs[rm];
-
- __asm__ __volatile__ (
- BLX("%[fn]")
- : "=r" (rtv), "=r" (rnv)
- : "1" (rnv), "r" (rmv), [fn] "r" (asi->insn_fn)
- : "lr", "memory", "cc"
- );
-
- if (rt == 15)
- load_write_pc(rtv, regs);
- else
- regs->uregs[rt] = rtv;
-
- if (is_writeback(insn))
- regs->uregs[rn] = rnv;
-}
-
-static void __kprobes
-emulate_str(probes_opcode_t insn,
- struct arch_probes_insn *asi, struct pt_regs *regs)
-{
- unsigned long rtpc = regs->ARM_pc - 4 + str_pc_offset;
- unsigned long rnpc = regs->ARM_pc + 4;
- int rt = (insn >> 12) & 0xf;
- int rn = (insn >> 16) & 0xf;
- int rm = insn & 0xf;
-
- register unsigned long rtv asm("r0") = (rt == 15) ? rtpc
- : regs->uregs[rt];
- register unsigned long rnv asm("r2") = (rn == 15) ? rnpc
- : regs->uregs[rn];
- register unsigned long rmv asm("r3") = regs->uregs[rm];
-
- __asm__ __volatile__ (
- BLX("%[fn]")
- : "=r" (rnv)
- : "r" (rtv), "0" (rnv), "r" (rmv), [fn] "r" (asi->insn_fn)
- : "lr", "memory", "cc"
- );
-
- if (is_writeback(insn))
- regs->uregs[rn] = rnv;
-}
-
-static void __kprobes
-emulate_rd12rn16rm0rs8_rwflags(probes_opcode_t insn,
- struct arch_probes_insn *asi, struct pt_regs *regs)
-{
- unsigned long pc = regs->ARM_pc + 4;
- int rd = (insn >> 12) & 0xf;
- int rn = (insn >> 16) & 0xf;
- int rm = insn & 0xf;
- int rs = (insn >> 8) & 0xf;
-
- register unsigned long rdv asm("r0") = regs->uregs[rd];
- register unsigned long rnv asm("r2") = (rn == 15) ? pc
- : regs->uregs[rn];
- register unsigned long rmv asm("r3") = (rm == 15) ? pc
- : regs->uregs[rm];
- register unsigned long rsv asm("r1") = regs->uregs[rs];
- unsigned long cpsr = regs->ARM_cpsr;
-
- __asm__ __volatile__ (
- "msr cpsr_fs, %[cpsr] \n\t"
- BLX("%[fn]")
- "mrs %[cpsr], cpsr \n\t"
- : "=r" (rdv), [cpsr] "=r" (cpsr)
- : "0" (rdv), "r" (rnv), "r" (rmv), "r" (rsv),
- "1" (cpsr), [fn] "r" (asi->insn_fn)
- : "lr", "memory", "cc"
- );
-
- if (rd == 15)
- alu_write_pc(rdv, regs);
- else
- regs->uregs[rd] = rdv;
- regs->ARM_cpsr = (regs->ARM_cpsr & ~APSR_MASK) | (cpsr & APSR_MASK);
-}
-
-static void __kprobes
-emulate_rd12rn16rm0_rwflags_nopc(probes_opcode_t insn,
- struct arch_probes_insn *asi, struct pt_regs *regs)
-{
- int rd = (insn >> 12) & 0xf;
- int rn = (insn >> 16) & 0xf;
- int rm = insn & 0xf;
-
- register unsigned long rdv asm("r0") = regs->uregs[rd];
- register unsigned long rnv asm("r2") = regs->uregs[rn];
- register unsigned long rmv asm("r3") = regs->uregs[rm];
- unsigned long cpsr = regs->ARM_cpsr;
-
- __asm__ __volatile__ (
- "msr cpsr_fs, %[cpsr] \n\t"
- BLX("%[fn]")
- "mrs %[cpsr], cpsr \n\t"
- : "=r" (rdv), [cpsr] "=r" (cpsr)
- : "0" (rdv), "r" (rnv), "r" (rmv),
- "1" (cpsr), [fn] "r" (asi->insn_fn)
- : "lr", "memory", "cc"
- );
-
- regs->uregs[rd] = rdv;
- regs->ARM_cpsr = (regs->ARM_cpsr & ~APSR_MASK) | (cpsr & APSR_MASK);
-}
-
-static void __kprobes
-emulate_rd16rn12rm0rs8_rwflags_nopc(probes_opcode_t insn,
- struct arch_probes_insn *asi,
- struct pt_regs *regs)
-{
- int rd = (insn >> 16) & 0xf;
- int rn = (insn >> 12) & 0xf;
- int rm = insn & 0xf;
- int rs = (insn >> 8) & 0xf;
-
- register unsigned long rdv asm("r2") = regs->uregs[rd];
- register unsigned long rnv asm("r0") = regs->uregs[rn];
- register unsigned long rmv asm("r3") = regs->uregs[rm];
- register unsigned long rsv asm("r1") = regs->uregs[rs];
- unsigned long cpsr = regs->ARM_cpsr;
-
- __asm__ __volatile__ (
- "msr cpsr_fs, %[cpsr] \n\t"
- BLX("%[fn]")
- "mrs %[cpsr], cpsr \n\t"
- : "=r" (rdv), [cpsr] "=r" (cpsr)
- : "0" (rdv), "r" (rnv), "r" (rmv), "r" (rsv),
- "1" (cpsr), [fn] "r" (asi->insn_fn)
- : "lr", "memory", "cc"
- );
-
- regs->uregs[rd] = rdv;
- regs->ARM_cpsr = (regs->ARM_cpsr & ~APSR_MASK) | (cpsr & APSR_MASK);
-}
-
-static void __kprobes
-emulate_rd12rm0_noflags_nopc(probes_opcode_t insn,
- struct arch_probes_insn *asi, struct pt_regs *regs)
-{
- int rd = (insn >> 12) & 0xf;
- int rm = insn & 0xf;
-
- register unsigned long rdv asm("r0") = regs->uregs[rd];
- register unsigned long rmv asm("r3") = regs->uregs[rm];
-
- __asm__ __volatile__ (
- BLX("%[fn]")
- : "=r" (rdv)
- : "0" (rdv), "r" (rmv), [fn] "r" (asi->insn_fn)
- : "lr", "memory", "cc"
- );
-
- regs->uregs[rd] = rdv;
-}
-
-static void __kprobes
-emulate_rdlo12rdhi16rn0rm8_rwflags_nopc(probes_opcode_t insn,
- struct arch_probes_insn *asi,
- struct pt_regs *regs)
-{
- int rdlo = (insn >> 12) & 0xf;
- int rdhi = (insn >> 16) & 0xf;
- int rn = insn & 0xf;
- int rm = (insn >> 8) & 0xf;
-
- register unsigned long rdlov asm("r0") = regs->uregs[rdlo];
- register unsigned long rdhiv asm("r2") = regs->uregs[rdhi];
- register unsigned long rnv asm("r3") = regs->uregs[rn];
- register unsigned long rmv asm("r1") = regs->uregs[rm];
- unsigned long cpsr = regs->ARM_cpsr;
-
- __asm__ __volatile__ (
- "msr cpsr_fs, %[cpsr] \n\t"
- BLX("%[fn]")
- "mrs %[cpsr], cpsr \n\t"
- : "=r" (rdlov), "=r" (rdhiv), [cpsr] "=r" (cpsr)
- : "0" (rdlov), "1" (rdhiv), "r" (rnv), "r" (rmv),
- "2" (cpsr), [fn] "r" (asi->insn_fn)
- : "lr", "memory", "cc"
- );
-
- regs->uregs[rdlo] = rdlov;
- regs->uregs[rdhi] = rdhiv;
- regs->ARM_cpsr = (regs->ARM_cpsr & ~APSR_MASK) | (cpsr & APSR_MASK);
-}
-
-const union decode_action kprobes_arm_actions[NUM_PROBES_ARM_ACTIONS] = {
- [PROBES_EMULATE_NONE] = {.handler = probes_emulate_none},
- [PROBES_SIMULATE_NOP] = {.handler = probes_simulate_nop},
- [PROBES_PRELOAD_IMM] = {.handler = probes_simulate_nop},
- [PROBES_PRELOAD_REG] = {.handler = probes_simulate_nop},
- [PROBES_BRANCH_IMM] = {.handler = simulate_blx1},
- [PROBES_MRS] = {.handler = simulate_mrs},
- [PROBES_BRANCH_REG] = {.handler = simulate_blx2bx},
- [PROBES_CLZ] = {.handler = emulate_rd12rm0_noflags_nopc},
- [PROBES_SATURATING_ARITHMETIC] = {
- .handler = emulate_rd12rn16rm0_rwflags_nopc},
- [PROBES_MUL1] = {.handler = emulate_rdlo12rdhi16rn0rm8_rwflags_nopc},
- [PROBES_MUL2] = {.handler = emulate_rd16rn12rm0rs8_rwflags_nopc},
- [PROBES_SWP] = {.handler = emulate_rd12rn16rm0_rwflags_nopc},
- [PROBES_LDRSTRD] = {.handler = emulate_ldrdstrd},
- [PROBES_LOAD_EXTRA] = {.handler = emulate_ldr},
- [PROBES_LOAD] = {.handler = emulate_ldr},
- [PROBES_STORE_EXTRA] = {.handler = emulate_str},
- [PROBES_STORE] = {.handler = emulate_str},
- [PROBES_MOV_IP_SP] = {.handler = simulate_mov_ipsp},
- [PROBES_DATA_PROCESSING_REG] = {
- .handler = emulate_rd12rn16rm0rs8_rwflags},
- [PROBES_DATA_PROCESSING_IMM] = {
- .handler = emulate_rd12rn16rm0rs8_rwflags},
- [PROBES_MOV_HALFWORD] = {.handler = emulate_rd12rm0_noflags_nopc},
- [PROBES_SEV] = {.handler = probes_emulate_none},
- [PROBES_WFE] = {.handler = probes_simulate_nop},
- [PROBES_SATURATE] = {.handler = emulate_rd12rn16rm0_rwflags_nopc},
- [PROBES_REV] = {.handler = emulate_rd12rm0_noflags_nopc},
- [PROBES_MMI] = {.handler = emulate_rd12rn16rm0_rwflags_nopc},
- [PROBES_PACK] = {.handler = emulate_rd12rn16rm0_rwflags_nopc},
- [PROBES_EXTEND] = {.handler = emulate_rd12rm0_noflags_nopc},
- [PROBES_EXTEND_ADD] = {.handler = emulate_rd12rn16rm0_rwflags_nopc},
- [PROBES_MUL_ADD_LONG] = {
- .handler = emulate_rdlo12rdhi16rn0rm8_rwflags_nopc},
- [PROBES_MUL_ADD] = {.handler = emulate_rd16rn12rm0rs8_rwflags_nopc},
- [PROBES_BITFIELD] = {.handler = emulate_rd12rm0_noflags_nopc},
- [PROBES_BRANCH] = {.handler = simulate_bbl},
- [PROBES_LDMSTM] = {.decoder = kprobe_decode_ldmstm}
-};
diff --git a/arch/arm/kernel/kprobes-common.c b/arch/arm/kernel/kprobes-common.c
deleted file mode 100644
index 0bf5d64eba1d..000000000000
--- a/arch/arm/kernel/kprobes-common.c
+++ /dev/null
@@ -1,171 +0,0 @@
-/*
- * arch/arm/kernel/kprobes-common.c
- *
- * Copyright (C) 2011 Jon Medhurst <tixy@yxit.co.uk>.
- *
- * Some contents moved here from arch/arm/include/asm/kprobes-arm.c which is
- * Copyright (C) 2006, 2007 Motorola Inc.
- *
- * This program is free software; you can redistribute it and/or modify
- * it under the terms of the GNU General Public License version 2 as
- * published by the Free Software Foundation.
- */
-
-#include <linux/kernel.h>
-#include <linux/kprobes.h>
-#include <asm/opcodes.h>
-
-#include "kprobes.h"
-
-
-static void __kprobes simulate_ldm1stm1(probes_opcode_t insn,
- struct arch_probes_insn *asi,
- struct pt_regs *regs)
-{
- 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(probes_opcode_t insn,
- struct arch_probes_insn *asi,
- struct pt_regs *regs)
-{
- unsigned long addr = regs->ARM_pc - 4;
-
- regs->ARM_pc = (long)addr + str_pc_offset;
- simulate_ldm1stm1(insn, asi, regs);
- regs->ARM_pc = (long)addr + 4;
-}
-
-static void __kprobes simulate_ldm1_pc(probes_opcode_t insn,
- struct arch_probes_insn *asi,
- struct pt_regs *regs)
-{
- simulate_ldm1stm1(insn, asi, regs);
- load_write_pc(regs->ARM_pc, regs);
-}
-
-static void __kprobes
-emulate_generic_r0_12_noflags(probes_opcode_t insn,
- struct arch_probes_insn *asi, struct pt_regs *regs)
-{
- register void *rregs asm("r1") = regs;
- register void *rfn asm("lr") = asi->insn_fn;
-
- __asm__ __volatile__ (
- "stmdb sp!, {%[regs], r11} \n\t"
- "ldmia %[regs], {r0-r12} \n\t"
-#if __LINUX_ARM_ARCH__ >= 6
- "blx %[fn] \n\t"
-#else
- "str %[fn], [sp, #-4]! \n\t"
- "adr lr, 1f \n\t"
- "ldr pc, [sp], #4 \n\t"
- "1: \n\t"
-#endif
- "ldr lr, [sp], #4 \n\t" /* lr = regs */
- "stmia lr, {r0-r12} \n\t"
- "ldr r11, [sp], #4 \n\t"
- : [regs] "=r" (rregs), [fn] "=r" (rfn)
- : "0" (rregs), "1" (rfn)
- : "r0", "r2", "r3", "r4", "r5", "r6", "r7",
- "r8", "r9", "r10", "r12", "memory", "cc"
- );
-}
-
-static void __kprobes
-emulate_generic_r2_14_noflags(probes_opcode_t insn,
- struct arch_probes_insn *asi, struct pt_regs *regs)
-{
- emulate_generic_r0_12_noflags(insn, asi,
- (struct pt_regs *)(regs->uregs+2));
-}
-
-static void __kprobes
-emulate_ldm_r3_15(probes_opcode_t insn,
- struct arch_probes_insn *asi, struct pt_regs *regs)
-{
- emulate_generic_r0_12_noflags(insn, asi,
- (struct pt_regs *)(regs->uregs+3));
- load_write_pc(regs->ARM_pc, regs);
-}
-
-enum probes_insn __kprobes
-kprobe_decode_ldmstm(probes_opcode_t insn, struct arch_probes_insn *asi,
- const struct decode_header *h)
-{
- probes_insn_handler_t *handler = 0;
- unsigned reglist = insn & 0xffff;
- int is_ldm = insn & 0x100000;
- int rn = (insn >> 16) & 0xf;
-
- if (rn <= 12 && (reglist & 0xe000) == 0) {
- /* Instruction only uses registers in the range R0..R12 */
- handler = emulate_generic_r0_12_noflags;
-
- } else if (rn >= 2 && (reglist & 0x8003) == 0) {
- /* Instruction only uses registers in the range R2..R14 */
- rn -= 2;
- reglist >>= 2;
- handler = emulate_generic_r2_14_noflags;
-
- } else if (rn >= 3 && (reglist & 0x0007) == 0) {
- /* Instruction only uses registers in the range R3..R15 */
- if (is_ldm && (reglist & 0x8000)) {
- rn -= 3;
- reglist >>= 3;
- handler = emulate_ldm_r3_15;
- }
- }
-
- if (handler) {
- /* We can emulate the instruction in (possibly) modified form */
- asi->insn[0] = __opcode_to_mem_arm((insn & 0xfff00000) |
- (rn << 16) | reglist);
- asi->insn_handler = handler;
- return INSN_GOOD;
- }
-
- /* Fallback to slower simulation... */
- if (reglist & 0x8000)
- handler = is_ldm ? simulate_ldm1_pc : simulate_stm1_pc;
- else
- handler = simulate_ldm1stm1;
- asi->insn_handler = handler;
- return INSN_GOOD_NO_SLOT;
-}
-
diff --git a/arch/arm/kernel/kprobes-test-arm.c b/arch/arm/kernel/kprobes-test-arm.c
deleted file mode 100644
index cb1424240ff6..000000000000
--- a/arch/arm/kernel/kprobes-test-arm.c
+++ /dev/null
@@ -1,1346 +0,0 @@
-/*
- * arch/arm/kernel/kprobes-test-arm.c
- *
- * Copyright (C) 2011 Jon Medhurst <tixy@yxit.co.uk>.
- *
- * This program is free software; you can redistribute it and/or modify
- * it under the terms of the GNU General Public License version 2 as
- * published by the Free Software Foundation.
- */
-
-#include <linux/kernel.h>
-#include <linux/module.h>
-#include <asm/system_info.h>
-#include <asm/opcodes.h>
-
-#include "kprobes-test.h"
-
-
-#define TEST_ISA "32"
-
-#define TEST_ARM_TO_THUMB_INTERWORK_R(code1, reg, val, code2) \
- TESTCASE_START(code1 #reg code2) \
- TEST_ARG_REG(reg, val) \
- TEST_ARG_REG(14, 99f) \
- TEST_ARG_END("") \
- "50: nop \n\t" \
- "1: "code1 #reg code2" \n\t" \
- " bx lr \n\t" \
- ".thumb \n\t" \
- "3: adr lr, 2f \n\t" \
- " bx lr \n\t" \
- ".arm \n\t" \
- "2: nop \n\t" \
- TESTCASE_END
-
-#define TEST_ARM_TO_THUMB_INTERWORK_P(code1, reg, val, code2) \
- TESTCASE_START(code1 #reg code2) \
- TEST_ARG_PTR(reg, val) \
- TEST_ARG_REG(14, 99f) \
- TEST_ARG_MEM(15, 3f+1) \
- TEST_ARG_END("") \
- "50: nop \n\t" \
- "1: "code1 #reg code2" \n\t" \
- " bx lr \n\t" \
- ".thumb \n\t" \
- "3: adr lr, 2f \n\t" \
- " bx lr \n\t" \
- ".arm \n\t" \
- "2: nop \n\t" \
- TESTCASE_END
-
-
-void kprobe_arm_test_cases(void)
-{
- kprobe_test_flags = 0;
-
- TEST_GROUP("Data-processing (register), (register-shifted register), (immediate)")
-
-#define _DATA_PROCESSING_DNM(op,s,val) \
- TEST_RR( op "eq" s " r0, r",1, VAL1,", r",2, val, "") \
- TEST_RR( op "ne" s " r1, r",1, VAL1,", r",2, val, ", lsl #3") \
- TEST_RR( op "cs" s " r2, r",3, VAL1,", r",2, val, ", lsr #4") \
- TEST_RR( op "cc" s " r3, r",3, VAL1,", r",2, val, ", asr #5") \
- TEST_RR( op "mi" s " r4, r",5, VAL1,", r",2, N(val),", asr #6") \
- TEST_RR( op "pl" s " r5, r",5, VAL1,", r",2, val, ", ror #7") \
- TEST_RR( op "vs" s " r6, r",7, VAL1,", r",2, val, ", rrx") \
- TEST_R( op "vc" s " r6, r",7, VAL1,", pc, lsl #3") \
- TEST_R( op "vc" s " r6, r",7, VAL1,", sp, lsr #4") \
- TEST_R( op "vc" s " r6, pc, r",7, VAL1,", asr #5") \
- TEST_R( op "vc" s " r6, sp, r",7, VAL1,", ror #6") \
- TEST_RRR( op "hi" s " r8, r",9, VAL1,", r",14,val, ", lsl r",0, 3,"")\
- TEST_RRR( op "ls" s " r9, r",9, VAL1,", r",14,val, ", lsr r",7, 4,"")\
- TEST_RRR( op "ge" s " r10, r",11,VAL1,", r",14,val, ", asr r",7, 5,"")\
- TEST_RRR( op "lt" s " r11, r",11,VAL1,", r",14,N(val),", asr r",7, 6,"")\
- TEST_RR( op "gt" s " r12, r13" ", r",14,val, ", ror r",14,7,"")\
- TEST_RR( op "le" s " r14, r",0, val, ", r13" ", lsl r",14,8,"")\
- TEST_R( op "eq" s " r0, r",11,VAL1,", #0xf5") \
- TEST_R( op "ne" s " r11, r",0, VAL1,", #0xf5000000") \
- TEST_R( op s " r7, r",8, VAL2,", #0x000af000") \
- TEST( op s " r4, pc" ", #0x00005a00")
-
-#define DATA_PROCESSING_DNM(op,val) \
- _DATA_PROCESSING_DNM(op,"",val) \
- _DATA_PROCESSING_DNM(op,"s",val)
-
-#define DATA_PROCESSING_NM(op,val) \
- TEST_RR( op "ne r",1, VAL1,", r",2, val, "") \
- TEST_RR( op "eq r",1, VAL1,", r",2, val, ", lsl #3") \
- TEST_RR( op "cc r",3, VAL1,", r",2, val, ", lsr #4") \
- TEST_RR( op "cs r",3, VAL1,", r",2, val, ", asr #5") \
- TEST_RR( op "pl r",5, VAL1,", r",2, N(val),", asr #6") \
- TEST_RR( op "mi r",5, VAL1,", r",2, val, ", ror #7") \
- TEST_RR( op "vc r",7, VAL1,", r",2, val, ", rrx") \
- TEST_R ( op "vs r",7, VAL1,", pc, lsl #3") \
- TEST_R ( op "vs r",7, VAL1,", sp, lsr #4") \
- TEST_R( op "vs pc, r",7, VAL1,", asr #5") \
- TEST_R( op "vs sp, r",7, VAL1,", ror #6") \
- TEST_RRR( op "ls r",9, VAL1,", r",14,val, ", lsl r",0, 3,"") \
- TEST_RRR( op "hi r",9, VAL1,", r",14,val, ", lsr r",7, 4,"") \
- TEST_RRR( op "lt r",11,VAL1,", r",14,val, ", asr r",7, 5,"") \
- TEST_RRR( op "ge r",11,VAL1,", r",14,N(val),", asr r",7, 6,"") \
- TEST_RR( op "le r13" ", r",14,val, ", ror r",14,7,"") \
- TEST_RR( op "gt r",0, val, ", r13" ", lsl r",14,8,"") \
- TEST_R( op "eq r",11,VAL1,", #0xf5") \
- TEST_R( op "ne r",0, VAL1,", #0xf5000000") \
- TEST_R( op " r",8, VAL2,", #0x000af000")
-
-#define _DATA_PROCESSING_DM(op,s,val) \
- TEST_R( op "eq" s " r0, r",1, val, "") \
- TEST_R( op "ne" s " r1, r",1, val, ", lsl #3") \
- TEST_R( op "cs" s " r2, r",3, val, ", lsr #4") \
- TEST_R( op "cc" s " r3, r",3, val, ", asr #5") \
- TEST_R( op "mi" s " r4, r",5, N(val),", asr #6") \
- TEST_R( op "pl" s " r5, r",5, val, ", ror #7") \
- TEST_R( op "vs" s " r6, r",10,val, ", rrx") \
- TEST( op "vs" s " r7, pc, lsl #3") \
- TEST( op "vs" s " r7, sp, lsr #4") \
- TEST_RR( op "vc" s " r8, r",7, val, ", lsl r",0, 3,"") \
- TEST_RR( op "hi" s " r9, r",9, val, ", lsr r",7, 4,"") \
- TEST_RR( op "ls" s " r10, r",9, val, ", asr r",7, 5,"") \
- TEST_RR( op "ge" s " r11, r",11,N(val),", asr r",7, 6,"") \
- TEST_RR( op "lt" s " r12, r",11,val, ", ror r",14,7,"") \
- TEST_R( op "gt" s " r14, r13" ", lsl r",14,8,"") \
- TEST( op "eq" s " r0, #0xf5") \
- TEST( op "ne" s " r11, #0xf5000000") \
- TEST( op s " r7, #0x000af000") \
- TEST( op s " r4, #0x00005a00")
-
-#define DATA_PROCESSING_DM(op,val) \
- _DATA_PROCESSING_DM(op,"",val) \
- _DATA_PROCESSING_DM(op,"s",val)
-
- DATA_PROCESSING_DNM("and",0xf00f00ff)
- DATA_PROCESSING_DNM("eor",0xf00f00ff)
- DATA_PROCESSING_DNM("sub",VAL2)
- DATA_PROCESSING_DNM("rsb",VAL2)
- DATA_PROCESSING_DNM("add",VAL2)
- DATA_PROCESSING_DNM("adc",VAL2)
- DATA_PROCESSING_DNM("sbc",VAL2)
- DATA_PROCESSING_DNM("rsc",VAL2)
- DATA_PROCESSING_NM("tst",0xf00f00ff)
- DATA_PROCESSING_NM("teq",0xf00f00ff)
- DATA_PROCESSING_NM("cmp",VAL2)
- DATA_PROCESSING_NM("cmn",VAL2)
- DATA_PROCESSING_DNM("orr",0xf00f00ff)
- DATA_PROCESSING_DM("mov",VAL2)
- DATA_PROCESSING_DNM("bic",0xf00f00ff)
- DATA_PROCESSING_DM("mvn",VAL2)
-
- TEST("mov ip, sp") /* This has special case emulation code */
-
- TEST_SUPPORTED("mov pc, #0x1000");
- TEST_SUPPORTED("mov sp, #0x1000");
- TEST_SUPPORTED("cmp pc, #0x1000");
- TEST_SUPPORTED("cmp sp, #0x1000");
-
- /* Data-processing with PC and a shift count in a register */
- TEST_UNSUPPORTED(__inst_arm(0xe15c0f1e) " @ cmp r12, r14, asl pc")
- TEST_UNSUPPORTED(__inst_arm(0xe1a0cf1e) " @ mov r12, r14, asl pc")
- TEST_UNSUPPORTED(__inst_arm(0xe08caf1e) " @ add r10, r12, r14, asl pc")
- TEST_UNSUPPORTED(__inst_arm(0xe151021f) " @ cmp r1, pc, lsl r2")
- TEST_UNSUPPORTED(__inst_arm(0xe17f0211) " @ cmn pc, r1, lsl r2")
- TEST_UNSUPPORTED(__inst_arm(0xe1a0121f) " @ mov r1, pc, lsl r2")
- TEST_UNSUPPORTED(__inst_arm(0xe1a0f211) " @ mov pc, r1, lsl r2")
- TEST_UNSUPPORTED(__inst_arm(0xe042131f) " @ sub r1, r2, pc, lsl r3")
- TEST_UNSUPPORTED(__inst_arm(0xe1cf1312) " @ bic r1, pc, r2, lsl r3")
- TEST_UNSUPPORTED(__inst_arm(0xe081f312) " @ add pc, r1, r2, lsl r3")
-
- /* Data-processing with PC as a target and status registers updated */
- TEST_UNSUPPORTED("movs pc, r1")
- TEST_UNSUPPORTED("movs pc, r1, lsl r2")
- TEST_UNSUPPORTED("movs pc, #0x10000")
- TEST_UNSUPPORTED("adds pc, lr, r1")
- TEST_UNSUPPORTED("adds pc, lr, r1, lsl r2")
- TEST_UNSUPPORTED("adds pc, lr, #4")
-
- /* Data-processing with SP as target */
- TEST("add sp, sp, #16")
- TEST("sub sp, sp, #8")
- TEST("bic sp, sp, #0x20")
- TEST("orr sp, sp, #0x20")
- TEST_PR( "add sp, r",10,0,", r",11,4,"")
- TEST_PRR("add sp, r",10,0,", r",11,4,", asl r",12,1,"")
- TEST_P( "mov sp, r",10,0,"")
- TEST_PR( "mov sp, r",10,0,", asl r",12,0,"")
-
- /* Data-processing with PC as target */
- TEST_BF( "add pc, pc, #2f-1b-8")
- TEST_BF_R ("add pc, pc, r",14,2f-1f-8,"")
- TEST_BF_R ("add pc, r",14,2f-1f-8,", pc")
- TEST_BF_R ("mov pc, r",0,2f,"")
- TEST_BF_R ("add pc, pc, r",14,(2f-1f-8)*2,", asr #1")
- TEST_BB( "sub pc, pc, #1b-2b+8")
-#if __LINUX_ARM_ARCH__ == 6 && !defined(CONFIG_CPU_V7)
- TEST_BB( "sub pc, pc, #1b-2b+8-2") /* UNPREDICTABLE before and after ARMv6 */
-#endif
- TEST_BB_R( "sub pc, pc, r",14, 1f-2f+8,"")
- TEST_BB_R( "rsb pc, r",14,1f-2f+8,", pc")
- TEST_R( "add pc, pc, r",10,-2,", asl #1")
-#ifdef CONFIG_THUMB2_KERNEL
- TEST_ARM_TO_THUMB_INTERWORK_R("add pc, pc, r",0,3f-1f-8+1,"")
- TEST_ARM_TO_THUMB_INTERWORK_R("sub pc, r",0,3f+8+1,", #8")
-#endif
- TEST_GROUP("Miscellaneous instructions")
-
- TEST("mrs r0, cpsr")
- TEST("mrspl r7, cpsr")
- TEST("mrs r14, cpsr")
- TEST_UNSUPPORTED(__inst_arm(0xe10ff000) " @ mrs r15, cpsr")
- TEST_UNSUPPORTED("mrs r0, spsr")
- TEST_UNSUPPORTED("mrs lr, spsr")
-
- TEST_UNSUPPORTED("msr cpsr, r0")
- TEST_UNSUPPORTED("msr cpsr_f, lr")
- TEST_UNSUPPORTED("msr spsr, r0")
-
- TEST_BF_R("bx r",0,2f,"")
- TEST_BB_R("bx r",7,2f,"")
- TEST_BF_R("bxeq r",14,2f,"")
-
-#if __LINUX_ARM_ARCH__ >= 5
- TEST_R("clz r0, r",0, 0x0,"")
- TEST_R("clzeq r7, r",14,0x1,"")
- TEST_R("clz lr, r",7, 0xffffffff,"")
- TEST( "clz r4, sp")
- TEST_UNSUPPORTED(__inst_arm(0x016fff10) " @ clz pc, r0")
- TEST_UNSUPPORTED(__inst_arm(0x016f0f1f) " @ clz r0, pc")
-
-#if __LINUX_ARM_ARCH__ >= 6
- TEST_UNSUPPORTED("bxj r0")
-#endif
-
- TEST_BF_R("blx r",0,2f,"")
- TEST_BB_R("blx r",7,2f,"")
- TEST_BF_R("blxeq r",14,2f,"")
- TEST_UNSUPPORTED(__inst_arm(0x0120003f) " @ blx pc")
-
- TEST_RR( "qadd r0, r",1, VAL1,", r",2, VAL2,"")
- TEST_RR( "qaddvs lr, r",9, VAL2,", r",8, VAL1,"")
- TEST_R( "qadd lr, r",9, VAL2,", r13")
- TEST_RR( "qsub r0, r",1, VAL1,", r",2, VAL2,"")
- TEST_RR( "qsubvs lr, r",9, VAL2,", r",8, VAL1,"")
- TEST_R( "qsub lr, r",9, VAL2,", r13")
- TEST_RR( "qdadd r0, r",1, VAL1,", r",2, VAL2,"")
- TEST_RR( "qdaddvs lr, r",9, VAL2,", r",8, VAL1,"")
- TEST_R( "qdadd lr, r",9, VAL2,", r13")
- TEST_RR( "qdsub r0, r",1, VAL1,", r",2, VAL2,"")
- TEST_RR( "qdsubvs lr, r",9, VAL2,", r",8, VAL1,"")
- TEST_R( "qdsub lr, r",9, VAL2,", r13")
- TEST_UNSUPPORTED(__inst_arm(0xe101f050) " @ qadd pc, r0, r1")
- TEST_UNSUPPORTED(__inst_arm(0xe121f050) " @ qsub pc, r0, r1")
- TEST_UNSUPPORTED(__inst_arm(0xe141f050) " @ qdadd pc, r0, r1")