aboutsummaryrefslogtreecommitdiffstats
path: root/arch/arm/kernel/kprobes.c
diff options
context:
space:
mode:
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 @@
22#include <linux/kernel.h> 22#include <linux/kernel.h>
23#include <linux/kprobes.h> 23#include <linux/kprobes.h>
24#include <linux/module.h> 24#include <linux/module.h>
25#include <linux/stop_machine.h>
25#include <linux/stringify.h> 26#include <linux/stringify.h>
26#include <asm/traps.h> 27#include <asm/traps.h>
27#include <asm/cacheflush.h> 28#include <asm/cacheflush.h>
@@ -83,10 +84,24 @@ void __kprobes arch_arm_kprobe(struct kprobe *p)
83 flush_insns(p->addr, 1); 84 flush_insns(p->addr, 1);
84} 85}
85 86
87/*
88 * The actual disarming is done here on each CPU and synchronized using
89 * stop_machine. This synchronization is necessary on SMP to avoid removing
90 * a probe between the moment the 'Undefined Instruction' exception is raised
91 * and the moment the exception handler reads the faulting instruction from
92 * memory.
93 */
94int __kprobes __arch_disarm_kprobe(void *p)
95{
96 struct kprobe *kp = p;
97 *kp->addr = kp->opcode;
98 flush_insns(kp->addr, 1);
99 return 0;
100}
101
86void __kprobes arch_disarm_kprobe(struct kprobe *p) 102void __kprobes arch_disarm_kprobe(struct kprobe *p)
87{ 103{
88 *p->addr = p->opcode; 104 stop_machine(__arch_disarm_kprobe, p, &cpu_online_map);
89 flush_insns(p->addr, 1);
90} 105}
91 106
92void __kprobes arch_remove_kprobe(struct kprobe *p) 107void __kprobes arch_remove_kprobe(struct kprobe *p)