diff options
Diffstat (limited to 'arch/x86_64')
-rw-r--r-- | arch/x86_64/kernel/kprobes.c | 26 |
1 files changed, 18 insertions, 8 deletions
diff --git a/arch/x86_64/kernel/kprobes.c b/arch/x86_64/kernel/kprobes.c index 203672ca7401..324bf57925a9 100644 --- a/arch/x86_64/kernel/kprobes.c +++ b/arch/x86_64/kernel/kprobes.c | |||
@@ -39,7 +39,7 @@ | |||
39 | #include <linux/slab.h> | 39 | #include <linux/slab.h> |
40 | #include <linux/preempt.h> | 40 | #include <linux/preempt.h> |
41 | #include <linux/moduleloader.h> | 41 | #include <linux/moduleloader.h> |
42 | 42 | #include <asm/cacheflush.h> | |
43 | #include <asm/pgtable.h> | 43 | #include <asm/pgtable.h> |
44 | #include <asm/kdebug.h> | 44 | #include <asm/kdebug.h> |
45 | 45 | ||
@@ -216,19 +216,28 @@ void arch_copy_kprobe(struct kprobe *p) | |||
216 | BUG_ON((s64) (s32) disp != disp); /* Sanity check. */ | 216 | BUG_ON((s64) (s32) disp != disp); /* Sanity check. */ |
217 | *ripdisp = disp; | 217 | *ripdisp = disp; |
218 | } | 218 | } |
219 | p->opcode = *p->addr; | ||
219 | } | 220 | } |
220 | 221 | ||
221 | void arch_remove_kprobe(struct kprobe *p) | 222 | void arch_arm_kprobe(struct kprobe *p) |
222 | { | 223 | { |
223 | up(&kprobe_mutex); | 224 | *p->addr = BREAKPOINT_INSTRUCTION; |
224 | free_insn_slot(p->ainsn.insn); | 225 | flush_icache_range((unsigned long) p->addr, |
225 | down(&kprobe_mutex); | 226 | (unsigned long) p->addr + sizeof(kprobe_opcode_t)); |
226 | } | 227 | } |
227 | 228 | ||
228 | static inline void disarm_kprobe(struct kprobe *p, struct pt_regs *regs) | 229 | void arch_disarm_kprobe(struct kprobe *p) |
229 | { | 230 | { |
230 | *p->addr = p->opcode; | 231 | *p->addr = p->opcode; |
231 | regs->rip = (unsigned long)p->addr; | 232 | flush_icache_range((unsigned long) p->addr, |
233 | (unsigned long) p->addr + sizeof(kprobe_opcode_t)); | ||
234 | } | ||
235 | |||
236 | void arch_remove_kprobe(struct kprobe *p) | ||
237 | { | ||
238 | up(&kprobe_mutex); | ||
239 | free_insn_slot(p->ainsn.insn); | ||
240 | down(&kprobe_mutex); | ||
232 | } | 241 | } |
233 | 242 | ||
234 | static void prepare_singlestep(struct kprobe *p, struct pt_regs *regs) | 243 | static void prepare_singlestep(struct kprobe *p, struct pt_regs *regs) |
@@ -311,7 +320,8 @@ int kprobe_handler(struct pt_regs *regs) | |||
311 | unlock_kprobes(); | 320 | unlock_kprobes(); |
312 | goto no_kprobe; | 321 | goto no_kprobe; |
313 | } | 322 | } |
314 | disarm_kprobe(p, regs); | 323 | arch_disarm_kprobe(p); |
324 | regs->rip = (unsigned long)p->addr; | ||
315 | ret = 1; | 325 | ret = 1; |
316 | } else { | 326 | } else { |
317 | p = current_kprobe; | 327 | p = current_kprobe; |