summaryrefslogtreecommitdiffstats
path: root/arch/arm/kernel/kprobes.c
diff options
context:
space:
mode:
authorRussell King <rmk+kernel@arm.linux.org.uk>2009-09-22 20:54:53 +0100
committerRussell King <rmk+kernel@arm.linux.org.uk>2009-09-22 21:01:40 +0100
commitae19ffbadc1b2100285a5b5b3d0a4e0a11390904 (patch)
tree3c2086ab67398a019089a47ca3f362a4bc6db74f /arch/arm/kernel/kprobes.c
parent34e84f39a27d059a3e6ec6e8b94aafa702e6f220 (diff)
parent9173a8ef24a6b1b8031507b35b8ffe5f85a87692 (diff)
downloadop-kernel-dev-ae19ffbadc1b2100285a5b5b3d0a4e0a11390904.zip
op-kernel-dev-ae19ffbadc1b2100285a5b5b3d0a4e0a11390904.tar.gz
Merge branch 'master' into for-linus
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 f692efd..60c62c3 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)
OpenPOWER on IntegriCloud