aboutsummaryrefslogtreecommitdiffstats
path: root/arch/powerpc/kernel/kprobes.c
diff options
context:
space:
mode:
authorKumar Gala <galak@kernel.crashing.org>2008-06-26 03:01:37 -0400
committerKumar Gala <galak@kernel.crashing.org>2008-06-26 04:35:46 -0400
commitf82796214a95b1ec00c2f121c1080d10f2b099a1 (patch)
treec5702217e2a482ee2f15fca17be547b9ba1a31a4 /arch/powerpc/kernel/kprobes.c
parentb76e59d1fb086c2fdac5d243e09786d6581f2026 (diff)
powerpc/booke: Add kprobes support for booke style processors
This patch is based on work done by Madhvesh. R. Sulibhavi back in March 2007. We refactor some of the single step handling since it differs between "classic" and "booke" powerpc cores. Signed-off-by: Kumar Gala <galak@kernel.crashing.org>
Diffstat (limited to 'arch/powerpc/kernel/kprobes.c')
-rw-r--r--arch/powerpc/kernel/kprobes.c25
1 files changed, 19 insertions, 6 deletions
diff --git a/arch/powerpc/kernel/kprobes.c b/arch/powerpc/kernel/kprobes.c
index 74693d91731f..4ba2af125450 100644
--- a/arch/powerpc/kernel/kprobes.c
+++ b/arch/powerpc/kernel/kprobes.c
@@ -34,6 +34,13 @@
34#include <asm/cacheflush.h> 34#include <asm/cacheflush.h>
35#include <asm/sstep.h> 35#include <asm/sstep.h>
36#include <asm/uaccess.h> 36#include <asm/uaccess.h>
37#include <asm/system.h>
38
39#ifdef CONFIG_BOOKE
40#define MSR_SINGLESTEP (MSR_DE)
41#else
42#define MSR_SINGLESTEP (MSR_SE)
43#endif
37 44
38DEFINE_PER_CPU(struct kprobe *, current_kprobe) = NULL; 45DEFINE_PER_CPU(struct kprobe *, current_kprobe) = NULL;
39DEFINE_PER_CPU(struct kprobe_ctlblk, kprobe_ctlblk); 46DEFINE_PER_CPU(struct kprobe_ctlblk, kprobe_ctlblk);
@@ -53,7 +60,8 @@ int __kprobes arch_prepare_kprobe(struct kprobe *p)
53 ret = -EINVAL; 60 ret = -EINVAL;
54 } 61 }
55 62
56 /* insn must be on a special executable page on ppc64 */ 63 /* insn must be on a special executable page on ppc64. This is
64 * not explicitly required on ppc32 (right now), but it doesn't hurt */
57 if (!ret) { 65 if (!ret) {
58 p->ainsn.insn = get_insn_slot(); 66 p->ainsn.insn = get_insn_slot();
59 if (!p->ainsn.insn) 67 if (!p->ainsn.insn)
@@ -100,7 +108,11 @@ static void __kprobes prepare_singlestep(struct kprobe *p, struct pt_regs *regs)
100 * possible we'd get the single step reported for an exception handler 108 * possible we'd get the single step reported for an exception handler
101 * like Decrementer or External Interrupt */ 109 * like Decrementer or External Interrupt */
102 regs->msr &= ~MSR_EE; 110 regs->msr &= ~MSR_EE;
103 regs->msr |= MSR_SE; 111 regs->msr |= MSR_SINGLESTEP;
112#ifdef CONFIG_BOOKE
113 regs->msr &= ~MSR_CE;
114 mtspr(SPRN_DBCR0, mfspr(SPRN_DBCR0) | DBCR0_IC | DBCR0_IDM);
115#endif
104 116
105 /* 117 /*
106 * On powerpc we should single step on the original 118 * On powerpc we should single step on the original
@@ -163,7 +175,8 @@ static int __kprobes kprobe_handler(struct pt_regs *regs)
163 kprobe_opcode_t insn = *p->ainsn.insn; 175 kprobe_opcode_t insn = *p->ainsn.insn;
164 if (kcb->kprobe_status == KPROBE_HIT_SS && 176 if (kcb->kprobe_status == KPROBE_HIT_SS &&
165 is_trap(insn)) { 177 is_trap(insn)) {
166 regs->msr &= ~MSR_SE; 178 /* Turn off 'trace' bits */
179 regs->msr &= ~MSR_SINGLESTEP;
167 regs->msr |= kcb->kprobe_saved_msr; 180 regs->msr |= kcb->kprobe_saved_msr;
168 goto no_kprobe; 181 goto no_kprobe;
169 } 182 }
@@ -404,10 +417,10 @@ out:
404 417
405 /* 418 /*
406 * if somebody else is singlestepping across a probe point, msr 419 * if somebody else is singlestepping across a probe point, msr
407 * will have SE set, in which case, continue the remaining processing 420 * will have DE/SE set, in which case, continue the remaining processing
408 * of do_debug, as if this is not a probe hit. 421 * of do_debug, as if this is not a probe hit.
409 */ 422 */
410 if (regs->msr & MSR_SE) 423 if (regs->msr & MSR_SINGLESTEP)
411 return 0; 424 return 0;
412 425
413 return 1; 426 return 1;
@@ -430,7 +443,7 @@ int __kprobes kprobe_fault_handler(struct pt_regs *regs, int trapnr)
430 * normal page fault. 443 * normal page fault.
431 */ 444 */
432 regs->nip = (unsigned long)cur->addr; 445 regs->nip = (unsigned long)cur->addr;
433 regs->msr &= ~MSR_SE; 446 regs->msr &= ~MSR_SINGLESTEP; /* Turn off 'trace' bits */
434 regs->msr |= kcb->kprobe_saved_msr; 447 regs->msr |= kcb->kprobe_saved_msr;
435 if (kcb->kprobe_status == KPROBE_REENTER) 448 if (kcb->kprobe_status == KPROBE_REENTER)
436 restore_previous_kprobe(kcb); 449 restore_previous_kprobe(kcb);