lkml.org 
[lkml]   [2005]   [Jul]   [29]   [last100]   RSS Feed
Views: [wrap][no wrap]   [headers]  [forward] 
 
Messages in this thread
    Patch in this message
    /
    Subject[patch 05/15] Basic MIPS support
    Date
    From

    CC: Manish Lachwani <mlachwani@mvista.com>, Ralf Baechle <ralf@linux-mips.org>
    This adds basic support to the MIPS architecture as well as support
    specifically for the MIPS Malta and SiByte 1250-SWARM (32 and 64bit), all from
    Manish Lachwani. This looks like it should work on anything with an
    8250-compatible uart, and be fairly easy to convert other boards custom uarts
    as needed.

    ---

    linux-2.6.13-rc3-trini/arch/mips/Kconfig.debug | 19
    linux-2.6.13-rc3-trini/arch/mips/kernel/Makefile | 3
    linux-2.6.13-rc3-trini/arch/mips/kernel/irq.c | 32
    linux-2.6.13-rc3-trini/arch/mips/kernel/kgdb-jmp.c | 62
    linux-2.6.13-rc3-trini/arch/mips/kernel/kgdb-setjmp.S | 23
    linux-2.6.13-rc3-trini/arch/mips/kernel/kgdb.c | 292 ++
    linux-2.6.13-rc3-trini/arch/mips/kernel/kgdb_handler.S | 58
    linux-2.6.13-rc3-trini/arch/mips/kernel/traps.c | 26
    linux-2.6.13-rc3-trini/arch/mips/mips-boards/generic/Makefile | 1
    linux-2.6.13-rc3-trini/arch/mips/mips-boards/generic/init.c | 62
    linux-2.6.13-rc3-trini/arch/mips/mips-boards/malta/malta_setup.c | 8
    linux-2.6.13-rc3-trini/arch/mips/mm/extable.c | 7
    linux-2.6.13-rc3-trini/arch/mips/sibyte/cfe/setup.c | 14
    linux-2.6.13-rc3-trini/arch/mips/sibyte/sb1250/Makefile | 1
    linux-2.6.13-rc3-trini/arch/mips/sibyte/sb1250/irq.c | 57
    linux-2.6.13-rc3-trini/arch/mips/sibyte/sb1250/irq_handler.S | 2
    linux-2.6.13-rc3-trini/arch/mips/sibyte/sb1250/kgdb_sibyte.c | 164 +
    linux-2.6.13-rc3-trini/arch/mips/sibyte/swarm/Makefile | 2
    linux-2.6.13-rc3-trini/include/asm-mips/kdebug.h | 47
    linux-2.6.13-rc3-trini/include/asm-mips/kgdb.h | 22
    linux-2.6.13-rc3-trini/lib/Kconfig.debug | 7
    linux-2.6.13-rc3/arch/mips/kernel/gdb-low.S | 370 ---
    linux-2.6.13-rc3/arch/mips/kernel/gdb-stub.c | 1091 ----------
    linux-2.6.13-rc3/arch/mips/sibyte/swarm/dbg_io.c | 76
    24 files changed, 729 insertions(+), 1717 deletions(-)

    diff -puN arch/mips/Kconfig.debug~mips-lite arch/mips/Kconfig.debug
    --- linux-2.6.13-rc3/arch/mips/Kconfig.debug~mips-lite 2005-07-29 11:55:31.000000000 -0700
    +++ linux-2.6.13-rc3-trini/arch/mips/Kconfig.debug 2005-07-29 11:55:31.000000000 -0700
    @@ -27,25 +27,6 @@ config DEBUG_STACK_USAGE

    This option will slow down process creation somewhat.

    -config KGDB
    - bool "Remote GDB kernel debugging"
    - depends on DEBUG_KERNEL
    - select DEBUG_INFO
    - help
    - If you say Y here, it will be possible to remotely debug the MIPS
    - kernel using gdb. This enlarges your kernel image disk size by
    - several megabytes and requires a machine with more than 16 MB,
    - better 32 MB RAM to avoid excessive linking time. This is only
    - useful for kernel hackers. If unsure, say N.
    -
    -config GDB_CONSOLE
    - bool "Console output to GDB"
    - depends on KGDB
    - help
    - If you are using GDB for remote debugging over a serial port and
    - would like kernel messages to be formatted into GDB $O packets so
    - that GDB prints them as program output, say 'Y'.
    -
    config SB1XXX_CORELIS
    bool "Corelis Debugger"
    depends on SIBYTE_SB1xxx_SOC
    diff -L arch/mips/kernel/gdb-low.S -puN arch/mips/kernel/gdb-low.S~mips-lite /dev/null
    --- linux-2.6.13-rc3/arch/mips/kernel/gdb-low.S
    +++ /dev/null 2005-07-25 10:57:32.312383000 -0700
    @@ -1,370 +0,0 @@
    -/*
    - * gdb-low.S contains the low-level trap handler for the GDB stub.
    - *
    - * Copyright (C) 1995 Andreas Busse
    - */
    -#include <linux/config.h>
    -#include <linux/sys.h>
    -
    -#include <asm/asm.h>
    -#include <asm/errno.h>
    -#include <asm/mipsregs.h>
    -#include <asm/regdef.h>
    -#include <asm/stackframe.h>
    -#include <asm/gdb-stub.h>
    -
    -#ifdef CONFIG_MIPS32
    -#define DMFC0 mfc0
    -#define DMTC0 mtc0
    -#define LDC1 lwc1
    -#define SDC1 lwc1
    -#endif
    -#ifdef CONFIG_MIPS64
    -#define DMFC0 dmfc0
    -#define DMTC0 dmtc0
    -#define LDC1 ldc1
    -#define SDC1 ldc1
    -#endif
    -
    -/*
    - * [jsun] We reserves about 2x GDB_FR_SIZE in stack. The lower (addressed)
    - * part is used to store registers and passed to exception handler.
    - * The upper part is reserved for "call func" feature where gdb client
    - * saves some of the regs, setups call frame and passes args.
    - *
    - * A trace shows about 200 bytes are used to store about half of all regs.
    - * The rest should be big enough for frame setup and passing args.
    - */
    -
    -/*
    - * The low level trap handler
    - */
    - .align 5
    - NESTED(trap_low, GDB_FR_SIZE, sp)
    - .set noat
    - .set noreorder
    -
    - mfc0 k0, CP0_STATUS
    - sll k0, 3 /* extract cu0 bit */
    - bltz k0, 1f
    - move k1, sp
    -
    - /*
    - * Called from user mode, go somewhere else.
    - */
    - lui k1, %hi(saved_vectors)
    - mfc0 k0, CP0_CAUSE
    - andi k0, k0, 0x7c
    - add k1, k1, k0
    - lw k0, %lo(saved_vectors)(k1)
    - jr k0
    - nop
    -1:
    - move k0, sp
    - subu sp, k1, GDB_FR_SIZE*2 # see comment above
    - LONG_S k0, GDB_FR_REG29(sp)
    - LONG_S $2, GDB_FR_REG2(sp)
    -
    -/*
    - * First save the CP0 and special registers
    - */
    -
    - mfc0 v0, CP0_STATUS
    - LONG_S v0, GDB_FR_STATUS(sp)
    - mfc0 v0, CP0_CAUSE
    - LONG_S v0, GDB_FR_CAUSE(sp)
    - DMFC0 v0, CP0_EPC
    - LONG_S v0, GDB_FR_EPC(sp)
    - DMFC0 v0, CP0_BADVADDR
    - LONG_S v0, GDB_FR_BADVADDR(sp)
    - mfhi v0
    - LONG_S v0, GDB_FR_HI(sp)
    - mflo v0
    - LONG_S v0, GDB_FR_LO(sp)
    -
    -/*
    - * Now the integer registers
    - */
    -
    - LONG_S zero, GDB_FR_REG0(sp) /* I know... */
    - LONG_S $1, GDB_FR_REG1(sp)
    - /* v0 already saved */
    - LONG_S $3, GDB_FR_REG3(sp)
    - LONG_S $4, GDB_FR_REG4(sp)
    - LONG_S $5, GDB_FR_REG5(sp)
    - LONG_S $6, GDB_FR_REG6(sp)
    - LONG_S $7, GDB_FR_REG7(sp)
    - LONG_S $8, GDB_FR_REG8(sp)
    - LONG_S $9, GDB_FR_REG9(sp)
    - LONG_S $10, GDB_FR_REG10(sp)
    - LONG_S $11, GDB_FR_REG11(sp)
    - LONG_S $12, GDB_FR_REG12(sp)
    - LONG_S $13, GDB_FR_REG13(sp)
    - LONG_S $14, GDB_FR_REG14(sp)
    - LONG_S $15, GDB_FR_REG15(sp)
    - LONG_S $16, GDB_FR_REG16(sp)
    - LONG_S $17, GDB_FR_REG17(sp)
    - LONG_S $18, GDB_FR_REG18(sp)
    - LONG_S $19, GDB_FR_REG19(sp)
    - LONG_S $20, GDB_FR_REG20(sp)
    - LONG_S $21, GDB_FR_REG21(sp)
    - LONG_S $22, GDB_FR_REG22(sp)
    - LONG_S $23, GDB_FR_REG23(sp)
    - LONG_S $24, GDB_FR_REG24(sp)
    - LONG_S $25, GDB_FR_REG25(sp)
    - LONG_S $26, GDB_FR_REG26(sp)
    - LONG_S $27, GDB_FR_REG27(sp)
    - LONG_S $28, GDB_FR_REG28(sp)
    - /* sp already saved */
    - LONG_S $30, GDB_FR_REG30(sp)
    - LONG_S $31, GDB_FR_REG31(sp)
    -
    - CLI /* disable interrupts */
    -
    -/*
    - * Followed by the floating point registers
    - */
    - mfc0 v0, CP0_STATUS /* FPU enabled? */
    - srl v0, v0, 16
    - andi v0, v0, (ST0_CU1 >> 16)
    -
    - beqz v0,2f /* disabled, skip */
    - nop
    -
    - SDC1 $0, GDB_FR_FPR0(sp)
    - SDC1 $1, GDB_FR_FPR1(sp)
    - SDC1 $2, GDB_FR_FPR2(sp)
    - SDC1 $3, GDB_FR_FPR3(sp)
    - SDC1 $4, GDB_FR_FPR4(sp)
    - SDC1 $5, GDB_FR_FPR5(sp)
    - SDC1 $6, GDB_FR_FPR6(sp)
    - SDC1 $7, GDB_FR_FPR7(sp)
    - SDC1 $8, GDB_FR_FPR8(sp)
    - SDC1 $9, GDB_FR_FPR9(sp)
    - SDC1 $10, GDB_FR_FPR10(sp)
    - SDC1 $11, GDB_FR_FPR11(sp)
    - SDC1 $12, GDB_FR_FPR12(sp)
    - SDC1 $13, GDB_FR_FPR13(sp)
    - SDC1 $14, GDB_FR_FPR14(sp)
    - SDC1 $15, GDB_FR_FPR15(sp)
    - SDC1 $16, GDB_FR_FPR16(sp)
    - SDC1 $17, GDB_FR_FPR17(sp)
    - SDC1 $18, GDB_FR_FPR18(sp)
    - SDC1 $19, GDB_FR_FPR19(sp)
    - SDC1 $20, GDB_FR_FPR20(sp)
    - SDC1 $21, GDB_FR_FPR21(sp)
    - SDC1 $22, GDB_FR_FPR22(sp)
    - SDC1 $23, GDB_FR_FPR23(sp)
    - SDC1 $24, GDB_FR_FPR24(sp)
    - SDC1 $25, GDB_FR_FPR25(sp)
    - SDC1 $26, GDB_FR_FPR26(sp)
    - SDC1 $27, GDB_FR_FPR27(sp)
    - SDC1 $28, GDB_FR_FPR28(sp)
    - SDC1 $29, GDB_FR_FPR29(sp)
    - SDC1 $30, GDB_FR_FPR30(sp)
    - SDC1 $31, GDB_FR_FPR31(sp)
    -
    -/*
    - * FPU control registers
    - */
    -
    - cfc1 v0, CP1_STATUS
    - LONG_S v0, GDB_FR_FSR(sp)
    - cfc1 v0, CP1_REVISION
    - LONG_S v0, GDB_FR_FIR(sp)
    -
    -/*
    - * Current stack frame ptr
    - */
    -
    -2:
    - LONG_S sp, GDB_FR_FRP(sp)
    -
    -/*
    - * CP0 registers (R4000/R4400 unused registers skipped)
    - */
    -
    - mfc0 v0, CP0_INDEX
    - LONG_S v0, GDB_FR_CP0_INDEX(sp)
    - mfc0 v0, CP0_RANDOM
    - LONG_S v0, GDB_FR_CP0_RANDOM(sp)
    - DMFC0 v0, CP0_ENTRYLO0
    - LONG_S v0, GDB_FR_CP0_ENTRYLO0(sp)
    - DMFC0 v0, CP0_ENTRYLO1
    - LONG_S v0, GDB_FR_CP0_ENTRYLO1(sp)
    - DMFC0 v0, CP0_CONTEXT
    - LONG_S v0, GDB_FR_CP0_CONTEXT(sp)
    - mfc0 v0, CP0_PAGEMASK
    - LONG_S v0, GDB_FR_CP0_PAGEMASK(sp)
    - mfc0 v0, CP0_WIRED
    - LONG_S v0, GDB_FR_CP0_WIRED(sp)
    - DMFC0 v0, CP0_ENTRYHI
    - LONG_S v0, GDB_FR_CP0_ENTRYHI(sp)
    - mfc0 v0, CP0_PRID
    - LONG_S v0, GDB_FR_CP0_PRID(sp)
    -
    - .set at
    -
    -/*
    - * Continue with the higher level handler
    - */
    -
    - move a0,sp
    -
    - jal handle_exception
    - nop
    -
    -/*
    - * Restore all writable registers, in reverse order
    - */
    -
    - .set noat
    -
    - LONG_L v0, GDB_FR_CP0_ENTRYHI(sp)
    - LONG_L v1, GDB_FR_CP0_WIRED(sp)
    - DMTC0 v0, CP0_ENTRYHI
    - mtc0 v1, CP0_WIRED
    - LONG_L v0, GDB_FR_CP0_PAGEMASK(sp)
    - LONG_L v1, GDB_FR_CP0_ENTRYLO1(sp)
    - mtc0 v0, CP0_PAGEMASK
    - DMTC0 v1, CP0_ENTRYLO1
    - LONG_L v0, GDB_FR_CP0_ENTRYLO0(sp)
    - LONG_L v1, GDB_FR_CP0_INDEX(sp)
    - DMTC0 v0, CP0_ENTRYLO0
    - LONG_L v0, GDB_FR_CP0_CONTEXT(sp)
    - mtc0 v1, CP0_INDEX
    - DMTC0 v0, CP0_CONTEXT
    -
    -
    -/*
    - * Next, the floating point registers
    - */
    - mfc0 v0, CP0_STATUS /* check if the FPU is enabled */
    - srl v0, v0, 16
    - andi v0, v0, (ST0_CU1 >> 16)
    -
    - beqz v0, 3f /* disabled, skip */
    - nop
    -
    - LDC1 $31, GDB_FR_FPR31(sp)
    - LDC1 $30, GDB_FR_FPR30(sp)
    - LDC1 $29, GDB_FR_FPR29(sp)
    - LDC1 $28, GDB_FR_FPR28(sp)
    - LDC1 $27, GDB_FR_FPR27(sp)
    - LDC1 $26, GDB_FR_FPR26(sp)
    - LDC1 $25, GDB_FR_FPR25(sp)
    - LDC1 $24, GDB_FR_FPR24(sp)
    - LDC1 $23, GDB_FR_FPR23(sp)
    - LDC1 $22, GDB_FR_FPR22(sp)
    - LDC1 $21, GDB_FR_FPR21(sp)
    - LDC1 $20, GDB_FR_FPR20(sp)
    - LDC1 $19, GDB_FR_FPR19(sp)
    - LDC1 $18, GDB_FR_FPR18(sp)
    - LDC1 $17, GDB_FR_FPR17(sp)
    - LDC1 $16, GDB_FR_FPR16(sp)
    - LDC1 $15, GDB_FR_FPR15(sp)
    - LDC1 $14, GDB_FR_FPR14(sp)
    - LDC1 $13, GDB_FR_FPR13(sp)
    - LDC1 $12, GDB_FR_FPR12(sp)
    - LDC1 $11, GDB_FR_FPR11(sp)
    - LDC1 $10, GDB_FR_FPR10(sp)
    - LDC1 $9, GDB_FR_FPR9(sp)
    - LDC1 $8, GDB_FR_FPR8(sp)
    - LDC1 $7, GDB_FR_FPR7(sp)
    - LDC1 $6, GDB_FR_FPR6(sp)
    - LDC1 $5, GDB_FR_FPR5(sp)
    - LDC1 $4, GDB_FR_FPR4(sp)
    - LDC1 $3, GDB_FR_FPR3(sp)
    - LDC1 $2, GDB_FR_FPR2(sp)
    - LDC1 $1, GDB_FR_FPR1(sp)
    - LDC1 $0, GDB_FR_FPR0(sp)
    -
    -/*
    - * Now the CP0 and integer registers
    - */
    -
    -3:
    - mfc0 t0, CP0_STATUS
    - ori t0, 0x1f
    - xori t0, 0x1f
    - mtc0 t0, CP0_STATUS
    -
    - LONG_L v0, GDB_FR_STATUS(sp)
    - LONG_L v1, GDB_FR_EPC(sp)
    - mtc0 v0, CP0_STATUS
    - DMTC0 v1, CP0_EPC
    - LONG_L v0, GDB_FR_HI(sp)
    - LONG_L v1, GDB_FR_LO(sp)
    - mthi v0
    - mtlo v1
    - LONG_L $31, GDB_FR_REG31(sp)
    - LONG_L $30, GDB_FR_REG30(sp)
    - LONG_L $28, GDB_FR_REG28(sp)
    - LONG_L $27, GDB_FR_REG27(sp)
    - LONG_L $26, GDB_FR_REG26(sp)
    - LONG_L $25, GDB_FR_REG25(sp)
    - LONG_L $24, GDB_FR_REG24(sp)
    - LONG_L $23, GDB_FR_REG23(sp)
    - LONG_L $22, GDB_FR_REG22(sp)
    - LONG_L $21, GDB_FR_REG21(sp)
    - LONG_L $20, GDB_FR_REG20(sp)
    - LONG_L $19, GDB_FR_REG19(sp)
    - LONG_L $18, GDB_FR_REG18(sp)
    - LONG_L $17, GDB_FR_REG17(sp)
    - LONG_L $16, GDB_FR_REG16(sp)
    - LONG_L $15, GDB_FR_REG15(sp)
    - LONG_L $14, GDB_FR_REG14(sp)
    - LONG_L $13, GDB_FR_REG13(sp)
    - LONG_L $12, GDB_FR_REG12(sp)
    - LONG_L $11, GDB_FR_REG11(sp)
    - LONG_L $10, GDB_FR_REG10(sp)
    - LONG_L $9, GDB_FR_REG9(sp)
    - LONG_L $8, GDB_FR_REG8(sp)
    - LONG_L $7, GDB_FR_REG7(sp)
    - LONG_L $6, GDB_FR_REG6(sp)
    - LONG_L $5, GDB_FR_REG5(sp)
    - LONG_L $4, GDB_FR_REG4(sp)
    - LONG_L $3, GDB_FR_REG3(sp)
    - LONG_L $2, GDB_FR_REG2(sp)
    - LONG_L $1, GDB_FR_REG1(sp)
    -#if defined(CONFIG_CPU_R3000) || defined(CONFIG_CPU_TX39XX)
    - LONG_L k0, GDB_FR_EPC(sp)
    - LONG_L $29, GDB_FR_REG29(sp) /* Deallocate stack */
    - jr k0
    - rfe
    -#else
    - LONG_L sp, GDB_FR_REG29(sp) /* Deallocate stack */
    -
    - .set mips3
    - eret
    - .set mips0
    -#endif
    - .set at
    - .set reorder
    - END(trap_low)
    -
    -LEAF(kgdb_read_byte)
    -4: lb t0, (a0)
    - sb t0, (a1)
    - li v0, 0
    - jr ra
    - .section __ex_table,"a"
    - PTR 4b, kgdbfault
    - .previous
    - END(kgdb_read_byte)
    -
    -LEAF(kgdb_write_byte)
    -5: sb a0, (a1)
    - li v0, 0
    - jr ra
    - .section __ex_table,"a"
    - PTR 5b, kgdbfault
    - .previous
    - END(kgdb_write_byte)
    -
    - .type kgdbfault@function
    - .ent kgdbfault
    -
    -kgdbfault: li v0, -EFAULT
    - jr ra
    - .end kgdbfault
    diff -L arch/mips/kernel/gdb-stub.c -puN arch/mips/kernel/gdb-stub.c~mips-lite /dev/null
    --- linux-2.6.13-rc3/arch/mips/kernel/gdb-stub.c
    +++ /dev/null 2005-07-25 10:57:32.312383000 -0700
    @@ -1,1091 +0,0 @@
    -/*
    - * arch/mips/kernel/gdb-stub.c
    - *
    - * Originally written by Glenn Engel, Lake Stevens Instrument Division
    - *
    - * Contributed by HP Systems
    - *
    - * Modified for SPARC by Stu Grossman, Cygnus Support.
    - *
    - * Modified for Linux/MIPS (and MIPS in general) by Andreas Busse
    - * Send complaints, suggestions etc. to <andy@waldorf-gmbh.de>
    - *
    - * Copyright (C) 1995 Andreas Busse
    - *
    - * Copyright (C) 2003 MontaVista Software Inc.
    - * Author: Jun Sun, jsun@mvista.com or jsun@junsun.net
    - */
    -
    -/*
    - * To enable debugger support, two things need to happen. One, 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.
    - * Two, a breakpoint needs to be generated to begin communication. This
    - * is most easily accomplished by a call to breakpoint(). Breakpoint()
    - * simulates a breakpoint by executing a BREAK instruction.
    - *
    - *
    - * 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
    - *
    - * c Resume at current address SNN ( signal NN)
    - * cAA..AA Continue at address AA..AA SNN
    - *
    - * s Step one instruction SNN
    - * sAA..AA Step one instruction from AA..AA SNN
    - *
    - * k kill
    - *
    - * ? What was the last sigval ? SNN (signal NN)
    - *
    - * bBB..BB Set baud rate to BB..BB OK or BNN, then sets
    - * baud rate
    - *
    - * All commands and responses are sent with a packet which includes a
    - * checksum. A packet consists of
    - *
    - * $<packet info>#<checksum>.
    - *
    - * where
    - * <packet info> :: <characters representing the command or response>
    - * <checksum> :: < two hex digits computed as modulo 256 sum of <packetinfo>>
    - *
    - * When a packet is received, it is first acknowledged with either '+' or '-'.
    - * '+' indicates a successful transfer. '-' indicates a failed transfer.
    - *
    - * Example:
    - *
    - * Host: Reply:
    - * $m0,10#2a +$00010203040506070809101112131415#42
    - *
    - *
    - * ==============
    - * MORE EXAMPLES:
    - * ==============
    - *
    - * For reference -- the following are the steps that one
    - * company took (RidgeRun Inc) to get remote gdb debugging
    - * going. In this scenario the host machine was a PC and the
    - * target platform was a Galileo EVB64120A MIPS evaluation
    - * board.
    - *
    - * Step 1:
    - * First download gdb-5.0.tar.gz from the internet.
    - * and then build/install the package.
    - *
    - * Example:
    - * $ tar zxf gdb-5.0.tar.gz
    - * $ cd gdb-5.0
    - * $ ./configure --target=mips-linux-elf
    - * $ make
    - * $ install
    - * $ which mips-linux-elf-gdb
    - * /usr/local/bin/mips-linux-elf-gdb
    - *
    - * Step 2:
    - * Configure linux for remote debugging and build it.
    - *
    - * Example:
    - * $ cd ~/linux
    - * $ make menuconfig <go to "Kernel Hacking" and turn on remote debugging>
    - * $ make
    - *
    - * Step 3:
    - * Download the kernel to the remote target and start
    - * the kernel running. It will promptly halt and wait
    - * for the host gdb session to connect. It does this
    - * since the "Kernel Hacking" option has defined
    - * CONFIG_KGDB which in turn enables your calls
    - * to:
    - * set_debug_traps();
    - * breakpoint();
    - *
    - * Step 4:
    - * Start the gdb session on the host.
    - *
    - * Example:
    - * $ mips-linux-elf-gdb vmlinux
    - * (gdb) set remotebaud 115200
    - * (gdb) target remote /dev/ttyS1
    - * ...at this point you are connected to
    - * the remote target and can use gdb
    - * in the normal fasion. Setting
    - * breakpoints, single stepping,
    - * printing variables, etc.
    - */
    -#include <linux/config.h>
    -#include <linux/string.h>
    -#include <linux/kernel.h>
    -#include <linux/signal.h>
    -#include <linux/sched.h>
    -#include <linux/mm.h>
    -#include <linux/console.h>
    -#include <linux/init.h>
    -#include <linux/smp.h>
    -#include <linux/spinlock.h>
    -#include <linux/slab.h>
    -#include <linux/reboot.h>
    -
    -#include <asm/asm.h>
    -#include <asm/cacheflush.h>
    -#include <asm/mipsregs.h>
    -#include <asm/pgtable.h>
    -#include <asm/system.h>
    -#include <asm/gdb-stub.h>
    -#include <asm/inst.h>
    -
    -/*
    - * external low-level support routines
    - */
    -
    -extern int putDebugChar(char c); /* write a single character */
    -extern char getDebugChar(void); /* read and return a single char */
    -extern void trap_low(void);
    -
    -/*
    - * breakpoint and test functions
    - */
    -extern void breakpoint(void);
    -extern void breakinst(void);
    -extern void async_breakpoint(void);
    -extern void async_breakinst(void);
    -extern void adel(void);
    -
    -/*
    - * local prototypes
    - */
    -
    -static void getpacket(char *buffer);
    -static void putpacket(char *buffer);
    -static int computeSignal(int tt);
    -static int hex(unsigned char ch);
    -static int hexToInt(char **ptr, int *intValue);
    -static int hexToLong(char **ptr, long *longValue);
    -static unsigned char *mem2hex(char *mem, char *buf, int count, int may_fault);
    -void handle_exception(struct gdb_regs *regs);
    -
    -int kgdb_enabled;
    -
    -/*
    - * spin locks for smp case
    - */
    -static spinlock_t kgdb_lock = SPIN_LOCK_UNLOCKED;
    -static spinlock_t kgdb_cpulock[NR_CPUS] = { [0 ... NR_CPUS-1] = SPIN_LOCK_UNLOCKED};
    -
    -/*
    - * BUFMAX defines the maximum number of characters in inbound/outbound buffers
    - * at least NUMREGBYTES*2 are needed for register packets
    - */
    -#define BUFMAX 2048
    -
    -static char input_buffer[BUFMAX];
    -static char output_buffer[BUFMAX];
    -static int initialized; /* !0 means we've been initialized */
    -static int kgdb_started;
    -static const char hexchars[]="0123456789abcdef";
    -
    -/* Used to prevent crashes in memory access. Note that they'll crash anyway if
    - we haven't set up fault handlers yet... */
    -int kgdb_read_byte(unsigned char *address, unsigned char *dest);
    -int kgdb_write_byte(unsigned char val, unsigned char *dest);
    -
    -/*
    - * Convert ch from a hex digit to an int
    - */
    -static int hex(unsigned 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;
    -}
    -
    -/*
    - * scan for the sequence $<data>#<checksum>
    - */
    -static void getpacket(char *buffer)
    -{
    - unsigned char checksum;
    - unsigned char xmitcsum;
    - int i;
    - int count;
    - unsigned char ch;
    -
    - do {
    - /*
    - * wait around for the start character,
    - * ignore all other characters
    - */
    - while ((ch = (getDebugChar() & 0x7f)) != '$') ;
    -
    - checksum = 0;
    - xmitcsum = -1;
    - count = 0;
    -
    - /*
    - * now, read until a # or end of buffer is found
    - */
    - while (count < BUFMAX) {
    - ch = getDebugChar();
    - if (ch == '#')
    - break;
    - checksum = checksum + ch;
    - buffer[count] = ch;
    - count = count + 1;
    - }
    -
    - if (count >= BUFMAX)
    - continue;
    -
    - buffer[count] = 0;
    -
    - if (ch == '#') {
    - xmitcsum = hex(getDebugChar() & 0x7f) << 4;
    - xmitcsum |= hex(getDebugChar() & 0x7f);
    -
    - if (checksum != xmitcsum)
    - putDebugChar('-'); /* failed checksum */
    - else {
    - putDebugChar('+'); /* successful transfer */
    -
    - /*
    - * if a sequence char is present,
    - * reply the sequence ID
    - */
    - if (buffer[2] == ':') {
    - putDebugChar(buffer[0]);
    - putDebugChar(buffer[1]);
    -
    - /*
    - * remove sequence chars from buffer
    - */
    - count = strlen(buffer);
    - for (i=3; i <= count; i++)
    - buffer[i-3] = buffer[i];
    - }
    - }
    - }
    - }
    - while (checksum != xmitcsum);
    -}
    -
    -/*
    - * send the packet in buffer.
    - */
    -static void putpacket(char *buffer)
    -{
    - unsigned char checksum;
    - int count;
    - unsigned char ch;
    -
    - /*
    - * $<packet info>#<checksum>.
    - */
    -
    - do {
    - putDebugChar('$');
    - checksum = 0;
    - count = 0;
    -
    - while ((ch = buffer[count]) != 0) {
    - if (!(putDebugChar(ch)))
    - return;
    - checksum += ch;
    - count += 1;
    - }
    -
    - putDebugChar('#');
    - putDebugChar(hexchars[checksum >> 4]);
    - putDebugChar(hexchars[checksum & 0xf]);
    -
    - }
    - while ((getDebugChar() & 0x7f) != '+');
    -}
    -
    -
    -/*
    - * Convert the memory pointed to by mem into hex, placing result in buf.
    - * Return a pointer to the last char put in buf (null), in case of mem fault,
    - * return 0.
    - * may_fault is non-zero if we are reading from arbitrary memory, but is currently
    - * not used.
    - */
    -static unsigned char *mem2hex(char *mem, char *buf, int count, int may_fault)
    -{
    - unsigned char ch;
    -
    - while (count-- > 0) {
    - if (kgdb_read_byte(mem++, &ch) != 0)
    - return 0;
    - *buf++ = hexchars[ch >> 4];
    - *buf++ = hexchars[ch & 0xf];
    - }
    -
    - *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
    - * may_fault is non-zero if we are reading from arbitrary memory, but is currently
    - * not used.
    - */
    -static char *hex2mem(char *buf, char *mem, int count, int binary, int may_fault)
    -{
    - int i;
    - unsigned char ch;
    -
    - for (i=0; i<count; i++)
    - {
    - if (binary) {
    - ch = *buf++;
    - if (ch == 0x7d)
    - ch = 0x20 ^ *buf++;
    - }
    - else {
    - ch = hex(*buf++) << 4;
    - ch |= hex(*buf++);
    - }
    - if (kgdb_write_byte(ch, mem++) != 0)
    - return 0;
    - }
    -
    - return mem;
    -}
    -
    -/*
    - * This table contains the mapping between SPARC hardware trap types, and
    - * signals, which are primarily what GDB understands. It also indicates
    - * which hardware traps we need to commandeer when initializing the stub.
    - */
    -static struct hard_trap_info {
    - unsigned char tt; /* Trap type code for MIPS R3xxx and R4xxx */
    - unsigned char signo; /* Signal that we map this trap into */
    -} hard_trap_info[] = {
    - { 6, SIGBUS }, /* instruction bus error */
    - { 7, SIGBUS }, /* data bus error */
    - { 9, SIGTRAP }, /* break */
    - { 10, SIGILL }, /* reserved instruction */
    -/* { 11, SIGILL }, */ /* CPU unusable */
    - { 12, SIGFPE }, /* overflow */
    - { 13, SIGTRAP }, /* trap */
    - { 14, SIGSEGV }, /* virtual instruction cache coherency */
    - { 15, SIGFPE }, /* floating point exception */
    - { 23, SIGSEGV }, /* watch */
    - { 31, SIGSEGV }, /* virtual data cache coherency */
    - { 0, 0} /* Must be last */
    -};
    -
    -/* Save the normal trap handlers for user-mode traps. */
    -void *saved_vectors[32];
    -
    -/*
    - * Set up exception handlers for tracing and breakpoints
    - */
    -void set_debug_traps(void)
    -{
    - struct hard_trap_info *ht;
    - unsigned long flags;
    - unsigned char c;
    -
    - local_irq_save(flags);
    - for (ht = hard_trap_info; ht->tt && ht->signo; ht++)
    - saved_vectors[ht->tt] = set_except_vector(ht->tt, trap_low);
    -
    - putDebugChar('+'); /* 'hello world' */
    - /*
    - * In case GDB is started before us, ack any packets
    - * (presumably "$?#xx") sitting there.
    - */
    - while((c = getDebugChar()) != '$');
    - while((c = getDebugChar()) != '#');
    - c = getDebugChar(); /* eat first csum byte */
    - c = getDebugChar(); /* eat second csum byte */
    - putDebugChar('+'); /* ack it */
    -
    - initialized = 1;
    - local_irq_restore(flags);
    -}
    -
    -void restore_debug_traps(void)
    -{
    - struct hard_trap_info *ht;
    - unsigned long flags;
    -
    - local_irq_save(flags);
    - for (ht = hard_trap_info; ht->tt && ht->signo; ht++)
    - set_except_vector(ht->tt, saved_vectors[ht->tt]);
    - local_irq_restore(flags);
    -}
    -
    -/*
    - * Convert the MIPS hardware trap type code to a Unix signal number.
    - */
    -static int computeSignal(int tt)
    -{
    - struct hard_trap_info *ht;
    -
    - for (ht = hard_trap_info; ht->tt && ht->signo; ht++)
    - if (ht->tt == tt)
    - return ht->signo;
    -
    - return SIGHUP; /* default for things we don't know about */
    -}
    -
    -/*
    - * While we find nice hex chars, build an int.
    - * Return number of chars processed.
    - */
    -static int hexToInt(char **ptr, int *intValue)
    -{
    - int numChars = 0;
    - int hexValue;
    -
    - *intValue = 0;
    -
    - while (**ptr) {
    - hexValue = hex(**ptr);
    - if (hexValue < 0)
    - break;
    -
    - *intValue = (*intValue << 4) | hexValue;
    - numChars ++;
    -
    - (*ptr)++;
    - }
    -
    - return (numChars);
    -}
    -
    -static int hexToLong(char **ptr, long *longValue)
    -{
    - int numChars = 0;
    - int hexValue;
    -
    - *longValue = 0;
    -
    - while (**ptr) {
    - hexValue = hex(**ptr);
    - if (hexValue < 0)
    - break;
    -
    - *longValue = (*longValue << 4) | hexValue;
    - numChars ++;
    -
    - (*ptr)++;
    - }
    -
    - return numChars;
    -}
    -
    -
    -#if 0
    -/*
    - * Print registers (on target console)
    - * Used only to debug the stub...
    - */
    -void show_gdbregs(struct gdb_regs * regs)
    -{
    - /*
    - * Saved main processor registers
    - */
    - printk("$0 : %08lx %08lx %08lx %08lx %08lx %08lx %08lx %08lx\n",
    - regs->reg0, regs->reg1, regs->reg2, regs->reg3,
    - regs->reg4, regs->reg5, regs->reg6, regs->reg7);
    - printk("$8 : %08lx %08lx %08lx %08lx %08lx %08lx %08lx %08lx\n",
    - regs->reg8, regs->reg9, regs->reg10, regs->reg11,
    - regs->reg12, regs->reg13, regs->reg14, regs->reg15);
    - printk("$16: %08lx %08lx %08lx %08lx %08lx %08lx %08lx %08lx\n",
    - regs->reg16, regs->reg17, regs->reg18, regs->reg19,
    - regs->reg20, regs->reg21, regs->reg22, regs->reg23);
    - printk("$24: %08lx %08lx %08lx %08lx %08lx %08lx %08lx %08lx\n",
    - regs->reg24, regs->reg25, regs->reg26, regs->reg27,
    - regs->reg28, regs->reg29, regs->reg30, regs->reg31);
    -
    - /*
    - * Saved cp0 registers
    - */
    - printk("epc : %08lx\nStatus: %08lx\nCause : %08lx\n",
    - regs->cp0_epc, regs->cp0_status, regs->cp0_cause);
    -}
    -#endif /* dead code */
    -
    -/*
    - * We single-step by setting breakpoints. When an exception
    - * is handled, we need to restore the instructions hoisted
    - * when the breakpoints were set.
    - *
    - * This is where we save the original instructions.
    - */
    -static struct gdb_bp_save {
    - unsigned long addr;
    - unsigned int val;
    -} step_bp[2];
    -
    -#define BP 0x0000000d /* break opcode */
    -
    -/*
    - * Set breakpoint instructions for single stepping.
    - */
    -static void single_step(struct gdb_regs *regs)
    -{
    - union mips_instruction insn;
    - unsigned long targ;
    - int is_branch, is_cond, i;
    -
    - targ = regs->cp0_epc;
    - insn.word = *(unsigned int *)targ;
    - is_branch = is_cond = 0;
    -
    - switch (insn.i_format.opcode) {
    - /*
    - * jr and jalr are in r_format format.
    - */
    - case spec_op:
    - switch (insn.r_format.func) {
    - case jalr_op:
    - case jr_op:
    - targ = *(&regs->reg0 + insn.r_format.rs);
    - is_branch = 1;
    - break;
    - }
    - break;
    -
    - /*
    - * This group contains:
    - * bltz_op, bgez_op, bltzl_op, bgezl_op,
    - * bltzal_op, bgezal_op, bltzall_op, bgezall_op.
    - */
    - case bcond_op:
    - is_branch = is_cond = 1;
    - targ += 4 + (insn.i_format.simmediate << 2);
    - break;
    -
    - /*
    - * These are unconditional and in j_format.
    - */
    - case jal_op:
    - case j_op:
    - is_branch = 1;
    - targ += 4;
    - targ >>= 28;
    - targ <<= 28;
    - targ |= (insn.j_format.target << 2);
    - break;
    -
    - /*
    - * These are conditional.
    - */
    - case beq_op:
    - case beql_op:
    - case bne_op:
    - case bnel_op:
    - case blez_op:
    - case blezl_op:
    - case bgtz_op:
    - case bgtzl_op:
    - case cop0_op:
    - case cop1_op:
    - case cop2_op:
    - case cop1x_op:
    - is_branch = is_cond = 1;
    - targ += 4 + (insn.i_format.simmediate << 2);
    - break;
    - }
    -
    - if (is_branch) {
    - i = 0;
    - if (is_cond && targ != (regs->cp0_epc + 8)) {
    - step_bp[i].addr = regs->cp0_epc + 8;
    - step_bp[i++].val = *(unsigned *)(regs->cp0_epc + 8);
    - *(unsigned *)(regs->cp0_epc + 8) = BP;
    - }
    - step_bp[i].addr = targ;
    - step_bp[i].val = *(unsigned *)targ;
    - *(unsigned *)targ = BP;
    - } else {
    - step_bp[0].addr = regs->cp0_epc + 4;
    - step_bp[0].val = *(unsigned *)(regs->cp0_epc + 4);
    - *(unsigned *)(regs->cp0_epc + 4) = BP;
    - }
    -}
    -
    -/*
    - * If asynchronously interrupted by gdb, then we need to set a breakpoint
    - * at the interrupted instruction so that we wind up stopped with a
    - * reasonable stack frame.
    - */
    -static struct gdb_bp_save async_bp;
    -
    -/*
    - * Swap the interrupted EPC with our asynchronous breakpoint routine.
    - * This is safer than stuffing the breakpoint in-place, since no cache
    - * flushes (or resulting smp_call_functions) are required. The
    - * assumption is that only one CPU will be handling asynchronous bp's,
    - * and only one can be active at a time.
    - */
    -extern spinlock_t smp_call_lock;
    -void set_async_breakpoint(unsigned long *epc)
    -{
    - /* skip breaking into userland */
    - if ((*epc & 0x80000000) == 0)
    - return;
    -
    - /* avoid deadlock if someone is make IPC */
    - if (spin_is_locked(&smp_call_lock))
    - return;
    -
    - async_bp.addr = *epc;
    - *epc = (unsigned long)async_breakpoint;
    -}
    -
    -void kgdb_wait(void *arg)
    -{
    - unsigned flags;
    - int cpu = smp_processor_id();
    -
    - local_irq_save(flags);
    -
    - spin_lock(&kgdb_cpulock[cpu]);
    - spin_unlock(&kgdb_cpulock[cpu]);
    -
    - local_irq_restore(flags);
    -}
    -
    -
    -/*
    - * This function does all command processing for interfacing to gdb. It
    - * returns 1 if you should skip the instruction at the trap address, 0
    - * otherwise.
    - */
    -void handle_exception (struct gdb_regs *regs)
    -{
    - int trap; /* Trap type */
    - int sigval;
    - long addr;
    - int length;
    - char *ptr;
    - unsigned long *stack;
    - int i;
    - int bflag = 0;
    -
    - kgdb_started = 1;
    -
    - /*
    - * acquire the big kgdb spinlock
    - */
    - if (!spin_trylock(&kgdb_lock)) {
    - /*
    - * some other CPU has the lock, we should go back to
    - * receive the gdb_wait IPC
    - */
    - return;
    - }
    -
    - /*
    - * If we're in async_breakpoint(), restore the real EPC from
    - * the breakpoint.
    - */
    - if (regs->cp0_epc == (unsigned long)async_breakinst) {
    - regs->cp0_epc = async_bp.addr;
    - async_bp.addr = 0;
    - }
    -
    - /*
    - * acquire the CPU spinlocks
    - */
    - for (i = num_online_cpus()-1; i >= 0; i--)
    - if (spin_trylock(&kgdb_cpulock[i]) == 0)
    - panic("kgdb: couldn't get cpulock %d\n", i);
    -
    - /*
    - * force other cpus to enter kgdb
    - */
    - smp_call_function(kgdb_wait, NULL, 0, 0);
    -
    - /*
    - * If we're in breakpoint() increment the PC
    - */
    - trap = (regs->cp0_cause & 0x7c) >> 2;
    - if (trap == 9 && regs->cp0_epc == (unsigned long)breakinst)
    - regs->cp0_epc += 4;
    -
    - /*
    - * If we were single_stepping, restore the opcodes hoisted
    - * for the breakpoint[s].
    - */
    - if (step_bp[0].addr) {
    - *(unsigned *)step_bp[0].addr = step_bp[0].val;
    - step_bp[0].addr = 0;
    -
    - if (step_bp[1].addr) {
    - *(unsigned *)step_bp[1].addr = step_bp[1].val;
    - step_bp[1].addr = 0;
    - }
    - }
    -
    - stack = (long *)regs->reg29; /* stack ptr */
    - sigval = computeSignal(trap);
    -
    - /*
    - * reply to host that an exception has occurred
    - */
    - ptr = output_buffer;
    -
    - /*
    - * Send trap type (converted to signal)
    - */
    - *ptr++ = 'T';
    - *ptr++ = hexchars[sigval >> 4];
    - *ptr++ = hexchars[sigval & 0xf];
    -
    - /*
    - * Send Error PC
    - */
    - *ptr++ = hexchars[REG_EPC >> 4];
    - *ptr++ = hexchars[REG_EPC & 0xf];
    - *ptr++ = ':';
    - ptr = mem2hex((char *)&regs->cp0_epc, ptr, sizeof(long), 0);
    - *ptr++ = ';';
    -
    - /*
    - * Send frame pointer
    - */
    - *ptr++ = hexchars[REG_FP >> 4];
    - *ptr++ = hexchars[REG_FP & 0xf];
    - *ptr++ = ':';
    - ptr = mem2hex((char *)&regs->reg30, ptr, sizeof(long), 0);
    - *ptr++ = ';';
    -
    - /*
    - * Send stack pointer
    - */
    - *ptr++ = hexchars[REG_SP >> 4];
    - *ptr++ = hexchars[REG_SP & 0xf];
    - *ptr++ = ':';
    - ptr = mem2hex((char *)&regs->reg29, ptr, sizeof(long), 0);
    - *ptr++ = ';';
    -
    - *ptr++ = 0;
    - putpacket(output_buffer); /* send it off... */
    -
    - /*
    - * Wait for input from remote GDB
    - */
    - while (1) {
    - output_buffer[0] = 0;
    - getpacket(input_buffer);
    -
    - switch (input_buffer[0])
    - {
    - case '?':
    - output_buffer[0] = 'S';
    - output_buffer[1] = hexchars[sigval >> 4];
    - output_buffer[2] = hexchars[sigval & 0xf];
    - output_buffer[3] = 0;
    - break;
    -
    - /*
    - * Detach debugger; let CPU run
    - */
    - case 'D':
    - putpacket(output_buffer);
    - goto finish_kgdb;
    - break;
    -
    - case 'd':
    - /* toggle debug flag */
    - break;
    -
    - /*
    - * Return the value of the CPU registers
    - */
    - case 'g':
    - ptr = output_buffer;
    - ptr = mem2hex((char *)&regs->reg0, ptr, 32*sizeof(long), 0); /* r0...r31 */
    - ptr = mem2hex((char *)&regs->cp0_status, ptr, 6*sizeof(long), 0); /* cp0 */
    - ptr = mem2hex((char *)&regs->fpr0, ptr, 32*sizeof(long), 0); /* f0...31 */
    - ptr = mem2hex((char *)&regs->cp1_fsr, ptr, 2*sizeof(long), 0); /* cp1 */
    - ptr = mem2hex((char *)&regs->frame_ptr, ptr, 2*sizeof(long), 0); /* frp */
    - ptr = mem2hex((char *)&regs->cp0_index, ptr, 16*sizeof(long), 0); /* cp0 */
    - break;
    -
    - /*
    - * set the value of the CPU registers - return OK
    - */
    - case 'G':
    - {
    - ptr = &input_buffer[1];
    - hex2mem(ptr, (char *)&regs->reg0, 32*sizeof(long), 0, 0);
    - ptr += 32*(2*sizeof(long));
    - hex2mem(ptr, (char *)&regs->cp0_status, 6*sizeof(long), 0, 0);
    - ptr += 6*(2*sizeof(long));
    - hex2mem(ptr, (char *)&regs->fpr0, 32*sizeof(long), 0, 0);
    - ptr += 32*(2*sizeof(long));
    - hex2mem(ptr, (char *)&regs->cp1_fsr, 2*sizeof(long), 0, 0);
    - ptr += 2*(2*sizeof(long));
    - hex2mem(ptr, (char *)&regs->frame_ptr, 2*sizeof(long), 0, 0);
    - ptr += 2*(2*sizeof(long));
    - hex2mem(ptr, (char *)&regs->cp0_index, 16*sizeof(long), 0, 0);
    - strcpy(output_buffer,"OK");
    - }
    - break;
    -
    - /*
    - * mAA..AA,LLLL Read LLLL bytes at address AA..AA
    - */
    - case 'm':
    - ptr = &input_buffer[1];
    -
    - if (hexToLong(&ptr, &addr)
    - && *ptr++ == ','
    - && hexToInt(&ptr, &length)) {
    - if (mem2hex((char *)addr, output_buffer, length, 1))
    - break;
    - strcpy (output_buffer, "E03");
    - } else
    - strcpy(output_buffer,"E01");
    - break;
    -
    - /*
    - * XAA..AA,LLLL: Write LLLL escaped binary bytes at address AA.AA
    - */
    - case 'X':
    - bflag = 1;
    - /* fall through */
    -
    - /*
    - * MAA..AA,LLLL: Write LLLL bytes at address AA.AA return OK
    - */
    - case 'M':
    - ptr = &input_buffer[1];
    -
    - if (hexToLong(&ptr, &addr)
    - && *ptr++ == ','
    - && hexToInt(&ptr, &length)
    - && *ptr++ == ':') {
    - if (hex2mem(ptr, (char *)addr, length, bflag, 1))
    - strcpy(output_buffer, "OK");
    - else
    - strcpy(output_buffer, "E03");
    - }
    - else
    - strcpy(output_buffer, "E02");
    - break;
    -
    - /*
    - * cAA..AA Continue at address AA..AA(optional)
    - */
    - case 'c':
    - /* try to read optional parameter, pc unchanged if no parm */
    -
    - ptr = &input_buffer[1];
    - if (hexToLong(&ptr, &addr))
    - regs->cp0_epc = addr;
    -
    - goto exit_kgdb_exception;
    - break;
    -
    - /*
    - * kill the program; let us try to restart the machine
    - * Reset the whole machine.
    - */
    - case 'k':
    - case 'r':
    - machine_restart("kgdb restarts machine");
    - break;
    -
    - /*
    - * Step to next instruction
    - */
    - case 's':
    - /*
    - * There is no single step insn in the MIPS ISA, so we
    - * use breakpoints and continue, instead.
    - */
    - single_step(regs);
    - goto exit_kgdb_exception;
    - /* NOTREACHED */
    - break;
    -
    - /*
    - * Set baud rate (bBB)
    - * FIXME: Needs to be written
    - */
    - case 'b':
    - {
    -#if 0
    - int baudrate;
    - extern void set_timer_3();
    -
    - ptr = &input_buffer[1];
    - if (!hexToInt(&ptr, &baudrate))
    - {
    - strcpy(output_buffer,"B01");
    - break;
    - }
    -
    - /* Convert baud rate to uart clock divider */
    -
    - switch (baudrate)
    - {
    - case 38400:
    - baudrate = 16;
    - break;
    - case 19200:
    - baudrate = 33;
    - break;
    - case 9600:
    - baudrate = 65;
    - break;
    - default:
    - baudrate = 0;
    - strcpy(output_buffer,"B02");
    - goto x1;
    - }
    -
    - if (baudrate) {
    - putpacket("OK"); /* Ack before changing speed */
    - set_timer_3(baudrate); /* Set it */
    - }
    -#endif
    - }
    - break;
    -
    - } /* switch */
    -
    - /*
    - * reply to the request
    - */
    -
    - putpacket(output_buffer);
    -
    - } /* while */
    -
    - return;
    -
    -finish_kgdb:
    - restore_debug_traps();
    -
    -exit_kgdb_exception:
    - /* release locks so other CPUs can go */
    - for (i = num_online_cpus()-1; i >= 0; i--)
    - spin_unlock(&kgdb_cpulock[i]);
    - spin_unlock(&kgdb_lock);
    -
    - __flush_cache_all();
    - return;
    -}
    -
    -/*
    - * This function will generate a breakpoint exception. It is used at the
    - * beginning of a program to sync up with a debugger and can be used
    - * otherwise as a quick means to stop program execution and "break" into
    - * the debugger.
    - */
    -void breakpoint(void)
    -{
    - if (!initialized)
    - return;
    -
    - __asm__ __volatile__(
    - ".globl breakinst\n\t"
    - ".set\tnoreorder\n\t"
    - "nop\n"
    - "breakinst:\tbreak\n\t"
    - "nop\n\t"
    - ".set\treorder"
    - );
    -}
    -
    -/* Nothing but the break; don't pollute any registers */
    -void async_breakpoint(void)
    -{
    - __asm__ __volatile__(
    - ".globl async_breakinst\n\t"
    - ".set\tnoreorder\n\t"
    - "nop\n"
    - "async_breakinst:\tbreak\n\t"
    - "nop\n\t"
    - ".set\treorder"
    - );
    -}
    -
    -void adel(void)
    -{
    - __asm__ __volatile__(
    - ".globl\tadel\n\t"
    - "lui\t$8,0x8000\n\t"
    - "lw\t$9,1($8)\n\t"
    - );
    -}
    -
    -/*
    - * malloc is needed by gdb client in "call func()", even a private one
    - * will make gdb happy
    - */
    -static void *malloc(size_t size)
    -{
    - return kmalloc(size, GFP_ATOMIC);
    -}
    -
    -static void free(void *where)
    -{
    - kfree(where);
    -}
    -
    -#ifdef CONFIG_GDB_CONSOLE
    -
    -void gdb_putsn(const char *str, int l)
    -{
    - char outbuf[18];
    -
    - if (!kgdb_started)
    - return;
    -
    - outbuf[0]='O';
    -
    - while(l) {
    - int i = (l>8)?8:l;
    - mem2hex((char *)str, &outbuf[1], i, 0);
    - outbuf[(i*2)+1]=0;
    - putpacket(outbuf);
    - str += i;
    - l -= i;
    - }
    -}
    -
    -static void gdb_console_write(struct console *con, const char *s, unsigned n)
    -{
    - gdb_putsn(s, n);
    -}
    -
    -static struct console gdb_console = {
    - .name = "gdb",
    - .write = gdb_console_write,
    - .flags = CON_PRINTBUFFER,
    - .index = -1
    -};
    -
    -static int __init register_gdb_console(void)
    -{
    - register_console(&gdb_console);
    -
    - return 0;
    -}
    -
    -console_initcall(register_gdb_console);
    -
    -#endif
    diff -puN arch/mips/kernel/irq.c~mips-lite arch/mips/kernel/irq.c
    --- linux-2.6.13-rc3/arch/mips/kernel/irq.c~mips-lite 2005-07-29 11:55:31.000000000 -0700
    +++ linux-2.6.13-rc3-trini/arch/mips/kernel/irq.c 2005-07-29 11:55:31.000000000 -0700
    @@ -26,6 +26,10 @@
    #include <asm/atomic.h>
    #include <asm/system.h>
    #include <asm/uaccess.h>
    +#include <asm/kgdb.h>
    +
    +/* Keep track of if we've done certain initialization already or not. */
    +int kgdb_early_setup;

    /*
    * 'what should we do if we get a hw irq event on an illegal vector'.
    @@ -103,23 +107,13 @@ skip:
    return 0;
    }

    -#ifdef CONFIG_KGDB
    -extern void breakpoint(void);
    -extern void set_debug_traps(void);
    -
    -static int kgdb_flag = 1;
    -static int __init nokgdb(char *str)
    -{
    - kgdb_flag = 0;
    - return 1;
    -}
    -__setup("nokgdb", nokgdb);
    -#endif
    -
    void __init init_IRQ(void)
    {
    int i;

    + if (kgdb_early_setup)
    + return;
    +
    for (i = 0; i < NR_IRQS; i++) {
    irq_desc[i].status = IRQ_DISABLED;
    irq_desc[i].action = NULL;
    @@ -129,12 +123,12 @@ void __init init_IRQ(void)
    }

    arch_init_irq();
    -
    #ifdef CONFIG_KGDB
    - if (kgdb_flag) {
    - printk("Wait for gdb client connection ...\n");
    - set_debug_traps();
    - breakpoint();
    - }
    + /*
    + * We have been called before kgdb_arch_init(). Hence,
    + * we dont want the traps to be reinitialized
    + */
    + if (kgdb_early_setup == 0)
    + kgdb_early_setup = 1;
    #endif
    }
    diff -puN /dev/null arch/mips/kernel/kgdb.c
    --- /dev/null 2005-07-25 10:57:32.312383000 -0700
    +++ linux-2.6.13-rc3-trini/arch/mips/kernel/kgdb.c 2005-07-29 11:55:31.000000000 -0700
    @@ -0,0 +1,292 @@
    +/*
    + * arch/mips/kernel/kgdb.c
    + *
    + * Originally written by Glenn Engel, Lake Stevens Instrument Division
    + *
    + * Contributed by HP Systems
    + *
    + * Modified for SPARC by Stu Grossman, Cygnus Support.
    + *
    + * Modified for Linux/MIPS (and MIPS in general) by Andreas Busse
    + * Send complaints, suggestions etc. to <andy@waldorf-gmbh.de>
    + *
    + * Copyright (C) 1995 Andreas Busse
    + *
    + * Copyright (C) 2003 MontaVista Software Inc.
    + * Author: Jun Sun, jsun@mvista.com or jsun@junsun.net
    + *
    + * Copyright (C) 2004-2005 MontaVista Software Inc.
    + * Author: Manish Lachwani, mlachwani@mvista.com or manish@koffee-break.com
    + *
    + * 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 <asm/system.h>
    +#include <asm/ptrace.h> /* for linux pt_regs struct */
    +#include <linux/kgdb.h>
    +#include <linux/init.h>
    +#include <asm/inst.h>
    +#include <asm/gdb-stub.h>
    +#include <asm/cacheflush.h>
    +#include <asm/kdebug.h>
    +
    +static struct hard_trap_info {
    + unsigned char tt; /* Trap type code for MIPS R3xxx and R4xxx */
    + unsigned char signo; /* Signal that we map this trap into */
    +} hard_trap_info[] = {
    + { 6, SIGBUS }, /* instruction bus error */
    + { 7, SIGBUS }, /* data bus error */
    + { 9, SIGTRAP }, /* break */
    +/* { 11, SIGILL }, */ /* CPU unusable */
    + { 12, SIGFPE }, /* overflow */
    + { 13, SIGTRAP }, /* trap */
    + { 14, SIGSEGV }, /* virtual instruction cache coherency */
    + { 15, SIGFPE }, /* floating point exception */
    + { 23, SIGSEGV }, /* watch */
    + { 31, SIGSEGV }, /* virtual data cache coherency */
    + { 0, 0} /* Must be last */
    +};
    +
    +/* Save the normal trap handlers for user-mode traps. */
    +void *saved_vectors[32];
    +
    +extern void trap_low(void);
    +extern void breakinst(void);
    +extern void init_IRQ(void);
    +
    +void kgdb_call_nmi_hook(void *ignored)
    +{
    + kgdb_nmihook(smp_processor_id(), (void *)0);
    +}
    +
    +void kgdb_roundup_cpus(unsigned long flags)
    +{
    + local_irq_restore(flags);
    + smp_call_function(kgdb_call_nmi_hook, 0, 0, 0);
    + local_irq_save(flags);
    +}
    +
    +static int compute_signal(int tt)
    +{
    + struct hard_trap_info *ht;
    +
    + for (ht = hard_trap_info; ht->tt && ht->signo; ht++)
    + if (ht->tt == tt)
    + return ht->signo;
    +
    + return SIGHUP; /* default for things we don't know about */
    +}
    +
    +/*
    + * Set up exception handlers for tracing and breakpoints
    + */
    +void handle_exception(struct pt_regs *regs)
    +{
    + int trap = (regs->cp0_cause & 0x7c) >> 2;
    +
    + if (atomic_read(&debugger_active))
    + kgdb_nmihook(smp_processor_id(), regs);
    +
    + if (atomic_read(&kgdb_setting_breakpoint))
    + if ((trap == 9) && (regs->cp0_epc == (unsigned long)breakinst))
    + regs->cp0_epc += 4;
    +
    + kgdb_handle_exception(0, compute_signal(trap), 0, regs);
    +
    + /* In SMP mode, __flush_cache_all does IPI */
    + __flush_cache_all();
    +}
    +
    +void set_debug_traps(void)
    +{
    + struct hard_trap_info *ht;
    + unsigned long flags;
    +
    + local_irq_save(flags);
    +
    + for (ht = hard_trap_info; ht->tt && ht->signo; ht++)
    + saved_vectors[ht->tt] = set_except_vector(ht->tt, trap_low);
    +
    + local_irq_restore(flags);
    +}
    +
    +#if 0
    +/* This should be called before we exit kgdb_handle_exception() I believe.
    + * -- Tom
    + */
    +void restore_debug_traps(void)
    +{
    + struct hard_trap_info *ht;
    + unsigned long flags;
    +
    + local_irq_save(flags);
    + for (ht = hard_trap_info; ht->tt && ht->signo; ht++)
    + set_except_vector(ht->tt, saved_vectors[ht->tt]);
    + local_irq_restore(flags);
    +}
    +#endif
    +
    +void regs_to_gdb_regs(unsigned long *gdb_regs, struct pt_regs *regs)
    +{
    + int reg = 0;
    + unsigned long *ptr = gdb_regs;
    +
    + for (reg = 0; reg < 32; reg++)
    + *(ptr++) = regs->regs[reg];
    +
    + *(ptr++) = regs->cp0_status;
    + *(ptr++) = regs->lo;
    + *(ptr++) = regs->hi;
    + *(ptr++) = regs->cp0_badvaddr;
    + *(ptr++) = regs->cp0_cause;
    + *(ptr++) = regs->cp0_epc;
    +
    + return;
    +}
    +
    +void gdb_regs_to_regs(unsigned long *gdb_regs, struct pt_regs *regs)
    +{
    + int reg = 0;
    + unsigned long *ptr = gdb_regs;
    +
    + for (reg = 0; reg < 32; reg++)
    + regs->regs[reg] = *(ptr++);
    +
    + regs->cp0_status = *(ptr++);
    + regs->lo = *(ptr++);
    + regs->hi = *(ptr++);
    + regs->cp0_badvaddr = *(ptr++);
    + regs->cp0_cause = *(ptr++);
    + regs->cp0_epc = *(ptr++);
    +
    + return;
    +}
    +
    +/*
    + * Similar to regs_to_gdb_regs() except that process is sleeping and so
    + * we may not be able to get all the info.
    + */
    +void sleeping_thread_to_gdb_regs(unsigned long *gdb_regs, struct task_struct *p)
    +{
    + int reg = 0;
    + struct thread_info *ti = p->thread_info;
    + unsigned long ksp = (unsigned long)ti + THREAD_SIZE - 32;
    + struct pt_regs *regs = (struct pt_regs *)ksp - 1;
    + unsigned long *ptr = gdb_regs;
    +
    + for (reg = 0; reg < 16; reg++)
    + *(ptr++) = regs->regs[reg];
    +
    + /* S0 - S7 */
    + for (reg = 16; reg < 24; reg++)
    + *(ptr++) = regs->regs[reg];
    +
    + for (reg = 24; reg < 28; reg++)
    + *(ptr++) = 0;
    +
    + /* GP, SP, FP, RA */
    + for (reg = 28; reg < 32; reg++)
    + *(ptr++) = regs->regs[reg];
    +
    + *(ptr++) = regs->cp0_status;
    + *(ptr++) = regs->lo;
    + *(ptr++) = regs->hi;
    + *(ptr++) = regs->cp0_badvaddr;
    + *(ptr++) = regs->cp0_cause;
    + *(ptr++) = regs->cp0_epc;
    +
    + return;
    +}
    +
    +/*
    + * Calls linux_debug_hook before the kernel dies. If KGDB is enabled,
    + * then try to fall into the debugger
    + */
    +static int kgdb_mips_notify(struct notifier_block *self, unsigned long cmd,
    + void *ptr)
    +{
    + struct die_args *args = (struct die_args *)ptr;
    + struct pt_regs *regs = args->regs;
    + int trap = (regs->cp0_cause & 0x7c) >> 2;
    +
    + /* See if KGDB is interested. */
    + if (user_mode(regs))
    + /* Userpace events, ignore. */
    + return NOTIFY_DONE;
    +
    + kgdb_handle_exception(trap, compute_signal(trap), 0, regs);
    + return NOTIFY_OK;
    +}
    +
    +static struct notifier_block kgdb_notifier = {
    + .notifier_call = kgdb_mips_notify,
    +};
    +
    +/*
    + * Handle the 's' and 'c' commands
    + */
    +int kgdb_arch_handle_exception(int vector, int signo, int err_code,
    + char *remcom_in_buffer, char *remcom_out_buffer,
    + struct pt_regs *regs)
    +{
    + char *ptr;
    + unsigned long address;
    + int cpu = smp_processor_id();
    +
    + switch (remcom_in_buffer[0]) {
    + case 's':
    + case 'c':
    + /* handle the optional parameter */
    + ptr = &remcom_in_buffer[1];
    + if (kgdb_hex2long(&ptr, &address))
    + regs->cp0_epc = address;
    +
    + atomic_set(&cpu_doing_single_step, -1);
    + if (remcom_in_buffer[0] == 's')
    + if (kgdb_contthread)
    + atomic_set(&cpu_doing_single_step, cpu);
    +
    + return 0;
    + }
    +
    + return -1;
    +}
    +
    +struct kgdb_arch arch_kgdb_ops = {
    +#ifdef CONFIG_CPU_LITTLE_ENDIAN
    + .gdb_bpt_instr = {0xd},
    +#else
    + .gdb_bpt_instr = {0x00, 0x00, 0x00, 0x0d},
    +#endif
    +};
    +
    +/*
    + * We use kgdb_early_setup so that functions we need to call now don't
    + * cause trouble when called again later.
    + */
    +int kgdb_arch_init(void)
    +{
    + /* Board-specifics. */
    + /* Force some calls to happen earlier. */
    + if (kgdb_early_setup == 0) {
    + trap_init();
    + init_IRQ();
    + kgdb_early_setup = 1;
    + }
    +
    + /* Set our traps. */
    + /* This needs to be done more finely grained again, paired in
    + * a before/after in kgdb_handle_exception(...) -- Tom */
    + set_debug_traps();
    + notifier_chain_register(&mips_die_chain, &kgdb_notifier);
    +
    + return 0;
    +}
    diff -puN /dev/null arch/mips/kernel/kgdb_handler.S
    --- /dev/null 2005-07-25 10:57:32.312383000 -0700
    +++ linux-2.6.13-rc3-trini/arch/mips/kernel/kgdb_handler.S 2005-07-29 11:55:31.000000000 -0700
    @@ -0,0 +1,58 @@
    +/*
    + * arch/mips/kernel/kgdb_handler.S
    + *
    + * Copyright (C) 2004 MontaVista Software Inc.
    + * Author: Manish Lachwani, mlachwani@mvista.com or manish@koffee-break.com
    + *
    + * This file is licensed under the terms of the GNU General Public
    + * version 2. This program is licensed "as is" without any warranty of any
    + * kind, whether express or implied.
    + */
    +
    +/*
    + * Trap Handler for the new KGDB framework. The main KGDB handler is
    + * handle_exception that will be called from here
    + *
    + */
    +
    +#include <linux/config.h>
    +#include <linux/sys.h>
    +
    +#include <asm/asm.h>
    +#include <asm/errno.h>
    +#include <asm/mipsregs.h>
    +#include <asm/regdef.h>
    +#include <asm/stackframe.h>
    +
    + .align 5
    + NESTED(trap_low, PT_SIZE, sp)
    + .set noat
    + .set noreorder
    + SAVE_ALL
    + /*
    + * Check for privileged instructions in user mode. For
    + * this, check the cu0 bit in the CPU status register.
    + */
    + mfc0 k0, CP0_STATUS
    + sll k0, 3
    + bltz k0, 1f
    + move k1, sp
    +
    + /*
    + * GDB userland from within KGDB. If a user mode address
    + * then jump to the saved exception handler
    + */
    + lui k1, %hi(saved_vectors)
    + mfc0 k0, CP0_CAUSE
    + andi k0, k0, 0x7c
    + add k1, k1, k0
    + lw k0, %lo(saved_vectors)(k1)
    + jr k0
    + nop
    +1:
    + .set at
    + .set reorder
    + move a0, sp
    + jal handle_exception
    + j ret_from_exception
    + END(trap_low)
    diff -puN /dev/null arch/mips/kernel/kgdb-jmp.c
    --- /dev/null 2005-07-25 10:57:32.312383000 -0700
    +++ linux-2.6.13-rc3-trini/arch/mips/kernel/kgdb-jmp.c 2005-07-29 11:55:31.000000000 -0700
    @@ -0,0 +1,62 @@
    +/*
    + * arch/mips/kernel/kgdb-jmp.c
    + *
    + * Save and restore system registers so that within a limited frame we
    + * may have a fault and "jump back" to a known safe location.
    + *
    + * Author: Tom Rini <trini@kernel.crashing.org>
    + *
    + * Cribbed from glibc, which carries the following:
    + * Copyright (C) 1996, 1997, 2000, 2002, 2003 Free Software Foundation, Inc.
    + * Copyright (C) 2005 by MontaVista Software.
    + *
    + * This file is licensed under the terms of the GNU General Public License
    + * version 2. This program as licensed "as is" without any warranty of
    + * any kind, whether express or implied.
    + */
    +
    +#include <linux/kgdb.h>
    +#include <asm/interrupt.h>
    +
    +int kgdb_fault_setjmp_aux(unsigned long *curr_context, int sp, int fp)
    +{
    + __asm__ __volatile__("sw $gp, %0" : : "m" (curr_context[0]));
    + __asm__ __volatile__("sw $16, %0" : : "m" (curr_context[1]));
    + __asm__ __volatile__("sw $17, %0" : : "m" (curr_context[2]));
    + __asm__ __volatile__("sw $18, %0" : : "m" (curr_context[3]));
    + __asm__ __volatile__("sw $19, %0" : : "m" (curr_context[4]));
    + __asm__ __volatile__("sw $20, %0" : : "m" (curr_context[5]));
    + __asm__ __volatile__("sw $21, %0" : : "m" (curr_context[6]));
    + __asm__ __volatile__("sw $22, %0" : : "m" (curr_context[7]));
    + __asm__ __volatile__("sw $23, %0" : : "m" (curr_context[8]));
    + __asm__ __volatile__("sw $31, %0" : : "m" (curr_context[9]));
    + curr_context[10] = (long *)sp;
    + curr_context[11] = (long *)fp;
    +
    + return 0;
    +}
    +
    +void kgdb_fault_longjmp(unsigned long *curr_context)
    +{
    + unsigned long sp_val, fp_val;
    +
    + __asm__ __volatile__("lw $gp, %0" : : "m" (curr_context[0]));
    + __asm__ __volatile__("lw $16, %0" : : "m" (curr_context[1]));
    + __asm__ __volatile__("lw $17, %0" : : "m" (curr_context[2]));
    + __asm__ __volatile__("lw $18, %0" : : "m" (curr_context[3]));
    + __asm__ __volatile__("lw $19, %0" : : "m" (curr_context[4]));
    + __asm__ __volatile__("lw $20, %0" : : "m" (curr_context[5]));
    + __asm__ __volatile__("lw $21, %0" : : "m" (curr_context[6]));
    + __asm__ __volatile__("lw $22, %0" : : "m" (curr_context[7]));
    + __asm__ __volatile__("lw $23, %0" : : "m" (curr_context[8]));
    + __asm__ __volatile__("lw $25, %0" : : "m" (curr_context[9]));
    + sp_val = curr_context[10];
    + fp_val = curr_context[11];
    + __asm__ __volatile__("lw $29, %0\n\t"
    + "lw $30, %1\n\t" : : "m" (sp_val), "m" (fp_val));
    +
    + __asm__ __volatile__("li $2, 1");
    + __asm__ __volatile__("jr $25");
    +
    + for (;;);
    +}
    diff -puN /dev/null arch/mips/kernel/kgdb-setjmp.S
    --- /dev/null 2005-07-25 10:57:32.312383000 -0700
    +++ linux-2.6.13-rc3-trini/arch/mips/kernel/kgdb-setjmp.S 2005-07-29 11:55:31.000000000 -0700
    @@ -0,0 +1,23 @@
    +/*
    + * arch/mips/kernel/kgdb-jmp.c
    + *
    + * Save and restore system registers so that within a limited frame we
    + * may have a fault and "jump back" to a known safe location.
    + *
    + * Copyright (C) 2005 by MontaVista Software.
    + *
    + * This file is licensed under the terms of the GNU General Public License
    + * version 2. This program as licensed "as is" without any warranty of
    + * any kind, whether express or implied.
    + */
    +
    +#include <asm/asm.h>
    +#include <asm/mipsregs.h>
    +#include <asm/regdef.h>
    +#include <asm/stackframe.h>
    +
    +ENTRY (kgdb_fault_setjmp)
    + move a1, sp
    + move a2, fp
    + j kgdb_fault_setjmp_aux
    + .end kgdb_fault_setjmp
    diff -puN arch/mips/kernel/Makefile~mips-lite arch/mips/kernel/Makefile
    --- linux-2.6.13-rc3/arch/mips/kernel/Makefile~mips-lite 2005-07-29 11:55:31.000000000 -0700
    +++ linux-2.6.13-rc3-trini/arch/mips/kernel/Makefile 2005-07-29 11:55:31.000000000 -0700
    @@ -52,7 +52,8 @@ obj-$(CONFIG_MIPS32_COMPAT) += ioctl32.o
    obj-$(CONFIG_MIPS32_N32) += binfmt_elfn32.o scall64-n32.o signal_n32.o
    obj-$(CONFIG_MIPS32_O32) += binfmt_elfo32.o scall64-o32.o ptrace32.o

    -obj-$(CONFIG_KGDB) += gdb-low.o gdb-stub.o
    +obj-$(CONFIG_KGDB) += kgdb_handler.o kgdb.o kgdb-jmp.o \
    + kgdb-setjmp.o
    obj-$(CONFIG_PROC_FS) += proc.o

    obj-$(CONFIG_MIPS64) += cpu-bugs64.o
    diff -puN arch/mips/kernel/traps.c~mips-lite arch/mips/kernel/traps.c
    --- linux-2.6.13-rc3/arch/mips/kernel/traps.c~mips-lite 2005-07-29 11:55:31.000000000 -0700
    +++ linux-2.6.13-rc3-trini/arch/mips/kernel/traps.c 2005-07-29 11:55:31.000000000 -0700
    @@ -10,6 +10,8 @@
    * Kevin D. Kissell, kevink@mips.com and Carsten Langgaard, carstenl@mips.com
    * Copyright (C) 2000, 01 MIPS Technologies, Inc.
    * Copyright (C) 2002, 2003, 2004 Maciej W. Rozycki
    + *
    + * KGDB specific changes - Manish Lachwani (mlachwani@mvista.com)
    */
    #include <linux/config.h>
    #include <linux/init.h>
    @@ -20,6 +22,7 @@
    #include <linux/smp_lock.h>
    #include <linux/spinlock.h>
    #include <linux/kallsyms.h>
    +#include <linux/kgdb.h>

    #include <asm/bootinfo.h>
    #include <asm/branch.h>
    @@ -37,6 +40,7 @@
    #include <asm/mmu_context.h>
    #include <asm/watch.h>
    #include <asm/types.h>
    +#include <asm/kdebug.h>

    extern asmlinkage void handle_tlbm(void);
    extern asmlinkage void handle_tlbl(void);
    @@ -69,6 +73,21 @@ int (*board_be_handler)(struct pt_regs *
    */
    #define MODULE_RANGE (8*1024*1024)

    +struct notifier_block *mips_die_chain;
    +static spinlock_t die_notifier_lock = SPIN_LOCK_UNLOCKED;
    +
    +int register_die_notifier(struct notifier_block *nb)
    +{
    + int err = 0;
    + unsigned long flags;
    +
    + spin_lock_irqsave(&die_notifier_lock, flags);
    + err = notifier_chain_register(&mips_die_chain, nb);
    + spin_unlock_irqrestore(&die_notifier_lock, flags);
    +
    + return err;
    +}
    +
    /*
    * This routine abuses get_user()/put_user() to reference pointers
    * with at least a bit of error checking ...
    @@ -271,8 +290,10 @@ NORET_TYPE void __die(const char * str,
    void __die_if_kernel(const char * str, struct pt_regs * regs,
    const char * file, const char * func, unsigned long line)
    {
    - if (!user_mode(regs))
    + if (!user_mode(regs)) {
    + notify_die(DIE_TRAP, (char *)str, regs, 0);
    __die(str, regs, file, func, line);
    + }
    }

    extern const struct exception_table_entry __start___dbe_table[];
    @@ -958,6 +979,9 @@ void __init trap_init(void)
    extern char except_vec4;
    unsigned long i;

    + if (kgdb_early_setup)
    + return; /* Already done */
    +
    per_cpu_trap_init();

    /*
    diff -puN arch/mips/mips-boards/generic/init.c~mips-lite arch/mips/mips-boards/generic/init.c
    --- linux-2.6.13-rc3/arch/mips/mips-boards/generic/init.c~mips-lite 2005-07-29 11:55:31.000000000 -0700
    +++ linux-2.6.13-rc3-trini/arch/mips/mips-boards/generic/init.c 2005-07-29 11:55:31.000000000 -0700
    @@ -35,15 +35,6 @@
    #include <asm/mips-boards/malta.h>
    #endif

    -#ifdef CONFIG_KGDB
    -extern int rs_kgdb_hook(int, int);
    -extern int rs_putDebugChar(char);
    -extern char rs_getDebugChar(void);
    -extern int saa9730_kgdb_hook(int);
    -extern int saa9730_putDebugChar(char);
    -extern char saa9730_getDebugChar(void);
    -#endif
    -
    int prom_argc;
    int *_prom_argv, *_prom_envp;

    @@ -170,59 +161,6 @@ static void __init console_config(void)
    }
    #endif

    -#ifdef CONFIG_KGDB
    -void __init kgdb_config (void)
    -{
    - extern int (*generic_putDebugChar)(char);
    - extern char (*generic_getDebugChar)(void);
    - char *argptr;
    - int line, speed;
    -
    - argptr = prom_getcmdline();
    - if ((argptr = strstr(argptr, "kgdb=ttyS")) != NULL) {
    - argptr += strlen("kgdb=ttyS");
    - if (*argptr != '0' && *argptr != '1')
    - printk("KGDB: Unknown serial line /dev/ttyS%c, "
    - "falling back to /dev/ttyS1\n", *argptr);
    - line = *argptr == '0' ? 0 : 1;
    - printk("KGDB: Using serial line /dev/ttyS%d for session\n", line);
    -
    - speed = 0;
    - if (*++argptr == ',')
    - {
    - int c;
    - while ((c = *++argptr) && ('0' <= c && c <= '9'))
    - speed = speed * 10 + c - '0';
    - }
    -#ifdef CONFIG_MIPS_ATLAS
    - if (line == 1) {
    - speed = saa9730_kgdb_hook(speed);
    - generic_putDebugChar = saa9730_putDebugChar;
    - generic_getDebugChar = saa9730_getDebugChar;
    - }
    - else
    -#endif
    - {
    - speed = rs_kgdb_hook(line, speed);
    - generic_putDebugChar = rs_putDebugChar;
    - generic_getDebugChar = rs_getDebugChar;
    - }
    -
    - prom_printf("KGDB: Using serial line /dev/ttyS%d at %d for session, "
    - "please connect your debugger\n", line ? 1 : 0, speed);
    -
    - {
    - char *s;
    - for (s = "Please connect GDB to this port\r\n"; *s; )
    - generic_putDebugChar (*s++);
    - }
    -
    - kgdb_enabled = 1;
    - /* Breakpoint is invoked after interrupts are initialised */
    - }
    -}
    -#endif
    -
    void __init prom_init(void)
    {
    prom_argc = fw_arg0;
    diff -puN arch/mips/mips-boards/generic/Makefile~mips-lite arch/mips/mips-boards/generic/Makefile
    --- linux-2.6.13-rc3/arch/mips/mips-boards/generic/Makefile~mips-lite 2005-07-29 11:55:31.000000000 -0700
    +++ linux-2.6.13-rc3-trini/arch/mips/mips-boards/generic/Makefile 2005-07-29 11:55:31.000000000 -0700
    @@ -21,6 +21,5 @@
    obj-y := mipsIRQ.o reset.o display.o init.o memory.o \
    printf.o cmdline.o time.o
    obj-$(CONFIG_PCI) += pci.o
    -obj-$(CONFIG_KGDB) += gdb_hook.o

    EXTRA_AFLAGS := $(CFLAGS)
    diff -puN arch/mips/mips-boards/malta/malta_setup.c~mips-lite arch/mips/mips-boards/malta/malta_setup.c
    --- linux-2.6.13-rc3/arch/mips/mips-boards/malta/malta_setup.c~mips-lite 2005-07-29 11:55:31.000000000 -0700
    +++ linux-2.6.13-rc3-trini/arch/mips/mips-boards/malta/malta_setup.c 2005-07-29 11:55:31.000000000 -0700
    @@ -48,10 +48,6 @@ extern void mips_time_init(void);
    extern void mips_timer_setup(struct irqaction *irq);
    extern unsigned long mips_rtc_get_time(void);

    -#ifdef CONFIG_KGDB
    -extern void kgdb_config(void);
    -#endif
    -
    struct resource standard_io_resources[] = {
    { "dma1", 0x00, 0x1f, IORESOURCE_BUSY },
    { "timer", 0x40, 0x5f, IORESOURCE_BUSY },
    @@ -124,10 +120,6 @@ static int __init malta_setup(void)
    */
    enable_dma(4);

    -#ifdef CONFIG_KGDB
    - kgdb_config ();
    -#endif
    -
    if ((mips_revision_corid == MIPS_REVISION_CORID_BONITO64) ||
    (mips_revision_corid == MIPS_REVISION_CORID_CORE_20K) ||
    (mips_revision_corid == MIPS_REVISION_CORID_CORE_EMUL_BON)) {
    diff -puN arch/mips/mm/extable.c~mips-lite arch/mips/mm/extable.c
    --- linux-2.6.13-rc3/arch/mips/mm/extable.c~mips-lite 2005-07-29 11:55:31.000000000 -0700
    +++ linux-2.6.13-rc3-trini/arch/mips/mm/extable.c 2005-07-29 11:55:31.000000000 -0700
    @@ -3,6 +3,7 @@
    */
    #include <linux/module.h>
    #include <linux/spinlock.h>
    +#include <linux/kgdb.h>
    #include <asm/branch.h>
    #include <asm/uaccess.h>

    @@ -16,6 +17,12 @@ int fixup_exception(struct pt_regs *regs

    return 1;
    }
    +#ifdef CONFIG_KGDB
    + if (atomic_read(&debugger_active) && kgdb_may_fault)
    + /* Restore our previous state. */
    + kgdb_fault_longjmp(kgdb_fault_jmp_regs);
    + /* Not reached. */
    +#endif

    return 0;
    }
    diff -puN arch/mips/sibyte/cfe/setup.c~mips-lite arch/mips/sibyte/cfe/setup.c
    --- linux-2.6.13-rc3/arch/mips/sibyte/cfe/setup.c~mips-lite 2005-07-29 11:55:31.000000000 -0700
    +++ linux-2.6.13-rc3-trini/arch/mips/sibyte/cfe/setup.c 2005-07-29 11:55:31.000000000 -0700
    @@ -58,10 +58,6 @@ int cfe_cons_handle;
    extern unsigned long initrd_start, initrd_end;
    #endif

    -#ifdef CONFIG_KGDB
    -extern int kgdb_port;
    -#endif
    -
    static void ATTRIB_NORET cfe_linux_exit(void *arg)
    {
    int warm = *(int *)arg;
    @@ -242,9 +238,6 @@ void __init prom_init(void)
    int argc = fw_arg0;
    char **envp = (char **) fw_arg2;
    int *prom_vec = (int *) fw_arg3;
    -#ifdef CONFIG_KGDB
    - char *arg;
    -#endif

    _machine_restart = cfe_linux_restart;
    _machine_halt = cfe_linux_halt;
    @@ -308,13 +301,6 @@ void __init prom_init(void)
    }
    }

    -#ifdef CONFIG_KGDB
    - if ((arg = strstr(arcs_cmdline,"kgdb=duart")) != NULL)
    - kgdb_port = (arg[10] == '0') ? 0 : 1;
    - else
    - kgdb_port = 1;
    -#endif
    -
    #ifdef CONFIG_BLK_DEV_INITRD
    {
    char *ptr;
    diff -puN arch/mips/sibyte/sb1250/irq.c~mips-lite arch/mips/sibyte/sb1250/irq.c
    --- linux-2.6.13-rc3/arch/mips/sibyte/sb1250/irq.c~mips-lite 2005-07-29 11:55:31.000000000 -0700
    +++ linux-2.6.13-rc3-trini/arch/mips/sibyte/sb1250/irq.c 2005-07-29 11:55:31.000000000 -0700
    @@ -31,6 +31,7 @@
    #include <asm/system.h>
    #include <asm/ptrace.h>
    #include <asm/io.h>
    +#include <asm/kgdb.h>

    #include <asm/sibyte/sb1250_regs.h>
    #include <asm/sibyte/sb1250_int.h>
    @@ -60,16 +61,6 @@ static void sb1250_set_affinity(unsigned
    extern unsigned long ldt_eoi_space;
    #endif

    -#ifdef CONFIG_KGDB
    -static int kgdb_irq;
    -
    -/* Default to UART1 */
    -int kgdb_port = 1;
    -#ifdef CONFIG_SIBYTE_SB1250_DUART
    -extern char sb1250_duart_present[];
    -#endif
    -#endif
    -
    static struct hw_interrupt_type sb1250_irq_type = {
    "SB1250-IMR",
    startup_sb1250_irq,
    @@ -338,6 +329,11 @@ void __init arch_init_irq(void)
    unsigned int imask = STATUSF_IP4 | STATUSF_IP3 | STATUSF_IP2 |
    STATUSF_IP1 | STATUSF_IP0;

    +#ifdef CONFIG_KGDB
    + if (kgdb_early_setup)
    + return;
    +#endif
    +
    /* Default everything to IP2 */
    for (i = 0; i < SB1250_NR_IRQS; i++) { /* was I0 */
    bus_writeq(IMR_IP2_VAL,
    @@ -387,45 +383,4 @@ void __init arch_init_irq(void)
    /* Enable necessary IPs, disable the rest */
    change_c0_status(ST0_IM, imask);
    set_except_vector(0, sb1250_irq_handler);
    -
    -#ifdef CONFIG_KGDB
    - if (kgdb_flag) {
    - kgdb_irq = K_INT_UART_0 + kgdb_port;
    -
    -#ifdef CONFIG_SIBYTE_SB1250_DUART
    - sb1250_duart_present[kgdb_port] = 0;
    -#endif
    - /* Setup uart 1 settings, mapper */
    - bus_writeq(M_DUART_IMR_BRK, IOADDR(A_DUART_IMRREG(kgdb_port)));
    -
    - sb1250_steal_irq(kgdb_irq);
    - bus_writeq(IMR_IP6_VAL,
    - IOADDR(A_IMR_REGISTER(0, R_IMR_INTERRUPT_MAP_BASE) +
    - (kgdb_irq<<3)));
    - sb1250_unmask_irq(0, kgdb_irq);
    - }
    -#endif
    }
    -
    -#ifdef CONFIG_KGDB
    -
    -#include <linux/delay.h>
    -
    -#define duart_out(reg, val) csr_out32(val, IOADDR(A_DUART_CHANREG(kgdb_port,reg)))
    -#define duart_in(reg) csr_in32(IOADDR(A_DUART_CHANREG(kgdb_port,reg)))
    -
    -void sb1250_kgdb_interrupt(struct pt_regs *regs)
    -{
    - /*
    - * Clear break-change status (allow some time for the remote
    - * host to stop the break, since we would see another
    - * interrupt on the end-of-break too)
    - */
    - kstat_this_cpu.irqs[kgdb_irq]++;
    - mdelay(500);
    - duart_out(R_DUART_CMD, V_DUART_MISC_CMD_RESET_BREAK_INT |
    - M_DUART_RX_EN | M_DUART_TX_EN);
    - set_async_breakpoint(&regs->cp0_epc);
    -}
    -
    -#endif /* CONFIG_KGDB */
    diff -puN arch/mips/sibyte/sb1250/irq_handler.S~mips-lite arch/mips/sibyte/sb1250/irq_handler.S
    --- linux-2.6.13-rc3/arch/mips/sibyte/sb1250/irq_handler.S~mips-lite 2005-07-29 11:55:31.000000000 -0700
    +++ linux-2.6.13-rc3-trini/arch/mips/sibyte/sb1250/irq_handler.S 2005-07-29 11:55:31.000000000 -0700
    @@ -102,7 +102,7 @@
    2:
    #endif

    -#ifdef CONFIG_KGDB
    +#ifdef CONFIG_KGDB_SIBYTE
    /* KGDB (uart 1) interrupt is routed to IP[6] */
    andi t1, s0, CAUSEF_IP6
    beqz t1, 1f
    diff -puN /dev/null arch/mips/sibyte/sb1250/kgdb_sibyte.c
    --- /dev/null 2005-07-25 10:57:32.312383000 -0700
    +++ linux-2.6.13-rc3-trini/arch/mips/sibyte/sb1250/kgdb_sibyte.c 2005-07-29 11:55:31.000000000 -0700
    @@ -0,0 +1,164 @@
    +/*
    + * arch/mips/sibyte/sb1250/kgdb_sibyte.c
    + *
    + * Author: Manish Lachwani, mlachwani@mvista.com or manish@koffee-break.com
    + *
    + * 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.
    + */
    +
    +/*
    + * Support for KGDB on the Broadcom Sibyte. The SWARM board
    + * for example does not have a 8250/16550 compatible serial
    + * port. Hence, we need to have a driver for the serial
    + * ports to handle KGDB. This board needs nothing in addition
    + * to what is normally provided by the gdb portion of the stub.
    + */
    +
    +#include <linux/delay.h>
    +#include <linux/kernel_stat.h>
    +#include <linux/init.h>
    +#include <linux/kgdb.h>
    +
    +#include <asm/io.h>
    +#include <asm/sibyte/sb1250.h>
    +#include <asm/sibyte/sb1250_regs.h>
    +#include <asm/sibyte/sb1250_uart.h>
    +#include <asm/sibyte/sb1250_int.h>
    +#include <asm/addrspace.h>
    +
    +int kgdb_port = 1;
    +static int kgdb_irq;
    +
    +extern char sb1250_duart_present[];
    +extern int sb1250_steal_irq(int irq);
    +
    +/* Forward declarations. */
    +static void kgdbsibyte_init_duart(void);
    +static int kgdb_init_io(void);
    +
    +#define IMR_IP6_VAL K_INT_MAP_I4
    +#define duart_out(reg, val) csr_out32(val, IOADDR(A_DUART_CHANREG(kgdb_port,reg)))
    +#define duart_in(reg) csr_in32(IOADDR(A_DUART_CHANREG(kgdb_port,reg)))
    +
    +static void kgdb_swarm_write_char(int c)
    +{
    + while ((duart_in(R_DUART_STATUS) & M_DUART_TX_RDY) == 0) ;
    + duart_out(R_DUART_TX_HOLD, c);
    +}
    +
    +static int kgdb_swarm_read_char(void)
    +{
    + int ret_char;
    + unsigned int status;
    +
    + status = duart_in(R_DUART_STATUS);
    + while ((status & M_DUART_RX_RDY) == 0) {
    + status = duart_in(R_DUART_STATUS);
    + }
    +
    + /*
    + * Check for framing error
    + */
    + if (status & M_DUART_FRM_ERR) {
    + kgdbsibyte_init_duart();
    + kgdb_swarm_write_char('-');
    + return '-';
    + }
    +
    + ret_char = duart_in(R_DUART_RX_HOLD);
    +
    + return ret_char;
    +}
    +
    +void sb1250_kgdb_interrupt(struct pt_regs *regs)
    +{
    + int kgdb_irq = K_INT_UART_0 + kgdb_port;
    + /*
    + * Clear break-change status (allow some time for the remote
    + * host to stop the break, since we would see another
    + * interrupt on the end-of-break too)
    + */
    + kstat_this_cpu.irqs[kgdb_irq]++;
    + mdelay(500);
    + duart_out(R_DUART_CMD, V_DUART_MISC_CMD_RESET_BREAK_INT |
    + M_DUART_RX_EN | M_DUART_TX_EN);
    + if (kgdb_io_ops.init != kgdb_init_io) {
    + /* Throw away the data if another I/O routine is
    + * active.
    + */
    + unsigned int status;
    +
    + status = duart_in(R_DUART_STATUS);
    + while ((status & M_DUART_RX_RDY) == 0) {
    + status = duart_in(R_DUART_STATUS);
    + }
    + /*
    + * Check for framing error
    + */
    + if (status & M_DUART_FRM_ERR) {
    + kgdbsibyte_init_duart();
    + }
    + duart_in(R_DUART_RX_HOLD);
    + } else
    + breakpoint();
    +
    +}
    +
    +/*
    + * We use port #1 and we set it for 115200 BAUD, 8n1.
    + */
    +static void kgdbsibyte_init_duart(void)
    +{
    + /* Set 8n1. */
    + duart_out(R_DUART_MODE_REG_1,
    + V_DUART_BITS_PER_CHAR_8 | V_DUART_PARITY_MODE_NONE);
    + duart_out(R_DUART_MODE_REG_2, M_DUART_STOP_BIT_LEN_1);
    + /* Set baud rate of 115200. */
    + duart_out(R_DUART_CLK_SEL, V_DUART_BAUD_RATE(115200));
    + /* Enable rx and tx */
    + duart_out(R_DUART_CMD, M_DUART_RX_EN | M_DUART_TX_EN);
    +}
    +
    +static int kgdb_init_io(void)
    +{
    +#ifdef CONFIG_SIBYTE_SB1250_DUART
    + sb1250_duart_present[kgdb_port] = 0;
    +#endif
    +
    + kgdbsibyte_init_duart();
    +
    + return 0;
    +}
    +
    +/*
    + * Hookup our IRQ line. We will already have been initialized a
    + * this point.
    + */
    +static void __init kgdbsibyte_hookup_irq(void)
    +{
    + /* Steal the IRQ. */
    + kgdb_irq = K_INT_UART_0 + kgdb_port;
    +
    + /* Setup uart 1 settings, mapper */
    + __raw_writeq(M_DUART_IMR_BRK, IOADDR(A_DUART_IMRREG(kgdb_port)));
    +
    + sb1250_steal_irq(kgdb_irq);
    +
    + __raw_writeq(IMR_IP6_VAL,
    + IOADDR(A_IMR_REGISTER(0, R_IMR_INTERRUPT_MAP_BASE) +
    + (kgdb_irq << 3)));
    +
    + sb1250_unmask_irq(0, kgdb_irq);
    +}
    +
    +struct kgdb_io kgdb_io_ops = {
    + .read_char = kgdb_swarm_read_char,
    + .write_char = kgdb_swarm_write_char,
    + .init = kgdb_init_io,
    + .late_init = kgdbsibyte_hookup_irq,
    + .pre_exception = NULL,
    + .post_exception = NULL
    +};
    diff -puN arch/mips/sibyte/sb1250/Makefile~mips-lite arch/mips/sibyte/sb1250/Makefile
    --- linux-2.6.13-rc3/arch/mips/sibyte/sb1250/Makefile~mips-lite 2005-07-29 11:55:31.000000000 -0700
    +++ linux-2.6.13-rc3-trini/arch/mips/sibyte/sb1250/Makefile 2005-07-29 11:55:31.000000000 -0700
    @@ -4,5 +4,6 @@ obj-$(CONFIG_SMP) += smp.o
    obj-$(CONFIG_SIBYTE_TBPROF) += bcm1250_tbprof.o
    obj-$(CONFIG_SIBYTE_STANDALONE) += prom.o
    obj-$(CONFIG_SIBYTE_BUS_WATCHER) += bus_watcher.o
    +obj-$(CONFIG_KGDB_SIBYTE) += kgdb_sibyte.o

    EXTRA_AFLAGS := $(CFLAGS)
    diff -L arch/mips/sibyte/swarm/dbg_io.c -puN arch/mips/sibyte/swarm/dbg_io.c~mips-lite /dev/null
    --- linux-2.6.13-rc3/arch/mips/sibyte/swarm/dbg_io.c
    +++ /dev/null 2005-07-25 10:57:32.312383000 -0700
    @@ -1,76 +0,0 @@
    -/*
    - * kgdb debug routines for SiByte boards.
    - *
    - * Copyright (C) 2001 MontaVista Software Inc.
    - * Author: Jun Sun, jsun@mvista.com or jsun@junsun.net
    - *
    - * This program is free software; you can redistribute it and/or modify it
    - * under the terms of the GNU General Public License as published by the
    - * Free Software Foundation; either version 2 of the License, or (at your
    - * option) any later version.
    - *
    - */
    -
    -/* -------------------- BEGINNING OF CONFIG --------------------- */
    -
    -#include <linux/delay.h>
    -#include <asm/io.h>
    -#include <asm/sibyte/sb1250.h>
    -#include <asm/sibyte/sb1250_regs.h>
    -#include <asm/sibyte/sb1250_uart.h>
    -#include <asm/sibyte/sb1250_int.h>
    -#include <asm/addrspace.h>
    -
    -/*
    - * We use the second serial port for kgdb traffic.
    - * 115200, 8, N, 1.
    - */
    -
    -#define BAUD_RATE 115200
    -#define CLK_DIVISOR V_DUART_BAUD_RATE(BAUD_RATE)
    -#define DATA_BITS V_DUART_BITS_PER_CHAR_8 /* or 7 */
    -#define PARITY V_DUART_PARITY_MODE_NONE /* or even */
    -#define STOP_BITS M_DUART_STOP_BIT_LEN_1 /* or 2 */
    -
    -static int duart_initialized = 0; /* 0: need to be init'ed by kgdb */
    -
    -/* -------------------- END OF CONFIG --------------------- */
    -extern int kgdb_port;
    -
    -#define duart_out(reg, val) csr_out32(val, IOADDR(A_DUART_CHANREG(kgdb_port,reg)))
    -#define duart_in(reg) csr_in32(IOADDR(A_DUART_CHANREG(kgdb_port,reg)))
    -
    -void putDebugChar(unsigned char c);
    -unsigned char getDebugChar(void);
    -static void
    -duart_init(int clk_divisor, int data, int parity, int stop)
    -{
    - duart_out(R_DUART_MODE_REG_1, data | parity);
    - duart_out(R_DUART_MODE_REG_2, stop);
    - duart_out(R_DUART_CLK_SEL, clk_divisor);
    -
    - duart_out(R_DUART_CMD, M_DUART_RX_EN | M_DUART_TX_EN); /* enable rx and tx */
    -}
    -
    -void
    -putDebugChar(unsigned char c)
    -{
    - if (!duart_initialized) {
    - duart_initialized = 1;
    - duart_init(CLK_DIVISOR, DATA_BITS, PARITY, STOP_BITS);
    - }
    - while ((duart_in(R_DUART_STATUS) & M_DUART_TX_RDY) == 0);
    - duart_out(R_DUART_TX_HOLD, c);
    -}
    -
    -unsigned char
    -getDebugChar(void)
    -{
    - if (!duart_initialized) {
    - duart_initialized = 1;
    - duart_init(CLK_DIVISOR, DATA_BITS, PARITY, STOP_BITS);
    - }
    - while ((duart_in(R_DUART_STATUS) & M_DUART_RX_RDY) == 0) ;
    - return duart_in(R_DUART_RX_HOLD);
    -}
    -
    diff -puN arch/mips/sibyte/swarm/Makefile~mips-lite arch/mips/sibyte/swarm/Makefile
    --- linux-2.6.13-rc3/arch/mips/sibyte/swarm/Makefile~mips-lite 2005-07-29 11:55:31.000000000 -0700
    +++ linux-2.6.13-rc3-trini/arch/mips/sibyte/swarm/Makefile 2005-07-29 11:55:31.000000000 -0700
    @@ -1,3 +1 @@
    lib-y = setup.o rtc_xicor1241.o rtc_m41t81.o
    -
    -lib-$(CONFIG_KGDB) += dbg_io.o
    diff -puN /dev/null include/asm-mips/kdebug.h
    --- /dev/null 2005-07-25 10:57:32.312383000 -0700
    +++ linux-2.6.13-rc3-trini/include/asm-mips/kdebug.h 2005-07-29 11:55:31.000000000 -0700
    @@ -0,0 +1,47 @@
    +/*
    + *
    + * Copyright (C) 2004 MontaVista Software Inc.
    + * Author: Manish Lachwani, mlachwani@mvista.com or manish@koffee-break.com
    + *
    + * This program is free software; you can redistribute it and/or modify it
    + * under the terms of the GNU General Public License as published by the
    + * Free Software Foundation; either version 2 of the License, or (at your
    + * option) any later version.
    + *
    + */
    +#ifndef _MIPS_KDEBUG_H
    +#define _MIPS_KDEBUG_H
    +
    +#include <linux/notifier.h>
    +
    +struct pt_regs;
    +
    +struct die_args {
    + struct pt_regs *regs;
    + const char *str;
    + long err;
    +};
    +
    +int register_die_notifier(struct notifier_block *nb);
    +extern struct notifier_block *mips_die_chain;
    +
    +enum die_val {
    + DIE_OOPS = 1,
    + DIE_PANIC,
    + DIE_DIE,
    + DIE_KERNELDEBUG,
    + DIE_TRAP,
    + DIE_PAGE_FAULT,
    +};
    +
    +/*
    + * trap number can be computed from regs and signr can be computed using
    + * compute_signal()
    + */
    +static inline int notify_die(enum die_val val,char *str,struct pt_regs *regs,long err)
    +{
    + struct die_args args = { .regs=regs, .str=str, .err=err };
    + return notifier_call_chain(&mips_die_chain, val, &args);
    +}
    +
    +#endif /* _MIPS_KDEBUG_H */
    diff -puN /dev/null include/asm-mips/kgdb.h
    --- /dev/null 2005-07-25 10:57:32.312383000 -0700
    +++ linux-2.6.13-rc3-trini/include/asm-mips/kgdb.h 2005-07-29 12:48:10.000000000 -0700
    @@ -0,0 +1,22 @@
    +#ifdef __KERNEL__
    +#ifndef _ASM_KGDB_H_
    +#define _ASM_KGDB_H_
    +
    +#define BUFMAX 2048
    +#define NUMREGBYTES (90*sizeof(long))
    +#define NUMCRITREGBYTES (12*sizeof(long))
    +#define BREAK_INSTR_SIZE 4
    +#define BREAKPOINT() __asm__ __volatile__( \
    + ".globl breakinst\n\t" \
    + ".set\tnoreorder\n\t" \
    + "nop\n" \
    + "breakinst:\tbreak\n\t" \
    + "nop\n\t" \
    + ".set\treorder")
    +#define CHECK_EXCEPTION_STACK() 1
    +#define CACHE_FLUSH_IS_SAFE 0
    +
    +extern int kgdb_early_setup;
    +
    +#endif /* _ASM_KGDB_H_ */
    +#endif /* __KERNEL__ */
    diff -puN lib/Kconfig.debug~mips-lite lib/Kconfig.debug
    --- linux-2.6.13-rc3/lib/Kconfig.debug~mips-lite 2005-07-29 11:55:31.000000000 -0700
    +++ linux-2.6.13-rc3-trini/lib/Kconfig.debug 2005-07-29 13:23:57.000000000 -0700
    @@ -163,7 +163,7 @@ config FRAME_POINTER

    config KGDB
    bool "KGDB: kernel debugging with remote gdb"
    - depends on DEBUG_KERNEL && (X86 || ((!SMP || BROKEN) && (PPC32)))
    + depends on DEBUG_KERNEL && (X86 || MIPS32 || ((!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
    @@ -189,6 +189,7 @@ choice
    prompt "Method for KGDB communication"
    depends on KGDB
    default KGDB_ONLY_MODULES
    + default KGDB_SIBYTE if SIBYTE_SB1xxx_SOC
    default KGDB_MPSC if SERIAL_MPSC
    help
    There are a number of different ways in which you can communicate
    @@ -222,6 +223,10 @@ config KGDB_MPSC
    Controller (MPSC) channel. Note that the GT64260A is not
    supported.

    +config KGDB_SIBYTE
    + bool "KGDB: On the Broadcom SWARM serial port"
    + depends on MIPS && SIBYTE_SB1xxx_SOC
    +
    endchoice

    config KGDB_8250
    _
    -
    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/
    \
     
     \ /
      Last update: 2005-07-30 01:13    [W:0.165 / U:60.776 seconds]
    ©2003-2016 Jasper Spaans. hosted at Digital OceanAdvertise on this site