aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--Documentation/kprobes.txt1
-rw-r--r--arch/powerpc/kernel/kprobes.c25
-rw-r--r--arch/powerpc/kernel/traps.c26
3 files changed, 37 insertions, 15 deletions
diff --git a/Documentation/kprobes.txt b/Documentation/kprobes.txt
index 6877e7187113..a79633d702bf 100644
--- a/Documentation/kprobes.txt
+++ b/Documentation/kprobes.txt
@@ -172,6 +172,7 @@ architectures:
172- ia64 (Does not support probes on instruction slot1.) 172- ia64 (Does not support probes on instruction slot1.)
173- sparc64 (Return probes not yet implemented.) 173- sparc64 (Return probes not yet implemented.)
174- arm 174- arm
175- ppc
175 176
1763. Configuring Kprobes 1773. Configuring Kprobes
177 178
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);
diff --git a/arch/powerpc/kernel/traps.c b/arch/powerpc/kernel/traps.c
index 4b5b7ff4f78b..b463d48145a4 100644
--- a/arch/powerpc/kernel/traps.c
+++ b/arch/powerpc/kernel/traps.c
@@ -1030,21 +1030,29 @@ void SoftwareEmulation(struct pt_regs *regs)
1030 1030
1031#if defined(CONFIG_40x) || defined(CONFIG_BOOKE) 1031#if defined(CONFIG_40x) || defined(CONFIG_BOOKE)
1032 1032
1033void DebugException(struct pt_regs *regs, unsigned long debug_status) 1033void __kprobes DebugException(struct pt_regs *regs, unsigned long debug_status)
1034{ 1034{
1035 if (debug_status & DBSR_IC) { /* instruction completion */ 1035 if (debug_status & DBSR_IC) { /* instruction completion */
1036 regs->msr &= ~MSR_DE; 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 if (user_mode(regs)) { 1051 if (user_mode(regs)) {
1038 current->thread.dbcr0 &= ~DBCR0_IC; 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#endif /* CONFIG_4xx || CONFIG_BOOKE */ 1058#endif /* CONFIG_4xx || CONFIG_BOOKE */