[patch 08/15] Basic SuperH support

From: Tom Rini (trini_at_kernel.crashing.org)
Date: 07/29/05

  • Next message: Tom Rini: "[patch 12/15] KGDB: Add CFI DWARF2 annotation support."
    Date:	Fri, 29 Jul 2005 14:20:14 -0700
    To: akpm@osdl.org
    
    

    CC: Paul Mundt <lethal@linux-sh.org>, Kazumoto Kojima <kkojima@rr.iij4u.or.jp>
    This adds basic support for KGDB on SuperH as well as adding some architecture
    specific notes to the DocBook file and converting the 7751 to use this. I
    have tested all combinations of 8250 and SCI(F) ports being used as KGDB and
    console that I could (one of each usable to me).

    ---
     linux-2.6.13-rc3-trini/Documentation/DocBook/kgdb.tmpl |   16 
     linux-2.6.13-rc3-trini/arch/sh/Kconfig.debug           |   92 -
     linux-2.6.13-rc3-trini/arch/sh/Makefile                |    1 
     linux-2.6.13-rc3-trini/arch/sh/boards/se/7751/setup.c  |  139 -
     linux-2.6.13-rc3-trini/arch/sh/kernel/Makefile         |    2 
     linux-2.6.13-rc3-trini/arch/sh/kernel/cpu/sh3/ex.S     |    2 
     linux-2.6.13-rc3-trini/arch/sh/kernel/cpu/sh4/ex.S     |    2 
     linux-2.6.13-rc3-trini/arch/sh/kernel/entry.S          |   30 
     linux-2.6.13-rc3-trini/arch/sh/kernel/kgdb-jmp.S       |   32 
     linux-2.6.13-rc3-trini/arch/sh/kernel/kgdb.c           |  363 ++++
     linux-2.6.13-rc3-trini/arch/sh/kernel/setup.c          |   94 -
     linux-2.6.13-rc3-trini/arch/sh/kernel/time.c           |   11 
     linux-2.6.13-rc3-trini/arch/sh/kernel/traps.c          |   20 
     linux-2.6.13-rc3-trini/arch/sh/mm/extable.c            |    7 
     linux-2.6.13-rc3-trini/arch/sh/mm/fault-nommu.c        |   14 
     linux-2.6.13-rc3-trini/arch/sh/mm/fault.c              |   12 
     linux-2.6.13-rc3-trini/drivers/serial/sh-sci.c         |  314 ++-
     linux-2.6.13-rc3-trini/include/asm-sh/kgdb.h           |  118 -
     linux-2.6.13-rc3-trini/include/asm-sh/system.h         |   40 
     linux-2.6.13-rc3-trini/lib/Kconfig.debug               |   14 
     linux-2.6.13-rc3/arch/sh/kernel/kgdb_jmp.S             |   33 
     linux-2.6.13-rc3/arch/sh/kernel/kgdb_stub.c            | 1491 -----------------
     22 files changed, 702 insertions(+), 2145 deletions(-)
    diff -puN arch/sh/boards/se/7751/setup.c~sh-lite arch/sh/boards/se/7751/setup.c
    --- linux-2.6.13-rc3/arch/sh/boards/se/7751/setup.c~sh-lite	2005-07-29 11:55:32.000000000 -0700
    +++ linux-2.6.13-rc3-trini/arch/sh/boards/se/7751/setup.c	2005-07-29 11:55:32.000000000 -0700
    @@ -18,10 +18,6 @@
     #include <asm/io.h>
     #include <asm/se7751/se7751.h>
     
    -#ifdef CONFIG_SH_KGDB
    -#include <asm/kgdb.h>
    -#endif
    -
     /*
      * Configure the Super I/O chip
      */
    @@ -83,12 +79,6 @@ const char *get_system_type(void)
     	return "7751 SolutionEngine";
     }
     
    -#ifdef CONFIG_SH_KGDB
    -static int kgdb_uart_setup(void);
    -static struct kgdb_sermap kgdb_uart_sermap = 
    -{ "ttyS", 0, kgdb_uart_setup, NULL };
    -#endif
    - 
     /*
      * Initialize the board
      */
    @@ -96,133 +86,4 @@ void __init platform_setup(void)
     {
     	/* Call init_smsc() replacement to set up SuperIO. */
     	/* XXX: RTC setting comes here */
    -#ifdef CONFIG_SH_KGDB
    -	kgdb_register_sermap(&kgdb_uart_sermap);
    -#endif
    -}
    -
    -/*********************************************************************
    - * Currently a hack (e.g. does not interact well w/serial.c, lots of *
    - * hardcoded stuff) but may be useful if SCI/F needs debugging.      *
    - * Mostly copied from x86 code (see files asm-i386/kgdb_local.h and  *
    - * arch/i386/lib/kgdb_serial.c).                                     *
    - *********************************************************************/
    -
    -#ifdef CONFIG_SH_KGDB
    -#include <linux/types.h>
    -#include <linux/serial.h>
    -#include <linux/serialP.h>
    -#include <linux/serial_reg.h>
    -
    -#define COM1_PORT 0x3f8  /* Base I/O address */
    -#define COM1_IRQ  4      /* IRQ not used yet */
    -#define COM2_PORT 0x2f8  /* Base I/O address */
    -#define COM2_IRQ  3      /* IRQ not used yet */
    -
    -#define SB_CLOCK 1843200 /* Serial baud clock */
    -#define SB_BASE (SB_CLOCK/16)
    -#define SB_MCR UART_MCR_OUT2 | UART_MCR_DTR | UART_MCR_RTS
    -
    -struct uart_port {
    -	int base;
    -};
    -#define UART_NPORTS 2
    -struct uart_port uart_ports[] = {
    -	{ COM1_PORT },
    -	{ COM2_PORT },
    -};
    -struct uart_port *kgdb_uart_port;
    -
    -#define UART_IN(reg)	inb_p(kgdb_uart_port->base + reg)
    -#define UART_OUT(reg,v)	outb_p((v), kgdb_uart_port->base + reg)
    -
    -/* Basic read/write functions for the UART */
    -#define UART_LSR_RXCERR    (UART_LSR_BI | UART_LSR_FE | UART_LSR_PE)
    -static int kgdb_uart_getchar(void)
    -{
    -	int lsr;
    -	int c = -1;
    -
    -	while (c == -1) {
    -		lsr = UART_IN(UART_LSR);
    -		if (lsr & UART_LSR_DR) 
    -			c = UART_IN(UART_RX);
    -		if ((lsr & UART_LSR_RXCERR))
    -			c = -1;
    -	}
    -	return c;
    -}
    -
    -static void kgdb_uart_putchar(int c)
    -{
    -	while ((UART_IN(UART_LSR) & UART_LSR_THRE) == 0)
    -		;
    -	UART_OUT(UART_TX, c);
    -}
    -
    -/*
    - * Initialize UART to configured/requested values.
    - * (But we don't interrupts yet, or interact w/serial.c)
    - */
    -static int kgdb_uart_setup(void)
    -{
    -	int port;
    -	int lcr = 0;
    -	int bdiv = 0;
    -
    -	if (kgdb_portnum >= UART_NPORTS) {
    -		KGDB_PRINTK("uart port %d invalid.\n", kgdb_portnum);
    -		return -1;
    -	}
    -
    -	kgdb_uart_port = &uart_ports[kgdb_portnum];
    -
    -	/* Init sequence from gdb_hook_interrupt */
    -	UART_IN(UART_RX);
    -	UART_OUT(UART_IER, 0);
    -
    -	UART_IN(UART_RX);	/* Serial driver comments say */
    -	UART_IN(UART_IIR);	/* this clears interrupt regs */
    -	UART_IN(UART_MSR);
    -
    -	/* Figure basic LCR values */
    -	switch (kgdb_bits) {
    -	case '7':
    -		lcr |= UART_LCR_WLEN7;
    -		break;
    -	default: case '8': 
    -		lcr |= UART_LCR_WLEN8;
    -		break;
    -	}
    -	switch (kgdb_parity) {
    -	case 'O':
    -		lcr |= UART_LCR_PARITY;
    -		break;
    -	case 'E':
    -		lcr |= (UART_LCR_PARITY | UART_LCR_EPAR);
    -		break;
    -	default: break;
    -	}
    -
    -	/* Figure the baud rate divisor */
    -	bdiv = (SB_BASE/kgdb_baud);
    -	
    -	/* Set the baud rate and LCR values */
    -	UART_OUT(UART_LCR, (lcr | UART_LCR_DLAB));
    -	UART_OUT(UART_DLL, (bdiv & 0xff));
    -	UART_OUT(UART_DLM, ((bdiv >> 8) & 0xff));
    -	UART_OUT(UART_LCR, lcr);
    -
    -	/* Set the MCR */
    -	UART_OUT(UART_MCR, SB_MCR);
    -
    -	/* Turn off FIFOs for now */
    -	UART_OUT(UART_FCR, 0);
    -
    -	/* Setup complete: initialize function pointers */
    -	kgdb_getchar = kgdb_uart_getchar;
    -	kgdb_putchar = kgdb_uart_putchar;
    -
    -	return 0;
     }
    -#endif /* CONFIG_SH_KGDB */
    diff -puN arch/sh/Kconfig.debug~sh-lite arch/sh/Kconfig.debug
    --- linux-2.6.13-rc3/arch/sh/Kconfig.debug~sh-lite	2005-07-29 11:55:32.000000000 -0700
    +++ linux-2.6.13-rc3-trini/arch/sh/Kconfig.debug	2005-07-29 11:55:32.000000000 -0700
    @@ -29,96 +29,4 @@ config EARLY_PRINTK
     	  This option is only useful porting the kernel to a new machine,
     	  when the kernel may crash or hang before the serial console is
     	  initialised. If unsure, say N.
    -
    -config KGDB
    -	bool "Include KGDB kernel debugger"
    -	help
    -	  Include in-kernel hooks for kgdb, the Linux kernel source level
    -	  debugger.  See <http://kgdb.sourceforge.net/> for more information.
    -	  Unless you are intending to debug the kernel, say N here.
    -
    -menu "KGDB configuration options"
    -	depends on KGDB
    -
    -config MORE_COMPILE_OPTIONS
    -	bool "Add any additional compile options"
    -	help
    -	  If you want to add additional CFLAGS to the kernel build, enable this
    -	  option and then enter what you would like to add in the next question.
    -	  Note however that -g is already appended with the selection of KGDB.
    -
    -config COMPILE_OPTIONS
    -	string "Additional compile arguments"
    -	depends on MORE_COMPILE_OPTIONS
    -
    -config KGDB_NMI
    -	bool "Enter KGDB on NMI"
    -	default n
    -
    -config KGDB_THREAD
    -	bool "Include KGDB thread support"
    -	default y
    -
    -config SH_KGDB_CONSOLE
    -	bool "Console messages through GDB"
    -	default n
    -
    -config KGDB_SYSRQ
    -	bool "Allow SysRq 'G' to enter KGDB"
    -	default y
    -
    -config KGDB_KERNEL_ASSERTS
    -	bool "Include KGDB kernel assertions"
    -	default n
    -
    -comment "Serial port setup"
    -
    -config KGDB_DEFPORT
    -	int "Port number (ttySCn)"
    -	default "1"
    -
    -config KGDB_DEFBAUD
    -	int "Baud rate"
    -	default "115200"
    -
    -choice
    -	prompt "Parity"
    -	depends on KGDB
    -	default KGDB_DEFPARITY_N
    -
    -config KGDB_DEFPARITY_N
    -	bool "None"
    -
    -config KGDB_DEFPARITY_E
    -	bool "Even"
    -
    -config KGDB_DEFPARITY_O
    -	bool "Odd"
    -
    -endchoice
    -
    -choice
    -	prompt "Data bits"
    -	depends on KGDB
    -	default KGDB_DEFBITS_8
    -
    -config KGDB_DEFBITS_8
    -	bool "8"
    -
    -config KGDB_DEFBITS_7
    -	bool "7"
    -
    -endchoice
    -
    -endmenu
    -
    -config FRAME_POINTER
    -	bool "Compile the kernel with frame pointers"
    -	default y if KGDB
    -	help
    -	  If you say Y here the resulting kernel image will be slightly larger
    -	  and slower, but it will give very useful debugging information.
    -	  If you don't debug the kernel, you can say N, but we may not be able
    -	  to solve problems without frame pointers.
    -
     endmenu
    diff -puN arch/sh/kernel/cpu/sh3/ex.S~sh-lite arch/sh/kernel/cpu/sh3/ex.S
    --- linux-2.6.13-rc3/arch/sh/kernel/cpu/sh3/ex.S~sh-lite	2005-07-29 11:55:32.000000000 -0700
    +++ linux-2.6.13-rc3-trini/arch/sh/kernel/cpu/sh3/ex.S	2005-07-29 11:55:32.000000000 -0700
    @@ -43,7 +43,7 @@ ENTRY(exception_handling_table)
     	.long	exception_error	! reserved_instruction (filled by trap_init) /* 180 */
     	.long	exception_error	! illegal_slot_instruction (filled by trap_init) /*1A0*/
     ENTRY(nmi_slot)
    -#if defined (CONFIG_KGDB_NMI)
    +#if defined (CONFIG_KGDB)
     	.long	debug_enter	/* 1C0 */	! Allow trap to debugger
     #else
     	.long	exception_none	/* 1C0 */	! Not implemented yet
    diff -puN arch/sh/kernel/cpu/sh4/ex.S~sh-lite arch/sh/kernel/cpu/sh4/ex.S
    --- linux-2.6.13-rc3/arch/sh/kernel/cpu/sh4/ex.S~sh-lite	2005-07-29 11:55:32.000000000 -0700
    +++ linux-2.6.13-rc3-trini/arch/sh/kernel/cpu/sh4/ex.S	2005-07-29 11:55:32.000000000 -0700
    @@ -47,7 +47,7 @@ ENTRY(exception_handling_table)
     	.long	exception_error	! reserved_instruction (filled by trap_init) /* 180 */
     	.long	exception_error	! illegal_slot_instruction (filled by trap_init) /*1A0*/
     ENTRY(nmi_slot)
    -#if defined (CONFIG_KGDB_NMI)
    +#if defined (CONFIG_KGDB)
     	.long	debug_enter	/* 1C0 */	! Allow trap to debugger
     #else
     	.long	exception_none	/* 1C0 */	! Not implemented yet
    diff -puN arch/sh/kernel/entry.S~sh-lite arch/sh/kernel/entry.S
    --- linux-2.6.13-rc3/arch/sh/kernel/entry.S~sh-lite	2005-07-29 11:55:32.000000000 -0700
    +++ linux-2.6.13-rc3-trini/arch/sh/kernel/entry.S	2005-07-29 11:55:32.000000000 -0700
    @@ -92,7 +92,7 @@ INTEVT  = 0xff000028
     MMU_TEA = 0xff00000c		! TLB Exception Address Register
     #endif
     
    -#if defined(CONFIG_KGDB_NMI)
    +#if defined(CONFIG_KGDB)
     NMI_VEC = 0x1c0			! Must catch early for debounce
     #endif
     
    @@ -244,31 +244,33 @@ call_dae:
     2:	.long   do_address_error
     #endif /* CONFIG_MMU */
     
    -#if defined(CONFIG_SH_STANDARD_BIOS) || defined(CONFIG_SH_KGDB)
    +#if defined(CONFIG_SH_STANDARD_BIOS) || defined(CONFIG_KGDB)
     ! Handle kernel debug if either kgdb (SW) or gdb-stub (FW) is present.
     ! If both are configured, handle the debug traps (breakpoints) in SW,
     ! but still allow BIOS traps to FW.
     
     	.align	2
     debug_kernel:
    -#if defined(CONFIG_SH_STANDARD_BIOS) && defined(CONFIG_SH_KGDB)
    +#if defined(CONFIG_SH_STANDARD_BIOS) && defined(CONFIG_KGDB)
     	/* Force BIOS call to FW (debug_trap put TRA in r8) */
     	mov	r8,r0
     	shlr2	r0
     	cmp/eq	#0x3f,r0
     	bt	debug_kernel_fw
    -#endif /* CONFIG_SH_STANDARD_BIOS && CONFIG_SH_KGDB */
    +#endif /* CONFIG_SH_STANDARD_BIOS && CONFIG_KGDB */
     
    -debug_enter:		
    -#if defined(CONFIG_SH_KGDB)
    +	.align 2
    +	.globl debug_enter
    +debug_enter:
    +#if defined(CONFIG_KGDB)
     	/* Jump to kgdb, pass stacked regs as arg */
     debug_kernel_sw:
     	mov.l	3f, r0
     	jmp	@r0
     	 mov	r15, r4
     	.align	2
    -3:	.long	kgdb_handle_exception
    -#endif /* CONFIG_SH_KGDB */
    +3:	.long	kgdb_exception_handler
    +#endif /* CONFIG_KGDB */
     
     #if defined(CONFIG_SH_STANDARD_BIOS)
     	/* Unwind the stack and jmp to the debug entry */
    @@ -310,12 +312,12 @@ debug_kernel_fw:
     2:	.long	gdb_vbr_vector
     #endif /* CONFIG_SH_STANDARD_BIOS */
     
    -#endif /* CONFIG_SH_STANDARD_BIOS || CONFIG_SH_KGDB */
    +#endif /* CONFIG_SH_STANDARD_BIOS || CONFIG_KGDB */
     
     
     	.align	2
    -debug_trap:	
    -#if defined(CONFIG_SH_STANDARD_BIOS) || defined(CONFIG_SH_KGDB)
    +debug_trap:
    +#if defined(CONFIG_SH_STANDARD_BIOS) || defined(CONFIG_KGDB)
     	mov	#OFF_SR, r0
     	mov.l	@(r0,r15), r0		! get status register
     	shll	r0
    @@ -659,7 +661,7 @@ skip_restore:
     6:	or	k0, k2			! Set the IMASK-bits
     	ldc	k2, ssr
     	!
    -#if defined(CONFIG_KGDB_NMI)
    +#if defined(CONFIG_KGDB)
     	! Clear in_nmi
     	mov.l	4f, k0
     	mov	#0, k1
    @@ -711,7 +713,7 @@ tlb_miss:
     interrupt:
     	mov.l	2f, k2
     	mov.l	3f, k3
    -#if defined(CONFIG_KGDB_NMI)
    +#if defined(CONFIG_KGDB)
     	! Debounce (filter nested NMI)
     	mov.l	@k2, k0
     	mov.l	5f, k1
    @@ -726,7 +728,7 @@ interrupt:
     5:	.long	NMI_VEC
     6:	.long	in_nmi
     0:
    -#endif /* defined(CONFIG_KGDB_NMI) */
    +#endif /* defined(CONFIG_KGDB) */
     	bra	handle_exception
     	 mov.l	@k2, k2
     
    diff -puN /dev/null arch/sh/kernel/kgdb.c
    --- /dev/null	2005-07-25 10:57:32.312383000 -0700
    +++ linux-2.6.13-rc3-trini/arch/sh/kernel/kgdb.c	2005-07-29 11:55:32.000000000 -0700
    @@ -0,0 +1,363 @@
    +/*
    + * arch/sh/kernel/kgdb.c
    + *
    + * Contains SH-specific low-level support for KGDB.
    + *
    + * Containes extracts from code by Glenn Engel, Jim Kingdon,
    + * David Grothe <dave@gcom.com>, Tigran Aivazian <tigran@sco.com>,
    + * Amit S. Kale <akale@veritas.com>,  William Gatliff <bgat@open-widgets.com>,
    + * Ben Lee, Steve Chamberlain and Benoit Miller <fulg@iname.com>,
    + * Henry Bell <henry.bell@st.com> and Jeremy Siegel <jsiegel@mvista.com>
    + *
    + * Maintainer: Tom Rini <trini@kernel.crashing.org>
    + *
    + * 2004 (c) MontaVista Software, 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.
    + */
    +
    +#include <linux/string.h>
    +#include <linux/kernel.h>
    +#include <linux/sched.h>
    +#include <linux/smp.h>
    +#include <linux/spinlock.h>
    +#include <linux/delay.h>
    +#include <linux/linkage.h>
    +#include <linux/init.h>
    +#include <linux/kgdb.h>
    +
    +#include <asm/system.h>
    +#include <asm/current.h>
    +#include <asm/signal.h>
    +#include <asm/pgtable.h>
    +#include <asm/ptrace.h>
    +
    +extern void per_cpu_trap_init(void);
    +extern atomic_t cpu_doing_single_step;
    +
    +/* Function pointers for linkage */
    +static struct kgdb_regs trap_registers;
    +
    +/* Globals. */
    +char in_nmi;			/* Set during NMI to prevent reentry */
    +
    +/* TRA differs sh3/4 */
    +#if defined(CONFIG_CPU_SH3)
    +#define TRA 0xffffffd0
    +#elif defined(CONFIG_CPU_SH4)
    +#define TRA 0xff000020
    +#endif
    +
    +/* Macros for single step instruction identification */
    +#define OPCODE_BT(op)         (((op) & 0xff00) == 0x8900)
    +#define OPCODE_BF(op)         (((op) & 0xff00) == 0x8b00)
    +#define OPCODE_BTF_DISP(op)   (((op) & 0x80) ? (((op) | 0xffffff80) << 1) : \
    +			      (((op) & 0x7f ) << 1))
    +#define OPCODE_BFS(op)        (((op) & 0xff00) == 0x8f00)
    +#define OPCODE_BTS(op)        (((op) & 0xff00) == 0x8d00)
    +#define OPCODE_BRA(op)        (((op) & 0xf000) == 0xa000)
    +#define OPCODE_BRA_DISP(op)   (((op) & 0x800) ? (((op) | 0xfffff800) << 1) : \
    +			      (((op) & 0x7ff) << 1))
    +#define OPCODE_BRAF(op)       (((op) & 0xf0ff) == 0x0023)
    +#define OPCODE_BRAF_REG(op)   (((op) & 0x0f00) >> 8)
    +#define OPCODE_BSR(op)        (((op) & 0xf000) == 0xb000)
    +#define OPCODE_BSR_DISP(op)   (((op) & 0x800) ? (((op) | 0xfffff800) << 1) : \
    +			      (((op) & 0x7ff) << 1))
    +#define OPCODE_BSRF(op)       (((op) & 0xf0ff) == 0x0003)
    +#define OPCODE_BSRF_REG(op)   (((op) >> 8) & 0xf)
    +#define OPCODE_JMP(op)        (((op) & 0xf0ff) == 0x402b)
    +#define OPCODE_JMP_REG(op)    (((op) >> 8) & 0xf)
    +#define OPCODE_JSR(op)        (((op) & 0xf0ff) == 0x400b)
    +#define OPCODE_JSR_REG(op)    (((op) >> 8) & 0xf)
    +#define OPCODE_RTS(op)        ((op) == 0xb)
    +#define OPCODE_RTE(op)        ((op) == 0x2b)
    +
    +#define SR_T_BIT_MASK           0x1
    +#define STEP_OPCODE             0xc320
    +#define BIOS_CALL_TRAP          0x3f
    +
    +/* Exception codes as per SH-4 core manual */
    +#define ADDRESS_ERROR_LOAD_VEC   7
    +#define ADDRESS_ERROR_STORE_VEC  8
    +#define TRAP_VEC                 11
    +#define INVALID_INSN_VEC         12
    +#define INVALID_SLOT_VEC         13
    +#define NMI_VEC                  14
    +#define SERIAL_BREAK_VEC         58
    +
    +/* Misc static */
    +static int stepped_address;
    +static short stepped_opcode;
    +
    +/* Translate SH-3/4 exception numbers to unix-like signal values */
    +static int compute_signal(const int excep_code)
    +{
    +	switch (excep_code) {
    +	case INVALID_INSN_VEC:
    +	case INVALID_SLOT_VEC:
    +		return SIGILL;
    +	case ADDRESS_ERROR_LOAD_VEC:
    +	case ADDRESS_ERROR_STORE_VEC:
    +		return SIGSEGV;
    +	case SERIAL_BREAK_VEC:
    +	case NMI_VEC:
    +		return SIGINT;
    +	default:
    +		/* Act like it was a break/trap. */
    +		return SIGTRAP;
    +	}
    +}
    +
    +/*
    + * Translate the registers of the system into the format that GDB wants.  Since
    + * we use a local structure to store things, instead of getting them out
    + * of pt_regs, we can just do a memcpy.
    + */
    +void regs_to_gdb_regs(unsigned long *gdb_regs, struct pt_regs *ign)
    +{
    +	memcpy(gdb_regs, &trap_registers, sizeof(trap_registers));
    +}
    +
    +/*
    + * On SH we save: r1 (prev->thread.sp) r2 (prev->thread.pc) r4 (prev) r5 (next)
    + * r6 (next->thread.sp) r7 (next->thread.pc)
    + */
    +void sleeping_thread_to_gdb_regs(unsigned long *gdb_regs, struct task_struct *p)
    +{
    +	int count;
    +
    +	for (count = 0; count < 16; count++)
    +		*(gdb_regs++) = 0;
    +	*(gdb_regs++) = p->thread.pc;
    +	*(gdb_regs++) = 0;
    +	*(gdb_regs++) = 0;
    +	*(gdb_regs++) = 0;
    +	*(gdb_regs++) = 0;
    +	*(gdb_regs++) = 0;
    +	*(gdb_regs++) = 0;
    +}
    +
    +/*
    + * Translate the registers values that GDB has given us back into the
    + * format of the system.  See the comment above about memcpy.
    + */
    +void gdb_regs_to_regs(unsigned long *gdb_regs, struct pt_regs *ign)
    +{
    +	memcpy(&trap_registers, gdb_regs, sizeof(trap_registers));
    +}
    +
    +/* Calculate the new address for after a step */
    +static short *get_step_address(void)
    +{
    +	short op = *(short *)trap_registers.pc;
    +	long addr;
    +
    +	/* BT */
    +	if (OPCODE_BT(op)) {
    +		if (trap_registers.sr & SR_T_BIT_MASK)
    +			addr = trap_registers.pc + 4 + OPCODE_BTF_DISP(op);
    +		else
    +			addr = trap_registers.pc + 2;
    +	}
    +
    +	/* BTS */
    +	else if (OPCODE_BTS(op)) {
    +		if (trap_registers.sr & SR_T_BIT_MASK)
    +			addr = trap_registers.pc + 4 + OPCODE_BTF_DISP(op);
    +		else
    +			addr = trap_registers.pc + 4;	/* Not in delay slot */
    +	}
    +
    +	/* BF */
    +	else if (OPCODE_BF(op)) {
    +		if (!(trap_registers.sr & SR_T_BIT_MASK))
    +			addr = trap_registers.pc + 4 + OPCODE_BTF_DISP(op);
    +		else
    +			addr = trap_registers.pc + 2;
    +	}
    +
    +	/* BFS */
    +	else if (OPCODE_BFS(op)) {
    +		if (!(trap_registers.sr & SR_T_BIT_MASK))
    +			addr = trap_registers.pc + 4 + OPCODE_BTF_DISP(op);
    +		else
    +			addr = trap_registers.pc + 4;	/* Not in delay slot */
    +	}
    +
    +	/* BRA */
    +	else if (OPCODE_BRA(op))
    +		addr = trap_registers.pc + 4 + OPCODE_BRA_DISP(op);
    +
    +	/* BRAF */
    +	else if (OPCODE_BRAF(op))
    +		addr = trap_registers.pc + 4
    +		    + trap_registers.regs[OPCODE_BRAF_REG(op)];
    +
    +	/* BSR */
    +	else if (OPCODE_BSR(op))
    +		addr = trap_registers.pc + 4 + OPCODE_BSR_DISP(op);
    +
    +	/* BSRF */
    +	else if (OPCODE_BSRF(op))
    +		addr = trap_registers.pc + 4
    +		    + trap_registers.regs[OPCODE_BSRF_REG(op)];
    +
    +	/* JMP */
    +	else if (OPCODE_JMP(op))
    +		addr = trap_registers.regs[OPCODE_JMP_REG(op)];
    +
    +	/* JSR */
    +	else if (OPCODE_JSR(op))
    +		addr = trap_registers.regs[OPCODE_JSR_REG(op)];
    +
    +	/* RTS */
    +	else if (OPCODE_RTS(op))
    +		addr = trap_registers.pr;
    +
    +	/* RTE */
    +	else if (OPCODE_RTE(op))
    +		addr = trap_registers.regs[15];
    +
    +	/* Other */
    +	else
    +		addr = trap_registers.pc + 2;
    +
    +	kgdb_flush_icache_range(addr, addr + 2);
    +	return (short *)addr;
    +}
    +
    +/* The command loop, read and act on requests */
    +int kgdb_arch_handle_exception(int e_vector, int signo, int err_code,
    +			       char *remcom_in_buffer, char *remcom_out_buffer,
    +			       struct pt_regs *ign)
    +{
    +	unsigned long addr;
    +	char *ptr = &remcom_in_buffer[1];
    +
    +	/* Examine first char of buffer to see what we need to do */
    +	switch (remcom_in_buffer[0]) {
    +	case 'c':		/* Continue at address AA..AA (optional) */
    +	case 's':		/* Step one instruction from AA..AA */
    +		/* Try to read optional parameter, PC unchanged if none */
    +		if (kgdb_hex2long(&ptr, &addr))
    +			trap_registers.pc = addr;
    +
    +		atomic_set(&cpu_doing_single_step, -1);
    +		if (remcom_in_buffer[0] == 's') {
    +			/* Replace the instruction immediately after the
    +			 * current instruction (i.e. next in the expected
    +			 * flow of control) with a trap instruction, so that
    +			 * returning will cause only a single instruction to
    +			 * be executed. Note that this model is slightly
    +			 * broken for instructions with delay slots
    +			 * (e.g. B[TF]S, BSR, BRA etc), where both the branch
    +			 * and the instruction in the delay slot will be
    +			 * executed.
    +			 */
    +			/* Determine where the target instruction will send
    +			 * us to */
    +			unsigned short *next_addr = get_step_address();
    +			stepped_address = (int)next_addr;
    +
    +			/* Replace it */
    +			stepped_opcode = *(short *)next_addr;
    +			*next_addr = STEP_OPCODE;
    +
    +			/* Flush and return */
    +			kgdb_flush_icache_range((long)next_addr,
    +						(long)next_addr + 2);
    +			if (kgdb_contthread)
    +				atomic_set(&cpu_doing_single_step,
    +					   smp_processor_id());
    +		}
    +		return 0;
    +	}
    +	return -1;
    +}
    +
    +/*
    + * When an exception has occured, we are called.  We need to set things
    + * up so that we can call kgdb_handle_exception to handle requests from
    + * the remote GDB.
    + */
    +void kgdb_exception_handler(struct pt_regs *regs)
    +{
    +	int excep_code, vbr_val;
    +	int count;
    +
    +	/* Copy kernel regs (from stack) */
    +	for (count = 0; count < 16; count++)
    +		trap_registers.regs[count] = regs->regs[count];
    +	trap_registers.pc = regs->pc;
    +	trap_registers.pr = regs->pr;
    +	trap_registers.sr = regs->sr;
    +	trap_registers.gbr = regs->gbr;
    +	trap_registers.mach = regs->mach;
    +	trap_registers.macl = regs->macl;
    +
    +	__asm__ __volatile__("stc vbr, %0":"=r"(vbr_val));
    +	trap_registers.vbr = vbr_val;
    +
    +	/* Get the execption code. */
    +	__asm__ __volatile__("stc r2_bank, %0":"=r"(excep_code));
    +
    +	excep_code >>= 5;
    +
    +	/* If we got an NMI, and KGDB is not yet initialized, call
    +	 * breakpoint() to try and initialize everything for us. */
    +	if (excep_code == NMI_VEC && !kgdb_initialized) {
    +		breakpoint();
    +		return;
    +	}
    +
    +	/* TRAP_VEC exception indicates a software trap inserted in place of
    +	 * code by GDB so back up PC by one instruction, as this instruction
    +	 * will later be replaced by its original one.  Do NOT do this for
    +	 * trap 0xff, since that indicates a compiled-in breakpoint which
    +	 * will not be replaced (and we would retake the trap forever) */
    +	if (excep_code == TRAP_VEC &&
    +	    (*(volatile unsigned long *)TRA != (0xff << 2)))
    +		trap_registers.pc -= 2;
    +
    +	/* If we have been single-stepping, put back the old instruction.
    +	 * We use stepped_address in case we have stopped more than one
    +	 * instruction away. */
    +	if (stepped_opcode != 0) {
    +		*(short *)stepped_address = stepped_opcode;
    +		kgdb_flush_icache_range(stepped_address, stepped_address + 2);
    +	}
    +	stepped_opcode = 0;
    +
    +	/* Call the stub to do the processing.  Note that not everything we
    +	 * need to send back and forth lives in pt_regs. */
    +	kgdb_handle_exception(excep_code, compute_signal(excep_code), 0, regs);
    +
    +	/* Copy back the (maybe modified) registers */
    +	for (count = 0; count < 16; count++)
    +		regs->regs[count] = trap_registers.regs[count];
    +	regs->pc = trap_registers.pc;
    +	regs->pr = trap_registers.pr;
    +	regs->sr = trap_registers.sr;
    +	regs->gbr = trap_registers.gbr;
    +	regs->mach = trap_registers.mach;
    +	regs->macl = trap_registers.macl;
    +
    +	vbr_val = trap_registers.vbr;
    +	__asm__ __volatile__("ldc %0, vbr": :"r"(vbr_val));
    +}
    +
    +int __init kgdb_arch_init(void)
    +{
    +	per_cpu_trap_init();
    +
    +	return 0;
    +}
    +
    +struct kgdb_arch arch_kgdb_ops = {
    +#ifdef CONFIG_CPU_LITTLE_ENDIAN
    +	.gdb_bpt_instr = {0xff, 0xc3},
    +#else
    +	.gdb_bpt_instr = {0xc3, 0xff},
    +#endif
    +};
    diff -L arch/sh/kernel/kgdb_jmp.S -puN arch/sh/kernel/kgdb_jmp.S~sh-lite /dev/null
    --- linux-2.6.13-rc3/arch/sh/kernel/kgdb_jmp.S
    +++ /dev/null	2005-07-25 10:57:32.312383000 -0700
    @@ -1,33 +0,0 @@
    -#include <linux/linkage.h>
    -
    -ENTRY(setjmp)
    -	add	#(9*4), r4
    -	sts.l	pr, @-r4
    -	mov.l	r15, @-r4
    -	mov.l	r14, @-r4
    -	mov.l	r13, @-r4
    -	mov.l	r12, @-r4
    -	mov.l	r11, @-r4
    -	mov.l	r10, @-r4
    -	mov.l	r9, @-r4
    -	mov.l	r8, @-r4
    -	rts
    -	 mov	#0, r0
    -
    -ENTRY(longjmp)
    -	mov.l	@r4+, r8
    -	mov.l	@r4+, r9
    -	mov.l	@r4+, r10
    -	mov.l	@r4+, r11
    -	mov.l	@r4+, r12
    -	mov.l	@r4+, r13
    -	mov.l	@r4+, r14
    -	mov.l	@r4+, r15
    -	lds.l	@r4+, pr
    -	mov	r5, r0
    -	tst	r0, r0
    -	bf	1f
    -	mov	#1, r0	! in case val==0
    -1:	rts
    -	 nop
    -
    diff -puN /dev/null arch/sh/kernel/kgdb-jmp.S
    --- /dev/null	2005-07-25 10:57:32.312383000 -0700
    +++ linux-2.6.13-rc3-trini/arch/sh/kernel/kgdb-jmp.S	2005-07-29 11:55:32.000000000 -0700
    @@ -0,0 +1,32 @@
    +#include <linux/linkage.h>
    +
    +ENTRY(kgdb_fault_setjmp)
    +	add	#(9*4), r4
    +	sts.l	pr, @-r4
    +	mov.l	r15, @-r4
    +	mov.l	r14, @-r4
    +	mov.l	r13, @-r4
    +	mov.l	r12, @-r4
    +	mov.l	r11, @-r4
    +	mov.l	r10, @-r4
    +	mov.l	r9, @-r4
    +	mov.l	r8, @-r4
    +	rts
    +	 mov	#0, r0
    +
    +ENTRY(kgdb_fault_longjmp)
    +	mov.l	@r4+, r8
    +	mov.l	@r4+, r9
    +	mov.l	@r4+, r10
    +	mov.l	@r4+, r11
    +	mov.l	@r4+, r12
    +	mov.l	@r4+, r13
    +	mov.l	@r4+, r14
    +	mov.l	@r4+, r15
    +	lds.l	@r4+, pr
    +	mov	r5, r0
    +	tst	r0, r0
    +	bf	1f
    +	mov	#1, r0
    +1:	rts
    +	 nop
    diff -L arch/sh/kernel/kgdb_stub.c -puN arch/sh/kernel/kgdb_stub.c~sh-lite /dev/null
    --- linux-2.6.13-rc3/arch/sh/kernel/kgdb_stub.c
    +++ /dev/null	2005-07-25 10:57:32.312383000 -0700
    @@ -1,1491 +0,0 @@
    -/*
    - * May be copied or modified under the terms of the GNU General Public
    - * License.  See linux/COPYING for more information.
    - *
    - * Containes extracts from code by Glenn Engel, Jim Kingdon,
    - * David Grothe <dave@gcom.com>, Tigran Aivazian <tigran@sco.com>,
    - * Amit S. Kale <akale@veritas.com>,  William Gatliff <bgat@open-widgets.com>,
    - * Ben Lee, Steve Chamberlain and Benoit Miller <fulg@iname.com>.
    - * 
    - * This version by Henry Bell <henry.bell@st.com>
    - * Minor modifications by Jeremy Siegel <jsiegel@mvista.com>
    - * 
    - * Contains low-level support for remote debug using GDB. 
    - *
    - * To enable debugger support, two things need to happen. A call to
    - * set_debug_traps() is necessary in order to allow any breakpoints
    - * or error conditions to be properly intercepted and reported to gdb.
    - * A breakpoint also needs to be generated to begin communication.  This
    - * is most easily accomplished by a call to breakpoint() which does
    - * a trapa if the initialisation phase has been successfully completed.
    - *
    - * In this case, set_debug_traps() is not used to "take over" exceptions;
    - * other kernel code is modified instead to enter the kgdb functions here
    - * when appropriate (see entry.S for breakpoint traps and NMI interrupts,
    - * see traps.c for kernel error exceptions).
    - *
    - * The following gdb commands are supported:
    - *
    - *    Command       Function                               Return value
    - *
    - *    g             return the value of the CPU registers  hex data or ENN
    - *    G             set the value of the CPU registers     OK or ENN
    - *
    - *    mAA..AA,LLLL  Read LLLL bytes at address AA..AA      hex data or ENN
    - *    MAA..AA,LLLL: Write LLLL bytes at address AA.AA      OK or ENN
    - *    XAA..AA,LLLL: Same, but data is binary (not hex)     OK or ENN
    - *
    - *    c             Resume at current address              SNN   ( signal NN)
    - *    cAA..AA       Continue at address AA..AA             SNN
    - *    CNN;          Resume at current address with signal  SNN
    - *    CNN;AA..AA    Resume at address AA..AA with signal   SNN
    - *
    - *    s             Step one instruction                   SNN
    - *    sAA..AA       Step one instruction from AA..AA       SNN
    - *    SNN;          Step one instruction with signal       SNN
    - *    SNNAA..AA     Step one instruction from AA..AA w/NN  SNN
    - *
    - *    k             kill (Detach GDB)
    - *
    - *    d             Toggle debug flag
    - *    D             Detach GDB 
    - *
    - *    Hct           Set thread t for operations,           OK or ENN
    - *                  c = 'c' (step, cont), c = 'g' (other
    - *                  operations)
    - *
    - *    qC            Query current thread ID                QCpid
    - *    qfThreadInfo  Get list of current threads (first)    m<id>
    - *    qsThreadInfo   "    "  "     "      "   (subsequent)
    - *    qOffsets      Get section offsets                  Text=x;Data=y;Bss=z
    - * 
    - *    TXX           Find if thread XX is alive             OK or ENN
    - *    ?             What was the last sigval ?             SNN   (signal NN)
    - *    O             Output to GDB console
    - *
    - * Remote communication protocol.
    - *
    - *    A debug packet whose contents are <data> is encapsulated for
    - *    transmission in the form:
    - *
    - *       $ <data> # CSUM1 CSUM2
    - *
    - *       <data> must be ASCII alphanumeric and cannot include characters
    - *       '$' or '#'.  If <data> starts with two characters followed by
    - *       ':', then the existing stubs interpret this as a sequence number.
    - *
    - *       CSUM1 and CSUM2 are ascii hex representation of an 8-bit 
    - *       checksum of <data>, the most significant nibble is sent first.
    - *       the hex digits 0-9,a-f are used.
    - *
    - *    Receiver responds with:
    - *
    - *       +       - if CSUM is correct and ready for next packet
    - *       -       - if CSUM is incorrect
    - *
    - * Responses can be run-length encoded to save space.  A '*' means that
    - * the next character is an ASCII encoding giving a repeat count which
    - * stands for that many repititions of the character preceding the '*'.
    - * The encoding is n+29, yielding a printable character where n >=3 
    - * (which is where RLE starts to win).  Don't use an n > 126. 
    - *
    - * So "0* " means the same as "0000".
    - */
    -
    -#include <linux/string.h>
    -#include <linux/kernel.h>
    -#include <linux/sched.h>
    -#include <linux/smp.h>
    -#include <linux/spinlock.h>
    -#include <linux/delay.h>
    -#include <linux/linkage.h>
    -#include <linux/init.h>
    -
    -#include <asm/system.h>
    -#include <asm/current.h>
    -#include <asm/signal.h>
    -#include <asm/pgtable.h>
    -#include <asm/ptrace.h>
    -#include <asm/kgdb.h>
    -
    -#ifdef CONFIG_SH_KGDB_CONSOLE
    -#include <linux/console.h>
    -#endif
    -
    -/* Function pointers for linkage */
    -kgdb_debug_hook_t *kgdb_debug_hook;
    -kgdb_bus_error_hook_t *kgdb_bus_err_hook;
    -
    -int (*kgdb_getchar)(void);
    -void (*kgdb_putchar)(int);
    -
    -static void put_debug_char(int c)
    -{
    -	if (!kgdb_putchar)
    -		return;
    -	(*kgdb_putchar)(c);
    -}
    -static int get_debug_char(void)
    -{
    -	if (!kgdb_getchar)
    -		return -1;
    -	return (*kgdb_getchar)();
    -}
    -
    -/* Num chars in in/out bound buffers, register packets need NUMREGBYTES * 2 */
    -#define BUFMAX 1024
    -#define NUMREGBYTES (MAXREG*4)
    -#define OUTBUFMAX (NUMREGBYTES*2+512)
    -
    -enum regs {
    -	R0 = 0, R1,  R2,  R3,   R4,   R5,  R6, R7,
    -	R8, R9, R10, R11, R12,  R13,  R14, R15,
    -	PC, PR, GBR, VBR, MACH, MACL, SR,
    -	/*  */
    -	MAXREG
    -};
    -
    -static unsigned int registers[MAXREG];
    -struct kgdb_regs trap_registers;
    -
    -char kgdb_in_gdb_mode;
    -char in_nmi;			/* Set during NMI to prevent reentry */
    -int kgdb_nofault;		/* Boolean to ignore bus errs (i.e. in GDB) */
    -int kgdb_enabled = 1;		/* Default to enabled, cmdline can disable */
    -int kgdb_halt;
    -
    -/* Exposed for user access */
    -struct task_struct *kgdb_current;
    -unsigned int kgdb_g_imask;
    -int kgdb_trapa_val;
    -int kgdb_excode;
    -
    -/* Default values for SCI (can override via kernel args in setup.c) */
    -#ifndef CONFIG_KGDB_DEFPORT
    -#define CONFIG_KGDB_DEFPORT 1
    -#endif
    -
    -#ifndef CONFIG_KGDB_DEFBAUD
    -#define CONFIG_KGDB_DEFBAUD 115200
    -#endif
    -
    -#if defined(CONFIG_KGDB_DEFPARITY_E)
    -#define CONFIG_KGDB_DEFPARITY 'E'
    -#elif defined(CONFIG_KGDB_DEFPARITY_O)
    -#define CONFIG_KGDB_DEFPARITY 'O'
    -#else /* CONFIG_KGDB_DEFPARITY_N */
    -#define CONFIG_KGDB_DEFPARITY 'N'
    -#endif
    -
    -#ifdef CONFIG_KGDB_DEFBITS_7
    -#define CONFIG_KGDB_DEFBITS '7'
    -#else /* CONFIG_KGDB_DEFBITS_8 */
    -#define CONFIG_KGDB_DEFBITS '8'
    -#endif
    -
    -/* SCI/UART settings, used in kgdb_console_setup() */
    -int  kgdb_portnum = CONFIG_KGDB_DEFPORT;
    -int  kgdb_baud = CONFIG_KGDB_DEFBAUD;
    -char kgdb_parity = CONFIG_KGDB_DEFPARITY;
    -char kgdb_bits = CONFIG_KGDB_DEFBITS;
    -
    -/* Jump buffer for setjmp/longjmp */
    -static jmp_buf rem_com_env;
    -
    -/* TRA differs sh3/4 */
    -#if defined(CONFIG_CPU_SH3)
    -#define TRA 0xffffffd0
    -#elif defined(CONFIG_CPU_SH4)
    -#define TRA 0xff000020
    -#endif
    -
    -/* Macros for single step instruction identification */
    -#define OPCODE_BT(op)         (((op) & 0xff00) == 0x8900)
    -#define OPCODE_BF(op)         (((op) & 0xff00) == 0x8b00)
    -#define OPCODE_BTF_DISP(op)   (((op) & 0x80) ? (((op) | 0xffffff80) << 1) : \
    -			      (((op) & 0x7f ) << 1))
    -#define OPCODE_BFS(op)        (((op) & 0xff00) == 0x8f00)
    -#define OPCODE_BTS(op)        (((op) & 0xff00) == 0x8d00)
    -#define OPCODE_BRA(op)        (((op) & 0xf000) == 0xa000)
    -#define OPCODE_BRA_DISP(op)   (((op) & 0x800) ? (((op) | 0xfffff800) << 1) : \
    -			      (((op) & 0x7ff) << 1))
    -#define OPCODE_BRAF(op)       (((op) & 0xf0ff) == 0x0023)
    -#define OPCODE_BRAF_REG(op)   (((op) & 0x0f00) >> 8)
    -#define OPCODE_BSR(op)        (((op) & 0xf000) == 0xb000)
    -#define OPCODE_BSR_DISP(op)   (((op) & 0x800) ? (((op) | 0xfffff800) << 1) : \
    -			      (((op) & 0x7ff) << 1))
    -#define OPCODE_BSRF(op)       (((op) & 0xf0ff) == 0x0003)
    -#define OPCODE_BSRF_REG(op)   (((op) >> 8) & 0xf)
    -#define OPCODE_JMP(op)        (((op) & 0xf0ff) == 0x402b)
    -#define OPCODE_JMP_REG(op)    (((op) >> 8) & 0xf)
    -#define OPCODE_JSR(op)        (((op) & 0xf0ff) == 0x400b)
    -#define OPCODE_JSR_REG(op)    (((op) >> 8) & 0xf)
    -#define OPCODE_RTS(op)        ((op) == 0xb)
    -#define OPCODE_RTE(op)        ((op) == 0x2b)
    -
    -#define SR_T_BIT_MASK           0x1
    -#define STEP_OPCODE             0xc320
    -#define BIOS_CALL_TRAP          0x3f
    -
    -/* Exception codes as per SH-4 core manual */
    -#define ADDRESS_ERROR_LOAD_VEC   7
    -#define ADDRESS_ERROR_STORE_VEC  8
    -#define TRAP_VEC                 11
    -#define INVALID_INSN_VEC         12
    -#define INVALID_SLOT_VEC         13
    -#define NMI_VEC                  14
    -#define USER_BREAK_VEC           15
    -#define SERIAL_BREAK_VEC         58
    -
    -/* Misc static */
    -static int stepped_address;
    -static short stepped_opcode;
    -static const char hexchars[] = "0123456789abcdef";
    -static char in_buffer[BUFMAX];
    -static char out_buffer[OUTBUFMAX];
    -
    -static void kgdb_to_gdb(const char *s);
    -
    -#ifdef CONFIG_KGDB_THREAD
    -static struct task_struct *trapped_thread;
    -static struct task_struct *current_thread;
    -typedef unsigned char threadref[8];
    -#define BUF_THREAD_ID_SIZE 16
    -#endif
    -
    -/* Return addr as a real volatile address */
    -static inline unsigned int ctrl_inl(const unsigned long addr)
    -{
    -	return *(volatile unsigned long *) addr;
    -}
    -
    -/* Correctly set *addr using volatile */
    -static inline void ctrl_outl(const unsigned int b, unsigned long addr)
    -{
    -	*(volatile unsigned long *) addr = b;
    -}
    -
    -/* Get high hex bits */
    -static char highhex(const int x)
    -{
    -	return hexchars[(x >> 4) & 0xf];
    -}
    -
    -/* Get low hex bits */
    -static char lowhex(const int x)
    -{
    -	return hexchars[x & 0xf];
    -}
    -
    -/* Convert ch to hex */
    -static int hex(const char ch)
    -{
    -	if ((ch >= 'a') && (ch <= 'f'))
    -		return (ch - 'a' + 10);
    -	if ((ch >= '0') && (ch <= '9'))
    -		return (ch - '0');
    -	if ((ch >= 'A') && (ch <= 'F'))
    -		return (ch - 'A' + 10);
    -	return (-1);
    -}
    -
    -/* Convert the memory pointed to by mem into hex, placing result in buf.
    -   Returns a pointer to the last char put in buf (null) */
    -static char *mem_to_hex(const char *mem, char *buf, const int count)
    -{
    -	int i;
    -	int ch;
    -	unsigned short s_val;
    -	unsigned long l_val;
    -
    -	/* Check for 16 or 32 */
    -	if (count == 2 && ((long) mem & 1) == 0) {
    -		s_val = *(unsigned short *) mem;
    -		mem = (char *) &s_val;
    -	} else if (count == 4 && ((long) mem & 3) == 0) {
    -		l_val = *(unsigned long *) mem;
    -		mem = (char *) &l_val;
    -	}
    -	for (i = 0; i < count; i++) {
    -		ch = *mem++;
    -		*buf++ = highhex(ch);
    -		*buf++ = lowhex(ch);
    -	}
    -	*buf = 0;
    -	return (buf);
    -}
    -
    -/* Convert the hex array pointed to by buf into binary, to be placed in mem.
    -   Return a pointer to the character after the last byte written */
    -static char *hex_to_mem(const char *buf, char *mem, const int count)
    -{
    -	int i;
    -	unsigned char ch;
    -
    -	for (i = 0; i < count; i++) {
    -		ch = hex(*buf++) << 4;
    -		ch = ch + hex(*buf++);
    -		*mem++ = ch;
    -	}
    -	return (mem);
    -}
    -
    -/* While finding valid hex chars, convert to an integer, then return it */
    -static int hex_to_int(char **ptr, int *int_value)
    -{
    -	int num_chars = 0;
    -	int hex_value;
    -
    -	*int_value = 0;
    -
    -	while (**ptr) {
    -		hex_value = hex(**ptr);
    -		if (hex_value >= 0) {
    -			*int_value = (*int_value << 4) | hex_value;
    -			num_chars++;
    -		} else
    -			break;
    -		(*ptr)++;
    -	}
    -	return num_chars;
    -}
    -
    -/*  Copy the binary array pointed to by buf into mem.  Fix $, #,
    -    and 0x7d escaped with 0x7d.  Return a pointer to the character 
    -    after the last byte written. */
    -static char *ebin_to_mem(const char *buf, char *mem, int count)
    -{
    -	for (; count > 0; count--, buf++) {
    -		if (*buf == 0x7d)
    -			*mem++ = *(++buf) ^ 0x20;
    -		else
    -			*mem++ = *buf;
    -	}
    -	return mem;
    -}
    -
    -/* Pack a hex byte */
    -static char *pack_hex_byte(char *pkt, int byte)
    -{
    -	*pkt++ = hexchars[(byte >> 4) & 0xf];
    -	*pkt++ = hexchars[(byte & 0xf)];
    -	return pkt;
    -}
    -
    -#ifdef CONFIG_KGDB_THREAD
    -
    -/* Pack a thread ID */
    -static char *pack_threadid(char *pkt, threadref * id)
    -{
    -	char *limit;
    -	unsigned char *altid;
    -
    -	altid = (unsigned char *) id;
    -
    -	limit = pkt + BUF_THREAD_ID_SIZE;
    -	while (pkt < limit)
    -		pkt = pack_hex_byte(pkt, *altid++);
    -	return pkt;
    -}
    -
    -/* Convert an integer into our threadref */
    -static void int_to_threadref(threadref * id, const int value)
    -{
    -	unsigned char *scan = (unsigned char *) id;
    -	int i = 4;
    -
    -	while (i--)
    -		*scan++ = 0;
    -
    -	*scan++ = (value >> 24) & 0xff;
    -	*scan++ = (value >> 16) & 0xff;
    -	*scan++ = (value >> 8) & 0xff;
    -	*scan++ = (value & 0xff);
    -}
    -
    -/* Return a task structure ptr for a particular pid */
    -static struct task_struct *get_thread(int pid)
    -{
    -	struct task_struct *thread;
    -
    -	/* Use PID_MAX w/gdb for pid 0 */
    -	if (pid == PID_MAX) pid = 0;
    -
    -	/* First check via PID */
    -	thread = find_task_by_pid(pid);
    -
    -	if (thread)
    -		return thread;
    -
    -	/* Start at the start */
    -	thread = init_tasks[0];
    -
    -	/* Walk along the linked list of tasks */
    -	do {
    -		if (thread->pid == pid)
    -			return thread;
    -		thread = thread->next_task;
    -	} while (thread != init_tasks[0]);
    -
    -	return NULL;
    -}
    -
    -#endif /* CONFIG_KGDB_THREAD */
    -
    -/* Scan for the start char '$', read the packet and check the checksum */
    -static void get_packet(char *buffer, int buflen)
    -{
    -	unsigned char checksum;
    -	unsigned char xmitcsum;
    -	int i;
    -	int count;
    -	char ch;
    -
    -	do {
    -		/* Ignore everything until the start character */
    -		while ((ch = get_debug_char()) != '$');
    -
    -		checksum = 0;
    -		xmitcsum = -1;
    -		count = 0;
    -
    -		/* Now, read until a # or end of buffer is found */
    -		while (count < (buflen - 1)) {
    -			ch = get_debug_char();
    -
    -			if (ch == '#')
    -				break;
    -
    -			checksum = checksum + ch;
    -			buffer[count] = ch;
    -			count = count + 1;
    -		}
    -
    -		buffer[count] = 0;
    -
    -		/* Continue to read checksum following # */
    -		if (ch == '#') {
    -			xmitcsum = hex(get_debug_char()) << 4;
    -			xmitcsum += hex(get_debug_char());
    -
    -			/* Checksum */
    -			if (checksum != xmitcsum)
    -				put_debug_char('-');	/* Failed checksum */
    -			else {
    -				/* Ack successful transfer */
    -				put_debug_char('+');
    -
    -				/* If a sequence char is present, reply 
    -				   the sequence ID */
    -				if (buffer[2] == ':') {
    -					put_debug_char(buffer[0]);
    -					put_debug_char(buffer[1]);
    -
    -					/* Remove sequence chars from buffer */
    -					count = strlen(buffer);
    -					for (i = 3; i <= count; i++)
    -						buffer[i - 3] = buffer[i];
    -				}
    -			}
    -		}
    -	}
    -	while (checksum != xmitcsum);	/* Keep trying while we fail */
    -}
    -
    -/* Send the packet in the buffer with run-length encoding */
    -static void put_packet(char *buffer)
    -{
    -	int checksum;
    -	char *src;
    -	int runlen;
    -	int encode;
    -
    -	do {
    -		src = buffer;
    -		put_debug_char('$');
    -		checksum = 0;
    -
    -		/* Continue while we still have chars left */
    -		while (*src) {
    -			/* Check for runs up to 99 chars long */
    -			for (runlen = 1; runlen < 99; runlen++) {
    -				if (src[0] != src[runlen])
    -					break;
    -			}
    -
    -			if (runlen > 3) {
    -				/* Got a useful amount, send encoding */
    -				encode = runlen + ' ' - 4;
    -				put_debug_char(*src);   checksum += *src;
    -				put_debug_char('*');    checksum += '*';
    -				put_debug_char(encode); checksum += encode;
    -				src += runlen;
    -			} else {
    -				/* Otherwise just send the current char */
    -				put_debug_char(*src);   checksum += *src;
    -				src += 1;
    -			}
    -		}
    -
    -		/* '#' Separator, put high and low components of checksum */
    -		put_debug_char('#');
    -		put_debug_char(highhex(checksum));
    -		put_debug_char(lowhex(checksum));
    -	}
    -	while ((get_debug_char()) != '+');	/* While no ack */
    -}
    -
    -/* A bus error has occurred - perform a longjmp to return execution and
    -   allow handling of the error */
    -static void kgdb_handle_bus_error(void)
    -{
    -	longjmp(rem_com_env, 1);
    -}
    -
    -/* Translate SH-3/4 exception numbers to unix-like signal values */
    -static int compute_signal(const int excep_code)
    -{
    -	int sigval;
    -
    -	switch (excep_code) {
    -
    -	case INVALID_INSN_VEC:
    -	case INVALID_SLOT_VEC:
    -		sigval = SIGILL;
    -		break;
    -	case ADDRESS_ERROR_LOAD_VEC:
    -	case ADDRESS_ERROR_STORE_VEC:
    -		sigval = SIGSEGV;
    -		break;
    -
    -	case SERIAL_BREAK_VEC:
    -	case NMI_VEC:
    -		sigval = SIGINT;
    -		break;
    -
    -	case USER_BREAK_VEC:
    -	case TRAP_VEC:
    -		sigval = SIGTRAP;
    -		break;
    -
    -	default:
    -		sigval = SIGBUS;	/* "software generated" */
    -		break;
    -	}
    -
    -	return (sigval);
    -}
    -
    -/* Make a local copy of the registers passed into the handler (bletch) */
    -static void kgdb_regs_to_gdb_regs(const struct kgdb_regs *regs,
    -				  int *gdb_regs)
    -{
    -	gdb_regs[R0] = regs->regs[R0];
    -	gdb_regs[R1] = regs->regs[R1];
    -	gdb_regs[R2] = regs->regs[R2];
    -	gdb_regs[R3] = regs->regs[R3];
    -	gdb_regs[R4] = regs->regs[R4];
    -	gdb_regs[R5] = regs->regs[R5];
    -	gdb_regs[R6] = regs->regs[R6];
    -	gdb_regs[R7] = regs->regs[R7];
    -	gdb_regs[R8] = regs->regs[R8];
    -	gdb_regs[R9] = regs->regs[R9];
    -	gdb_regs[R10] = regs->regs[R10];
    -	gdb_regs[R11] = regs->regs[R11];
    -	gdb_regs[R12] = regs->regs[R12];
    -	gdb_regs[R13] = regs->regs[R13];
    -	gdb_regs[R14] = regs->regs[R14];
    -	gdb_regs[R15] = regs->regs[R15];
    -	gdb_regs[PC] = regs->pc;
    -	gdb_regs[PR] = regs->pr;
    -	gdb_regs[GBR] = regs->gbr;
    -	gdb_regs[MACH] = regs->mach;
    -	gdb_regs[MACL] = regs->macl;
    -	gdb_regs[SR] = regs->sr;
    -	gdb_regs[VBR] = regs->vbr;
    -}
    -
    -/* Copy local gdb registers back to kgdb regs, for later copy to kernel */
    -static void gdb_regs_to_kgdb_regs(const int *gdb_regs,
    -				  struct kgdb_regs *regs)
    -{
    -	regs->regs[R0] = gdb_regs[R0];
    -	regs->regs[R1] = gdb_regs[R1];
    -	regs->regs[R2] = gdb_regs[R2];
    -	regs->regs[R3] = gdb_regs[R3];
    -	regs->regs[R4] = gdb_regs[R4];
    -	regs->regs[R5] = gdb_regs[R5];
    -	regs->regs[R6] = gdb_regs[R6];
    -	regs->regs[R7] = gdb_regs[R7];
    -	regs->regs[R8] = gdb_regs[R8];
    -	regs->regs[R9] = gdb_regs[R9];
    -	regs->regs[R10] = gdb_regs[R10];
    -	regs->regs[R11] = gdb_regs[R11];
    -	regs->regs[R12] = gdb_regs[R12];
    -	regs->regs[R13] = gdb_regs[R13];
    -	regs->regs[R14] = gdb_regs[R14];
    -	regs->regs[R15] = gdb_regs[R15];
    -	regs->pc = gdb_regs[PC];
    -	regs->pr = gdb_regs[PR];
    -	regs->gbr = gdb_regs[GBR];
    -	regs->mach = gdb_regs[MACH];
    -	regs->macl = gdb_regs[MACL];
    -	regs->sr = gdb_regs[SR];
    -	regs->vbr = gdb_regs[VBR];
    -}
    -
    -#ifdef CONFIG_KGDB_THREAD
    -/* Make a local copy of registers from the specified thread */
    -asmlinkage void ret_from_fork(void);
    -static void thread_regs_to_gdb_regs(const struct task_struct *thread,
    -				    int *gdb_regs)
    -{
    -	int regno;
    -	int *tregs;
    -
    -	/* Initialize to zero */
    -	for (regno = 0; regno < MAXREG; regno++)
    -		gdb_regs[regno] = 0;
    -
    -	/* Just making sure... */
    -	if (thread == NULL)
    -		return;
    -
    -	/* A new fork has pt_regs on the stack from a fork() call */
    -	if (thread->thread.pc == (unsigned long)ret_from_fork) {
    -
    -		int vbr_val;
    -		struct pt_regs *kregs;
    -		kregs = (struct pt_regs*)thread->thread.sp;
    -
    -		gdb_regs[R0] = kregs->regs[R0];
    -		gdb_regs[R1] = kregs->regs[R1];
    -		gdb_regs[R2] = kregs->regs[R2];
    -		gdb_regs[R3] = kregs->regs[R3];
    -		gdb_regs[R4] = kregs->regs[R4];
    -		gdb_regs[R5] = kregs->regs[R5];
    -		gdb_regs[R6] = kregs->regs[R6];
    -		gdb_regs[R7] = kregs->regs[R7];
    -		gdb_regs[R8] = kregs->regs[R8];
    -		gdb_regs[R9] = kregs->regs[R9];
    -		gdb_regs[R10] = kregs->regs[R10];
    -		gdb_regs[R11] = kregs->regs[R11];
    -		gdb_regs[R12] = kregs->regs[R12];
    -		gdb_regs[R13] = kregs->regs[R13];
    -		gdb_regs[R14] = kregs->regs[R14];
    -		gdb_regs[R15] = kregs->regs[R15];
    -		gdb_regs[PC] = kregs->pc;
    -		gdb_regs[PR] = kregs->pr;
    -		gdb_regs[GBR] = kregs->gbr;
    -		gdb_regs[MACH] = kregs->mach;
    -		gdb_regs[MACL] = kregs->macl;
    -		gdb_regs[SR] = kregs->sr;
    -
    -		asm("stc vbr, %0":"=r"(vbr_val));
    -		gdb_regs[VBR] = vbr_val;
    -		return;
    -	}
    -
    -	/* Otherwise, we have only some registers from switch_to() */
    -	tregs = (int *)thread->thread.sp;
    -	gdb_regs[R15] = (int)tregs;
    -	gdb_regs[R14] = *tregs++;
    -	gdb_regs[R13] = *tregs++;
    -	gdb_regs[R12] = *tregs++;
    -	gdb_regs[R11] = *tregs++;
    -	gdb_regs[R10] = *tregs++;
    -	gdb_regs[R9] = *tregs++;
    -	gdb_regs[R8] = *tregs++;
    -	gdb_regs[PR] = *tregs++;
    -	gdb_regs[GBR] = *tregs++;
    -	gdb_regs[PC] = thread->thread.pc;
    -}
    -#endif /* CONFIG_KGDB_THREAD */
    -
    -/* Calculate the new address for after a step */
    -static short *get_step_address(void)
    -{
    -	short op = *(short *) trap_registers.pc;
    -	long addr;
    -
    -	/* BT */
    -	if (OPCODE_BT(op)) {
    -		if (trap_registers.sr & SR_T_BIT_MASK)
    -			addr = trap_registers.pc + 4 + OPCODE_BTF_DISP(op);
    -		else
    -			addr = trap_registers.pc + 2;
    -	}
    -
    -	/* BTS */
    -	else if (OPCODE_BTS(op)) {
    -		if (trap_registers.sr & SR_T_BIT_MASK)
    -			addr = trap_registers.pc + 4 + OPCODE_BTF_DISP(op);
    -		else
    -			addr = trap_registers.pc + 4;	/* Not in delay slot */
    -	}
    -
    -	/* BF */
    -	else if (OPCODE_BF(op)) {
    -		if (!(trap_registers.sr & SR_T_BIT_MASK))
    -			addr = trap_registers.pc + 4 + OPCODE_BTF_DISP(op);
    -		else
    -			addr = trap_registers.pc + 2;
    -	}
    -
    -	/* BFS */
    -	else if (OPCODE_BFS(op)) {
    -		if (!(trap_registers.sr & SR_T_BIT_MASK))
    -			addr = trap_registers.pc + 4 + OPCODE_BTF_DISP(op);
    -		else
    -			addr = trap_registers.pc + 4;	/* Not in delay slot */
    -	}
    -
    -	/* BRA */
    -	else if (OPCODE_BRA(op))
    -		addr = trap_registers.pc + 4 + OPCODE_BRA_DISP(op);
    -
    -	/* BRAF */
    -	else if (OPCODE_BRAF(op))
    -		addr = trap_registers.pc + 4
    -		    + trap_registers.regs[OPCODE_BRAF_REG(op)];
    -
    -	/* BSR */
    -	else if (OPCODE_BSR(op))
    -		addr = trap_registers.pc + 4 + OPCODE_BSR_DISP(op);
    -
    -	/* BSRF */
    -	else if (OPCODE_BSRF(op))
    -		addr = trap_registers.pc + 4
    -		    + trap_registers.regs[OPCODE_BSRF_REG(op)];
    -
    -	/* JMP */
    -	else if (OPCODE_JMP(op))
    -		addr = trap_registers.regs[OPCODE_JMP_REG(op)];
    -
    -	/* JSR */
    -	else if (OPCODE_JSR(op))
    -		addr = trap_registers.regs[OPCODE_JSR_REG(op)];
    -
    -	/* RTS */
    -	else if (OPCODE_RTS(op))
    -		addr = trap_registers.pr;
    -
    -	/* RTE */
    -	else if (OPCODE_RTE(op))
    -		addr = trap_registers.regs[15];
    -
    -	/* Other */
    -	else
    -		addr = trap_registers.pc + 2;
    -
    -	kgdb_flush_icache_range(addr, addr + 2);
    -	return (short *) addr;
    -}
    -
    -/* Set up a single-step.  Replace the instruction immediately after the 
    -   current instruction (i.e. next in the expected flow of control) with a
    -   trap instruction, so that returning will cause only a single instruction
    -   to be executed. Note that this model is slightly broken for instructions
    -   with delay slots (e.g. B[TF]S, BSR, BRA etc), where both the branch
    -   and the instruction in the delay slot will be executed. */
    -static void do_single_step(void)
    -{
    -	unsigned short *addr = 0;
    -
    -	/* Determine where the target instruction will send us to */
    -	addr = get_step_address();
    -	stepped_address = (int)addr;
    -
    -	/* Replace it */
    -	stepped_opcode = *(short *)addr;
    -	*addr = STEP_OPCODE;
    -
    -	/* Flush and return */
    -	kgdb_flush_icache_range((long) addr, (long) addr + 2);
    -	return;
    -}
    -
    -/* Undo a single step */
    -static void undo_single_step(void)
    -{
    -	/* If we have stepped, put back the old instruction */
    -	/* Use stepped_address in case we stopped elsewhere */
    -	if (stepped_opcode != 0) {
    -		*(short*)stepped_address = stepped_opcode;
    -		kgdb_flush_icache_range(stepped_address, stepped_address + 2);
    -	}
    -	stepped_opcode = 0;
    -}
    -
    -/* Send a signal message */
    -static void send_signal_msg(const int signum)
    -{
    -#ifndef CONFIG_KGDB_THREAD
    -	out_buffer[0] = 'S';
    -	out_buffer[1] = highhex(signum);
    -	out_buffer[2] = lowhex(signum);
    -	out_buffer[3] = 0;
    -	put_packet(out_buffer);
    -#else /* CONFIG_KGDB_THREAD */
    -	int threadid;
    -	threadref thref;
    -	char *out = out_buffer;
    -	const char *tstring = "thread";
    -
    -	*out++ = 'T';
    -	*out++ = highhex(signum);
    -	*out++ = lowhex(signum);
    -
    -	while (*tstring) {
    -		*out++ = *tstring++;
    -	}
    -	*out++ = ':';
    -
    -	threadid = trapped_thread->pid;
    -	if (threadid == 0) threadid = PID_MAX;
    -	int_to_threadref(&thref, threadid);
    -	pack_threadid(out, &thref);
    -	out += BUF_THREAD_ID_SIZE;
    -	*out++ = ';';
    -
    -	*out = 0;
    -	put_packet(out_buffer);
    -#endif /* CONFIG_KGDB_THREAD */
    -}
    -
    -/* Reply that all was well */
    -static void send_ok_msg(void)
    -{
    -	strcpy(out_buffer, "OK");
    -	put_packet(out_buffer);
    -}
    -
    -/* Reply that an error occurred */
    -static void send_err_msg(void)
    -{
    -	strcpy(out_buffer, "E01");
    -	put_packet(out_buffer);
    -}
    -
    -/* Empty message indicates unrecognised command */
    -static void send_empty_msg(void)
    -{
    -	put_packet("");
    -}
    -
    -/* Read memory due to 'm' message */
    -static void read_mem_msg(void)
    -{
    -	char *ptr;
    -	int addr;
    -	int length;
    -
    -	/* Jmp, disable bus error handler */
    -	if (setjmp(rem_com_env) == 0) {
    -
    -		kgdb_nofault = 1;
    -
    -		/* Walk through, have m<addr>,<length> */
    -		ptr = &in_buffer[1];
    -		if (hex_to_int(&ptr, &addr) && (*ptr++ == ','))
    -			if (hex_to_int(&ptr, &length)) {
    -				ptr = 0;
    -				if (length * 2 > OUTBUFMAX)
    -					length = OUTBUFMAX / 2;
    -				mem_to_hex((char *) addr, out_buffer, length);
    -			}
    -		if (ptr)
    -			send_err_msg();
    -		else
    -			put_packet(out_buffer);
    -	} else
    -		send_err_msg();
    -
    -	/* Restore bus error handler */
    -	kgdb_nofault = 0;
    -}
    -
    -/* Write memory due to 'M' or 'X' message */
    -static void write_mem_msg(int binary)
    -{
    -	char *ptr;
    -	int addr;
    -	int length;
    -
    -	if (setjmp(rem_com_env) == 0) {
    -
    -		kgdb_nofault = 1;
    -
    -		/* Walk through, have M<addr>,<length>:<data> */
    -		ptr = &in_buffer[1];
    -		if (hex_to_int(&ptr, &addr) && (*ptr++ == ','))
    -			if (hex_to_int(&ptr, &length) && (*ptr++ == ':')) {
    -				if (binary)
    -					ebin_to_mem(ptr, (char*)addr, length);
    -				else
    -					hex_to_mem(ptr, (char*)addr, length);
    -				kgdb_flush_icache_range(addr, addr + length);
    -				ptr = 0;
    -				send_ok_msg();
    -			}
    -		if (ptr)
    -			send_err_msg();
    -	} else
    -		send_err_msg();
    -
    -	/* Restore bus error handler */
    -	kgdb_nofault = 0;
    -}
    -
    -/* Continue message  */
    -static void continue_msg(void)
    -{
    -	/* Try to read optional parameter, PC unchanged if none */
    -	char *ptr = &in_buffer[1];
    -	int addr;
    -
    -	if (hex_to_int(&ptr, &addr))
    -		trap_registers.pc = addr;
    -}
    -
    -/* Continue message with signal */
    -static void continue_with_sig_msg(void)
    -{
    -	int signal;
    -	char *ptr = &in_buffer[1];
    -	int addr;
    -
    -	/* Report limitation */
    -	kgdb_to_gdb("Cannot force signal in kgdb, continuing anyway.\n");
    -
    -	/* Signal */
    -	hex_to_int(&ptr, &signal);
    -	if (*ptr == ';')
    -		ptr++;
    -
    -	/* Optional address */
    -	if (hex_to_int(&ptr, &addr))
    -		trap_registers.pc = addr;
    -}
    -
    -/* Step message */
    -static void step_msg(void)
    -{
    -	continue_msg();
    -	do_single_step();
    -}
    -
    -/* Step message with signal */
    -static void step_with_sig_msg(void)
    -{
    -	continue_with_sig_msg();
    -	do_single_step();
    -}
    -
    -/* Send register contents */
    -static void send_regs_msg(void)
    -{
    -#ifdef CONFIG_KGDB_THREAD
    -	if (!current_thread)
    -		kgdb_regs_to_gdb_regs(&trap_registers, registers);
    -	else
    -		thread_regs_to_gdb_regs(current_thread, registers);
    -#else
    -	kgdb_regs_to_gdb_regs(&trap_registers, registers);
    -#endif
    -
    -	mem_to_hex((char *) registers, out_buffer, NUMREGBYTES);
    -	put_packet(out_buffer);
    -}
    -
    -/* Set register contents - currently can't set other thread's registers */
    -static void set_regs_msg(void)
    -{
    -#ifdef CONFIG_KGDB_THREAD
    -	if (!current_thread) {
    -#endif
    -		kgdb_regs_to_gdb_regs(&trap_registers, registers);
    -		hex_to_mem(&in_buffer[1], (char *) registers, NUMREGBYTES);
    -		gdb_regs_to_kgdb_regs(registers, &trap_registers);
    -		send_ok_msg();
    -#ifdef CONFIG_KGDB_THREAD
    -	} else
    -		send_err_msg();
    -#endif
    -}
    -
    -
    -#ifdef CONFIG_KGDB_THREAD
    -
    -/* Set the status for a thread */
    -void set_thread_msg(void)
    -{
    -	int threadid;
    -	struct task_struct *thread = NULL;
    -	char *ptr;
    -
    -	switch (in_buffer[1]) {
    -
    -       	/* To select which thread for gG etc messages, i.e. supported */
    -	case 'g':
    -
    -		ptr = &in_buffer[2];
    -		hex_to_int(&ptr, &threadid);
    -		thread = get_thread(threadid);
    -
    -		/* If we haven't found it */
    -		if (!thread) {
    -			send_err_msg();
    -			break;
    -		}
    -
    -		/* Set current_thread (or not) */
    -		if (thread == trapped_thread)
    -			current_thread = NULL;
    -		else
    -			current_thread = thread;
    -		send_ok_msg();
    -		break;
    -
    -	/* To select which thread for cCsS messages, i.e. unsupported */
    -	case 'c':
    -		send_ok_msg();
    -		break;
    -
    -	default:
    -		send_empty_msg();
    -		break;
    -	}
    -}
    -
    -/* Is a thread alive? */
    -static void thread_status_msg(void)
    -{
    -	char *ptr;
    -	int threadid;
    -	struct task_struct *thread = NULL;
    -
    -	ptr = &in_buffer[1];
    -	hex_to_int(&ptr, &threadid);
    -	thread = get_thread(threadid);
    -	if (thread)
    -		send_ok_msg();
    -	else
    -		send_err_msg();
    -}
    -/* Send the current thread ID */
    -static void thread_id_msg(void)
    -{
    -	int threadid;
    -	threadref thref;
    -
    -	out_buffer[0] = 'Q';
    -	out_buffer[1] = 'C';
    -
    -	if (current_thread)
    -		threadid = current_thread->pid;
    -	else if (trapped_thread)
    -		threadid = trapped_thread->pid;
    -	else /* Impossible, but just in case! */
    -	{
    -		send_err_msg();
    -		return;
    -	}
    -
    -	/* Translate pid 0 to PID_MAX for gdb */
    -	if (threadid == 0) threadid = PID_MAX;
    -
    -	int_to_threadref(&thref, threadid);
    -	pack_threadid(out_buffer + 2, &thref);
    -	out_buffer[2 + BUF_THREAD_ID_SIZE] = '\0';
    -	put_packet(out_buffer);
    -}
    -
    -/* Send thread info */
    -static void thread_info_msg(void)
    -{
    -	struct task_struct *thread = NULL;
    -	int threadid;
    -	char *pos;
    -	threadref thref;
    -
    -	/* Start with 'm' */
    -	out_buffer[0] = 'm';
    -	pos = &out_buffer[1];
    -
    -	/* For all possible thread IDs - this will overrun if > 44 threads! */
    -	/* Start at 1 and include PID_MAX (since GDB won't use pid 0...) */
    -	for (threadid = 1; threadid <= PID_MAX; threadid++) {
    -
    -		read_lock(&tasklist_lock);
    -		thread = get_thread(threadid);
    -		read_unlock(&tasklist_lock);
    -
    -		/* If it's a valid thread */
    -		if (thread) {
    -			int_to_threadref(&thref, threadid);
    -			pack_threadid(pos, &thref);
    -			pos += BUF_THREAD_ID_SIZE;
    -			*pos++ = ',';
    -		}
    -	}
    -	*--pos = 0;		/* Lose final comma */
    -	put_packet(out_buffer);
    -
    -}
    -
    -/* Return printable info for gdb's 'info threads' command */
    -static void thread_extra_info_msg(void)
    -{
    -	int threadid;
    -	struct task_struct *thread = NULL;
    -	char buffer[20], *ptr;
    -	int i;
    -
    -	/* Extract thread ID */
    -	ptr = &in_buffer[17];
    -	hex_to_int(&ptr, &threadid);
    -	thread = get_thread(threadid);
    -
    -	/* If we don't recognise it, say so */
    -	if (thread == NULL)
    -		strcpy(buffer, "(unknown)");
    -	else
    -		strcpy(buffer, thread->comm);
    -
    -	/* Construct packet */
    -	for (i = 0, ptr = out_buffer; buffer[i]; i++)
    -		ptr = pack_hex_byte(ptr, buffer[i]);
    -
    -	if (thread->thread.pc == (unsigned long)ret_from_fork) {
    -		strcpy(buffer, "<new fork>");
    -		for (i = 0; buffer[i]; i++)
    -			ptr = pack_hex_byte(ptr, buffer[i]);
    -	}
    -
    -	*ptr = '\0';
    -	put_packet(out_buffer);
    -}
    -
    -/* Handle all qFooBarBaz messages - have to use an if statement as
    -   opposed to a switch because q messages can have > 1 char id. */
    -static void query_msg(void)
    -{
    -	const char *q_start = &in_buffer[1];
    -
    -	/* qC = return current thread ID */
    -	if (strncmp(q_start, "C", 1) == 0)
    -		thread_id_msg();
    -
    -	/* qfThreadInfo = query all threads (first) */
    -	else if (strncmp(q_start, "fThreadInfo", 11) == 0)
    -		thread_info_msg();
    -
    -	/* qsThreadInfo = query all threads (subsequent). We know we have sent
    -	   them all after the qfThreadInfo message, so there are no to send */
    -	else if (strncmp(q_start, "sThreadInfo", 11) == 0)
    -		put_packet("l");	/* el = last */
    -
    -	/* qThreadExtraInfo = supply printable information per thread */
    -	else if (strncmp(q_start, "ThreadExtraInfo", 15) == 0)
    -		thread_extra_info_msg();
    -
    -	/* Unsupported - empty message as per spec */
    -	else
    -		send_empty_msg();
    -}
    -#endif /* CONFIG_KGDB_THREAD */
    -
    -/*
    - * Bring up the ports..
    - */
    -static int kgdb_serial_setup(void)
    -{
    -	extern int kgdb_console_setup(struct console *co, char *options);
    -	struct console dummy;
    -
    -	kgdb_console_setup(&dummy, 0);
    -
    -	return 0;
    -}
    -
    -/* The command loop, read and act on requests */
    -static void kgdb_command_loop(const int excep_code, const int trapa_value)
    -{
    -	int sigval;
    -
    -	if (excep_code == NMI_VEC) {
    -#ifndef CONFIG_KGDB_NMI
    -		KGDB_PRINTK("Ignoring unexpected NMI?\n");
    -		return;
    -#else /* CONFIG_KGDB_NMI */
    -		if (!kgdb_enabled) {
    -			kgdb_enabled = 1;
    -			kgdb_init();
    -		}
    -#endif /* CONFIG_KGDB_NMI */
    -	}
    -
    -	/* Ignore if we're disabled */
    -	if (!kgdb_enabled)
    -		return;
    -
    -#ifdef CONFIG_KGDB_THREAD
    -	/* Until GDB specifies a thread */
    -	current_thread = NULL;
    -	trapped_thread = current;
    -#endif
    -
    -	/* Enter GDB mode (e.g. after detach) */
    -	if (!kgdb_in_gdb_mode) {
    -		/* Do serial setup, notify user, issue preemptive ack */
    -		kgdb_serial_setup();
    -		KGDB_PRINTK("Waiting for GDB (on %s%d at %d baud)\n",
    -			    (kgdb_porttype ? kgdb_porttype->name : ""),
    -			    kgdb_portnum, kgdb_baud);
    -		kgdb_in_gdb_mode = 1;
    -		put_debug_char('+');
    -	}
    -
    -	/* Reply to host that an exception has occurred */
    -	sigval = compute_signal(excep_code);
    -	send_signal_msg(sigval);
    -
    -	/* TRAP_VEC exception indicates a software trap inserted in place of
    -	   code by GDB so back up PC by one instruction, as this instruction
    -	   will later be replaced by its original one.  Do NOT do this for
    -	   trap 0xff, since that indicates a compiled-in breakpoint which
    -	   will not be replaced (and we would retake the trap forever) */
    -	if ((excep_code == TRAP_VEC) && (trapa_value != (0xff << 2))) {
    -		trap_registers.pc -= 2;
    -	}
    -
    -	/* Undo any stepping we may have done */
    -	undo_single_step();
    -
    -	while (1) {
    -
    -		out_buffer[0] = 0;
    -		get_packet(in_buffer, BUFMAX);
    -
    -		/* Examine first char of buffer to see what we need to do */
    -		switch (in_buffer[0]) {
    -
    -		case '?':	/* Send which signal we've received */
    -			send_signal_msg(sigval);
    -			break;
    -
    -		case 'g':	/* Return the values of the CPU registers */
    -			send_regs_msg();
    -			break;
    -
    -		case 'G':	/* Set the value of the CPU registers */
    -			set_regs_msg();
    -			break;
    -
    -		case 'm':	/* Read LLLL bytes address AA..AA */
    -			read_mem_msg();
    -			break;
    -
    -		case 'M':	/* Write LLLL bytes address AA..AA, ret OK */
    -			write_mem_msg(0);	/* 0 = data in hex */
    -			break;
    -
    -		case 'X':	/* Write LLLL bytes esc bin address AA..AA */
    -			if (kgdb_bits == '8')
    -				write_mem_msg(1); /* 1 = data in binary */
    -			else
    -				send_empty_msg();
    -			break;
    -
    -		case 'C':	/* Continue, signum included, we ignore it */
    -			continue_with_sig_msg();
    -			return;
    -
    -		case 'c':	/* Continue at address AA..AA (optional) */
    -			continue_msg();
    -			return;
    -
    -		case 'S':	/* Step, signum included, we ignore it */
    -			step_with_sig_msg();
    -			return;
    -
    -		case 's':	/* Step one instruction from AA..AA */
    -			step_msg();
    -			return;
    -
    -#ifdef CONFIG_KGDB_THREAD
    -
    -		case 'H':	/* Task related */
    -			set_thread_msg();
    -			break;
    -
    -		case 'T':	/* Query thread status */
    -			thread_status_msg();
    -			break;
    -
    -		case 'q':	/* Handle query - currently thread-related */
    -			query_msg();
    -			break;
    -#endif
    -
    -		case 'k':	/* 'Kill the program' with a kernel ? */
    -			break;
    -
    -		case 'D':	/* Detach from program, send reply OK */
    -			kgdb_in_gdb_mode = 0;
    -			send_ok_msg();
    -			get_debug_char();
    -			return;
    -
    -		default:
    -			send_empty_msg();
    -			break;
    -		}
    -	}
    -}
    -
    -/* There has been an exception, most likely a breakpoint. */
    -void kgdb_handle_exception(struct pt_regs *regs)
    -{
    -	int excep_code, vbr_val;
    -	int count;
    -	int trapa_value = ctrl_inl(TRA);
    -
    -	/* Copy kernel regs (from stack) */
    -	for (count = 0; count < 16; count++)
    -		trap_registers.regs[count] = regs->regs[count];
    -	trap_registers.pc = regs->pc;
    -	trap_registers.pr = regs->pr;
    -	trap_registers.sr = regs->sr;
    -	trap_registers.gbr = regs->gbr;
    -	trap_registers.mach = regs->mach;
    -	trap_registers.macl = regs->macl;
    -
    -	asm("stc vbr, %0":"=r"(vbr_val));
    -	trap_registers.vbr = vbr_val;
    -
    -	/* Get excode for command loop call, user access */
    -	asm("stc r2_bank, %0":"=r"(excep_code));
    -	kgdb_excode = excep_code;
    -
    -	/* Other interesting environment items for reference */
    -	asm("stc r6_bank, %0":"=r"(kgdb_g_imask));
    -	kgdb_current = current;
    -	kgdb_trapa_val = trapa_value;
    -
    -	/* Act on the exception */
    -	kgdb_command_loop(excep_code >> 5, trapa_value);
    -
    -	kgdb_current = NULL;
    -
    -	/* Copy back the (maybe modified) registers */
    -	for (count = 0; count < 16; count++)
    -		regs->regs[count] = trap_registers.regs[count];
    -	regs->pc = trap_registers.pc;
    -	regs->pr = trap_registers.pr;
    -	regs->sr = trap_registers.sr;
    -	regs->gbr = trap_registers.gbr;
    -	regs->mach = trap_registers.mach;
    -	regs->macl = trap_registers.macl;
    -
    -	vbr_val = trap_registers.vbr;
    -	asm("ldc %0, vbr": :"r"(vbr_val));
    -
    -	return;
    -}
    -
    -/* Trigger a breakpoint by function */
    -void breakpoint(void)
    -{
    -	if (!kgdb_enabled) {
    -		kgdb_enabled = 1;
    -		kgdb_init();
    -	}
    -	BREAKPOINT();
    -}
    -
    -/* Initialise the KGDB data structures and serial configuration */
    -int kgdb_init(void)
    -{
    -	if (!kgdb_enabled)
    -		return 1;
    -
    -	in_nmi = 0;
    -	kgdb_nofault = 0;
    -	stepped_opcode = 0;
    -	kgdb_in_gdb_mode = 0;
    -
    -	if (kgdb_serial_setup() != 0) {
    -		KGDB_PRINTK("serial setup error\n");
    -		return -1;
    -	}
    -
    -	/* Init ptr to exception handler */
    -	kgdb_debug_hook = kgdb_handle_exception;
    -	kgdb_bus_err_hook = kgdb_handle_bus_error;
    -
    -	/* Enter kgdb now if requested, or just report init done */
    -	if (kgdb_halt) {
    -		kgdb_in_gdb_mode = 1;
    -		put_debug_char('+');
    -		breakpoint();
    -	}
    -	else
    -	{
    -		KGDB_PRINTK("stub is initialized.\n");
    -	}
    -
    -	return 0;
    -}
    -
    -/* Make function available for "user messages"; console will use it too. */
    -
    -char gdbmsgbuf[BUFMAX];
    -#define MAXOUT ((BUFMAX-2)/2)
    -
    -static void kgdb_msg_write(const char *s, unsigned count)
    -{
    -	int i;
    -	int wcount;
    -	char *bufptr;
    -
    -	/* 'O'utput */
    -	gdbmsgbuf[0] = 'O';
    -
    -	/* Fill and send buffers... */
    -	while (count > 0) {
    -		bufptr = gdbmsgbuf + 1;
    -
    -		/* Calculate how many this time */
    -		wcount = (count > MAXOUT) ? MAXOUT : count;
    -		
    -		/* Pack in hex chars */
    -		for (i = 0; i < wcount; i++)
    -			bufptr = pack_hex_byte(bufptr, s[i]);
    -		*bufptr = '\0';
    -
    -		/* Move up */
    -		s += wcount;
    -		count -= wcount;
    -
    -		/* Write packet */
    -		put_packet(gdbmsgbuf);
    -	}
    -}
    -
    -static void kgdb_to_gdb(const char *s)
    -{
    -	kgdb_msg_write(s, strlen(s));
    -}
    -
    -#ifdef CONFIG_SH_KGDB_CONSOLE
    -void kgdb_console_write(struct console *co, const char *s, unsigned count)
    -{
    -	/* Bail if we're not talking to GDB */
    -	if (!kgdb_in_gdb_mode)
    -		return;
    -
    -	kgdb_msg_write(s, count);
    -}
    -#endif
    diff -puN arch/sh/kernel/Makefile~sh-lite arch/sh/kernel/Makefile
    --- linux-2.6.13-rc3/arch/sh/kernel/Makefile~sh-lite	2005-07-29 11:55:32.000000000 -0700
    +++ linux-2.6.13-rc3-trini/arch/sh/kernel/Makefile	2005-07-29 11:55:32.000000000 -0700
    @@ -13,7 +13,7 @@ obj-y				+= cpu/
     obj-$(CONFIG_SMP)		+= smp.o
     obj-$(CONFIG_CF_ENABLER)	+= cf-enabler.o
     obj-$(CONFIG_SH_STANDARD_BIOS)	+= sh_bios.o
    -obj-$(CONFIG_SH_KGDB)		+= kgdb_stub.o kgdb_jmp.o
    +obj-$(CONFIG_KGDB)		+= kgdb.o kgdb-jmp.o
     obj-$(CONFIG_SH_CPU_FREQ)	+= cpufreq.o
     obj-$(CONFIG_MODULES)		+= module.o
     obj-$(CONFIG_EARLY_PRINTK)	+= early_printk.o
    diff -puN arch/sh/kernel/setup.c~sh-lite arch/sh/kernel/setup.c
    --- linux-2.6.13-rc3/arch/sh/kernel/setup.c~sh-lite	2005-07-29 11:55:32.000000000 -0700
    +++ linux-2.6.13-rc3-trini/arch/sh/kernel/setup.c	2005-07-29 11:55:32.000000000 -0700
    @@ -27,10 +27,6 @@
     #include <asm/irq.h>
     #include <asm/setup.h>
     
    -#ifdef CONFIG_SH_KGDB
    -#include <asm/kgdb.h>
    -static int kgdb_parse_options(char *options);
    -#endif
     extern void * __rd_start, * __rd_end;
     /*
      * Machine setup..
    @@ -557,93 +553,3 @@ struct seq_operations cpuinfo_op = {
     	.show	= show_cpuinfo,
     };
     #endif /* CONFIG_PROC_FS */
    -
    -#ifdef CONFIG_SH_KGDB
    -/*
    - * Parse command-line kgdb options.  By default KGDB is enabled,
    - * entered on error (or other action) using default serial info.
    - * The command-line option can include a serial port specification
    - * and an action to override default or configured behavior.
    - */
    -struct kgdb_sermap kgdb_sci_sermap =
    -{ "ttySC", 5, kgdb_sci_setup, NULL };
    -
    -struct kgdb_sermap *kgdb_serlist = &kgdb_sci_sermap;
    -struct kgdb_sermap *kgdb_porttype = &kgdb_sci_sermap;
    -
    -void kgdb_register_sermap(struct kgdb_sermap *map)
    -{
    -	struct kgdb_sermap *last;
    -
    -	for (last = kgdb_serlist; last->next; last = last->next)
    -		;
    -	last->next = map;
    -	if (!map->namelen) {
    -		map->namelen = strlen(map->name);
    -	}
    -}
    -
    -static int __init kgdb_parse_options(char *options)
    -{
    -	char c;
    -	int baud;
    -
    -	/* Check for port spec (or use default) */
    -
    -	/* Determine port type and instance */
    -	if (!memcmp(options, "tty", 3)) {
    -		struct kgdb_sermap *map = kgdb_serlist;
    -
    -		while (map && memcmp(options, map->name, map->namelen))
    -			map = map->next;
    -
    -		if (!map) {
    -			KGDB_PRINTK("unknown port spec in %s\n", options);
    -			return -1;
    -		}
    -
    -		kgdb_porttype = map;
    -		kgdb_serial_setup = map->setup_fn;
    -		kgdb_portnum = options[map->namelen] - '0';
    -		options += map->namelen + 1;
    -
    -		options = (*options == ',') ? options+1 : options;
    -		
    -		/* Read optional parameters (baud/parity/bits) */
    -		baud = simple_strtoul(options, &options, 10);
    -		if (baud != 0) {
    -			kgdb_baud = baud;
    -
    -			c = toupper(*options);
    -			if (c == 'E' || c == 'O' || c == 'N') {
    -				kgdb_parity = c;
    -				options++;
    -			}
    -
    -			c = *options;
    -			if (c == '7' || c == '8') {
    -				kgdb_bits = c;
    -				options++;
    -			}
    -			options = (*options == ',') ? options+1 : options;
    -		}
    -	}
    -
    -	/* Check for action specification */
    -	if (!memcmp(options, "halt", 4)) {
    -		kgdb_halt = 1;
    -		options += 4;
    -	} else if (!memcmp(options, "disabled", 8)) {
    -		kgdb_enabled = 0;
    -		options += 8;
    -	}
    -
    -	if (*options) {
    -                KGDB_PRINTK("ignored unknown options: %s\n", options);
    -		return 0;
    -	}
    -	return 1;
    -}
    -__setup("kgdb=", kgdb_parse_options);
    -#endif /* CONFIG_SH_KGDB */
    -
    diff -puN arch/sh/kernel/time.c~sh-lite arch/sh/kernel/time.c
    --- linux-2.6.13-rc3/arch/sh/kernel/time.c~sh-lite	2005-07-29 11:55:32.000000000 -0700
    +++ linux-2.6.13-rc3-trini/arch/sh/kernel/time.c	2005-07-29 11:55:32.000000000 -0700
    @@ -34,9 +34,6 @@
     #include <asm/rtc.h>
     #include <asm/freq.h>
     #include <asm/cpu/timer.h>
    -#ifdef CONFIG_SH_KGDB
    -#include <asm/kgdb.h>
    -#endif
     
     #include <linux/timex.h>
     #include <linux/irq.h>
    @@ -646,12 +643,4 @@ void __init time_init(void)
     	ctrl_outl(interval, TMU0_TCOR);
     	ctrl_outl(interval, TMU0_TCNT);
     	ctrl_outb(TMU_TSTR_INIT, TMU_TSTR);
    -
    -#if defined(CONFIG_SH_KGDB)
    -	/*
    -	 * Set up kgdb as requested. We do it here because the serial
    -	 * init uses the timer vars we just set up for figuring baud.
    -	 */
    -	kgdb_init();
    -#endif
     }
    diff -puN arch/sh/kernel/traps.c~sh-lite arch/sh/kernel/traps.c
    --- linux-2.6.13-rc3/arch/sh/kernel/traps.c~sh-lite	2005-07-29 11:55:32.000000000 -0700
    +++ linux-2.6.13-rc3-trini/arch/sh/kernel/traps.c	2005-07-29 11:55:32.000000000 -0700
    @@ -27,6 +27,7 @@
     #include <linux/spinlock.h>
     #include <linux/module.h>
     #include <linux/kallsyms.h>
    +#include <linux/kgdb.h>
     
     #include <asm/system.h>
     #include <asm/uaccess.h>
    @@ -35,17 +36,8 @@
     #include <asm/processor.h>
     #include <asm/sections.h>
     
    -#ifdef CONFIG_SH_KGDB
    -#include <asm/kgdb.h>
    -#define CHK_REMOTE_DEBUG(regs)                                               \
    -{                                                                            \
    -  if ((kgdb_debug_hook != (kgdb_debug_hook_t *) NULL) && (!user_mode(regs))) \
    -  {                                                                          \
    -    (*kgdb_debug_hook)(regs);                                                \
    -  }                                                                          \
    -}
    -#else
    -#define CHK_REMOTE_DEBUG(regs)
    +#ifndef CONFIG_KGDB
    +#define kgdb_handle_exception(t, s, e, r)
     #endif
     
     #define DO_ERROR(trapnr, signr, str, name, tsk)				\
    @@ -66,7 +58,7 @@ asmlinkage void do_##name(unsigned long 
     	local_irq_enable();						\
     	tsk->thread.error_code = error_code;				\
     	tsk->thread.trap_no = trapnr;					\
    -        CHK_REMOTE_DEBUG(&regs);					\
    +	kgdb_handle_exception(trapnr, signr, error_code, &regs);	\
     	force_sig(signr, tsk);						\
     	die_if_no_fixup(str,&regs,error_code);				\
     }
    @@ -93,10 +85,12 @@ void die(const char * str, struct pt_reg
     {
     	static int die_counter;
     
    +#ifdef CONFIG_KGDB
    +	kgdb_handle_exception(1, SIGTRAP, err, regs);
    +#endif
     	console_verbose();
     	spin_lock_irq(&die_lock);
     	printk("%s: %04lx [#%d]\n", str, err & 0xffff, ++die_counter);
    -	CHK_REMOTE_DEBUG(regs);
     	show_regs(regs);
     	spin_unlock_irq(&die_lock);
     	do_exit(SIGSEGV);
    diff -puN arch/sh/Makefile~sh-lite arch/sh/Makefile
    --- linux-2.6.13-rc3/arch/sh/Makefile~sh-lite	2005-07-29 11:55:32.000000000 -0700
    +++ linux-2.6.13-rc3-trini/arch/sh/Makefile	2005-07-29 11:55:32.000000000 -0700
    @@ -23,7 +23,6 @@ cflags-$(CONFIG_CPU_SH4)		+= -m4 \
     	$(call cc-option,-mno-implicit-fp,-m4-nofpu)
     
     cflags-$(CONFIG_SH_DSP)			+= -Wa,-dsp
    -cflags-$(CONFIG_SH_KGDB)		+= -g
     
     cflags-$(CONFIG_MORE_COMPILE_OPTIONS)	+= \
     	$(shell echo $(CONFIG_COMPILE_OPTIONS) | sed -e 's/"//g')
    diff -puN arch/sh/mm/extable.c~sh-lite arch/sh/mm/extable.c
    --- linux-2.6.13-rc3/arch/sh/mm/extable.c~sh-lite	2005-07-29 11:55:32.000000000 -0700
    +++ linux-2.6.13-rc3-trini/arch/sh/mm/extable.c	2005-07-29 11:55:32.000000000 -0700
    @@ -6,6 +6,7 @@
     
     #include <linux/config.h>
     #include <linux/module.h>
    +#include <linux/kgdb.h>
     #include <asm/uaccess.h>
     
     int fixup_exception(struct pt_regs *regs)
    @@ -17,6 +18,12 @@ int fixup_exception(struct pt_regs *regs
     		regs->pc = fixup->fixup;
     		return 1;
     	}
    +#ifdef CONFIG_KGDB
    +	if (atomic_read(&debugger_active) && kgdb_may_fault)
    +		/* Restore our previous state. */
    +		kgdb_fault_longjmp(kgdb_fault_jmp_regs);
    +		/* Never reached. */
    +#endif
     
     	return 0;
     }
    diff -puN arch/sh/mm/fault.c~sh-lite arch/sh/mm/fault.c
    --- linux-2.6.13-rc3/arch/sh/mm/fault.c~sh-lite	2005-07-29 11:55:32.000000000 -0700
    +++ linux-2.6.13-rc3-trini/arch/sh/mm/fault.c	2005-07-29 11:55:32.000000000 -0700
    @@ -28,7 +28,6 @@
     #include <asm/pgalloc.h>
     #include <asm/mmu_context.h>
     #include <asm/cacheflush.h>
    -#include <asm/kgdb.h>
     
     extern void die(const char *,struct pt_regs *,long);
     
    @@ -45,11 +44,6 @@ asmlinkage void do_page_fault(struct pt_
     	struct vm_area_struct * vma;
     	unsigned long page;
     
    -#ifdef CONFIG_SH_KGDB
    -	if (kgdb_nofault && kgdb_bus_err_hook)
    -		kgdb_bus_err_hook();
    -#endif
    -
     	tsk = current;
     	mm = tsk->mm;
     
    @@ -153,6 +147,7 @@ no_context:
     	}
     	die("Oops", regs, writeaccess);
     	do_exit(SIGKILL);
    +	dump_stack();
     
     /*
      * We ran out of memory, or some other thing happened to us that made
    @@ -199,11 +194,6 @@ asmlinkage int __do_page_fault(struct pt
     	pte_t *pte;
     	pte_t entry;
     
    -#ifdef CONFIG_SH_KGDB
    -	if (kgdb_nofault && kgdb_bus_err_hook)
    -		kgdb_bus_err_hook();
    -#endif
    -
     #ifdef CONFIG_SH_STORE_QUEUES
     	addrmax = P4SEG_STORE_QUE + 0x04000000;
     #endif
    diff -puN arch/sh/mm/fault-nommu.c~sh-lite arch/sh/mm/fault-nommu.c
    --- linux-2.6.13-rc3/arch/sh/mm/fault-nommu.c~sh-lite	2005-07-29 11:55:32.000000000 -0700
    +++ linux-2.6.13-rc3-trini/arch/sh/mm/fault-nommu.c	2005-07-29 11:55:32.000000000 -0700
    @@ -29,10 +29,6 @@
     #include <asm/mmu_context.h>
     #include <asm/cacheflush.h>
     
    -#if defined(CONFIG_SH_KGDB)
    -#include <asm/kgdb.h>
    -#endif
    -
     extern void die(const char *,struct pt_regs *,long);
     
     /*
    @@ -43,11 +39,6 @@ extern void die(const char *,struct pt_r
     asmlinkage void do_page_fault(struct pt_regs *regs, unsigned long writeaccess,
     			      unsigned long address)
     {
    -#if defined(CONFIG_SH_KGDB)
    -	if (kgdb_nofault && kgdb_bus_err_hook)
    -		kgdb_bus_err_hook();
    -#endif
    -
     	/*
     	 * Oops. The kernel tried to access some bad page. We'll have to
     	 * terminate things with extreme prejudice.
    @@ -69,11 +60,6 @@ asmlinkage void do_page_fault(struct pt_
     asmlinkage int __do_page_fault(struct pt_regs *regs, unsigned long writeaccess,
     			       unsigned long address)
     {
    -#if defined(CONFIG_SH_KGDB)
    -	if (kgdb_nofault && kgdb_bus_err_hook)
    -		kgdb_bus_err_hook();
    -#endif
    -
     	if (address >= TASK_SIZE)
     		return 1;
     
    diff -puN Documentation/DocBook/kgdb.tmpl~sh-lite Documentation/DocBook/kgdb.tmpl
    --- linux-2.6.13-rc3/Documentation/DocBook/kgdb.tmpl~sh-lite	2005-07-29 11:55:32.000000000 -0700
    +++ linux-2.6.13-rc3-trini/Documentation/DocBook/kgdb.tmpl	2005-07-29 11:55:32.000000000 -0700
    @@ -127,6 +127,10 @@
         <constant>kgdbwait</constant> after this arguement.
         </para>
         <para>
    +    To specify the values of the SH SCI(F) serial port at boot:
    +    <constant>kgdbsci=0,115200</constant>.
    +    </para>
    +    <para>
         To configure the <symbol>CONFIG_KGDB_ETH</symbol> driver, pass in
         <constant>kgdboe=[src-port]@&lt;src-ip&gt;/[dev],[tgt-port]@&lt;tgt-ip&gt;/[tgt-macaddr]</constant>
         where:
    @@ -168,6 +172,18 @@
         application program.
         </para>
       </chapter>
    +  <chapter id="ArchitectureNotes">
    +    <title>Architecture specific notes</title>
    +      <para>
    +      SuperH: The NMI switch found on some boards can be used to trigger an
    +      initial breakpoint.  Subsequent triggers do nothing.  If console
    +      is enabled on the SCI(F) serial port, and that is the port being used
    +      for KGDB, then you must trigger a breakpoint via sysrq, NMI, or
    +      some other method prior to connecting, or echo a control-c to the
    +      serial port.  Also, to use the SCI(F) port for KGDB, the
    +      <symbol>CONFIG_SERIAL_SH_SCI</symbol> driver must be enabled.
    +      </para>
    +  </chapter>
       <chapter id="CommonBackEndReq">
         <title>The common backend (required)</title>
           <para>
    diff -puN drivers/serial/sh-sci.c~sh-lite drivers/serial/sh-sci.c
    --- linux-2.6.13-rc3/drivers/serial/sh-sci.c~sh-lite	2005-07-29 11:55:32.000000000 -0700
    +++ linux-2.6.13-rc3-trini/drivers/serial/sh-sci.c	2005-07-29 11:55:32.000000000 -0700
    @@ -42,6 +42,7 @@
     #include <linux/delay.h>
     #include <linux/console.h>
     #include <linux/bitops.h>
    +#include <linux/kgdb.h>
     
     #ifdef CONFIG_CPU_FREQ
     #include <linux/notifier.h>
    @@ -65,14 +66,34 @@
     
     #include "sh-sci.h"
     
    -#ifdef CONFIG_SH_KGDB
    -#include <asm/kgdb.h>
    +#ifdef CONFIG_KGDB_SH_SCI
    +/* Speed of the UART. */
    +#if defined(CONFIG_KGDB_9600BAUD)
    +static int kgdbsci_baud = 9600;
    +#elif defined(CONFIG_KGDB_19200BAUD)
    +static int kgdbsci_baud = 19200;
    +#elif defined(CONFIG_KGDB_38400BAUD)
    +static int kgdbsci_baud = 38400;
    +#elif defined(CONFIG_KGDB_57600BAUD)
    +static int kgdbsci_baud = 57600;
    +#else
    +static int kgdbsci_baud = 115200;	/* Start with this if not given */
    +#endif
     
    -static int kgdb_get_char(struct sci_port *port);
    -static void kgdb_put_char(struct sci_port *port, char c);
    -static void kgdb_handle_error(struct sci_port *port);
    -static struct sci_port *kgdb_sci_port;
    -#endif /* CONFIG_SH_KGDB */
    +/* Index of the UART, matches ttySCX naming. */
    +#if defined(CONFIG_KGDB_SERIAL_PORT_1)
    +static int kgdbsci_ttySC = 1;
    +#elif defined(CONFIG_KGDB_SERIAL_PORT_2)
    +static int kgdbsci_ttySC = 2;
    +#elif defined(CONFIG_KGDB_SERIAL_PORT_3)
    +static int kgdbsci_ttySC = 3;
    +#else
    +static int kgdbsci_ttySC = 0;		/* Start with this if not given */
    +#endif
    +
    +/* Make life easier on us. */
    +#define KGDBPORT	sci_ports[kgdbsci_ttySC]
    +#endif /* CONFIG_KGDB_SH_SCI */
     
     #ifdef CONFIG_SERIAL_SH_SCI_CONSOLE
     static struct sci_port *serial_console_port = 0;
    @@ -85,18 +106,15 @@ static void sci_start_rx(struct uart_por
     static void sci_stop_rx(struct uart_port *port);
     static int sci_request_irq(struct sci_port *port);
     static void sci_free_irq(struct sci_port *port);
    +static void sci_set_termios(struct uart_port *port, struct termios *termios,
    +			    struct termios *old);
    +static int kgdbsci_init(void);
     
     static struct sci_port sci_ports[SCI_NPORTS];
     static struct uart_driver sci_uart_driver;
     
    -#if defined(CONFIG_SH_STANDARD_BIOS) || defined(CONFIG_SH_KGDB)
    -
    -static void handle_error(struct uart_port *port)
    -{				/* Clear error flags */
    -	sci_out(port, SCxSR, SCxSR_ERROR_CLEAR(port));
    -}
    -
    -static int get_char(struct uart_port *port)
    +#if defined(CONFIG_SH_STANDARD_BIOS) || defined(CONFIG_KGDB_SH_SCI)
    +static int get_char_for_gdb(struct uart_port *port)
     {
     	unsigned long flags;
     	unsigned short status;
    @@ -106,7 +124,8 @@ static int get_char(struct uart_port *po
             do {
     		status = sci_in(port, SCxSR);
     		if (status & SCxSR_ERRORS(port)) {
    -			handle_error(port);
    +			/* Clear error flags. */
    +			sci_out(port, SCxSR, SCxSR_ERROR_CLEAR(port));
     			continue;
     		}
     	} while (!(status & SCxSR_RDxF(port)));
    @@ -117,21 +136,7 @@ static int get_char(struct uart_port *po
     
     	return c;
     }
    -
    -/* Taken from sh-stub.c of GDB 4.18 */
    -static const char hexchars[] = "0123456789abcdef";
    -
    -static __inline__ char highhex(int  x)
    -{
    -	return hexchars[(x >> 4) & 0xf];
    -}
    -
    -static __inline__ char lowhex(int  x)
    -{
    -	return hexchars[x & 0xf];
    -}
    -
    -#endif /* CONFIG_SH_STANDARD_BIOS || CONFIG_SH_KGDB */
    +#endif /* CONFIG_SH_STANDARD_BIOS || CONFIG_KGDB_SH_SCI */
     
     /*
      * Send the packet in buffer.  The host gets one chance to read it.
    @@ -163,21 +168,14 @@ static void put_string(struct sci_port *
     	const unsigned char *p = buffer;
     	int i;
     
    -#if defined(CONFIG_SH_STANDARD_BIOS) || defined(CONFIG_SH_KGDB)
    +#ifdef CONFIG_SH_STANDARD_BIOS
     	int checksum;
    -	int usegdb=0;
    +	const char hexchars[] = "0123456789abcdef";
     
    -#ifdef CONFIG_SH_STANDARD_BIOS
         	/* This call only does a trap the first time it is
     	 * called, and so is safe to do here unconditionally
     	 */
    -	usegdb |= sh_bios_in_gdb_mode();
    -#endif
    -#ifdef CONFIG_SH_KGDB
    -	usegdb |= (kgdb_in_gdb_mode && (port == kgdb_sci_port));
    -#endif
    -
    -	if (usegdb) {
    +	if (sh_bios_in_gdb_mode()) {
     	    /*  $<packet info>#<checksum>. */
     	    do {
     		unsigned char c;
    @@ -189,18 +187,18 @@ static void put_string(struct sci_port *
     			int h, l;
     
     			c = *p++;
    -			h = highhex(c);
    -			l = lowhex(c);
    +			h = hexchars[c >> 4];
    +			l = hexchars[c % 16];
     			put_char(port, h);
     			put_char(port, l);
     			checksum += h + l;
     		}
     		put_char(port, '#');
    -		put_char(port, highhex(checksum));
    -		put_char(port, lowhex(checksum));
    +		put_char(port, hexchars[checksum >> 4]);
    +		put_char(port, hexchars[checksum & 16]);
     	    } while  (get_char(port) != '+');
     	} else
    -#endif /* CONFIG_SH_STANDARD_BIOS || CONFIG_SH_KGDB */
    +#endif /* CONFIG_SH_STANDARD_BIOS */
     	for (i=0; i<count; i++) {
     		if (*p == 10)
     			put_char(port, '\r');
    @@ -210,90 +208,163 @@ static void put_string(struct sci_port *
     #endif /* CONFIG_SERIAL_SH_SCI_CONSOLE */
     
     
    -#ifdef CONFIG_SH_KGDB
    -
    -/* Is the SCI ready, ie is there a char waiting? */
    -static int kgdb_is_char_ready(struct sci_port *port)
    +#ifdef CONFIG_KGDB_SH_SCI
    +static int kgdbsci_read_char(void)
     {
    -        unsigned short status = sci_in(port, SCxSR);
    -
    -        if (status & (SCxSR_ERRORS(port) | SCxSR_BRK(port)))
    -                kgdb_handle_error(port);
    -
    -        return (status & SCxSR_RDxF(port));
    +	return get_char_for_gdb(&KGDBPORT.port);
     }
     
    -/* Write a char */
    -static void kgdb_put_char(struct sci_port *port, char c)
    +/* Called from kgdbstub.c to put a character, just a wrapper */
    +static void kgdbsci_write_char(int c)
     {
    -        unsigned short status;
    -
    -        do
    -                status = sci_in(port, SCxSR);
    -        while (!(status & SCxSR_TDxE(port)));
    +	unsigned short status;
     
    -        sci_out(port, SCxTDR, c);
    -        sci_in(port, SCxSR);    /* Dummy read */
    -        sci_out(port, SCxSR, SCxSR_TDxE_CLEAR(port));
    +	do
    +		status = sci_in(&KGDBPORT.port, SCxSR);
    +	while (!(status & SCxSR_TDxE(&KGDBPORT.port)));
    +
    +	sci_out(&KGDBPORT.port, SCxTDR, c);
    +	sci_in(&KGDBPORT.port, SCxSR);	/* Dummy read */
    +	sci_out(&KGDBPORT.port, SCxSR, SCxSR_TDxE_CLEAR(&KGDBPORT.port));
     }
     
    -/* Get a char if there is one, else ret -1 */
    -static int kgdb_get_char(struct sci_port *port)
    +#ifndef CONFIG_SERIAL_SH_SCI_CONSOLE
    +/* If we don't have console, we never hookup IRQs.  But we need to
    + * hookup one so that we can interrupt the system.
    + */
    +static irqreturn_t kgdbsci_rx_interrupt(int irq, void *ptr,
    +		struct pt_regs *regs)
     {
    -        int c;
    -
    -        if (kgdb_is_char_ready(port) == 0)
    -                c = -1;
    -        else {
    -                c = sci_in(port, SCxRDR);
    -                sci_in(port, SCxSR);    /* Dummy read */
    -                sci_out(port, SCxSR, SCxSR_RDxF_CLEAR(port));
    -        }
    +	struct uart_port *port = ptr;
     
    -        return c;
    -}
    +	if (!(sci_in(port, SCxSR) & SCxSR_RDxF(port)))
    +		return IRQ_NONE;
     
    -/* Called from kgdbstub.c to get a character, i.e. is blocking */
    -static int kgdb_sci_getchar(void)
    -{
    -        volatile int c;
    +	if (kgdb_io_ops.init != kgdbsci_init) {
    +		/* Throw away the data if another I/O routine is active */
    +		get_char_for_gdb(&KGDBPORT.port);
    +	} else
    +		/* We've got an interrupt, so go ahead and call breakpoint() */
    +		breakpoint();
     
    -        /* Keep trying to read a character, this could be neater */
    -        while ((c = kgdb_get_char(kgdb_sci_port)) < 0);
    +	sci_in(port, SCxSR); /* dummy read */
    +	sci_out(port, SCxSR, SCxSR_RDxF_CLEAR(port));
     
    -        return c;
    +	return IRQ_HANDLED;
     }
     
    -/* Called from kgdbstub.c to put a character, just a wrapper */
    -static void kgdb_sci_putchar(int c)
    +static irqreturn_t kgdbsci_mpxed_interrupt(int irq, void *ptr,
    +		struct pt_regs *regs)
     {
    +        unsigned short ssr_status, scr_status;
    +        struct uart_port *port = ptr;
    +
    +        ssr_status = sci_in(port,SCxSR);
    +        scr_status = sci_in(port,SCSCR);
     
    -        kgdb_put_char(kgdb_sci_port, c);
    +	/* Rx Interrupt */
    +        if ((ssr_status&0x0002) && (scr_status&0x0040))
    +		kgdbsci_rx_interrupt(irq, ptr, regs);
    +
    +	return IRQ_HANDLED;
     }
     
    -/* Clear any errors on the SCI */
    -static void kgdb_handle_error(struct sci_port *port)
    +static void __init kgdbsci_lateinit(void)
     {
    -        sci_out(port, SCxSR, SCxSR_ERROR_CLEAR(port));  /* Clear error flags */
    +	if (KGDBPORT.irqs[0] == KGDBPORT.irqs[1]) {
    +		if (!KGDBPORT.irqs[0]) {
    +			printk(KERN_ERR "kgdbsci: Cannot allocate irq.\n");
    +			return;
    +		}
    +		if (request_irq(KGDBPORT.irqs[0], kgdbsci_mpxed_interrupt,
    +					SA_INTERRUPT, "kgdbsci",
    +					&KGDBPORT.port)) {
    +			printk(KERN_ERR "kgdbsci: Cannot allocate irq.\n");
    +			return;
    +		}
    +	} else {
    +		if (KGDBPORT.irqs[1])
    +			request_irq(KGDBPORT.irqs[1],
    +					kgdbsci_rx_interrupt, SA_INTERRUPT,
    +					"kgdbsci", &KGDBPORT.port);
    +	}
     }
    +#endif
     
    -/* Breakpoint if there's a break sent on the serial port */
    -static void kgdb_break_interrupt(int irq, void *ptr, struct pt_regs *regs)
    +/*
    + * We use the normal init routine to setup the port, so we can't be
    + * in here too early.
    + */
    +static int kgdbsci_init(void)
     {
    -        struct sci_port *port = ptr;
    -        unsigned short status = sci_in(port, SCxSR);
    +	struct termios termios;
     
    -        if (status & SCxSR_BRK(port)) {
    +	memset(&termios, 0, sizeof(struct termios));
     
    -                /* Break into the debugger if a break is detected */
    -                BREAKPOINT();
    +	termios.c_cflag = CREAD | HUPCL | CLOCAL | CS8;
    +	switch (kgdbsci_baud) {
    +	case 9600:
    +		termios.c_cflag |= B9600;
    +		break;
    +	case 19200:
    +		termios.c_cflag |= B19200;
    +		break;
    +	case 38400:
    +		termios.c_cflag |= B38400;
    +		break;
    +	case 57600:
    +		termios.c_cflag |= B57600;
    +		break;
    +	case 115200:
    +		termios.c_cflag |= B115200;
    +		break;
    +	}
    +	sci_set_termios(&KGDBPORT.port, &termios, NULL);
     
    -                /* Clear */
    -                sci_out(port, SCxSR, SCxSR_BREAK_CLEAR(port));
    -        }
    +	return 0;
     }
     
    -#endif /* CONFIG_SH_KGDB */
    +struct kgdb_io kgdb_io_ops = {
    +	.read_char = kgdbsci_read_char,
    +	.write_char = kgdbsci_write_char,
    +	.init = kgdbsci_init,
    +#ifndef CONFIG_SERIAL_SH_SCI_CONSOLE
    +	.late_init = kgdbsci_lateinit,
    +#else /* ! CONFIG_SERIAL_SH_SCI_CONSOLE */
    +	.late_init = NULL,
    +#endif /* ! CONFIG_SERIAL_SH_SCI_CONSOLE */
    +	.pre_exception = NULL,
    +	.post_exception = NULL
    +};
    +
    +/*
    + * Syntax for this cmdline option is "kgdbsci=ttyno,baudrate".
    + */
    +static int __init
    +kgdbsci_opt(char *str)
    +{
    +	/* We might have anywhere from 1 to 3 ports. */
    +	if (*str < '0' || *str > SCI_NPORTS + '0')
    +		 goto errout;
    +	kgdbsci_ttySC = *str - '0';
    +	str++;
    +	if (*str != ',')
    +		 goto errout;
    +	str++;
    +	kgdbsci_baud = simple_strtoul(str, &str, 10);
    +	if (kgdbsci_baud != 9600 && kgdbsci_baud != 19200 &&
    +	    kgdbsci_baud != 38400 && kgdbsci_baud != 57600 &&
    +	    kgdbsci_baud != 115200)
    +		 goto errout;
    +
    +	return 0;
    +
    +errout:
    +	printk(KERN_ERR "Invalid syntax for option kgdbsci=\n");
    +	return 1;
    +}
    +__setup("kgdbsci", kgdbsci_opt);
    +#endif /* CONFIG_KGDB_SH_SCI */
     
     #if defined(__H8300S__)
     enum { sci_disable, sci_enable };
    @@ -541,6 +612,16 @@ static inline void sci_receive_chars(str
     					continue;
     				}
     
    +#ifdef CONFIG_KGDB_SH_SCI
    +				/* We assume that a ^C on the port KGDB
    +				 * is using means that KGDB wants to
    +				 * interrupt the running system.
    +				 */
    +				if (port->line == KGDBPORT.port.line &&
    +						c == 3)
    +					breakpoint();
    +#endif
    +
     				/* Store data and status */
     				tty->flip.char_buf_ptr[i] = c;
     				if (status&SCxSR_FER(port)) {
    @@ -1552,6 +1633,7 @@ static int __init sci_console_init(void)
     console_initcall(sci_console_init);
     #endif /* CONFIG_SERIAL_SH_SCI_CONSOLE */
     
    +#if 0
     #ifdef CONFIG_SH_KGDB
     /*
      * FIXME: Most of this can go away.. at the moment, we rely on
    @@ -1597,30 +1679,9 @@ int __init kgdb_console_setup(struct con
     	return uart_set_options(port, co, baud, parity, bits, flow);
     }
     #endif /* CONFIG_SH_KGDB */
    +#endif /* 0 */
     
    -#ifdef CONFIG_SH_KGDB_CONSOLE
    -static struct console kgdb_console = {
    -        .name		= "ttySC",
    -        .write		= kgdb_console_write,
    -        .setup		= kgdb_console_setup,
    -        .flags		= CON_PRINTBUFFER | CON_ENABLED,
    -        .index		= -1,
    -	.data		= &sci_uart_driver,
    -};
    -
    -/* Register the KGDB console so we get messages (d'oh!) */
    -static int __init kgdb_console_init(void)
    -{
    -	register_console(&kgdb_console);
    -	return 0;
    -}
    -
    -console_initcall(kgdb_console_init);
    -#endif /* CONFIG_SH_KGDB_CONSOLE */
    -
    -#if defined(CONFIG_SH_KGDB_CONSOLE)
    -#define SCI_CONSOLE	&kgdb_console
    -#elif defined(CONFIG_SERIAL_SH_SCI_CONSOLE)
    +#ifdef CONFIG_SERIAL_SH_SCI_CONSOLE
     #define SCI_CONSOLE	&serial_console
     #else
     #define SCI_CONSOLE 	0
    @@ -1689,4 +1750,3 @@ static void __exit sci_exit(void)
     
     module_init(sci_init);
     module_exit(sci_exit);
    -
    diff -puN include/asm-sh/kgdb.h~sh-lite include/asm-sh/kgdb.h
    --- linux-2.6.13-rc3/include/asm-sh/kgdb.h~sh-lite	2005-07-29 11:55:32.000000000 -0700
    +++ linux-2.6.13-rc3-trini/include/asm-sh/kgdb.h	2005-07-29 12:48:10.000000000 -0700
    @@ -2,94 +2,41 @@
      * May be copied or modified under the terms of the GNU General Public
      * License.  See linux/COPYING for more information.
      *
    - * Based on original code by Glenn Engel, Jim Kingdon,
    - * David Grothe <dave@gcom.com>, Tigran Aivazian, <tigran@sco.com> and
    - * Amit S. Kale <akale@veritas.com>
    - * 
    - * Super-H port based on sh-stub.c (Ben Lee and Steve Chamberlain) by
    - * Henry Bell <henry.bell@st.com>
    - * 
    - * Header file for low-level support for remote debug using GDB. 
    + * Based on a file that was modified or based on files by: Glenn Engel,
    + * Jim Kingdon, David Grothe <dave@gcom.com>, Tigran Aivazian <tigran@sco.com>,
    + * Amit S. Kale <akale@veritas.com>, sh-stub.c from Ben Lee and
    + * Steve Chamberlain, Henry Bell <henry.bell@st.com>
    + *
    + * Maintainer: Tom Rini <trini@kernel.crashing.org>
      *
      */
     
     #ifndef __KGDB_H
     #define __KGDB_H
     
    -#include <asm/ptrace.h>
    -
    -struct console;
    +#include <asm-generic/kgdb.h>
    +/* Based on sh-gdb.c from gdb-6.1, Glenn
    +     Engel at HP  Ben Lee and Steve Chamberlain */
    +#define NUMREGBYTES	112	/* 92 */
    +#define NUMCRITREGBYTES	(9 << 2)
    +#define BUFMAX		400
     
    -/* Same as pt_regs but has vbr in place of syscall_nr */
    +#ifndef __ASSEMBLY__
     struct kgdb_regs {
             unsigned long regs[16];
             unsigned long pc;
             unsigned long pr;
    -        unsigned long sr;
             unsigned long gbr;
    +        unsigned long vbr;
             unsigned long mach;
             unsigned long macl;
    -        unsigned long vbr;
    -};
    -
    -/* State info */
    -extern char kgdb_in_gdb_mode;
    -extern int kgdb_done_init;
    -extern int kgdb_enabled;
    -extern int kgdb_nofault;	/* Ignore bus errors (in gdb mem access) */
    -extern int kgdb_halt;		/* Execute initial breakpoint at startup */
    -extern char in_nmi;		/* Debounce flag to prevent NMI reentry*/
    -
    -/* SCI */
    -extern int kgdb_portnum;
    -extern int kgdb_baud;
    -extern char kgdb_parity;
    -extern char kgdb_bits;
    -extern int kgdb_console_setup(struct console *, char *);
    -
    -/* Init and interface stuff */
    -extern int kgdb_init(void);
    -extern int (*kgdb_serial_setup)(void);
    -extern int (*kgdb_getchar)(void);
    -extern void (*kgdb_putchar)(int);
    -
    -struct kgdb_sermap {
    -	char *name;
    -	int namelen;
    -	int (*setup_fn)(struct console *, char *);
    -	struct kgdb_sermap *next;
    +        unsigned long sr;
     };
    -extern void kgdb_register_sermap(struct kgdb_sermap *map);
    -extern struct kgdb_sermap *kgdb_porttype;
     
    -/* Trap functions */
    -typedef void (kgdb_debug_hook_t)(struct pt_regs *regs); 
    -typedef void (kgdb_bus_error_hook_t)(void);
    -extern kgdb_debug_hook_t  *kgdb_debug_hook;
    -extern kgdb_bus_error_hook_t *kgdb_bus_err_hook;
    -
    -extern void breakpoint(void);
    -
    -/* Console */
    -struct console;
    -void kgdb_console_write(struct console *co, const char *s, unsigned count);
    -void kgdb_console_init(void);
    -
    -/* Prototypes for jmp fns */
    -#define _JBLEN 9
    -typedef        int jmp_buf[_JBLEN];
    -extern void    longjmp(jmp_buf __jmpb, int __retval);
    -extern int     setjmp(jmp_buf __jmpb);
    -
    -/* Variadic macro to print our own message to the console */
    -#define KGDB_PRINTK(...) printk("KGDB: " __VA_ARGS__)
    -
    -/* Forced breakpoint */
    -#define BREAKPOINT() do {                                     \
    -  if (kgdb_enabled) {                                         \
    -    asm volatile("trapa   #0xff");                            \
    -  }                                                           \
    -} while (0)
    +#define BREAKPOINT()		asm("trapa #0xff");
    +#define BREAK_INSTR_SIZE	2
    +#define CHECK_EXCEPTION_STACK()	1
    +#define CACHE_FLUSH_IS_SAFE	1
     
     /* KGDB should be able to flush all kernel text space */
     #if defined(CONFIG_CPU_SH4)
    @@ -102,30 +49,5 @@ extern int     setjmp(jmp_buf __jmpb);
     #else
     #define kgdb_flush_icache_range(start, end)	do { } while (0)
     #endif
    -
    -/* Kernel assert macros */
    -#ifdef CONFIG_KGDB_KERNEL_ASSERTS
    -
    -/* Predefined conditions */
    -#define KA_VALID_ERRNO(errno) ((errno) > 0 && (errno) <= EMEDIUMTYPE)
    -#define KA_VALID_PTR_ERR(ptr) KA_VALID_ERRNO(-PTR_ERR(ptr))
    -#define KA_VALID_KPTR(ptr)  (!(ptr) || \
    -              ((void *)(ptr) >= (void *)PAGE_OFFSET &&  \
    -               (void *)(ptr) < ERR_PTR(-EMEDIUMTYPE)))
    -#define KA_VALID_PTRORERR(errptr) \
    -               (KA_VALID_KPTR(errptr) || KA_VALID_PTR_ERR(errptr))
    -#define KA_HELD_GKL()  (current->lock_depth >= 0)
    -
    -/* The actual assert */
    -#define KGDB_ASSERT(condition, message) do {                   \
    -       if (!(condition) && (kgdb_enabled)) {                   \
    -               KGDB_PRINTK("Assertion failed at %s:%d: %s\n",  \
    -                                  __FILE__, __LINE__, message);\
    -               BREAKPOINT();                                   \
    -       }                                                       \
    -} while (0)
    -#else
    -#define KGDB_ASSERT(condition, message)
    -#endif
    -
    +#endif				/* !__ASSEMBLY__ */
     #endif
    diff -puN include/asm-sh/system.h~sh-lite include/asm-sh/system.h
    --- linux-2.6.13-rc3/include/asm-sh/system.h~sh-lite	2005-07-29 11:55:32.000000000 -0700
    +++ linux-2.6.13-rc3-trini/include/asm-sh/system.h	2005-07-29 11:55:32.000000000 -0700
    @@ -7,6 +7,7 @@
      */
     
     #include <linux/config.h>
    +#include <asm/types.h>
     
     /*
      *	switch_to() should switch tasks to task nr n, first
    @@ -252,6 +253,45 @@ static __inline__ unsigned long __xchg(u
     	return x;
     }
     
    +static inline unsigned long __cmpxchg_u32(volatile int * m, unsigned long old,
    +	unsigned long new)
    +{
    +	__u32 retval;
    +	unsigned long flags;
    +
    +	local_irq_save(flags);
    +	retval = *m;
    +	if (retval == old)
    +		*m = new;
    +	local_irq_restore(flags);       /* implies memory barrier  */
    +	return retval;
    +}
    +
    +/* This function doesn't exist, so you'll get a linker error
    + * if something tries to do an invalid cmpxchg(). */
    +extern void __cmpxchg_called_with_bad_pointer(void);
    +
    +#define __HAVE_ARCH_CMPXCHG	1
    +
    +static inline unsigned long __cmpxchg(volatile void * ptr, unsigned long old,
    +		unsigned long new, int size)
    +{
    +	switch (size) {
    +	case 4:
    +		return __cmpxchg_u32(ptr, old, new);
    +	}
    +	__cmpxchg_called_with_bad_pointer();
    +	return old;
    +}
    +
    +#define cmpxchg(ptr,o,n)						 \
    +  ({									 \
    +     __typeof__(*(ptr)) _o_ = (o);					 \
    +     __typeof__(*(ptr)) _n_ = (n);					 \
    +     (__typeof__(*(ptr))) __cmpxchg((ptr), (unsigned long)_o_,		 \
    +				    (unsigned long)_n_, sizeof(*(ptr))); \
    +  })
    +
     /* XXX
      * disable hlt during certain critical i/o operations
      */
    diff -puN lib/Kconfig.debug~sh-lite lib/Kconfig.debug
    --- linux-2.6.13-rc3/lib/Kconfig.debug~sh-lite	2005-07-29 11:55:32.000000000 -0700
    +++ linux-2.6.13-rc3-trini/lib/Kconfig.debug	2005-07-29 13:18:16.000000000 -0700
    @@ -152,7 +152,7 @@ config DEBUG_FS
     
     config FRAME_POINTER
     	bool "Compile the kernel with frame pointers"
    -	depends on DEBUG_KERNEL && ((X86 && !X86_64) || CRIS || M68K || M68KNOMMU || FRV || UML)
    +	depends on DEBUG_KERNEL && ((X86 && !X86_64) || CRIS || M68K || M68KNOMMU || FRV || UML || SUPERH)
     	default y if DEBUG_INFO && UML
     	default y if KGDB
     	help
    @@ -163,7 +163,7 @@ config FRAME_POINTER
     
     config KGDB
     	bool "KGDB: kernel debugging with remote gdb"
    -	depends on DEBUG_KERNEL && (X86 || MIPS32 || IA64 || X86_64 || ((!SMP || BROKEN) && PPC32))
    +	depends on DEBUG_KERNEL && (X86 || MIPS32 || (SUPERH && !SUPERH64) || IA64 || X86_64 || ((!SMP || BROKEN) && PPC32))
     	help
     	  If you say Y here, it will be possible to remotely debug the
     	  kernel using gdb. It is strongly suggested that you enable
    @@ -227,6 +227,12 @@ config KGDB_SIBYTE
     	bool "KGDB: On the Broadcom SWARM serial port"
     	depends on MIPS && SIBYTE_SB1xxx_SOC
     
    +config KGDB_SH_SCI
    +	bool "KGDB: On SH SCI(F) serial port"
    +	depends on SUPERH && SERIAL_SH_SCI
    +	help
    +	  Uses the SCI(F) serial port found on the board.
    +
     endchoice
     
     config KGDB_8250
    @@ -239,7 +245,7 @@ config KGDB_8250
     
     config KGDB_SIMPLE_SERIAL
     	bool "Simple selection of KGDB serial port"
    -	depends on KGDB_8250
    +	depends on KGDB_8250 || KGDB_SH_SCI
     	help
     	  If you say Y here, you will only have to pick the baud rate
     	  and serial port (ttyS) that you wish to use for KGDB.  If you
    @@ -249,7 +255,7 @@ config KGDB_SIMPLE_SERIAL
     
     choice
         	prompt "Debug serial port BAUD"
    -	depends on KGDB_8250
    +	depends on KGDB_8250 || KGDB_SH_SCI
     	default KGDB_115200BAUD
     	help
     	  gdb and the kernel stub need to agree on the baud rate to be
    _
    -
    To unsubscribe from this list: send the line "unsubscribe linux-kernel" in
    the body of a message to majordomo@vger.kernel.org
    More majordomo info at  http://vger.kernel.org/majordomo-info.html
    Please read the FAQ at  http://www.tux.org/lkml/
    

  • Next message: Tom Rini: "[patch 12/15] KGDB: Add CFI DWARF2 annotation support."

    Relevant Pages

    • [patch 1/8] A different KGDB stub for -mm
      ... The following series of patches adds KGDB ... kgdb is a source level debugger for linux kernel. ... +typedef int gdb_debug_hook(int exVector, int signo, int err_code, ... +void kgdb_nmihook; ...
      (Linux-Kernel)
    • [patch 1/8] A different KGDB stub for -mm
      ... The following series of patches adds KGDB ... kgdb is a source level debugger for linux kernel. ... +typedef int gdb_debug_hook(int exVector, int signo, int err_code, ... +void kgdb_nmihook; ...
      (Linux-Kernel)
    • Re: BitKeeper repo for KGDB
      ... > trying to merge the various versions of KGDB around, ... > What I'd like is for someone to move the ethernet bits from the -mm tree ... -static int bufnum; ... -static void kgdbeth_unlock ...
      (Linux-Kernel)
    • [PATCH,RFC 2.6.14 01/15] KGDB: core infrastructure
      ... This is the core of the KGDB stub. ... +extern int kgdb_connected; ... +extern void kgdb_roundup_cpus; ...
      (Linux-Kernel)
    • [PATCH 1/2] kgdb, mips: Remove existing kgdb implementation
      ... is intended to be followed by a patch that adds a kgdb implementation ... -static int remoteDebugInitialized; ... -asmlinkage void excite_kgdb_inthdl ... * To enable debugger support, ...
      (Linux-Kernel)