Checked-in this in cvs
Files Changed
- ChangeLog
- powerpc-lite.patch
On Fri, 2006-09-08 at 15:58 +0400, Vitaly Wool wrote:
> 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
>
>
--
Milind
"The world is divided into one group: those who start counting at 0,
and those who don't."
-------------------------------------------------------------------------
Take Surveys. Earn Cash. Influence the Future of IT
Join SourceForge.net's Techsay panel and you'll get the chance to share your
opinions on IT & business topics through brief surveys -- and earn cash
http://www.techsay.com/default.php?page=join.php&p=sourceforge&CID=DEVDEV
_______________________________________________
Kgdb-bugreport mailing list
[email protected]
https://lists.sourceforge.net/lists/listinfo/kgdb-bugreport