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>
This commit is contained in:
Roland McGrath
2009-05-28 21:26:38 +00:00
committed by Benjamin Herrenschmidt
parent dac4ccfb64
commit ec097c84df
4 changed files with 60 additions and 11 deletions

View File

@@ -1041,7 +1041,34 @@ void SoftwareEmulation(struct pt_regs *regs)
void __kprobes DebugException(struct pt_regs *regs, unsigned long debug_status)
{
if (debug_status & DBSR_IC) { /* instruction completion */
/* Hack alert: On BookE, Branch Taken stops on the branch itself, while
* on server, it stops on the target of the branch. In order to simulate
* the server behaviour, we thus restart right away with a single step
* instead of stopping here when hitting a BT
*/
if (debug_status & DBSR_BT) {
regs->msr &= ~MSR_DE;
/* Disable BT */
mtspr(SPRN_DBCR0, mfspr(SPRN_DBCR0) & ~DBCR0_BT);
/* Clear the BT event */
mtspr(SPRN_DBSR, DBSR_BT);
/* Do the single step trick only when coming from userspace */
if (user_mode(regs)) {
current->thread.dbcr0 &= ~DBCR0_BT;
current->thread.dbcr0 |= DBCR0_IDM | DBCR0_IC;
regs->msr |= MSR_DE;
return;
}
if (notify_die(DIE_SSTEP, "block_step", regs, 5,
5, SIGTRAP) == NOTIFY_STOP) {
return;
}
if (debugger_sstep(regs))
return;
} else if (debug_status & DBSR_IC) { /* Instruction complete */
regs->msr &= ~MSR_DE;
/* Disable instruction completion */
@@ -1057,9 +1084,8 @@ void __kprobes DebugException(struct pt_regs *regs, unsigned long debug_status)
if (debugger_sstep(regs))
return;
if (user_mode(regs)) {
current->thread.dbcr0 &= ~DBCR0_IC;
}
if (user_mode(regs))
current->thread.dbcr0 &= ~(DBCR0_IC);
_exception(SIGTRAP, regs, TRAP_TRACE, regs->nip);
} else if (debug_status & (DBSR_DAC1R | DBSR_DAC1W)) {