2004-10-30 00:58:07

by Matt Porter

[permalink] [raw]
Subject: [PATCH][PPC32][1/2] 40x and Book E debug: core support

This patch updates the 40x and Book E Debug exception handling paths
to handle kernel space debug events. It also fixes up the in-kernel
ppc32 kgdb stub to work properly.

Signed-off-by: Matt Porter <[email protected]>

diff -Nru a/arch/ppc/kernel/head_44x.S b/arch/ppc/kernel/head_44x.S
--- a/arch/ppc/kernel/head_44x.S 2004-10-29 17:13:29 -07:00
+++ b/arch/ppc/kernel/head_44x.S 2004-10-29 17:13:29 -07:00
@@ -599,64 +599,8 @@
mfspr r10, SPRG0
b InstructionStorage

-/* 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/DTLB 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 handler's_ MSR (the debug trap is
- * a critical exception, so we are using SPRN_CSRR1 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.
- */
/* Debug Interrupt */
- START_EXCEPTION(Debug)
- CRITICAL_EXCEPTION_PROLOG
-
- /*
- * If this is a single step or branch-taken exception in an
- * exception entry sequence, it was probably meant to apply to
- * the code where the exception occurred (since exception entry
- * doesn't turn off DE automatically). We simulate the effect
- * of turning off DE on entry to an exception handler by turning
- * off DE in the CSRR1 value and clearing the debug status.
- */
- mfspr r10,SPRN_DBSR /* check single-step/branch taken */
- andis. r10,r10,(DBSR_IC|DBSR_BT)@h
- beq+ 1f
- andi. r0,r9,MSR_PR /* check supervisor */
- beq 2f /* branch if we need to fix it up... */
-
- /* continue normal handling for a critical exception... */
-1: mfspr r4,SPRN_DBSR
- addi r3,r1,STACK_FRAME_OVERHEAD
- EXC_XFER_TEMPLATE(DebugException, 0x2002, \
- (MSR_KERNEL & ~(MSR_ME|MSR_DE|MSR_CE)), \
- NOCOPY, crit_transfer_to_handler, ret_from_crit_exc)
-
- /* here it looks like we got an inappropriate debug exception. */
-2: rlwinm r9,r9,0,~MSR_DE /* clear DE in the CSRR1 value */
- mtspr SPRN_DBSR,r10 /* clear the IC/BT debug intr status */
- /* restore state and get out */
- lwz r10,_CCR(r11)
- lwz r0,GPR0(r11)
- lwz r1,GPR1(r11)
- mtcrf 0x80,r10
- mtspr CSRR0,r12
- mtspr CSRR1,r9
- lwz r9,GPR9(r11)
-
- mtspr SPRG2,r8; /* SPRG2 only used in criticals */
- lis r8,crit_save@ha;
- lwz r10,crit_r10@l(r8)
- lwz r11,crit_r11@l(r8)
- mfspr r8,SPRG2
-
- rfci
- b .
+ DEBUG_EXCEPTION

/*
* Local functions
diff -Nru a/arch/ppc/kernel/head_4xx.S b/arch/ppc/kernel/head_4xx.S
--- a/arch/ppc/kernel/head_4xx.S 2004-10-29 17:13:29 -07:00
+++ b/arch/ppc/kernel/head_4xx.S 2004-10-29 17:13:29 -07:00
@@ -709,8 +709,20 @@
EXCEPTION(0x1E00, Trap_1E, UnknownException, EXC_XFER_EE)
EXCEPTION(0x1F00, Trap_1F, UnknownException, EXC_XFER_EE)

-/* 0x2000 - Debug Exception
-*/
+/* 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/DTLB 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 handler's_ MSR (the debug trap is
+ * a critical exception, so we are using SPRN_CSRR1 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.
+ */
+ /* 0x2000 - Debug Exception */
START_EXCEPTION(0x2000, DebugTrap)
CRITICAL_EXCEPTION_PROLOG

@@ -723,21 +735,20 @@
* off DE in the SRR3 value and clearing the debug status.
*/
mfspr r10,SPRN_DBSR /* check single-step/branch taken */
- andis. r10,r10,(DBSR_IC|DBSR_BT)@h
- beq+ 1f
- andi. r0,r9,MSR_IR|MSR_PR /* check supervisor + MMU off */
- beq 2f /* branch if we need to fix it up... */
+ andis. r10,r10,DBSR_IC@h
+ beq+ 2f

- /* continue normal handling for a critical exception... */
-1: mfspr r4,SPRN_DBSR
- addi r3,r1,STACK_FRAME_OVERHEAD
- EXC_XFER_TEMPLATE(DebugException, 0x2002, \
- (MSR_KERNEL & ~(MSR_ME|MSR_DE|MSR_CE)), \
- NOCOPY, crit_transfer_to_handler, ret_from_crit_exc)
+ andi. r10,r9,MSR_IR|MSR_PR /* check supervisor + MMU off */
+ beq 1f /* branch and fix it up */
+
+ mfspr r10,SPRN_SRR2 /* Faulting instruction address */
+ cmplwi r10,0x2100
+ bgt+ 2f /* address above exception vectors */

/* here it looks like we got an inappropriate debug exception. */
-2: rlwinm r9,r9,0,~MSR_DE /* clear DE in the SRR3 value */
- mtspr SPRN_DBSR,r10 /* clear the IC/BT debug intr status */
+1: rlwinm r9,r9,0,~MSR_DE /* clear DE in the SRR3 value */
+ lis r10,DBSR_IC@h /* clear the IC event */
+ mtspr SPRN_DBSR,r10
/* restore state and get out */
lwz r10,_CCR(r11)
lwz r0,GPR0(r11)
@@ -752,6 +763,13 @@
PPC405_ERR77_SYNC
rfci
b .
+
+ /* continue normal handling for a critical exception... */
+2: mfspr r4,SPRN_DBSR
+ addi r3,r1,STACK_FRAME_OVERHEAD
+ EXC_XFER_TEMPLATE(DebugException, 0x2002, \
+ (MSR_KERNEL & ~(MSR_ME|MSR_DE|MSR_CE)), \
+ NOCOPY, crit_transfer_to_handler, ret_from_crit_exc)

/*
* The other Data TLB exceptions bail out to this point
diff -Nru a/arch/ppc/kernel/head_booke.h b/arch/ppc/kernel/head_booke.h
--- a/arch/ppc/kernel/head_booke.h 2004-10-29 17:13:29 -07:00
+++ b/arch/ppc/kernel/head_booke.h 2004-10-29 17:13:29 -07:00
@@ -237,4 +237,70 @@
ret_from_except)


+/* 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/DTLB 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 handler's_ MSR (the debug trap is
+ * a critical exception, so we are using SPRN_CSRR1 to manipulate the MSR).
+ * The exception handler was handling a non-critical interrupt, so it will
+ * save (and later restore) the MSR via SPRN_CSRR1, which will still have
+ * the MSR_DE bit set.
+ */
+#define DEBUG_EXCEPTION \
+ START_EXCEPTION(Debug); \
+ CRITICAL_EXCEPTION_PROLOG; \
+ \
+ /* \
+ * If there is a single step or branch-taken exception in an \
+ * exception entry sequence, it was probably meant to apply to \
+ * the code where the exception occurred (since exception entry \
+ * doesn't turn off DE automatically). We simulate the effect \
+ * of turning off DE on entry to an exception handler by turning \
+ * off DE in the CSRR1 value and clearing the debug status. \
+ */ \
+ mfspr r10,SPRN_DBSR; /* check single-step/branch taken */ \
+ andis. r10,r10,DBSR_IC@h; \
+ beq+ 2f; \
+ \
+ lis r10,KERNELBASE@h; /* check if exception in vectors */ \
+ ori r10,r10,KERNELBASE@l; \
+ cmplw r12,r10; \
+ blt+ 2f; /* addr below exception vectors */ \
+ \
+ lis r10,Debug@h; \
+ ori r10,r10,Debug@l; \
+ cmplw r12,r10; \
+ bgt+ 2f; /* addr above exception vectors */ \
+ \
+ /* here it looks like we got an inappropriate debug exception. */ \
+1: rlwinm r9,r9,0,~MSR_DE; /* clear DE in the CSRR1 value */ \
+ lis r10,DBSR_IC@h; /* clear the IC event */ \
+ mtspr SPRN_DBSR,r10; \
+ /* restore state and get out */ \
+ lwz r10,_CCR(r11); \
+ lwz r0,GPR0(r11); \
+ lwz r1,GPR1(r11); \
+ mtcrf 0x80,r10; \
+ mtspr CSRR0,r12; \
+ mtspr CSRR1,r9; \
+ lwz r9,GPR9(r11); \
+ lwz r12,GPR12(r11); \
+ mtspr SPRG2,r8; /* SPRG2 only used in criticals */ \
+ lis r8,crit_save@ha; \
+ lwz r10,crit_r10@l(r8); \
+ lwz r11,crit_r11@l(r8); \
+ mfspr r8,SPRG2; \
+ \
+ rfci; \
+ b .; \
+ \
+ /* continue normal handling for a critical exception... */ \
+2: mfspr r4,SPRN_DBSR; \
+ addi r3,r1,STACK_FRAME_OVERHEAD; \
+ EXC_XFER_TEMPLATE(DebugException, 0x2002, (MSR_KERNEL & ~(MSR_ME|MSR_DE|MSR_CE)), NOCOPY, crit_transfer_to_handler, ret_from_crit_exc)
+
#endif /* __HEAD_BOOKE_H__ */
diff -Nru a/arch/ppc/kernel/head_e500.S b/arch/ppc/kernel/head_e500.S
--- a/arch/ppc/kernel/head_e500.S 2004-10-29 17:13:29 -07:00
+++ b/arch/ppc/kernel/head_e500.S 2004-10-29 17:13:29 -07:00
@@ -668,64 +668,8 @@
/* Performance Monitor */
EXCEPTION(0x2060, PerformanceMonitor, UnknownException, EXC_XFER_EE)

-/* 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/DTLB 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 handler's_ MSR (the debug trap is
- * a critical exception, so we are using SPRN_CSRR1 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.
- */
/* Debug Interrupt */
- START_EXCEPTION(Debug)
- CRITICAL_EXCEPTION_PROLOG
-
- /*
- * If this is a single step or branch-taken exception in an
- * exception entry sequence, it was probably meant to apply to
- * the code where the exception occurred (since exception entry
- * doesn't turn off DE automatically). We simulate the effect
- * of turning off DE on entry to an exception handler by turning
- * off DE in the CSRR1 value and clearing the debug status.
- */
- mfspr r10,SPRN_DBSR /* check single-step/branch taken */
- andis. r10,r10,(DBSR_IC|DBSR_BT)@h
- beq+ 1f
- andi. r0,r9,MSR_PR /* check supervisor */
- beq 2f /* branch if we need to fix it up... */
-
- /* continue normal handling for a critical exception... */
-1: mfspr r4,SPRN_DBSR
- addi r3,r1,STACK_FRAME_OVERHEAD
- EXC_XFER_TEMPLATE(DebugException, 0x2002, \
- (MSR_KERNEL & ~(MSR_ME|MSR_DE|MSR_CE)), \
- NOCOPY, crit_transfer_to_handler, ret_from_crit_exc)
-
- /* here it looks like we got an inappropriate debug exception. */
-2: rlwinm r9,r9,0,~MSR_DE /* clear DE in the CSRR1 value */
- mtspr SPRN_DBSR,r10 /* clear the IC/BT debug intr status */
- /* restore state and get out */
- lwz r10,_CCR(r11)
- lwz r0,GPR0(r11)
- lwz r1,GPR1(r11)
- mtcrf 0x80,r10
- mtspr CSRR0,r12
- mtspr CSRR1,r9
- lwz r9,GPR9(r11)
-
- mtspr SPRG2,r8; /* SPRG2 only used in criticals */
- lis r8,crit_save@ha;
- lwz r10,crit_r10@l(r8)
- lwz r11,crit_r11@l(r8)
- mfspr r8,SPRG2
-
- rfci
- b .
+ DEBUG_EXCEPTION

/*
* Local functions
diff -Nru a/arch/ppc/kernel/ppc-stub.c b/arch/ppc/kernel/ppc-stub.c
--- a/arch/ppc/kernel/ppc-stub.c 2004-10-29 17:13:29 -07:00
+++ b/arch/ppc/kernel/ppc-stub.c 2004-10-29 17:13:29 -07:00
@@ -498,7 +498,7 @@
unsigned int tt; /* Trap type code for powerpc */
unsigned char signo; /* Signal that we map this trap into */
} hard_trap_info[] = {
-#if defined(CONFIG_40x)
+#if defined(CONFIG_40x) || defined(CONFIG_BOOKE)
{ 0x100, SIGINT }, /* critical input interrupt */
{ 0x200, SIGSEGV }, /* machine check */
{ 0x300, SIGSEGV }, /* data storage */
@@ -521,7 +521,7 @@
** 0x1100 data TLB miss
** 0x1200 instruction TLB miss
*/
- { 0x2000, SIGTRAP}, /* debug */
+ { 0x2002, SIGTRAP}, /* debug */
#else
{ 0x200, SIGSEGV }, /* machine check */
{ 0x300, SIGSEGV }, /* address error (store) */
@@ -602,11 +602,6 @@
sigval = computeSignal(regs->trap);
ptr = remcomOutBuffer;

-#if defined(CONFIG_40x)
- *ptr++ = 'S';
- *ptr++ = hexchars[sigval >> 4];
- *ptr++ = hexchars[sigval & 0xf];
-#else
*ptr++ = 'T';
*ptr++ = hexchars[sigval >> 4];
*ptr++ = hexchars[sigval & 0xf];
@@ -620,8 +615,6 @@
*ptr++ = ':';
ptr = mem2hex(((char *)regs) + SP_REGNUM*4, ptr, 4);
*ptr++ = ';';
-#endif
-
*ptr++ = 0;

putpacket(remcomOutBuffer);
@@ -774,10 +767,6 @@
* some location may have changed something that is in the instruction cache.
*/
kgdb_flush_cache_all();
-#if defined(CONFIG_40x)
- strcpy(remcomOutBuffer, "OK");
- putpacket(remcomOutBuffer);
-#endif
mtmsr(msr);

kgdb_interruptible(1);
@@ -791,10 +780,9 @@

case 's':
kgdb_flush_cache_all();
-#if defined(CONFIG_40x)
+#if defined(CONFIG_40x) || defined(CONFIG_BOOKE)
+ mtspr(SPRN_DBCR0, mfspr(SPRN_DBCR0) | DBCR0_IC);
regs->msr |= MSR_DE;
- regs->dbcr0 |= (DBCR0_IDM | DBCR0_IC);
- mtmsr(msr);
#else
regs->msr |= MSR_SE;
#endif
diff -Nru a/arch/ppc/kernel/ptrace.c b/arch/ppc/kernel/ptrace.c
--- a/arch/ppc/kernel/ptrace.c 2004-10-29 17:13:29 -07:00
+++ b/arch/ppc/kernel/ptrace.c 2004-10-29 17:13:29 -07:00
@@ -35,7 +35,7 @@
/*
* Set of msr bits that gdb can change on behalf of a process.
*/
-#if defined(CONFIG_4xx) || defined(CONFIG_BOOKE)
+#if defined(CONFIG_40x) || defined(CONFIG_BOOKE)
#define MSR_DEBUGCHANGE 0
#else
#define MSR_DEBUGCHANGE (MSR_SE | MSR_BE)
@@ -201,9 +201,9 @@
struct pt_regs *regs = task->thread.regs;

if (regs != NULL) {
-#if defined(CONFIG_4xx) || defined(CONFIG_BOOKE)
+#if defined(CONFIG_40x) || defined(CONFIG_BOOKE)
task->thread.dbcr0 = DBCR0_IDM | DBCR0_IC;
- /* MSR.DE should already be set */
+ regs->msr |= MSR_DE;
#else
regs->msr |= MSR_SE;
#endif
@@ -216,8 +216,9 @@
struct pt_regs *regs = task->thread.regs;

if (regs != NULL) {
-#if defined(CONFIG_4xx) || defined(CONFIG_BOOKE)
+#if defined(CONFIG_40x) || defined(CONFIG_BOOKE)
task->thread.dbcr0 = 0;
+ regs->msr &= ~MSR_DE;
#else
regs->msr &= ~MSR_SE;
#endif
diff -Nru a/arch/ppc/kernel/traps.c b/arch/ppc/kernel/traps.c
--- a/arch/ppc/kernel/traps.c 2004-10-29 17:13:29 -07:00
+++ b/arch/ppc/kernel/traps.c 2004-10-29 17:13:29 -07:00
@@ -647,22 +647,22 @@
}
#endif /* CONFIG_8xx */

-#if defined(CONFIG_4xx) || defined(CONFIG_BOOKE)
+#if defined(CONFIG_40x) || defined(CONFIG_BOOKE)

void DebugException(struct pt_regs *regs, unsigned long debug_status)
{
-#if 0
- if (debug_status & DBSR_TIE) { /* trap instruction*/
- if (!user_mode(regs) && debugger_bpt(regs))
- return;
- _exception(SIGTRAP, regs, 0, 0);
-
- }
-#endif
if (debug_status & DBSR_IC) { /* instruction completion */
- if (!user_mode(regs) && debugger_sstep(regs))
- return;
- current->thread.dbcr0 &= ~DBCR0_IC;
+ regs->msr &= ~MSR_DE;
+ if (user_mode(regs)) {
+ current->thread.dbcr0 &= ~DBCR0_IC;
+ } else {
+ /* Disable instruction completion */
+ mtspr(SPRN_DBCR0, mfspr(SPRN_DBCR0) & ~DBCR0_IC);
+ /* Clear the instruction completion event */
+ mtspr(SPRN_DBSR, DBSR_IC);
+ if (debugger_sstep(regs))
+ return;
+ }
_exception(SIGTRAP, regs, TRAP_TRACE, 0);
}
}
diff -Nru a/include/asm-ppc/reg_booke.h b/include/asm-ppc/reg_booke.h
--- a/include/asm-ppc/reg_booke.h 2004-10-29 17:13:29 -07:00
+++ b/include/asm-ppc/reg_booke.h 2004-10-29 17:13:29 -07:00
@@ -63,9 +63,9 @@

/* Default MSR for kernel mode. */
#if defined (CONFIG_40x)
-#define MSR_KERNEL (MSR_ME|MSR_RI|MSR_IR|MSR_DR|MSR_CE|MSR_DE)
+#define MSR_KERNEL (MSR_ME|MSR_RI|MSR_IR|MSR_DR|MSR_CE)
#elif defined(CONFIG_BOOKE)
-#define MSR_KERNEL (MSR_ME|MSR_RI|MSR_CE|MSR_DE)
+#define MSR_KERNEL (MSR_ME|MSR_RI|MSR_CE)
#endif

/* Special Purpose Registers (SPRNs)*/


2004-10-30 01:17:48

by Matt Porter

[permalink] [raw]
Subject: [PATCH][PPC32][2/2] 40x and Book E debug: 4xx platform support

This patch adds support to the 40x and 44x platform code for
initializing debug events and using the in-kernel kgdb stub.

Signed-off-by: Matt Porter <[email protected]>

diff -Nru a/arch/ppc/platforms/4xx/Kconfig b/arch/ppc/platforms/4xx/Kconfig
--- a/arch/ppc/platforms/4xx/Kconfig 2004-10-29 17:22:22 -07:00
+++ b/arch/ppc/platforms/4xx/Kconfig 2004-10-29 17:22:22 -07:00
@@ -201,7 +201,7 @@

config PPC_GEN550
bool
- depends on 44x
+ depends on 4xx
default y

config PM
diff -Nru a/arch/ppc/platforms/4xx/ebony.c b/arch/ppc/platforms/4xx/ebony.c
--- a/arch/ppc/platforms/4xx/ebony.c 2004-10-29 17:22:22 -07:00
+++ b/arch/ppc/platforms/4xx/ebony.c 2004-10-29 17:22:22 -07:00
@@ -313,14 +313,6 @@
struct ocp_def *def;
struct ocp_func_emac_data *emacdata;

-#if !defined(CONFIG_BDI_SWITCH)
- /*
- * The Abatron BDI JTAG debugger does not tolerate others
- * mucking with the debug registers.
- */
- mtspr(SPRN_DBCR0, (DBCR0_TDE | DBCR0_IDM));
-#endif
-
/* Set mac_addr for each EMAC */
vpd_base = ioremap64(EBONY_VPD_BASE, EBONY_VPD_SIZE);
def = ocp_get_one_device(OCP_VENDOR_IBM, OCP_FUNC_EMAC, 0);
diff -Nru a/arch/ppc/platforms/4xx/ocotea.c b/arch/ppc/platforms/4xx/ocotea.c
--- a/arch/ppc/platforms/4xx/ocotea.c 2004-10-29 17:22:22 -07:00
+++ b/arch/ppc/platforms/4xx/ocotea.c 2004-10-29 17:22:22 -07:00
@@ -291,14 +291,6 @@

ibm440gx_tah_enable();

-#if !defined(CONFIG_BDI_SWITCH)
- /*
- * The Abatron BDI JTAG debugger does not tolerate others
- * mucking with the debug registers.
- */
- mtspr(SPRN_DBCR0, (DBCR0_TDE | DBCR0_IDM));
-#endif
-
/* Setup TODC access */
TODC_INIT(TODC_TYPE_DS1743,
0,
diff -Nru a/arch/ppc/syslib/Makefile b/arch/ppc/syslib/Makefile
--- a/arch/ppc/syslib/Makefile 2004-10-29 17:22:22 -07:00
+++ b/arch/ppc/syslib/Makefile 2004-10-29 17:22:22 -07:00
@@ -25,7 +25,6 @@
obj-$(CONFIG_PPC4xx_DMA) += ppc4xx_dma.o
obj-$(CONFIG_PPC4xx_EDMA) += ppc4xx_sgdma.o
ifeq ($(CONFIG_40x),y)
-obj-$(CONFIG_KGDB) += ppc4xx_kgdb.o
obj-$(CONFIG_PCI) += indirect_pci.o pci_auto.o ppc405_pci.o
endif
endif
diff -Nru a/arch/ppc/syslib/ibm44x_common.c b/arch/ppc/syslib/ibm44x_common.c
--- a/arch/ppc/syslib/ibm44x_common.c 2004-10-29 17:22:22 -07:00
+++ b/arch/ppc/syslib/ibm44x_common.c 2004-10-29 17:22:22 -07:00
@@ -166,5 +166,17 @@
#ifdef CONFIG_KGDB
ppc_md.kgdb_map_scc = gen550_kgdb_map_scc;
#endif
+
+ /*
+ * The Abatron BDI JTAG debugger does not tolerate others
+ * mucking with the debug registers.
+ */
+#if !defined(CONFIG_BDI_SWITCH)
+ /* Enable internal debug mode */
+ mtspr(SPRN_DBCR0, (DBCR0_IDM));
+
+ /* Clear any residual debug events */
+ mtspr(SPRN_DBSR, 0xffffffff);
+#endif
}

diff -Nru a/arch/ppc/syslib/ppc4xx_setup.c b/arch/ppc/syslib/ppc4xx_setup.c
--- a/arch/ppc/syslib/ppc4xx_setup.c 2004-10-29 17:22:22 -07:00
+++ b/arch/ppc/syslib/ppc4xx_setup.c 2004-10-29 17:22:22 -07:00
@@ -42,6 +42,8 @@
#include <asm/pci-bridge.h>
#include <asm/bootinfo.h>

+#include <syslib/gen550.h>
+
/* Function Prototypes */
extern void abort(void);
extern void ppc4xx_find_bridges(void);
@@ -56,8 +58,16 @@
void __init
ppc4xx_setup_arch(void)
{
- /* Setup PCI host bridges */
+#if !defined(CONFIG_BDI_SWITCH)
+ /*
+ * The Abatron BDI JTAG debugger does not tolerate others
+ * mucking with the debug registers.
+ */
+ mtspr(SPRN_DBCR0, (DBCR0_IDM));
+ mtspr(SPRN_DBSR, 0xffffffff);
+#endif

+ /* Setup PCI host bridges */
#ifdef CONFIG_PCI
ppc4xx_find_bridges();
#endif
@@ -189,34 +199,6 @@
/* Set the PIT reload value and just let it run. */
mtspr(SPRN_PIT, tb_ticks_per_jiffy);
}
-#ifdef CONFIG_SERIAL_TEXT_DEBUG
-
-/* We assume that the UART has already been initialized by the
- firmware or the boot loader */
-static void
-serial_putc(u8 * com_port, unsigned char c)
-{
- while ((readb(com_port + (UART_LSR)) & UART_LSR_THRE) == 0) ;
- writeb(c, com_port);
-}
-
-static void
-ppc4xx_progress(char *s, unsigned short hex)
-{
- char c;
-#ifdef SERIAL_DEBUG_IO_BASE
- u8 *com_port = (u8 *) SERIAL_DEBUG_IO_BASE;
-
- while ((c = *s++) != '\0') {
- serial_putc(com_port, c);
- }
- serial_putc(com_port, '\r');
- serial_putc(com_port, '\n');
-#else
- printk("%s\r\n");
-#endif
-}
-#endif /* CONFIG_SERIAL_TEXT_DEBUG */

/*
* IDE stuff.
@@ -319,13 +301,9 @@
ppc_md.setup_io_mappings = ppc4xx_map_io;

#ifdef CONFIG_SERIAL_TEXT_DEBUG
- ppc_md.progress = ppc4xx_progress;
+ ppc_md.progress = gen550_progress;
#endif

-/*
-** m8xx_setup.c, prep_setup.c use
-** defined(CONFIG_BLK_DEV_IDE) || defined(CONFIG_BLK_DEV_IDE_MODULE)
-*/
#if defined(CONFIG_PCI) && defined(CONFIG_IDE)
ppc_ide_md.ide_init_hwif = ppc4xx_ide_init_hwif_ports;
#endif /* defined(CONFIG_PCI) && defined(CONFIG_IDE) */

2004-11-01 19:25:23

by Tom Rini

[permalink] [raw]
Subject: Re: [PATCH][PPC32][2/2] 40x and Book E debug: 4xx platform support

On Fri, Oct 29, 2004 at 06:08:14PM -0700, Matt Porter wrote:

> This patch adds support to the 40x and 44x platform code for
> initializing debug events and using the in-kernel kgdb stub.
>
> Signed-off-by: Matt Porter <[email protected]>

On top of this, I have the following to add these boards, and a few
other BookE boards to registering with the kgdb_8250 driver. This has
been tested on an IBM 440GP Eval board.

Signed-off-by: Tom Rini <[email protected]>

--- linux-2.6.10-rc1.orig/arch/ppc/platforms/4xx/bubinga.c
+++ linux-2.6.10-rc1/arch/ppc/platforms/4xx/bubinga.c
@@ -4,7 +4,7 @@
* Author: SAW (IBM), derived from walnut.c.
* Maintained by MontaVista Software <[email protected]>
*
- * 2003 (c) MontaVista Softare Inc. This file is licensed under the
+ * 2003-2004 (c) MontaVista Softare Inc. This file is licensed under the
* terms of the GNU General Public License version 2. This program is
* licensed "as is" without any warranty of any kind, whether express
* or implied.
@@ -101,17 +101,26 @@ bubinga_early_serial_map(void)
port.flags = ASYNC_BOOT_AUTOCONF | ASYNC_SKIP_TEST;
port.line = 0;

- if (early_serial_setup(&port) != 0) {
+#ifdef CONFIG_SERIAL_8250
+ if (early_serial_setup(&port) != 0)
printk("Early serial init of port 0 failed\n");
- }
+#endif
+
+#ifdef CONFIG_KGDB_8250
+ kgdb8250_add_port(0, &port);
+#endif

port.membase = (void*)ACTING_UART1_IO_BASE;
port.irq = ACTING_UART1_INT;
port.line = 1;

- if (early_serial_setup(&port) != 0) {
+#ifdef CONFIG_SERIAL_8250
+ if (early_serial_setup(&port) != 0)
printk("Early serial init of port 1 failed\n");
- }
+#endif
+#ifdef CONFIG_KGDB_8250
+ kgdb8250_add_port(1, &port);
+#endif
}

void __init
@@ -256,8 +265,4 @@ platform_init(unsigned long r3, unsigned
ppc_md.nvram_read_val = todc_direct_read_val;
ppc_md.nvram_write_val = todc_direct_write_val;
#endif
-#ifdef CONFIG_KGDB
- ppc_md.early_serial_map = bubinga_early_serial_map;
-#endif
}
-
--- linux-2.6.10-rc1.orig/arch/ppc/platforms/4xx/ebony.c
+++ linux-2.6.10-rc1/arch/ppc/platforms/4xx/ebony.c
@@ -36,6 +36,7 @@
#include <linux/tty.h>
#include <linux/serial.h>
#include <linux/serial_core.h>
+#include <linux/kgdb.h>

#include <asm/system.h>
#include <asm/pgtable.h>
@@ -282,30 +283,38 @@ ebony_early_serial_map(void)
port.flags = ASYNC_BOOT_AUTOCONF | ASYNC_SKIP_TEST;
port.line = 0;

- if (early_serial_setup(&port) != 0) {
+#ifdef CONFIG_SERIAL_8250
+ if (early_serial_setup(&port) != 0)
printk("Early serial init of port 0 failed\n");
- }
-
-#if defined(CONFIG_SERIAL_TEXT_DEBUG) || defined(CONFIG_KGDB)
+#endif
+#ifdef CONFIG_SERIAL_TEXT_DEBUG
/* Configure debug serial access */
gen550_init(0, &port);
#endif
+#ifdef CONFIG_KGDB_8250
+ kgdb8250_add_port(0, &port);
+#endif
+

port.membase = ioremap64(PPC440GP_UART1_ADDR, 8);
port.irq = 1;
port.uartclk = clocks.uart1;
port.line = 1;

- if (early_serial_setup(&port) != 0) {
+#ifdef CONFIG_SERIAL_8250
+ if (early_serial_setup(&port) != 0)
printk("Early serial init of port 1 failed\n");
- }
-
-#if defined(CONFIG_SERIAL_TEXT_DEBUG) || defined(CONFIG_KGDB)
+#endif
+#ifdef CONFIG_SERIAL_TEXT_DEBUG
/* Configure debug serial access */
gen550_init(1, &port);
#endif
+#ifdef CONFIG_KGDB_8250
+ kgdb8250_add_port(1, &port);
+#endif
}

+
static void __init
ebony_setup_arch(void)
{
@@ -383,8 +392,4 @@ void __init platform_init(unsigned long

ppc_md.nvram_read_val = todc_direct_read_val;
ppc_md.nvram_write_val = todc_direct_write_val;
-#ifdef CONFIG_KGDB
- ppc_md.early_serial_map = ebony_early_serial_map;
-#endif
}
-
--- linux-2.6.10-rc1.orig/arch/ppc/platforms/4xx/ocotea.c
+++ linux-2.6.10-rc1/arch/ppc/platforms/4xx/ocotea.c
@@ -260,28 +260,34 @@ ocotea_early_serial_map(void)
port.flags = ASYNC_BOOT_AUTOCONF | ASYNC_SKIP_TEST;
port.line = 0;

- if (early_serial_setup(&port) != 0) {
+#ifdef CONFIG_SERIAL_8250
+ if (early_serial_setup(&port) != 0)
printk("Early serial init of port 0 failed\n");
- }
-
-#if defined(CONFIG_SERIAL_TEXT_DEBUG) || defined(CONFIG_KGDB)
+#endif
+#ifdef CONFIG_SERIAL_TEXT_DEBUG
/* Configure debug serial access */
gen550_init(0, &port);
#endif
+#ifdef CONFIG_KGDB_8250
+ kgdb8250_add_port(0, &port);
+#endif

port.membase = ioremap64(PPC440GX_UART1_ADDR, 8);
port.irq = UART1_INT;
port.uartclk = clocks.uart1;
port.line = 1;

- if (early_serial_setup(&port) != 0) {
+#ifdef CONFIG_SERIAL_8250
+ if (early_serial_setup(&port) != 0)
printk("Early serial init of port 1 failed\n");
- }
-
-#if defined(CONFIG_SERIAL_TEXT_DEBUG) || defined(CONFIG_KGDB)
+#endif
+#ifdef CONFIG_SERIAL_TEXT_DEBUG
/* Configure debug serial access */
gen550_init(1, &port);
#endif
+#ifdef CONFIG_KGDB_8250
+ kgdb8250_add_port(1, &port);
+#endif
}

static void __init
--- linux-2.6.10-rc1.orig/arch/ppc/platforms/4xx/xilinx_ml300.c
+++ linux-2.6.10-rc1/arch/ppc/platforms/4xx/xilinx_ml300.c
@@ -42,9 +42,6 @@
* ppc4xx_map_io arch/ppc/syslib/ppc4xx_setup.c
* start_kernel init/main.c
* setup_arch arch/ppc/kernel/setup.c
- * #if defined(CONFIG_KGDB)
- * *ppc_md.kgdb_map_scc() == gen550_kgdb_map_scc
- * #endif
* *ppc_md.setup_arch == ml300_setup_arch this file
* ppc4xx_setup_arch arch/ppc/syslib/ppc4xx_setup.c
* ppc4xx_find_bridges arch/ppc/syslib/ppc405_pci.c
@@ -83,7 +80,6 @@ ml300_map_io(void)
static void __init
ml300_early_serial_map(void)
{
-#ifdef CONFIG_SERIAL_8250
struct serial_state old_ports[] = { SERIAL_PORT_DFNS };
struct uart_port port;
int i;
@@ -99,11 +95,14 @@ ml300_early_serial_map(void)
port.flags = ASYNC_BOOT_AUTOCONF | ASYNC_SKIP_TEST;
port.line = i;

- if (early_serial_setup(&port) != 0) {
+#ifdef CONFIG_SERIAL_8250
+ if (early_serial_setup(&port) != 0)
printk("Early serial init of port %d failed\n", i);
- }
+#endif
+#ifdef CONFIG_KGDB_8250
+ kgdb8250_add_port(i, &port)
+#endif
}
-#endif /* CONFIG_SERIAL_8250 */
}

void __init
@@ -156,9 +155,4 @@ platform_init(unsigned long r3, unsigned
#if defined(XPAR_POWER_0_POWERDOWN_BASEADDR)
ppc_md.power_off = xilinx_power_off;
#endif
-
-#ifdef CONFIG_KGDB
- ppc_md.early_serial_map = ml300_early_serial_map;
-#endif
}
-
--- linux-2.6.10-rc1.orig/arch/ppc/platforms/85xx/sbc8560.c
+++ linux-2.6.10-rc1/arch/ppc/platforms/85xx/sbc8560.c
@@ -78,8 +78,6 @@ struct ocp_fs_i2c_data mpc85xx_i2c1_def
.flags = FS_I2C_SEPARATE_DFSRR,
};

-
-#ifdef CONFIG_SERIAL_8250
static void __init
sbc8560_early_serial_map(void)
{
@@ -95,27 +93,34 @@ sbc8560_early_serial_map(void)
uart_req.membase = ioremap(uart_req.mapbase, MPC85xx_UART0_SIZE);
uart_req.type = PORT_16650;

-#if defined(CONFIG_SERIAL_TEXT_DEBUG) || defined(CONFIG_KGDB)
- gen550_init(0, &uart_req);
+#ifdef CONFIG_SERIAL_8250
+ if (early_serial_setup(&serial_req) != 0)
+ printk("Early serial init of port 0 failed\n");
#endif
-
- if (early_serial_setup(&uart_req) != 0)
- printk("Early serial init of port 0 failed\n");
-
+#ifdef CONFIG_SERIAL_TEXT_DEBUG
+ gen550_init(0, &serial_req);
+#endif
+#ifdef CONFIG_KGDB_8250
+ kgdb8250_add_port(0, &port);
+#endif
+
/* Assume early_serial_setup() doesn't modify uart_req */
uart_req.line = 1;
uart_req.mapbase = UARTB_ADDR;
uart_req.membase = ioremap(uart_req.mapbase, MPC85xx_UART1_SIZE);
uart_req.irq = MPC85xx_IRQ_EXT10;
-
-#if defined(CONFIG_SERIAL_TEXT_DEBUG) || defined(CONFIG_KGDB)
- gen550_init(1, &uart_req);
+
+#ifdef CONFIG_SERIAL_8250
+ if (early_serial_setup(&serial_req) != 0)
+ printk("Early serial init of port 1 failed\n");
#endif
-
- if (early_serial_setup(&uart_req) != 0)
- printk("Early serial init of port 1 failed\n");
-}
+#ifdef CONFIG_SERIAL_TEXT_DEBUG
+ gen550_init(1, &serial_req);
#endif
+#ifdef CONFIG_KGDB_8250
+ kgdb8250_add_port(1, &port);
+#endif
+}

/* ************************************************************************
*
@@ -144,9 +149,7 @@ sbc8560_setup_arch(void)
/* setup PCI host bridges */
mpc85xx_setup_hose();
#endif
-#ifdef CONFIG_SERIAL_8250
sbc8560_early_serial_map();
-#endif
#ifdef CONFIG_SERIAL_TEXT_DEBUG
/* Invalidate the entry we stole earlier the serial ports
* should be properly mapped */
--- linux-2.6.10-rc1.orig/arch/ppc/platforms/mcpn765.c
+++ linux-2.6.10-rc1/arch/ppc/platforms/mcpn765.c
@@ -518,9 +518,4 @@ platform_init(unsigned long r3, unsigned
#ifdef CONFIG_SERIAL_TEXT_DEBUG
ppc_md.progress = gen550_progress;
#endif
-#ifdef CONFIG_KGDB
- ppc_md.kgdb_map_scc = gen550_kgdb_map_scc;
-#endif
-
- return;
}
--- linux-2.6.10-rc1.orig/arch/ppc/platforms/pcore.c
+++ linux-2.6.10-rc1/arch/ppc/platforms/pcore.c
@@ -345,7 +345,4 @@ platform_init(unsigned long r3, unsigned
#ifdef CONFIG_SERIAL_TEXT_DEBUG
ppc_md.progress = gen550_progress;
#endif
-#ifdef CONFIG_KGDB
- ppc_md.kgdb_map_scc = gen550_kgdb_map_scc;
-#endif
}
--- linux-2.6.10-rc1.orig/arch/ppc/platforms/pplus.c
+++ linux-2.6.10-rc1/arch/ppc/platforms/pplus.c
@@ -907,9 +907,6 @@ platform_init(unsigned long r3, unsigned
#ifdef CONFIG_SERIAL_TEXT_DEBUG
ppc_md.progress = gen550_progress;
#endif /* CONFIG_SERIAL_TEXT_DEBUG */
-#ifdef CONFIG_KGDB
- ppc_md.kgdb_map_scc = gen550_kgdb_map_scc;
-#endif
#ifdef CONFIG_SMP
ppc_md.smp_ops = &pplus_smp_ops;
#endif /* CONFIG_SMP */
--- linux-2.6.10-rc1.orig/arch/ppc/platforms/spruce.c
+++ linux-2.6.10-rc1/arch/ppc/platforms/spruce.c
@@ -181,26 +181,32 @@ spruce_early_serial_map(void)
serial_req.membase = (u_char *)UART0_IO_BASE;
serial_req.regshift = 0;

-#if defined(CONFIG_KGDB) || defined(CONFIG_SERIAL_TEXT_DEBUG)
- gen550_init(0, &serial_req);
-#endif
#ifdef CONFIG_SERIAL_8250
if (early_serial_setup(&serial_req) != 0)
printk("Early serial init of port 0 failed\n");
#endif
+#ifdef CONFIG_SERIAL_TEXT_DEBUG
+ gen550_init(0, &serial_req);
+#endif
+#ifdef CONFIG_KGDB_8250
+ kgdb8250_add_port(0, &port);
+#endif

/* Assume early_serial_setup() doesn't modify serial_req */
serial_req.line = 1;
serial_req.irq = UART1_INT;
serial_req.membase = (u_char *)UART1_IO_BASE;

-#if defined(CONFIG_KGDB) || defined(CONFIG_SERIAL_TEXT_DEBUG)
- gen550_init(1, &serial_req);
-#endif
#ifdef CONFIG_SERIAL_8250
if (early_serial_setup(&serial_req) != 0)
printk("Early serial init of port 1 failed\n");
#endif
+#ifdef CONFIG_SERIAL_TEXT_DEBUG
+ gen550_init(1, &serial_req);
+#endif
+#ifdef CONFIG_KGDB_8250
+ kgdb8250_add_port(1, &port);
+#endif
}

TODC_ALLOC();
@@ -319,7 +325,4 @@ platform_init(unsigned long r3, unsigned
#ifdef CONFIG_SERIAL_TEXT_DEBUG
ppc_md.progress = gen550_progress;
#endif /* CONFIG_SERIAL_TEXT_DEBUG */
-#ifdef CONFIG_KGDB
- ppc_md.kgdb_map_scc = gen550_kgdb_map_scc;
-#endif
}
--- linux-2.6.10-rc1.orig/arch/ppc/syslib/gen550.h
+++ linux-2.6.10-rc1/arch/ppc/syslib/gen550.h
@@ -13,4 +13,3 @@

extern void gen550_progress(char *, unsigned short);
extern void gen550_init(int, struct uart_port *);
-extern void gen550_kgdb_map_scc(void);
--- linux-2.6.10-rc1.orig/arch/ppc/syslib/ibm44x_common.c
+++ linux-2.6.10-rc1/arch/ppc/syslib/ibm44x_common.c
@@ -163,9 +163,6 @@ void __init ibm44x_platform_init(void)
#ifdef CONFIG_SERIAL_TEXT_DEBUG
ppc_md.progress = gen550_progress;
#endif /* CONFIG_SERIAL_TEXT_DEBUG */
-#ifdef CONFIG_KGDB
- ppc_md.kgdb_map_scc = gen550_kgdb_map_scc;
-#endif

/*
* The Abatron BDI JTAG debugger does not tolerate others
--- linux-2.6.10-rc1.orig/arch/ppc/syslib/ppc85xx_setup.c
+++ linux-2.6.10-rc1/arch/ppc/syslib/ppc85xx_setup.c
@@ -69,7 +69,6 @@ mpc85xx_calibrate_decr(void)
mtspr(SPRN_TCR, TCR_DIE);
}

-#ifdef CONFIG_SERIAL_8250
void __init
mpc85xx_early_serial_map(void)
{
@@ -88,12 +87,16 @@ mpc85xx_early_serial_map(void)
serial_req.mapbase = duart_paddr;
serial_req.regshift = 0;

-#if defined(CONFIG_SERIAL_TEXT_DEBUG) || defined(CONFIG_KGDB)
- gen550_init(0, &serial_req);
-#endif
-
+#ifdef CONFIG_SERIAL_8250
if (early_serial_setup(&serial_req) != 0)
printk("Early serial init of port 0 failed\n");
+#endif
+#ifdef CONFIG_SERIAL_TEXT_DEBUG
+ gen550_init(0, &serial_req);
+#endif
+#ifdef CONFIG_KGDB_8250
+ kgdb8250_add_port(0, &port);
+#endif

/* Assume early_serial_setup() doesn't modify serial_req */
duart_paddr = binfo->bi_immr_base + MPC85xx_UART1_OFFSET;
@@ -101,14 +104,17 @@ mpc85xx_early_serial_map(void)
serial_req.mapbase = duart_paddr;
serial_req.membase = ioremap(duart_paddr, MPC85xx_UART1_SIZE);

-#if defined(CONFIG_SERIAL_TEXT_DEBUG) || defined(CONFIG_KGDB)
- gen550_init(1, &serial_req);
-#endif
-
+#ifdef CONFIG_SERIAL_8250
if (early_serial_setup(&serial_req) != 0)
printk("Early serial init of port 1 failed\n");
-}
#endif
+#ifdef CONFIG_SERIAL_TEXT_DEBUG
+ gen550_init(1, &serial_req);
+#endif
+#ifdef CONFIG_KGDB_8250
+ kgdb8250_add_port(1, &port);
+#endif
+}

void
mpc85xx_restart(char *cmd)
@@ -345,5 +351,3 @@ mpc85xx_setup_hose(void)
return;
}
#endif /* CONFIG_PCI */
-
-
--- linux-2.6.10-rc1.orig/include/asm-ppc/machdep.h
+++ linux-2.6.10-rc1/include/asm-ppc/machdep.h
@@ -56,9 +56,7 @@ struct machdep_calls {
unsigned long (*find_end_of_memory)(void);
void (*setup_io_mappings)(void);

- void (*early_serial_map)(void);
void (*progress)(char *, unsigned short);
- void (*kgdb_map_scc)(void);

unsigned char (*nvram_read_val)(int addr);
void (*nvram_write_val)(int addr, unsigned char val);

--
Tom Rini
http://gate.crashing.org/~trini/