summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorraj <raj@FreeBSD.org>2009-02-27 12:08:24 +0000
committerraj <raj@FreeBSD.org>2009-02-27 12:08:24 +0000
commitb86fc6783988150fa890cbba0bbd1c3547e6360d (patch)
tree8b41f61a7208bd8888ebad2d80a7da1d913c93f4
parent01cc5b6616afb7ff0d494ccddc3dc721ad54ef68 (diff)
downloadFreeBSD-src-b86fc6783988150fa890cbba0bbd1c3547e6360d.zip
FreeBSD-src-b86fc6783988150fa890cbba0bbd1c3547e6360d.tar.gz
Make Book-E debug register state part of the PCB context.
Previously, DBCR0 flags were set "globally", but this leads to problems because Book-E fine grained debug settings work only in conjuction with the debug master enable bit in MSR: in scenarios when the DBCR0 was set with intention to debug one process, but another one with MSR[DE] set got scheduled, the latter would immediately cause debug exceptions to occur upon execution of its own code instructions (and not the one intended for debugging). To avoid such problems and properly handle debugging context, DBCR0 state should be managed individually per process. Submitted by: Grzegorz Bernacki gjb ! semihalf dot com Reviewed by: marcel
-rw-r--r--sys/powerpc/booke/machdep.c7
-rw-r--r--sys/powerpc/booke/swtch.S5
-rw-r--r--sys/powerpc/booke/trap.c1
-rw-r--r--sys/powerpc/booke/trap_subr.S6
-rw-r--r--sys/powerpc/include/frame.h1
-rw-r--r--sys/powerpc/include/pcb.h1
-rw-r--r--sys/powerpc/powerpc/genassym.c2
7 files changed, 18 insertions, 5 deletions
diff --git a/sys/powerpc/booke/machdep.c b/sys/powerpc/booke/machdep.c
index 1803ef2..e42aa8c 100644
--- a/sys/powerpc/booke/machdep.c
+++ b/sys/powerpc/booke/machdep.c
@@ -806,14 +806,10 @@ int
ptrace_single_step(struct thread *td)
{
struct trapframe *tf;
- u_int reg;
-
- reg = mfspr(SPR_DBCR0);
- reg |= DBCR0_IC | DBCR0_IDM;
- mtspr(SPR_DBCR0, reg);
tf = td->td_frame;
tf->srr1 |= PSL_DE;
+ tf->cpu.booke.dbcr0 |= (DBCR0_IDM | DBCR0_IC);
return (0);
}
@@ -824,6 +820,7 @@ ptrace_clear_single_step(struct thread *td)
tf = td->td_frame;
tf->srr1 &= ~PSL_DE;
+ tf->cpu.booke.dbcr0 &= ~(DBCR0_IDM | DBCR0_IC);
return (0);
}
diff --git a/sys/powerpc/booke/swtch.S b/sys/powerpc/booke/swtch.S
index 80bf2b3..bfd7dd2 100644
--- a/sys/powerpc/booke/swtch.S
+++ b/sys/powerpc/booke/swtch.S
@@ -66,6 +66,7 @@
#include <machine/param.h>
#include <machine/psl.h>
#include <machine/asm.h>
+#include <machine/spr.h>
/*
* void cpu_switch(struct thread *old, struct thread *new)
@@ -87,6 +88,8 @@ ENTRY(cpu_switch)
stw %r16, PCB_BOOKE_CTR(%r5)
mfxer %r16
stw %r16, PCB_BOOKE_XER(%r5)
+ mfspr %r16, SPR_DBCR0
+ stw %r16, PCB_BOOKE_DBCR0(%r5)
stw %r1, PCB_SP(%r5) /* Save the stack pointer */
@@ -114,6 +117,8 @@ ENTRY(cpu_switch)
mtctr %r5
lwz %r5, PCB_BOOKE_XER(%r3)
mtxer %r5
+ lwz %r5, PCB_BOOKE_DBCR0(%r3)
+ mtspr SPR_DBCR0, %r5
lwz %r1, PCB_SP(%r3) /* Load the stack pointer */
blr
diff --git a/sys/powerpc/booke/trap.c b/sys/powerpc/booke/trap.c
index 88a0a51..0e746f4 100644
--- a/sys/powerpc/booke/trap.c
+++ b/sys/powerpc/booke/trap.c
@@ -187,6 +187,7 @@ trap(struct trapframe *frame)
case EXC_DEBUG: /* Single stepping */
mtspr(SPR_DBSR, mfspr(SPR_DBSR));
frame->srr1 &= ~PSL_DE;
+ frame->cpu.booke.dbcr0 &= ~(DBCR0_IDM || DBCR0_IC);
sig = SIGTRAP;
break;
diff --git a/sys/powerpc/booke/trap_subr.S b/sys/powerpc/booke/trap_subr.S
index f7a54a6..2a5820d 100644
--- a/sys/powerpc/booke/trap_subr.S
+++ b/sys/powerpc/booke/trap_subr.S
@@ -207,6 +207,9 @@
stw %r4, FRAME_CTR+8(1); \
li %r5, exc; \
stw %r5, FRAME_EXC+8(1); \
+ /* save DBCR0 */ \
+ mfspr %r3, SPR_DBCR0; \
+ stw %r3, FRAME_BOOKE_DBCR0+8(1); \
/* save xSSR0-1 */ \
lwz %r30, (savearea+CPUSAVE_SRR0)(%r2); \
lwz %r31, (savearea+CPUSAVE_SRR1)(%r2); \
@@ -231,6 +234,9 @@
mtxer %r5; \
mtlr %r6; \
mtcr %r7; \
+ /* restore DBCR0 */ \
+ lwz %r4, FRAME_BOOKE_DBCR0+8(%r1); \
+ mtspr SPR_DBCR0, %r4; \
/* restore xSRR0-1 */ \
lwz %r30, FRAME_SRR0+8(%r1); \
lwz %r31, FRAME_SRR1+8(%r1); \
diff --git a/sys/powerpc/include/frame.h b/sys/powerpc/include/frame.h
index 9f714e8..7ef23ef 100644
--- a/sys/powerpc/include/frame.h
+++ b/sys/powerpc/include/frame.h
@@ -65,6 +65,7 @@ struct trapframe {
struct {
register_t dear;
register_t esr;
+ register_t dbcr0;
} booke;
} cpu;
};
diff --git a/sys/powerpc/include/pcb.h b/sys/powerpc/include/pcb.h
index a57cef1..3469e10 100644
--- a/sys/powerpc/include/pcb.h
+++ b/sys/powerpc/include/pcb.h
@@ -70,6 +70,7 @@ struct pcb {
struct {
register_t ctr;
register_t xer;
+ register_t dbcr0;
} booke;
} pcb_cpu;
};
diff --git a/sys/powerpc/powerpc/genassym.c b/sys/powerpc/powerpc/genassym.c
index 1cb79f9..ebdddd4 100644
--- a/sys/powerpc/powerpc/genassym.c
+++ b/sys/powerpc/powerpc/genassym.c
@@ -158,6 +158,7 @@ ASSYM(FRAME_AIM_DAR, offsetof(struct trapframe, cpu.aim.dar));
ASSYM(FRAME_AIM_DSISR, offsetof(struct trapframe, cpu.aim.dsisr));
ASSYM(FRAME_BOOKE_DEAR, offsetof(struct trapframe, cpu.booke.dear));
ASSYM(FRAME_BOOKE_ESR, offsetof(struct trapframe, cpu.booke.esr));
+ASSYM(FRAME_BOOKE_DBCR0, offsetof(struct trapframe, cpu.booke.dbcr0));
ASSYM(CF_FUNC, offsetof(struct callframe, cf_func));
ASSYM(CF_ARG0, offsetof(struct callframe, cf_arg0));
@@ -176,6 +177,7 @@ ASSYM(PCB_VEC, PCB_VEC);
ASSYM(PCB_AIM_USR, offsetof(struct pcb, pcb_cpu.aim.usr));
ASSYM(PCB_BOOKE_CTR, offsetof(struct pcb, pcb_cpu.booke.ctr));
ASSYM(PCB_BOOKE_XER, offsetof(struct pcb, pcb_cpu.booke.xer));
+ASSYM(PCB_BOOKE_DBCR0, offsetof(struct pcb, pcb_cpu.booke.dbcr0));
ASSYM(TD_LOCK, offsetof(struct thread, td_lock));
ASSYM(TD_PROC, offsetof(struct thread, td_proc));
OpenPOWER on IntegriCloud