Hello folks,
the patch inlined enables KGDB for PowerPC32 targets in arch/powerpc.
Verified on 74xx and 85xx targets.
Signed-off-by: Vitaly Wool <[EMAIL PROTECTED]>
Signed-off-by: Sergey Shtylyov <[EMAIL PROTECTED]>
arch/powerpc/kernel/kgdb.c | 225 ++++++++++++++++++++++++++------
arch/powerpc/kernel/legacy_serial.c | 6
arch/powerpc/platforms/powermac/setup.c | 2
3 files changed, 193 insertions(+), 40 deletions(-)
Index: linux-2.6-kgdb.stg/arch/powerpc/kernel/legacy_serial.c
===================================================================
--- linux-2.6-kgdb.stg.orig/arch/powerpc/kernel/legacy_serial.c
+++ linux-2.6-kgdb.stg/arch/powerpc/kernel/legacy_serial.c
@@ -11,6 +11,9 @@
#include <asm/udbg.h>
#include <asm/pci-bridge.h>
#include <asm/ppc-pci.h>
+#ifdef CONFIG_KGDB_8250
+#include <linux/kgdb.h>
+#endif
#undef DEBUG
@@ -470,6 +473,9 @@ static int __init serial_dev_init(void)
fixup_port_pio(i, np, port);
if ((port->iotype == UPIO_MEM) || (port->iotype == UPIO_TSI))
fixup_port_mmio(i, np, port);
+#ifdef CONFIG_KGDB_8250
+ kgdb8250_add_platform_port(i, port);
+#endif
}
DBG("Registering platform serial ports\n");
Index: linux-2.6-kgdb.stg/arch/powerpc/kernel/kgdb.c
===================================================================
--- linux-2.6-kgdb.stg.orig/arch/powerpc/kernel/kgdb.c
+++ linux-2.6-kgdb.stg/arch/powerpc/kernel/kgdb.c
@@ -1,7 +1,7 @@
/*
- * arch/ppc64/kernel/kgdb.c
+ * arch/powerpc/kernel/kgdb.c
*
- * PowerPC64 backend to the KGDB stub.
+ * PowerPC backend to the KGDB stub.
*
* Maintainer: Tom Rini <[EMAIL PROTECTED]>
*
@@ -10,9 +10,10 @@
* Copyright (C) 1996 Paul Mackerras (setjmp/longjmp)
* 1998 (c) Michael AK Tesch ([EMAIL PROTECTED])
* Copyright (C) 2003 Timesys Corporation.
- * 2004 (c) MontaVista Software, Inc.
- * 2005 (c) MontaVista Software, Inc.
+ * Copyright (C) 2004-2006 MontaVista Software, Inc.
* PPC64 Mods (C) 2005 Frank Rowand ([EMAIL PROTECTED])
+ * PPC32 support restored by Vitaly Wool <[EMAIL PROTECTED]> and
+ * Sergei Shtylyov <[EMAIL PROTECTED]>
*
* This file is licensed under the terms of the GNU General Public License
* version 2. This program as licensed "as is" without any warranty of any
@@ -32,7 +33,7 @@
#include <asm/machdep.h>
/*
- * This table contains the mapping between PowerPC64 hardware trap types, and
+ * This table contains the mapping between PowerPC hardware trap types, and
* signals, which are primarily what GDB understands. GDB and the kernel
* don't always agree on values, so we use constants taken from gdb-6.2.
*/
@@ -44,27 +45,55 @@ static struct hard_trap_info
{ 0x0100, 0x02 /* SIGINT */ }, /* system reset */
{ 0x0200, 0x0b /* SIGSEGV */ }, /* machine check */
{ 0x0300, 0x0b /* SIGSEGV */ }, /* data access */
- { 0x0380, 0x0b /* SIGSEGV */ }, /* data SLB access */
- { 0x0400, 0x0a /* SIGBUS */ }, /* instruction access */
- { 0x0480, 0x0a /* SIGBUS */ }, /* instruction segment */
- { 0x0500, 0x02 /* SIGINT */ }, /* interrupt */
+ { 0x0400, 0x0b /* SIGSEGV */ }, /* instruction access */
+ { 0x0500, 0x02 /* SIGINT */ }, /* external interrupt */
{ 0x0600, 0x0a /* SIGBUS */ }, /* alignment */
- { 0x0700, 0x04 /* SIGILL */ }, /* program */
- { 0x0800, 0x08 /* SIGFPE */ }, /* fpu unavailable */
- { 0x0900, 0x0e /* SIGALRM */ }, /* decrementer */
- { 0x0a00, 0x04 /* SIGILL */ }, /* reserved */
- { 0x0b00, 0x04 /* SIGILL */ }, /* reserved */
- { 0x0c00, 0x14 /* SIGCHLD */ }, /* syscall */
- { 0x0d00, 0x05 /* SIGTRAP */ }, /* single step */
- { 0x0e00, 0x04 /* SIGILL */ }, /* reserved */
+ { 0x0700, 0x05 /* SIGTRAP */ }, /* program check */
+ { 0x0800, 0x08 /* SIGFPE */ }, /* fp unavailable */
+ { 0x0900, 0x0e /* SIGALRM */ }, /* decrementer */
+ { 0x0c00, 0x14 /* SIGCHLD */ }, /* system call */
+#if defined(CONFIG_40x) || defined(CONFIG_BOOKE)
+ { 0x2002, 0x05 /* SIGTRAP */ }, /* debug */
+#if defined(CONFIG_FSL_BOOKE)
+ { 0x2010, 0x08 /* SIGFPE */ }, /* spe unavailable */
+ { 0x2020, 0x08 /* SIGFPE */ }, /* spe unavailable */
+ { 0x2030, 0x08 /* SIGFPE */ }, /* spe fp data */
+ { 0x2040, 0x08 /* SIGFPE */ }, /* spe fp data */
+ { 0x2050, 0x08 /* SIGFPE */ }, /* spe fp round */
+ { 0x2060, 0x0e /* SIGILL */ }, /* performace monitor */
+ { 0x2900, 0x08 /* SIGFPE */ }, /* apu unavailable */
+ { 0x3100, 0x0e /* SIGALRM */ }, /* fixed interval timer */
+ { 0x3200, 0x02 /* SIGINT */ }, /* watchdog */
+#else
+ { 0x1000, 0x0e /* SIGALRM */ }, /* programmable interval timer
*/
+ { 0x1010, 0x0e /* SIGALRM */ }, /* fixed interval timer */
+ { 0x1020, 0x02 /* SIGINT */ }, /* watchdog */
+ { 0x2010, 0x08 /* SIGFPE */ }, /* fp unavailable */
+ { 0x2020, 0x08 /* SIGFPE */ }, /* ap unavailable */
+#endif
+#else
+ { 0x0d00, 0x05 /* SIGTRAP */ }, /* single-step */
+#if defined(CONFIG_8xx)
+ { 0x1000, 0x04 /* SIGILL */ }, /* software emulation */
+#else
{ 0x0f00, 0x04 /* SIGILL */ }, /* performance monitor */
{ 0x0f20, 0x08 /* SIGFPE */ }, /* altivec unavailable */
- { 0x1300, 0x05 /* SIGTRAP */ }, /* instruction address break */
+ { 0x1300, 0x05 /* SIGTRAP */ }, /* instruction address break */
+#if defined(CONFIG_PPC64)
+ { 0x1200, 0x05 /* SIGILL */ }, /* system error */
{ 0x1500, 0x04 /* SIGILL */ }, /* soft patch */
{ 0x1600, 0x04 /* SIGILL */ }, /* maintenance */
- { 0x1700, 0x04 /* SIGILL */ }, /* altivec assist */
+ { 0x1700, 0x08 /* SIGFPE */ }, /* altivec assist */
{ 0x1800, 0x04 /* SIGILL */ }, /* thermal */
- { 0x0000, 0x000 } /* Must be last */
+#else
+ { 0x1400, 0x02 /* SIGINT */ }, /* SMI */
+ { 0x1600, 0x08 /* SIGFPE */ }, /* altivec assist */
+ { 0x1700, 0x04 /* SIGILL */ }, /* TAU */
+ { 0x2000, 0x05 /* SIGTRAP */ }, /* run mode */
+#endif
+#endif
+#endif
+ { 0x0000, 0x00 } /* Must be last */
};
extern atomic_t cpu_doing_single_step;
@@ -114,10 +143,31 @@ static int kgdb_breakpoint(struct pt_reg
static int kgdb_singlestep(struct pt_regs *regs)
{
+ struct thread_info *thread_info, *exception_thread_info;
+
if (user_mode(regs))
return 0;
+ /*
+ * On Book E and perhaps other processsors, singlestep is handled on
+ * the critical exception stack. This causes current_thread_info()
+ * to fail, since it it locates the thread_info by masking off
+ * the low bits of the current stack pointer. We work around
+ * this issue by copying the thread_info from the kernel stack
+ * before calling kgdb_handle_exception, and copying it back
+ * afterwards. On most processors the copy is avoided since
+ * exception_thread_info == thread_info.
+ */
+ thread_info = (struct thread_info *)(regs->gpr[1] & ~(THREAD_SIZE-1));
+ exception_thread_info = current_thread_info();
+
+ if (thread_info != exception_thread_info)
+ memcpy(exception_thread_info, thread_info, sizeof *thread_info);
kgdb_handle_exception(0, SIGTRAP, 0, regs);
+
+ if (thread_info != exception_thread_info)
+ memcpy(thread_info, exception_thread_info, sizeof *thread_info);
+
return 1;
}
@@ -148,18 +198,28 @@ int kgdb_dabr_match(struct pt_regs *regs
ptr = (unsigned long *)ptr32; \
} while(0)
+
void regs_to_gdb_regs(unsigned long *gdb_regs, struct pt_regs *regs)
{
- int reg;
unsigned long *ptr = gdb_regs;
+ int reg;
memset(gdb_regs, 0, NUMREGBYTES);
for (reg = 0; reg < 32; reg++)
PACK64(ptr, regs->gpr[reg]);
- /* fp registers not used by kernel, leave zero */
+#ifdef CONFIG_FSL_BOOKE
+#ifdef CONFIG_SPE
+ for (reg = 0; reg < 32; reg++)
+ PACK64(ptr, current->thread.evr[reg]);
+#else
ptr += 32;
+#endif
+#else
+ /* fp registers not used by kernel, leave zero */
+ ptr += 32 * 8 / sizeof(long);
+#endif
PACK64(ptr, regs->nip);
PACK64(ptr, regs->msr);
@@ -176,17 +236,32 @@ void regs_to_gdb_regs(unsigned long *gdb
If this code is enabled, update the definition of NUMREGBYTES to
include the vector registers and vector state registers.
- PACK32(ptr, p->thread->fpscr);
+ PACK32(ptr, current->thread->fpscr);
/* vr registers not used by kernel, leave zero */
- ptr += 64;
+ ptr += 32 * 16 / sizeof(long);
- PACK32(ptr, p->thread->vscr);
- PACK32(ptr, p->thread->vrsave);
+#ifdef CONFIG_ALTIVEC
+ PACK32(ptr, current->thread->vscr);
+ PACK32(ptr, current->thread->vrsave);
+#else
+ ptr += 2 * 4 / sizeof(long);
+#endif
+#else
+#ifdef CONFIG_FSL_BOOKE
+#ifdef CONFIG_SPE
+ /* u64 acc */
+ PACK32(ptr, current->thread.acc >> 32);
+ PACK32(ptr, current->thread.acc & 0xffffffff);
+ PACK64(ptr, current->thread.spefscr);
+#else
+ ptr += 2 + 1;
+#endif
#else
/* fpscr not used by kernel, leave zero */
PACK32(ptr, 0);
#endif
+#endif
BUG_ON((unsigned long)ptr >
(unsigned long)(((void *)gdb_regs) + NUMREGBYTES));
@@ -196,8 +271,8 @@ void sleeping_thread_to_gdb_regs(unsigne
{
struct pt_regs *regs = (struct pt_regs *)(p->thread.ksp +
STACK_FRAME_OVERHEAD);
- int reg;
unsigned long *ptr = gdb_regs;
+ int reg;
memset(gdb_regs, 0, NUMREGBYTES);
@@ -206,15 +281,23 @@ void sleeping_thread_to_gdb_regs(unsigne
PACK64(ptr, regs->gpr[reg]);
/* Regs GPR3-13 are caller saved, not in regs->gpr[] */
- for (reg = 3; reg < 14; reg++)
- PACK64(ptr, 0);
+ ptr += 11;
/* Regs GPR14-31 */
for (reg = 14; reg < 32; reg++)
PACK64(ptr, regs->gpr[reg]);
- /* fp registers not used by kernel, leave zero */
+#ifdef CONFIG_FSL_BOOKE
+#ifdef CONFIG_SPE
+ for (reg = 0; reg < 32; reg++)
+ PACK64(ptr, p->thread.evr[reg]);
+#else
ptr += 32;
+#endif
+#else
+ /* fp registers not used by kernel, leave zero */
+ ptr += 32 * 8 / sizeof(long);
+#endif
PACK64(ptr, regs->nip);
PACK64(ptr, regs->msr);
@@ -234,14 +317,29 @@ void sleeping_thread_to_gdb_regs(unsigne
PACK32(ptr, p->thread->fpscr);
/* vr registers not used by kernel, leave zero */
- ptr += 64;
+ ptr += 32 * 16 / sizeof(long);
+#ifdef CONFIG_ALTIVEC
PACK32(ptr, p->thread->vscr);
PACK32(ptr, p->thread->vrsave);
#else
+ ptr += 2 * 4 / sizeof(long);
+#endif
+#else
+#ifdef CONFIG_FSL_BOOKE
+#ifdef CONFIG_SPE
+ /* u64 acc */
+ PACK32(ptr, p->thread.acc >> 32);
+ PACK32(ptr, p->thread.acc & 0xffffffff);
+ PACK64(ptr, p->thread.spefscr);
+#else
+ ptr += 2 + 1;
+#endif
+#else
/* fpscr not used by kernel, leave zero */
PACK32(ptr, 0);
#endif
+#endif
BUG_ON((unsigned long)ptr >
(unsigned long)(((void *)gdb_regs) + NUMREGBYTES));
@@ -258,14 +356,29 @@ void sleeping_thread_to_gdb_regs(unsigne
void gdb_regs_to_regs(unsigned long *gdb_regs, struct pt_regs *regs)
{
- int reg;
unsigned long *ptr = gdb_regs;
+ int reg;
+#ifdef CONFIG_SPE
+ union {
+ u32 v32[2];
+ u64 v64;
+ } acc;
+#endif
for (reg = 0; reg < 32; reg++)
UNPACK64(regs->gpr[reg], ptr);
- /* fp registers not used by kernel, leave zero */
+#ifdef CONFIG_FSL_BOOKE
+#ifdef CONFIG_SPE
+ for (reg = 0; reg < 32; reg++)
+ UNPACK64(current->thread.evr[reg], ptr);
+#else
ptr += 32;
+#endif
+#else
+ /* fp registers not used by kernel, leave zero */
+ ptr += 32 * 8 / sizeof(int);
+#endif
UNPACK64(regs->nip, ptr);
UNPACK64(regs->msr, ptr);
@@ -284,13 +397,29 @@ void gdb_regs_to_regs(unsigned long *gdb
/* fpscr, vscr, vrsave not used by kernel, leave unchanged */
- UNPACK32(p->thread->fpscr, ptr);
+ UNPACK32(current->thread->fpscr, ptr);
/* vr registers not used by kernel, leave zero */
- ptr += 64;
+ ptr += 32 * 16 / sizeof(long);
- UNPACK32(p->thread->vscr, ptr);
- UNPACK32(p->thread->vrsave, ptr);
+#ifdef CONFIG_ALTIVEC
+ UNPACK32(current->thread->vscr, ptr);
+ UNPACK32(current->thread->vrsave, ptr);
+#else
+ ptr += 2 * 4 / sizeof(long);
+#endif
+#else
+#ifdef CONFIG_FSL_BOOKE
+#ifdef CONFIG_SPE
+ /* u64 acc */
+ UNPACK32(acc.v32[0], ptr);
+ UNPACK32(acc.v32[1], ptr);
+ current->thread.acc = acc.v64;
+ UNPACK64(current->thread.spefscr, ptr);
+#else
+ ptr += 2 + 1;
+#endif
+#endif
#endif
BUG_ON((unsigned long)ptr >
@@ -298,7 +427,7 @@ void gdb_regs_to_regs(unsigned long *gdb
}
/*
- * This function does PowerPC64 specific procesing for interfacing to gdb.
+ * This function does PowerPC specific procesing for interfacing to gdb.
*/
int kgdb_arch_handle_exception(int vector, int signo, int err_code,
char *remcom_in_buffer, char *remcom_out_buffer,
@@ -321,7 +450,13 @@ int kgdb_arch_handle_exception(int vecto
atomic_set(&cpu_doing_single_step, -1);
/* set the trace bit if we're stepping */
if (remcom_in_buffer[0] == 's') {
+#if defined(CONFIG_40x) || defined(CONFIG_BOOKE)
+ mtspr(SPRN_DBCR0,
+ mfspr(SPRN_DBCR0) | DBCR0_IC | DBCR0_IDM);
+ linux_regs->msr |= MSR_DE;
+#else
linux_regs->msr |= MSR_SE;
+#endif
debugger_step = 1;
if (kgdb_contthread)
atomic_set(&cpu_doing_single_step,
@@ -335,6 +470,12 @@ int kgdb_arch_handle_exception(int vecto
int kgdb_fault_setjmp(unsigned long *curr_context)
{
+#ifdef CONFIG_PPC32
+ __asm__ __volatile__("mflr 0; stw 0,0(%0);\n\
+ stw 1,4(%0); stw 2,8(%0);\n\
+ mfcr 0; stw 0,12(%0);\n\
+ stmw 13,16(%0)\n" : : "r" (curr_context));
+#else
__asm__ __volatile__("mflr 0; std 0,0(%0)\n\
std 1,8(%0)\n\
std 2,16(%0)\n\
@@ -358,11 +499,18 @@ int kgdb_fault_setjmp(unsigned long *cur
std 29,160(%0)\n\
std 30,168(%0)\n\
std 31,176(%0)\n" : : "r" (curr_context));
+#endif
return 0;
}
void kgdb_fault_longjmp(unsigned long *curr_context)
{
+#ifdef CONFIG_PPC32
+ __asm__ __volatile__("lmw 13,16(%0);\n\
+ lwz 0,12(%0); mtcrf 0x38,0;\n\
+ lwz 0,0(%0); lwz 1,4(%0); lwz 2,8(%0);\n\
+ mtlr 0; mr 3,1\n" : : "r" (curr_context));
+#else
__asm__ __volatile__("ld 13,32(%0)\n\
ld 14,40(%0)\n\
ld 15,48(%0)\n\
@@ -389,6 +537,7 @@ void kgdb_fault_longjmp(unsigned long *c
ld 2,16(%0)\n\
mtlr 0\n\
mr 3,1\n" : : "r" (curr_context));
+#endif
}
/*
Index: linux-2.6-kgdb.stg/arch/powerpc/platforms/powermac/setup.c
===================================================================
--- linux-2.6-kgdb.stg.orig/arch/powerpc/platforms/powermac/setup.c
+++ linux-2.6-kgdb.stg/arch/powerpc/platforms/powermac/setup.c
@@ -98,8 +98,6 @@ extern struct machdep_calls pmac_md;
int sccdbg;
#endif
-extern void zs_kgdb_hook(int tty_num);
-
sys_ctrler_t sys_ctrler = SYS_CTRLER_UNKNOWN;
EXPORT_SYMBOL(sys_ctrler);
-------------------------------------------------------------------------
Using Tomcat but need to do more? Need to support web services, security?
Get stuff done quickly with pre-integrated technology to make your job easier
Download IBM WebSphere Application Server v.1.0.1 based on Apache Geronimo
http://sel.as-us.falkag.net/sel?cmd=lnk&kid=120709&bid=263057&dat=121642
_______________________________________________
Kgdb-bugreport mailing list
[email protected]
https://lists.sourceforge.net/lists/listinfo/kgdb-bugreport