Fix for 4xx KGDB continue command
Frank Rowand
frank_rowand at mvista.com
Tue Dec 4 13:20:48 EST 2001
Tom,
Can you apply the attached patch to fix problems with the 4xx
KGDB continue command in the 2_4_devel tree?
The symptom is that in some cases to continue from a breakpoint
the continue command has to be issued twice. This can be seen
by: 1) set a breakpoint at sys_sync, 2) type "sync" on the console,
3) type "c" in KGDB -- KGDB will return to the sys_sync breakpoint
instead of continueing, 4) type "c" in KGDB -- KGDB will continue
properly and the console prompt will be printed on the console.
The major change was to always use the Program exception to handle
KGDB trap instructions and to clean up the Program exception code path.
Files modified in the patch:
arch/ppc/config.in
- fix the if that allows CONFIG_COMPILE_OPTIONS to be set
arch/ppc/kernel/head_4xx.S
- update comments
- read value of SPRN_SRR3 before clearing the MSR_DE bit in
it
arch/ppc/kernel/ppc-stub.c
- Increase the coverage of the "kdebug" support to show the
communications protocol involved in continue and single step
(all other commands were already covered).
- Don't use the debug exception for the 4xx continue command.
- For 4xx single step include IDM in the value put in DBCR0,
don't set the (non-existent) MSR_SE bit, and properly restore msr.
arch/ppc/kernel/ppc4xx_kgdb.c
- remove call to ppc4xx_kgdb_init()
arch/ppc/kernel/ppc4xx_setup.c
- remove ppc4xx_kgdb_init() (no longer needed since debug exception
is not used for trap instruction).
- rename ppc4xx_gdb_init() to ppc4xx_bdi_init() to better reflect
its purpose.
arch/ppc/kernel/traps.c
- For 4xx Program exception, clear bit that indicates a trap
instruction occurred.
Thanks!
Frank
--
Frank Rowand <frank_rowand at mvista.com>
MontaVista Software, Inc
-------------- next part --------------
diff -ruN ORIG/linux/arch/ppc/config.in NEW/linux/arch/ppc/config.in
--- ORIG/linux/arch/ppc/config.in Mon Dec 3 16:13:54 2001
+++ NEW/linux/arch/ppc/config.in Mon Dec 3 16:14:12 2001
@@ -603,7 +603,7 @@
if [ "$CONFIG_KGDB" = "y" -o "$CONFIG_XMON" = "y" \
-o "$CONFIG_BDI_SWITCH" = "y" ]; then
bool 'Add any additional compile options' CONFIG_MORE_COMPILE_OPTIONS
- if [ "$CONFIG_COMPILE_OPTIONS" = "y" ]; then
+ if [ "$CONFIG_MORE_COMPILE_OPTIONS" = "y" ]; then
string 'Additional compile arguments' CONFIG_COMPILE_OPTIONS "-O1 -ggdb"
fi
fi
diff -ruN ORIG/linux/arch/ppc/kernel/head_4xx.S NEW/linux/arch/ppc/kernel/head_4xx.S
--- ORIG/linux/arch/ppc/kernel/head_4xx.S Mon Dec 3 17:19:45 2001
+++ NEW/linux/arch/ppc/kernel/head_4xx.S Mon Dec 3 17:20:37 2001
@@ -684,13 +684,13 @@
/* 0x2000 - Debug Exception
*/
- START_EXCEPTION(0x2000, DebugTrap);
+ START_EXCEPTION(0x2000, DebugTrap)
b check_single_step_in_exception
ret_to_debug_exception:
CRIT_EXCEPTION_PROLOG(0x2000)
- addi r3,r1,STACK_FRAME_OVERHEAD;
+ addi r3,r1,STACK_FRAME_OVERHEAD
li r7,CRIT_EXC;
- li r20,MSR_KERNEL; /* don't turn MSR_DE back on yet */
+ li r20,MSR_KERNEL
FINISH_EXCEPTION(DebugException)
/* Make sure the final interrupt handler has not spilled past the
@@ -698,12 +698,18 @@
*/
.=0x2100
-/* The Debug Enable in the MSR is not reset upon entering an exception.
- * This causes problems for single step, because we then single step
- * the first exception handler instruction instead of the user instruction.
- * If we get a debug trap while in an exception handler, we reset the
- * MSR_DE and continue. Upon exit of the exception handler, the original
- * msr is restored, hopefully single stepping the user instruction.
+/* Check for a single step debug exception while in an exception
+ * handler before state has been saved. This is to catch the case
+ * where an instruction that we are trying to single step causes
+ * an exception (eg ITLB miss) and thus the first instruction of
+ * the exception handler generates a single step debug exception.
+ *
+ * If we get a debug trap on the first instruction of an exception handler,
+ * we reset the MSR_DE in the _exception handlers_ MSR (the debug trap is
+ * a critical exception, so we are using SPRN_SRR3 to manipulate the MSR).
+ * The exception handler was handling a non-critical interrupt, so it will
+ * save (and later restore) the MSR via SPRN_SRR1, which will still have
+ * the MSR_DE bit set.
*/
check_single_step_in_exception:
@@ -714,17 +720,19 @@
mtspr SPRN_SPRG0,r20 /* Save some working registers... */
mtspr SPRN_SPRG1,r21
mfcr r20 /* ..and the cr because we change it */
- mfspr r21,SPRN_SRR3 /* MSR at the time of fault */
+
+ mfspr r21,SPRN_SRR3 /* MSR at the time of fault */
andi. r21,r21,MSR_PR
- bne+ 2f
+ bne+ 2f /* trapped from problem state */
- mfspr r21,SPRN_SRR2 /* Faulting instruction address */
+ mfspr r21,SPRN_SRR2 /* Faulting instruction address */
cmplwi r21,0x2100
- bgt+ 2f
+ bgt+ 2f /* address above exception vectors */
lis r21,DBSR_IC at h /* Remove the trap status */
mtspr SPRN_DBSR,r21
+ mfspr r21,SPRN_SRR3
rlwinm r21,r21,0,23,21 /* clear MSR_DE */
mtspr SPRN_SRR3, r21 /* restore MSR at rcfi without DE */
diff -ruN ORIG/linux/arch/ppc/kernel/ppc-stub.c NEW/linux/arch/ppc/kernel/ppc-stub.c
--- ORIG/linux/arch/ppc/kernel/ppc-stub.c Mon Dec 3 17:19:45 2001
+++ NEW/linux/arch/ppc/kernel/ppc-stub.c Mon Dec 3 17:20:37 2001
@@ -564,6 +564,9 @@
*ptr++ = 0;
putpacket(remcomOutBuffer);
+ if (kdebug) {
+ printk("remcomOutBuffer: %s\n", remcomOutBuffer);
+ }
/* XXX We may want to add some features dealing with poking the
* XXX page tables, ... (look at sparc-stub.c for more info)
@@ -719,30 +722,34 @@
#if defined(CONFIG_4xx)
strcpy(remcomOutBuffer, "OK");
putpacket(remcomOutBuffer);
- regs->msr |= MSR_DE;
- regs->dbcr0 |= DBCR0_IDM;
-
-#else
+#endif
set_msr(msr);
-#endif
kgdb_interruptible(1);
unlock_kernel();
kgdb_active = 0;
+ if (kdebug) {
+ printk("remcomInBuffer: %s\n", remcomInBuffer);
+ printk("remcomOutBuffer: %s\n", remcomOutBuffer);
+ }
return;
case 's':
kgdb_flush_cache_all();
- regs->msr |= MSR_SE;
#if defined(CONFIG_4xx)
regs->msr |= MSR_DE;
- regs->dbcr0 |= DBCR0_IC;
-
+ regs->dbcr0 |= (DBCR0_IDM | DBCR0_IC);
+ set_msr(msr);
#else
+ regs->msr |= MSR_SE;
set_msr(msr | MSR_SE);
#endif
unlock_kernel();
kgdb_active = 0;
+ if (kdebug) {
+ printk("remcomInBuffer: %s\n", remcomInBuffer);
+ printk("remcomOutBuffer: %s\n", remcomOutBuffer);
+ }
return;
case 'r': /* Reset (if user process..exit ???)*/
diff -ruN ORIG/linux/arch/ppc/kernel/ppc4xx_kgdb.c NEW/linux/arch/ppc/kernel/ppc4xx_kgdb.c
--- ORIG/linux/arch/ppc/kernel/ppc4xx_kgdb.c Mon Dec 3 17:19:45 2001
+++ NEW/linux/arch/ppc/kernel/ppc4xx_kgdb.c Mon Dec 3 17:20:37 2001
@@ -150,6 +150,5 @@
void
kgdb_map_scc(void)
{
- ppc4xx_kgdb_init();
kgdb_debugport = NS16550_init(KGDB_PORT);
}
diff -ruN ORIG/linux/arch/ppc/kernel/ppc4xx_setup.c NEW/linux/arch/ppc/kernel/ppc4xx_setup.c
--- ORIG/linux/arch/ppc/kernel/ppc4xx_setup.c Mon Dec 3 17:19:45 2001
+++ NEW/linux/arch/ppc/kernel/ppc4xx_setup.c Mon Dec 3 17:20:37 2001
@@ -133,10 +133,9 @@
board_setup_arch();
#if defined(CONFIG_BDI_SWITCH)
- ppc4xx_gdb_init();
+ ppc4xx_bdi_init();
#endif
-
}
@@ -242,32 +241,15 @@
while(1);
}
-#if defined CONFIG_BDI_SWITCH
-#define DEBUGGER_FLAGS DBCR0_EDM | DBCR0_TDE
-#else
-#define DEBUGGER_FLAGS DBCR0_TDE | DBCR0_IDM
-#endif
void
-ppc4xx_gdb_init( void )
+ppc4xx_bdi_init( void )
{
- mtspr(SPRN_DBCR0, ( DEBUGGER_FLAGS ));
+ mtspr(SPRN_DBCR0, (DBCR0_EDM | DBCR0_TDE));
mtspr(SPRN_DBCR1, 0);
- init_task.thread.regs->dbcr0 = (DEBUGGER_FLAGS);
- return;
-}
-
-#if defined(CONFIG_KGDB)
-void
-ppc4xx_kgdb_init( void )
-{
- _nmask_and_or_msr(0, MSR_DE);
- mtspr(SPRN_DBCR0,
- (mfspr(SPRN_DBCR0) | DEBUGGER_FLAGS));
- _nmask_and_or_msr(0, MSR_DE);
+ init_task.thread.regs->dbcr0 = (DBCR0_EDM | DBCR0_TDE);
return;
}
-#endif
/*
diff -ruN ORIG/linux/arch/ppc/kernel/traps.c NEW/linux/arch/ppc/kernel/traps.c
--- ORIG/linux/arch/ppc/kernel/traps.c Mon Dec 3 17:19:45 2001
+++ NEW/linux/arch/ppc/kernel/traps.c Mon Dec 3 17:20:37 2001
@@ -301,6 +301,8 @@
int isbpt = esr & ESR_PTR;
extern int do_mathemu(struct pt_regs *regs);
+ if (isbpt)
+ mtspr(SPRN_DBSR, DBSR_TIE);
#ifdef CONFIG_MATH_EMULATION
if (!isbpt && do_mathemu(regs) == 0)
return;
More information about the Linuxppc-dev
mailing list