diff options
Diffstat (limited to 'arch/i386/kernel/kprobes.c')
-rw-r--r-- | arch/i386/kernel/kprobes.c | 19 |
1 files changed, 15 insertions, 4 deletions
diff --git a/arch/i386/kernel/kprobes.c b/arch/i386/kernel/kprobes.c index 048f754bbe23..2314d8d306fd 100644 --- a/arch/i386/kernel/kprobes.c +++ b/arch/i386/kernel/kprobes.c | |||
@@ -33,6 +33,7 @@ | |||
33 | #include <linux/ptrace.h> | 33 | #include <linux/ptrace.h> |
34 | #include <linux/spinlock.h> | 34 | #include <linux/spinlock.h> |
35 | #include <linux/preempt.h> | 35 | #include <linux/preempt.h> |
36 | #include <asm/cacheflush.h> | ||
36 | #include <asm/kdebug.h> | 37 | #include <asm/kdebug.h> |
37 | #include <asm/desc.h> | 38 | #include <asm/desc.h> |
38 | 39 | ||
@@ -71,16 +72,25 @@ int arch_prepare_kprobe(struct kprobe *p) | |||
71 | void arch_copy_kprobe(struct kprobe *p) | 72 | void arch_copy_kprobe(struct kprobe *p) |
72 | { | 73 | { |
73 | memcpy(p->ainsn.insn, p->addr, MAX_INSN_SIZE * sizeof(kprobe_opcode_t)); | 74 | memcpy(p->ainsn.insn, p->addr, MAX_INSN_SIZE * sizeof(kprobe_opcode_t)); |
75 | p->opcode = *p->addr; | ||
74 | } | 76 | } |
75 | 77 | ||
76 | void arch_remove_kprobe(struct kprobe *p) | 78 | void arch_arm_kprobe(struct kprobe *p) |
77 | { | 79 | { |
80 | *p->addr = BREAKPOINT_INSTRUCTION; | ||
81 | flush_icache_range((unsigned long) p->addr, | ||
82 | (unsigned long) p->addr + sizeof(kprobe_opcode_t)); | ||
78 | } | 83 | } |
79 | 84 | ||
80 | static inline void disarm_kprobe(struct kprobe *p, struct pt_regs *regs) | 85 | void arch_disarm_kprobe(struct kprobe *p) |
81 | { | 86 | { |
82 | *p->addr = p->opcode; | 87 | *p->addr = p->opcode; |
83 | regs->eip = (unsigned long)p->addr; | 88 | flush_icache_range((unsigned long) p->addr, |
89 | (unsigned long) p->addr + sizeof(kprobe_opcode_t)); | ||
90 | } | ||
91 | |||
92 | void arch_remove_kprobe(struct kprobe *p) | ||
93 | { | ||
84 | } | 94 | } |
85 | 95 | ||
86 | static inline void prepare_singlestep(struct kprobe *p, struct pt_regs *regs) | 96 | static inline void prepare_singlestep(struct kprobe *p, struct pt_regs *regs) |
@@ -177,7 +187,8 @@ static int kprobe_handler(struct pt_regs *regs) | |||
177 | unlock_kprobes(); | 187 | unlock_kprobes(); |
178 | goto no_kprobe; | 188 | goto no_kprobe; |
179 | } | 189 | } |
180 | disarm_kprobe(p, regs); | 190 | arch_disarm_kprobe(p); |
191 | regs->eip = (unsigned long)p->addr; | ||
181 | ret = 1; | 192 | ret = 1; |
182 | } else { | 193 | } else { |
183 | p = current_kprobe; | 194 | p = current_kprobe; |