aboutsummaryrefslogtreecommitdiffstats
path: root/arch/x86_64
diff options
context:
space:
mode:
Diffstat (limited to 'arch/x86_64')
-rw-r--r--arch/x86_64/kernel/kprobes.c26
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
221void arch_remove_kprobe(struct kprobe *p) 222void 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
228static inline void disarm_kprobe(struct kprobe *p, struct pt_regs *regs) 229void 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
236void 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
234static void prepare_singlestep(struct kprobe *p, struct pt_regs *regs) 243static 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;