Commit f82796214a95b1ec00c2f121c1080d10f2b099a1

Authored by Kumar Gala
1 parent b76e59d1fb

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>

Showing 3 changed files with 37 additions and 15 deletions Side-by-side Diff

Documentation/kprobes.txt
... ... @@ -172,6 +172,7 @@
172 172 - ia64 (Does not support probes on instruction slot1.)
173 173 - sparc64 (Return probes not yet implemented.)
174 174 - arm
  175 +- ppc
175 176  
176 177 3. Configuring Kprobes
177 178  
arch/powerpc/kernel/kprobes.c
... ... @@ -34,7 +34,14 @@
34 34 #include <asm/cacheflush.h>
35 35 #include <asm/sstep.h>
36 36 #include <asm/uaccess.h>
  37 +#include <asm/system.h>
37 38  
  39 +#ifdef CONFIG_BOOKE
  40 +#define MSR_SINGLESTEP (MSR_DE)
  41 +#else
  42 +#define MSR_SINGLESTEP (MSR_SE)
  43 +#endif
  44 +
38 45 DEFINE_PER_CPU(struct kprobe *, current_kprobe) = NULL;
39 46 DEFINE_PER_CPU(struct kprobe_ctlblk, kprobe_ctlblk);
40 47  
... ... @@ -53,7 +60,8 @@
53 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 65 if (!ret) {
58 66 p->ainsn.insn = get_insn_slot();
59 67 if (!p->ainsn.insn)
... ... @@ -100,7 +108,11 @@
100 108 * possible we'd get the single step reported for an exception handler
101 109 * like Decrementer or External Interrupt */
102 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 118 * On powerpc we should single step on the original
... ... @@ -163,7 +175,8 @@
163 175 kprobe_opcode_t insn = *p->ainsn.insn;
164 176 if (kcb->kprobe_status == KPROBE_HIT_SS &&
165 177 is_trap(insn)) {
166   - regs->msr &= ~MSR_SE;
  178 + /* Turn off 'trace' bits */
  179 + regs->msr &= ~MSR_SINGLESTEP;
167 180 regs->msr |= kcb->kprobe_saved_msr;
168 181 goto no_kprobe;
169 182 }
170 183  
... ... @@ -404,10 +417,10 @@
404 417  
405 418 /*
406 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 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 424 return 0;
412 425  
413 426 return 1;
... ... @@ -430,7 +443,7 @@
430 443 * normal page fault.
431 444 */
432 445 regs->nip = (unsigned long)cur->addr;
433   - regs->msr &= ~MSR_SE;
  446 + regs->msr &= ~MSR_SINGLESTEP; /* Turn off 'trace' bits */
434 447 regs->msr |= kcb->kprobe_saved_msr;
435 448 if (kcb->kprobe_status == KPROBE_REENTER)
436 449 restore_previous_kprobe(kcb);
arch/powerpc/kernel/traps.c
... ... @@ -1030,21 +1030,29 @@
1030 1030  
1031 1031 #if defined(CONFIG_40x) || defined(CONFIG_BOOKE)
1032 1032  
1033   -void DebugException(struct pt_regs *regs, unsigned long debug_status)
  1033 +void __kprobes DebugException(struct pt_regs *regs, unsigned long debug_status)
1034 1034 {
1035 1035 if (debug_status & DBSR_IC) { /* instruction completion */
1036 1036 regs->msr &= ~MSR_DE;
  1037 +
  1038 + /* Disable instruction completion */
  1039 + mtspr(SPRN_DBCR0, mfspr(SPRN_DBCR0) & ~DBCR0_IC);
  1040 + /* Clear the instruction completion event */
  1041 + mtspr(SPRN_DBSR, DBSR_IC);
  1042 +
  1043 + if (notify_die(DIE_SSTEP, "single_step", regs, 5,
  1044 + 5, SIGTRAP) == NOTIFY_STOP) {
  1045 + return;
  1046 + }
  1047 +
  1048 + if (debugger_sstep(regs))
  1049 + return;
  1050 +
1037 1051 if (user_mode(regs)) {
1038 1052 current->thread.dbcr0 &= ~DBCR0_IC;
1039   - } else {
1040   - /* Disable instruction completion */
1041   - mtspr(SPRN_DBCR0, mfspr(SPRN_DBCR0) & ~DBCR0_IC);
1042   - /* Clear the instruction completion event */
1043   - mtspr(SPRN_DBSR, DBSR_IC);
1044   - if (debugger_sstep(regs))
1045   - return;
1046 1053 }
1047   - _exception(SIGTRAP, regs, TRAP_TRACE, 0);
  1054 +
  1055 + _exception(SIGTRAP, regs, TRAP_TRACE, regs->nip);
1048 1056 }
1049 1057 }
1050 1058 #endif /* CONFIG_4xx || CONFIG_BOOKE */