summaryrefslogtreecommitdiffstats
path: root/arch/arm/kernel/kprobes.c
diff options
context:
space:
mode:
authorPaul Mundt <lethal@linux-sh.org>2009-09-25 05:15:15 +0200
committerPaul Mundt <lethal@linux-sh.org>2009-09-25 05:15:15 +0200
commitc373ba999103fa794f041eab5bd490714d2dee88 (patch)
tree8f2b445b1e0af2491c83527967dbcda76054a486 /arch/arm/kernel/kprobes.c
parentsh: enable onenand support in kfr2r09 defconfig. (diff)
parentMerge branch 'for-linus' of git://www.linux-m32r.org/git/takata/linux-2.6_dev (diff)
downloadlinux-c373ba999103fa794f041eab5bd490714d2dee88.tar.xz
linux-c373ba999103fa794f041eab5bd490714d2dee88.zip
Merge branch 'master' of git://git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux-2.6
Diffstat (limited to 'arch/arm/kernel/kprobes.c')
-rw-r--r--arch/arm/kernel/kprobes.c19
1 files changed, 17 insertions, 2 deletions
diff --git a/arch/arm/kernel/kprobes.c b/arch/arm/kernel/kprobes.c
index f692efddd449..60c62c377fa9 100644
--- a/arch/arm/kernel/kprobes.c
+++ b/arch/arm/kernel/kprobes.c
@@ -22,6 +22,7 @@
#include <linux/kernel.h>
#include <linux/kprobes.h>
#include <linux/module.h>
+#include <linux/stop_machine.h>
#include <linux/stringify.h>
#include <asm/traps.h>
#include <asm/cacheflush.h>
@@ -83,10 +84,24 @@ void __kprobes arch_arm_kprobe(struct kprobe *p)
flush_insns(p->addr, 1);
}
+/*
+ * The actual disarming is done here on each CPU and synchronized using
+ * stop_machine. This synchronization is necessary on SMP to avoid removing
+ * a probe between the moment the 'Undefined Instruction' exception is raised
+ * and the moment the exception handler reads the faulting instruction from
+ * memory.
+ */
+int __kprobes __arch_disarm_kprobe(void *p)
+{
+ struct kprobe *kp = p;
+ *kp->addr = kp->opcode;
+ flush_insns(kp->addr, 1);
+ return 0;
+}
+
void __kprobes arch_disarm_kprobe(struct kprobe *p)
{
- *p->addr = p->opcode;
- flush_insns(p->addr, 1);
+ stop_machine(__arch_disarm_kprobe, p, &cpu_online_map);
}
void __kprobes arch_remove_kprobe(struct kprobe *p)