aboutsummaryrefslogtreecommitdiffstats
path: root/arch/powerpc/kernel/traps.c
diff options
context:
space:
mode:
authorRoland McGrath <roland@redhat.com>2009-05-28 17:26:38 -0400
committerBenjamin Herrenschmidt <benh@kernel.crashing.org>2009-06-08 23:29:25 -0400
commitec097c84dff17511f2693e6ef6c3064dfbf0a3af (patch)
tree3eac516a13730dcb371c094c0e8d35c9768c9c23 /arch/powerpc/kernel/traps.c
parentdac4ccfb64bcdd5b4c248ccc22903d67486573cd (diff)
powerpc: Add PTRACE_SINGLEBLOCK support
Reworked by: Benjamin Herrenschmidt <benh@kernel.crashing.org> This adds block-step support on powerpc, including a PTRACE_SINGLEBLOCK request for ptrace. The BookE implementation is tweaked to fire a single step after a block step in order to mimmic the server behaviour. Signed-off-by: Roland McGrath <roland@redhat.com> Signed-off-by: Benjamin Herrenschmidt <benh@kernel.crashing.org>
Diffstat (limited to 'arch/powerpc/kernel/traps.c')
-rw-r--r--arch/powerpc/kernel/traps.c34
1 files changed, 30 insertions, 4 deletions
diff --git a/arch/powerpc/kernel/traps.c b/arch/powerpc/kernel/traps.c
index 6a5b2b731f43..6f0ae1a9bfae 100644
--- a/arch/powerpc/kernel/traps.c
+++ b/arch/powerpc/kernel/traps.c
@@ -1041,7 +1041,34 @@ void SoftwareEmulation(struct pt_regs *regs)
1041 1041
1042void __kprobes DebugException(struct pt_regs *regs, unsigned long debug_status) 1042void __kprobes DebugException(struct pt_regs *regs, unsigned long debug_status)
1043{ 1043{
1044 if (debug_status & DBSR_IC) { /* instruction completion */ 1044 /* Hack alert: On BookE, Branch Taken stops on the branch itself, while
1045 * on server, it stops on the target of the branch. In order to simulate
1046 * the server behaviour, we thus restart right away with a single step
1047 * instead of stopping here when hitting a BT
1048 */
1049 if (debug_status & DBSR_BT) {
1050 regs->msr &= ~MSR_DE;
1051
1052 /* Disable BT */
1053 mtspr(SPRN_DBCR0, mfspr(SPRN_DBCR0) & ~DBCR0_BT);
1054 /* Clear the BT event */
1055 mtspr(SPRN_DBSR, DBSR_BT);
1056
1057 /* Do the single step trick only when coming from userspace */
1058 if (user_mode(regs)) {
1059 current->thread.dbcr0 &= ~DBCR0_BT;
1060 current->thread.dbcr0 |= DBCR0_IDM | DBCR0_IC;
1061 regs->msr |= MSR_DE;
1062 return;
1063 }
1064
1065 if (notify_die(DIE_SSTEP, "block_step", regs, 5,
1066 5, SIGTRAP) == NOTIFY_STOP) {
1067 return;
1068 }
1069 if (debugger_sstep(regs))
1070 return;
1071 } else if (debug_status & DBSR_IC) { /* Instruction complete */
1045 regs->msr &= ~MSR_DE; 1072 regs->msr &= ~MSR_DE;
1046 1073
1047 /* Disable instruction completion */ 1074 /* Disable instruction completion */
@@ -1057,9 +1084,8 @@ void __kprobes DebugException(struct pt_regs *regs, unsigned long debug_status)
1057 if (debugger_sstep(regs)) 1084 if (debugger_sstep(regs))
1058 return; 1085 return;
1059 1086
1060 if (user_mode(regs)) { 1087 if (user_mode(regs))
1061 current->thread.dbcr0 &= ~DBCR0_IC; 1088 current->thread.dbcr0 &= ~(DBCR0_IC);
1062 }
1063 1089
1064 _exception(SIGTRAP, regs, TRAP_TRACE, regs->nip); 1090 _exception(SIGTRAP, regs, TRAP_TRACE, regs->nip);
1065 } else if (debug_status & (DBSR_DAC1R | DBSR_DAC1W)) { 1091 } else if (debug_status & (DBSR_DAC1R | DBSR_DAC1W)) {