CC: Russell King <[EMAIL PROTECTED]>, Deepak Saxena <[EMAIL PROTECTED]>, George 
Davis <[EMAIL PROTECTED]>, Geoff Levand <[EMAIL PROTECTED]>, Nicolas Pitre 
<[EMAIL PROTECTED]>
This adds a backend, written by Deepak Saxena <[EMAIL PROTECTED]> and George
Davis <[EMAIL PROTECTED]> as well as support for the TI OMAP boards, ADI
Coyote, PXA2xx, and ARM Versatile.  Geoff Levand <[EMAIL PROTECTED]>
Nicolas Pitre, and Manish Lachwani have contributed various fixups here as
well.  This should only require (on boards that don't have a custom uart)
registering the uart with KGDB to add any other boards, or using kgdboe it
should Just Work.

---

 linux-2.6.13-rc3-trini/arch/arm/kernel/Makefile              |    1 
 linux-2.6.13-rc3-trini/arch/arm/kernel/kgdb-jmp.S            |   30 +
 linux-2.6.13-rc3-trini/arch/arm/kernel/kgdb.c                |  208 +++++++++++
 linux-2.6.13-rc3-trini/arch/arm/kernel/setup.c               |    5 
 linux-2.6.13-rc3-trini/arch/arm/kernel/traps.c               |   11 
 linux-2.6.13-rc3-trini/arch/arm/mach-ixp2000/core.c          |    5 
 linux-2.6.13-rc3-trini/arch/arm/mach-ixp2000/ixdp2x01.c      |    6 
 linux-2.6.13-rc3-trini/arch/arm/mach-ixp4xx/coyote-setup.c   |    5 
 linux-2.6.13-rc3-trini/arch/arm/mach-ixp4xx/ixdp425-setup.c  |   10 
 linux-2.6.13-rc3-trini/arch/arm/mach-omap1/board-osk.c       |    6 
 linux-2.6.13-rc3-trini/arch/arm/mach-omap1/serial.c          |    4 
 linux-2.6.13-rc3-trini/arch/arm/mach-pxa/Makefile            |    1 
 linux-2.6.13-rc3-trini/arch/arm/mach-pxa/kgdb-serial.c       |   98 +++++
 linux-2.6.13-rc3-trini/arch/arm/mach-versatile/kgdb_serial.c |  121 ++++++
 linux-2.6.13-rc3-trini/arch/arm/mm/extable.c                 |    7 
 linux-2.6.13-rc3-trini/drivers/serial/amba-pl011.c           |    2 
 linux-2.6.13-rc3-trini/drivers/serial/kgdb_8250.c            |   16 
 linux-2.6.13-rc3-trini/include/asm-arm/kgdb.h                |   90 ++++
 linux-2.6.13-rc3-trini/include/asm-arm/system.h              |   41 ++
 linux-2.6.13-rc3-trini/lib/Kconfig.debug                     |   35 +
 20 files changed, 695 insertions(+), 7 deletions(-)

diff -puN /dev/null arch/arm/kernel/kgdb.c
--- /dev/null   2005-07-25 10:57:32.312383000 -0700
+++ linux-2.6.13-rc3-trini/arch/arm/kernel/kgdb.c       2005-07-29 
11:55:32.000000000 -0700
@@ -0,0 +1,208 @@
+/*
+ * arch/arm/kernel/kgdb.c
+ *
+ * ARM KGDB support
+ *
+ * Copyright (c) 2002-2004 MontaVista Software, Inc
+ *
+ * Authors:  George Davis <[EMAIL PROTECTED]>
+ *           Deepak Saxena <[EMAIL PROTECTED]>
+ */
+#include <linux/config.h>
+#include <linux/types.h>
+#include <linux/kernel.h>
+#include <linux/signal.h>
+#include <linux/sched.h>
+#include <linux/mm.h>
+#include <linux/spinlock.h>
+#include <linux/personality.h>
+#include <linux/ptrace.h>
+#include <linux/elf.h>
+#include <linux/interrupt.h>
+#include <linux/init.h>
+#include <linux/kgdb.h>
+
+#include <asm/atomic.h>
+#include <asm/io.h>
+#include <asm/pgtable.h>
+#include <asm/system.h>
+#include <asm/uaccess.h>
+#include <asm/unistd.h>
+#include <asm/ptrace.h>
+#include <asm/traps.h>
+
+/* Make a local copy of the registers passed into the handler (bletch) */
+void regs_to_gdb_regs(unsigned long *gdb_regs, struct pt_regs *kernel_regs)
+{
+       int regno;
+
+       /* Initialize all to zero (??) */
+       for (regno = 0; regno < GDB_MAX_REGS; regno++)
+               gdb_regs[regno] = 0;
+
+       gdb_regs[_R0] = kernel_regs->ARM_r0;
+       gdb_regs[_R1] = kernel_regs->ARM_r1;
+       gdb_regs[_R2] = kernel_regs->ARM_r2;
+       gdb_regs[_R3] = kernel_regs->ARM_r3;
+       gdb_regs[_R4] = kernel_regs->ARM_r4;
+       gdb_regs[_R5] = kernel_regs->ARM_r5;
+       gdb_regs[_R6] = kernel_regs->ARM_r6;
+       gdb_regs[_R7] = kernel_regs->ARM_r7;
+       gdb_regs[_R8] = kernel_regs->ARM_r8;
+       gdb_regs[_R9] = kernel_regs->ARM_r9;
+       gdb_regs[_R10] = kernel_regs->ARM_r10;
+       gdb_regs[_FP] = kernel_regs->ARM_fp;
+       gdb_regs[_IP] = kernel_regs->ARM_ip;
+       gdb_regs[_SP] = kernel_regs->ARM_sp;
+       gdb_regs[_LR] = kernel_regs->ARM_lr;
+       gdb_regs[_PC] = kernel_regs->ARM_pc;
+       gdb_regs[_CPSR] = kernel_regs->ARM_cpsr;
+}
+
+/* Copy local gdb registers back to kgdb regs, for later copy to kernel */
+void gdb_regs_to_regs(unsigned long *gdb_regs, struct pt_regs *kernel_regs)
+{
+       kernel_regs->ARM_r0 = gdb_regs[_R0];
+       kernel_regs->ARM_r1 = gdb_regs[_R1];
+       kernel_regs->ARM_r2 = gdb_regs[_R2];
+       kernel_regs->ARM_r3 = gdb_regs[_R3];
+       kernel_regs->ARM_r4 = gdb_regs[_R4];
+       kernel_regs->ARM_r5 = gdb_regs[_R5];
+       kernel_regs->ARM_r6 = gdb_regs[_R6];
+       kernel_regs->ARM_r7 = gdb_regs[_R7];
+       kernel_regs->ARM_r8 = gdb_regs[_R8];
+       kernel_regs->ARM_r9 = gdb_regs[_R9];
+       kernel_regs->ARM_r10 = gdb_regs[_R10];
+       kernel_regs->ARM_fp = gdb_regs[_FP];
+       kernel_regs->ARM_ip = gdb_regs[_IP];
+       kernel_regs->ARM_sp = gdb_regs[_SP];
+       kernel_regs->ARM_lr = gdb_regs[_LR];
+       kernel_regs->ARM_pc = gdb_regs[_PC];
+       kernel_regs->ARM_cpsr = gdb_regs[GDB_MAX_REGS - 1];
+}
+
+static inline struct pt_regs *kgdb_get_user_regs(struct task_struct *task)
+{
+       return (struct pt_regs *)
+           ((unsigned long)task->thread_info + THREAD_SIZE -
+            8 - sizeof(struct pt_regs));
+}
+
+void sleeping_thread_to_gdb_regs(unsigned long *gdb_regs,
+                                struct task_struct *task)
+{
+       int regno;
+       struct pt_regs *thread_regs;
+
+       /* Just making sure... */
+       if (task == NULL)
+               return;
+
+       /* Initialize to zero */
+       for (regno = 0; regno < GDB_MAX_REGS; regno++)
+               gdb_regs[regno] = 0;
+
+       /* Otherwise, we have only some registers from switch_to() */
+       thread_regs = kgdb_get_user_regs(task);
+       gdb_regs[_R0] = thread_regs->ARM_r0;    /* Not really valid? */
+       gdb_regs[_R1] = thread_regs->ARM_r1;    /* "               " */
+       gdb_regs[_R2] = thread_regs->ARM_r2;    /* "               " */
+       gdb_regs[_R3] = thread_regs->ARM_r3;    /* "               " */
+       gdb_regs[_R4] = thread_regs->ARM_r4;
+       gdb_regs[_R5] = thread_regs->ARM_r5;
+       gdb_regs[_R6] = thread_regs->ARM_r6;
+       gdb_regs[_R7] = thread_regs->ARM_r7;
+       gdb_regs[_R8] = thread_regs->ARM_r8;
+       gdb_regs[_R9] = thread_regs->ARM_r9;
+       gdb_regs[_R10] = thread_regs->ARM_r10;
+       gdb_regs[_FP] = thread_regs->ARM_fp;
+       gdb_regs[_IP] = thread_regs->ARM_ip;
+       gdb_regs[_SP] = thread_regs->ARM_sp;
+       gdb_regs[_LR] = thread_regs->ARM_lr;
+       gdb_regs[_PC] = thread_regs->ARM_pc;
+       gdb_regs[_CPSR] = thread_regs->ARM_cpsr;
+}
+
+static int compiled_break;
+
+int kgdb_arch_handle_exception(int exception_vector, int signo,
+                              int err_code, char *remcom_in_buffer,
+                              char *remcom_out_buffer,
+                              struct pt_regs *linux_regs)
+{
+       long addr;
+       char *ptr;
+
+       switch (remcom_in_buffer[0]) {
+       case 'c':
+               kgdb_contthread = NULL;
+
+               /*
+                * Try to read optional parameter, pc unchanged if no parm.
+                * If this was a compiled breakpoint, we need to move
+                * to the next instruction or we will just breakpoint
+                * over and over again.
+                */
+               ptr = &remcom_in_buffer[1];
+               if (kgdb_hex2long(&ptr, &addr)) {
+                       linux_regs->ARM_pc = addr;
+               } else if (compiled_break == 1) {
+                       linux_regs->ARM_pc += 4;
+               }
+
+               compiled_break = 0;
+
+               return 0;
+       }
+
+       return -1;
+}
+
+static int kgdb_brk_fn(struct pt_regs *regs, unsigned int instr)
+{
+       kgdb_handle_exception(1, SIGTRAP, 0, regs);
+
+       return 0;
+}
+
+static int kgdb_compiled_brk_fn(struct pt_regs *regs, unsigned int instr)
+{
+       compiled_break = 1;
+       kgdb_handle_exception(1, SIGTRAP, 0, regs);
+
+       return 0;
+}
+
+static struct undef_hook kgdb_brkpt_hook = {
+       .instr_mask = 0xffffffff,
+       .instr_val = KGDB_BREAKINST,
+       .fn = kgdb_brk_fn
+};
+
+static struct undef_hook kgdb_compiled_brkpt_hook = {
+       .instr_mask = 0xffffffff,
+       .instr_val = KGDB_COMPILED_BREAK,
+       .fn = kgdb_compiled_brk_fn
+};
+
+/*
+ * Register our undef instruction hooks with ARM undef core.
+ * We regsiter a hook specifically looking for the KGB break inst
+ * and we handle the normal undef case within the do_undefinstr
+ * handler.
+ */
+int kgdb_arch_init(void)
+{
+       register_undef_hook(&kgdb_brkpt_hook);
+       register_undef_hook(&kgdb_compiled_brkpt_hook);
+
+       return 0;
+}
+
+struct kgdb_arch arch_kgdb_ops = {
+#ifndef __ARMEB__
+       .gdb_bpt_instr = {0xfe, 0xde, 0xff, 0xe7}
+#else
+       .gdb_bpt_instr = {0xe7, 0xff, 0xde, 0xfe}
+#endif
+};
diff -puN /dev/null arch/arm/kernel/kgdb-jmp.S
--- /dev/null   2005-07-25 10:57:32.312383000 -0700
+++ linux-2.6.13-rc3-trini/arch/arm/kernel/kgdb-jmp.S   2005-07-29 
11:55:32.000000000 -0700
@@ -0,0 +1,30 @@
+/*
+ * arch/arm/kernel/kgdb-jmp.S
+ *
+ * Trivial setjmp and longjmp procedures to support bus error recovery
+ * which may occur during kgdb memory read/write operations.
+ *
+ * Author: MontaVista Software, Inc. <[EMAIL PROTECTED]>
+ *         [EMAIL PROTECTED]
+ *
+ * 2002-2005 (c) MontaVista Software, Inc.  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/linkage.h>
+
+ENTRY (kgdb_fault_setjmp)
+       /* Save registers */
+       stmia   r0, {r0-r14}
+       str     lr,[r0, #60]
+       mrs     r1,cpsr
+       str     r1,[r0,#64]
+       ldr     r1,[r0,#4]
+       mov     r0, #0
+       mov     pc,lr
+
+ENTRY (kgdb_fault_longjmp)
+       /* Restore registers */
+       mov     r1,#1
+       str     r1,[r0]
+       ldmia   r0,{r0-pc}^
diff -puN arch/arm/kernel/Makefile~arm-lite arch/arm/kernel/Makefile
--- linux-2.6.13-rc3/arch/arm/kernel/Makefile~arm-lite  2005-07-29 
11:55:32.000000000 -0700
+++ linux-2.6.13-rc3-trini/arch/arm/kernel/Makefile     2005-07-29 
11:55:32.000000000 -0700
@@ -19,6 +19,7 @@ obj-$(CONFIG_ARTHUR)          += arthur.o
 obj-$(CONFIG_ISA_DMA)          += dma-isa.o
 obj-$(CONFIG_PCI)              += bios32.o
 obj-$(CONFIG_SMP)              += smp.o
+obj-$(CONFIG_KGDB)             += kgdb.o kgdb-jmp.o
 
 obj-$(CONFIG_IWMMXT)           += iwmmxt.o
 AFLAGS_iwmmxt.o                        := -Wa,-mcpu=iwmmxt
diff -puN arch/arm/kernel/setup.c~arm-lite arch/arm/kernel/setup.c
--- linux-2.6.13-rc3/arch/arm/kernel/setup.c~arm-lite   2005-07-29 
11:55:32.000000000 -0700
+++ linux-2.6.13-rc3-trini/arch/arm/kernel/setup.c      2005-07-29 
11:55:32.000000000 -0700
@@ -785,6 +785,11 @@ void __init setup_arch(char **cmdline_p)
        conswitchp = &dummy_con;
 #endif
 #endif
+
+#if    defined(CONFIG_KGDB)
+       extern void __init early_trap_init(void);
+       early_trap_init();
+#endif
 }
 
 
diff -puN arch/arm/kernel/traps.c~arm-lite arch/arm/kernel/traps.c
--- linux-2.6.13-rc3/arch/arm/kernel/traps.c~arm-lite   2005-07-29 
11:55:32.000000000 -0700
+++ linux-2.6.13-rc3-trini/arch/arm/kernel/traps.c      2005-07-29 
11:55:32.000000000 -0700
@@ -266,6 +266,7 @@ asmlinkage void do_undefinstr(struct pt_
        unsigned int instr;
        struct undef_hook *hook;
        siginfo_t info;
+       mm_segment_t fs;
        void __user *pc;
 
        /*
@@ -275,12 +276,15 @@ asmlinkage void do_undefinstr(struct pt_
         */
        regs->ARM_pc -= correction;
 
+       fs = get_fs();
+       set_fs(KERNEL_DS);
        pc = (void __user *)instruction_pointer(regs);
        if (thumb_mode(regs)) {
                get_user(instr, (u16 __user *)pc);
        } else {
                get_user(instr, (u32 __user *)pc);
        }
+       set_fs(fs);
 
        spin_lock_irq(&undef_lock);
        list_for_each_entry(hook, &undef_hook, node) {
@@ -663,6 +667,13 @@ EXPORT_SYMBOL(abort);
 
 void __init trap_init(void)
 {
+#if    defined(CONFIG_KGDB)
+       return;
+}
+
+void __init early_trap_init(void)
+{
+#endif
        extern char __stubs_start[], __stubs_end[];
        extern char __vectors_start[], __vectors_end[];
        extern char __kuser_helper_start[], __kuser_helper_end[];
diff -puN arch/arm/mach-ixp2000/core.c~arm-lite arch/arm/mach-ixp2000/core.c
--- linux-2.6.13-rc3/arch/arm/mach-ixp2000/core.c~arm-lite      2005-07-29 
11:55:32.000000000 -0700
+++ linux-2.6.13-rc3-trini/arch/arm/mach-ixp2000/core.c 2005-07-29 
11:55:32.000000000 -0700
@@ -35,6 +35,7 @@
 #include <asm/system.h>
 #include <asm/tlbflush.h>
 #include <asm/pgtable.h>
+#include <asm/kgdb.h>
 
 #include <asm/mach/map.h>
 #include <asm/mach/time.h>
@@ -145,6 +146,10 @@ void __init ixp2000_map_io(void)
 
        iotable_init(ixp2000_io_desc, ARRAY_SIZE(ixp2000_io_desc));
 
+#ifdef CONFIG_KGDB_8250
+       kgdb8250_add_port(0, &ixp2000_serial_port);
+#endif
+
        /* Set slowport to 8-bit mode.  */
        ixp2000_reg_write(IXP2000_SLOWPORT_FRM, 1);
 }
diff -puN arch/arm/mach-ixp2000/ixdp2x01.c~arm-lite 
arch/arm/mach-ixp2000/ixdp2x01.c
--- linux-2.6.13-rc3/arch/arm/mach-ixp2000/ixdp2x01.c~arm-lite  2005-07-29 
11:55:32.000000000 -0700
+++ linux-2.6.13-rc3-trini/arch/arm/mach-ixp2000/ixdp2x01.c     2005-07-29 
11:55:32.000000000 -0700
@@ -38,6 +38,7 @@
 #include <asm/system.h>
 #include <asm/hardware.h>
 #include <asm/mach-types.h>
+#include <asm/kgdb.h>
 
 #include <asm/mach/pci.h>
 #include <asm/mach/map.h>
@@ -175,6 +176,11 @@ static void __init ixdp2x01_map_io(void)
 
        early_serial_setup(&ixdp2x01_serial_ports[0]);
        early_serial_setup(&ixdp2x01_serial_ports[1]);
+
+#ifdef CONFIG_KGDB_8250
+       kgdb8250_add_port(0, &ixdp2x01_serial_ports[0]);
+       kgdb8250_add_port(1, &ixdp2x01_serial_ports[1]);
+#endif
 }
 
 
diff -puN arch/arm/mach-ixp4xx/coyote-setup.c~arm-lite 
arch/arm/mach-ixp4xx/coyote-setup.c
--- linux-2.6.13-rc3/arch/arm/mach-ixp4xx/coyote-setup.c~arm-lite       
2005-07-29 11:55:32.000000000 -0700
+++ linux-2.6.13-rc3-trini/arch/arm/mach-ixp4xx/coyote-setup.c  2005-07-29 
11:55:32.000000000 -0700
@@ -96,9 +96,12 @@ static void __init coyote_init(void)
                coyote_uart_data[0].irq = IRQ_IXP4XX_UART1;
        }
 
-
        ixp4xx_sys_init();
        platform_add_devices(coyote_devices, ARRAY_SIZE(coyote_devices));
+
+#ifdef CONFIG_KGDB_8250
+       kgdb8250_add_port(0, &coyote_serial_port);
+#endif
 }
 
 #ifdef CONFIG_ARCH_ADI_COYOTE
diff -puN arch/arm/mach-ixp4xx/ixdp425-setup.c~arm-lite 
arch/arm/mach-ixp4xx/ixdp425-setup.c
--- linux-2.6.13-rc3/arch/arm/mach-ixp4xx/ixdp425-setup.c~arm-lite      
2005-07-29 11:55:32.000000000 -0700
+++ linux-2.6.13-rc3-trini/arch/arm/mach-ixp4xx/ixdp425-setup.c 2005-07-29 
11:55:32.000000000 -0700
@@ -23,6 +23,7 @@
 #include <asm/irq.h>
 #include <asm/mach/arch.h>
 #include <asm/mach/flash.h>
+#include <asm/kgdb.h>
 
 void __init ixdp425_map_io(void) 
 {
@@ -82,7 +83,7 @@ static struct plat_serial8250_port ixdp4
                .mapbase        = IXP4XX_UART1_BASE_PHYS,
                .membase        = (char *)IXP4XX_UART1_BASE_VIRT + REG_OFFSET,
                .irq            = IRQ_IXP4XX_UART1,
-               .flags          = UPF_BOOT_AUTOCONF,
+               .flags          = UPF_BOOT_AUTOCONF | UPF_SHARE_IRQ,
                .iotype         = UPIO_MEM,
                .regshift       = 2,
                .uartclk        = IXP4XX_UART_XTAL,
@@ -91,7 +92,7 @@ static struct plat_serial8250_port ixdp4
                .mapbase        = IXP4XX_UART2_BASE_PHYS,
                .membase        = (char *)IXP4XX_UART2_BASE_VIRT + REG_OFFSET,
                .irq            = IRQ_IXP4XX_UART1,
-               .flags          = UPF_BOOT_AUTOCONF,
+               .flags          = UPF_BOOT_AUTOCONF | UPF_SHARE_IRQ,
                .iotype         = UPIO_MEM,
                .regshift       = 2,
                .uartclk        = IXP4XX_UART_XTAL,
@@ -126,6 +127,11 @@ static void __init ixdp425_init(void)
        }
 
        platform_add_devices(ixdp425_devices, ARRAY_SIZE(ixdp425_devices));
+
+#ifdef CONFIG_KGDB_8250
+       kgdb8250_add_port(0, &ixdp425_serial_ports[0]);
+       kgdb8250_add_port(1, &ixdp425_serial_ports[1]);
+#endif
 }
 
 MACHINE_START(IXDP425, "Intel IXDP425 Development Platform")
diff -puN arch/arm/mach-omap1/board-osk.c~arm-lite 
arch/arm/mach-omap1/board-osk.c
--- linux-2.6.13-rc3/arch/arm/mach-omap1/board-osk.c~arm-lite   2005-07-29 
11:55:32.000000000 -0700
+++ linux-2.6.13-rc3-trini/arch/arm/mach-omap1/board-osk.c      2005-07-29 
11:55:32.000000000 -0700
@@ -41,12 +41,14 @@
 #include <asm/arch/tc.h>
 #include <asm/arch/common.h>
 
+#if 0
 static struct map_desc osk5912_io_desc[] __initdata = {
 { OMAP_OSK_NOR_FLASH_BASE, OMAP_OSK_NOR_FLASH_START, OMAP_OSK_NOR_FLASH_SIZE,
        MT_DEVICE },
 };
+#endif
 
-static int __initdata osk_serial_ports[OMAP_MAX_NR_PORTS] = {1, 0, 0};
+static int __initdata osk_serial_ports[OMAP_MAX_NR_PORTS] = {1, 1, 1};
 
 static struct resource osk5912_smc91x_resources[] = {
        [0] = {
@@ -153,7 +155,7 @@ static void __init osk_init(void)
 static void __init osk_map_io(void)
 {
        omap_map_common_io();
-       iotable_init(osk5912_io_desc, ARRAY_SIZE(osk5912_io_desc));
+       //iotable_init(osk5912_io_desc, ARRAY_SIZE(osk5912_io_desc));
        omap_serial_init(osk_serial_ports);
 }
 
diff -puN arch/arm/mach-omap1/serial.c~arm-lite arch/arm/mach-omap1/serial.c
--- linux-2.6.13-rc3/arch/arm/mach-omap1/serial.c~arm-lite      2005-07-29 
11:55:32.000000000 -0700
+++ linux-2.6.13-rc3-trini/arch/arm/mach-omap1/serial.c 2005-07-29 
11:55:32.000000000 -0700
@@ -15,6 +15,7 @@
 #include <linux/delay.h>
 #include <linux/serial.h>
 #include <linux/tty.h>
+#include <linux/kgdb.h>
 #include <linux/serial_8250.h>
 #include <linux/serial_reg.h>
 
@@ -190,6 +191,9 @@ void __init omap_serial_init(int ports[O
                        break;
                }
                omap_serial_reset(&serial_platform_data[i]);
+#ifdef CONFIG_KGDB_8250
+               kgdb8250_add_platform_port(i, &serial_platform_data[i]);
+#endif
        }
 }
 
diff -puN /dev/null arch/arm/mach-pxa/kgdb-serial.c
--- /dev/null   2005-07-25 10:57:32.312383000 -0700
+++ linux-2.6.13-rc3-trini/arch/arm/mach-pxa/kgdb-serial.c      2005-07-29 
11:55:32.000000000 -0700
@@ -0,0 +1,98 @@
+/*
+ * linux/arch/arm/mach-pxa/kgdb-serial.c
+ *
+ * Provides low level kgdb serial support hooks for PXA2xx boards
+ *
+ * Author:     Nicolas Pitre
+ * Copyright:  (C) 2002-2005 MontaVista Software Inc.
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 as
+ * published by the Free Software Foundation.
+ */
+
+#include <linux/config.h>
+#include <linux/serial_reg.h>
+#include <linux/kgdb.h>
+#include <asm/processor.h>
+#include <asm/hardware.h>
+#include <asm/arch/pxa-regs.h>
+
+#if   defined(CONFIG_KGDB_PXA_FFUART)
+
+#define UART           FFUART
+#define CKEN_UART      CKEN6_FFUART
+#define GPIO_RX_MD     GPIO34_FFRXD_MD
+#define GPIO_TX_MD     GPIO39_FFTXD_MD
+
+#elif defined(CONFIG_KGDB_PXA_BTUART)
+
+#define UART           BTUART
+#define CKEN_UART      CKEN7_BTUART
+#define GPIO_RX_MD     GPIO42_BTRXD_MD
+#define GPIO_TX_MD     GPIO43_BTTXD_MD
+
+#elif defined(CONFIG_KGDB_PXA_STUART)
+
+#define UART           STUART
+#define CKEN_UART      CKEN5_STUART
+#define GPIO_RX_MD     GPIO46_STRXD_MD
+#define GPIO_TX_MD     GPIO47_STTXD_MD
+
+#endif
+
+#define UART_BAUDRATE  (CONFIG_KGDB_PXA_BAUDRATE)
+
+static volatile unsigned long *port = (unsigned long *)&UART;
+
+static int kgdb_serial_init(void)
+{
+       pxa_set_cken(CKEN_UART, 1);
+       pxa_gpio_mode(GPIO_RX_MD);
+       pxa_gpio_mode(GPIO_TX_MD);
+
+       port[UART_IER] = 0;
+       port[UART_LCR] = LCR_DLAB;
+       port[UART_DLL] = ((921600 / UART_BAUDRATE) & 0xff);
+       port[UART_DLM] = ((921600 / UART_BAUDRATE) >> 8);
+       port[UART_LCR] = LCR_WLS1 | LCR_WLS0;
+       port[UART_MCR] = 0;
+       port[UART_IER] = IER_UUE;
+       port[UART_FCR] = FCR_ITL_16;
+
+       return 0;
+}
+
+static void kgdb_serial_putchar(int c)
+{
+       if (!(CKEN & CKEN_UART) || port[UART_IER] != IER_UUE)
+               kgdb_serial_init();
+       while (!(port[UART_LSR] & LSR_TDRQ))
+               cpu_relax();
+       port[UART_TX] = c;
+}
+
+static void kgdb_serial_flush(void)
+{
+       if ((CKEN & CKEN_UART) && (port[UART_IER] & IER_UUE))
+               while (!(port[UART_LSR] & LSR_TEMT))
+                       cpu_relax();
+}
+
+static int kgdb_serial_getchar(void)
+{
+       unsigned char c;
+       if (!(CKEN & CKEN_UART) || port[UART_IER] != IER_UUE)
+               kgdb_serial_init();
+       while (!(port[UART_LSR] & UART_LSR_DR))
+               cpu_relax();
+       c = port[UART_RX];
+       return c;
+}
+
+struct kgdb_io kgdb_io_ops = {
+       .init = kgdb_serial_init,
+       .write_char = kgdb_serial_putchar,
+       .flush = kgdb_serial_flush,
+       .read_char = kgdb_serial_getchar,
+};
diff -puN arch/arm/mach-pxa/Makefile~arm-lite arch/arm/mach-pxa/Makefile
--- linux-2.6.13-rc3/arch/arm/mach-pxa/Makefile~arm-lite        2005-07-29 
11:55:32.000000000 -0700
+++ linux-2.6.13-rc3-trini/arch/arm/mach-pxa/Makefile   2005-07-29 
11:55:32.000000000 -0700
@@ -24,6 +24,7 @@ obj-$(CONFIG_LEDS) += $(led-y)
 
 # Misc features
 obj-$(CONFIG_PM) += pm.o sleep.o
+obj-$(CONFIG_KGDB_PXA_SERIAL) += kgdb-serial.o
 
 ifeq ($(CONFIG_PXA27x),y)
 obj-$(CONFIG_PM) += standby.o
diff -puN /dev/null arch/arm/mach-versatile/kgdb_serial.c
--- /dev/null   2005-07-25 10:57:32.312383000 -0700
+++ linux-2.6.13-rc3-trini/arch/arm/mach-versatile/kgdb_serial.c        
2005-07-29 11:55:32.000000000 -0700
@@ -0,0 +1,121 @@
+/*
+ * arch/arm/mach-versatile/kgdb_serial.c
+ *
+ * Author: Manish Lachwani, [EMAIL PROTECTED]
+ *
+ * 2005 (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 ARM Versatile.
+ */
+#include <linux/config.h>
+#include <linux/serial_reg.h>
+#include <linux/kgdb.h>
+#include <asm/io.h>
+#include <asm/processor.h>
+#include <asm/hardware.h>
+#include <asm/hardware/amba_serial.h>
+#include <asm/arch-versatile/hardware.h>
+
+#define ARM_BAUD_38400         23
+/*
+ * Functions that will be used later
+ */
+#define UART_GET_INT_STATUS(p) readb((p) + UART010_IIR)
+#define UART_GET_MIS(p)                readw((p) + UART011_MIS)
+#define UART_PUT_ICR(p, c)     writel((c), (p) + UART010_ICR)
+#define UART_GET_FR(p)         readb((p) + UART01x_FR)
+#define UART_GET_CHAR(p)       readb((p) + UART01x_DR)
+#define UART_PUT_CHAR(p, c)     writel((c), (p) + UART01x_DR)
+#define UART_GET_RSR(p)                readb((p) + UART01x_RSR)
+#define UART_GET_CR(p)         readb((p) + UART010_CR)
+#define UART_PUT_CR(p,c)        writel((c), (p) + UART010_CR)
+#define UART_GET_LCRL(p)       readb((p) + UART010_LCRL)
+#define UART_PUT_LCRL(p,c)     writel((c), (p) + UART010_LCRL)
+#define UART_GET_LCRM(p)        readb((p) + UART010_LCRM)
+#define UART_PUT_LCRM(p,c)     writel((c), (p) + UART010_LCRM)
+#define UART_GET_LCRH(p)       readb((p) + UART010_LCRH)
+#define UART_PUT_LCRH(p,c)     writel((c), (p) + UART010_LCRH)
+#define UART_RX_DATA(s)                (((s) & UART01x_FR_RXFE) == 0)
+#define UART_TX_READY(s)       (((s) & UART01x_FR_TXFF) == 0)
+#define UART_TX_EMPTY(p)       ((UART_GET_FR(p) & UART01x_FR_TMSK) == 0)
+
+/*
+ * KGDB IRQ
+ */
+static int kgdb_irq = 12;
+static volatile unsigned char *port = NULL;
+
+static int kgdb_serial_init(void)
+{
+       int rate = ARM_BAUD_38400;
+
+       port = IO_ADDRESS(0x101F1000);
+       UART_PUT_CR(port, 0);
+
+       /* Set baud rate */
+       UART_PUT_LCRM(port, ((rate & 0xf00) >> 8));
+       UART_PUT_LCRL(port, (rate & 0xff));
+       UART_PUT_LCRH(port, UART01x_LCRH_WLEN_8 | UART01x_LCRH_FEN);
+       UART_PUT_CR(port, UART01x_CR_UARTEN);
+
+       return 0;
+}
+
+static void kgdb_serial_putchar(int ch)
+{
+       unsigned int status;
+
+       do {
+               status = UART_GET_FR(port);
+       } while (!UART_TX_READY(status));
+
+       UART_PUT_CHAR(port, ch);
+}
+
+static int kgdb_serial_getchar(void)
+{
+       unsigned int status;
+       int ch;
+
+       do {
+               status = UART_GET_FR(port);
+       } while (!UART_RX_DATA(status));
+       ch = UART_GET_CHAR(port);
+       return ch;
+}
+
+static struct uart_port kgdb_amba_port = {
+       .irq = 12,
+       .iobase = 0,
+       .iotype = UPIO_MEM,
+       .membase = (unsigned char *)IO_ADDRESS(0x101F1000),
+};
+
+static irqreturn_t kgdb_interrupt(int irq, void *dev_id, struct pt_regs *regs)
+{
+       int status = UART_GET_MIS(port);
+
+       if (irq != kgdb_irq)
+               return IRQ_NONE;
+
+       if (status & 0x40)
+               breakpoint();
+
+       return IRQ_HANDLED;
+}
+
+static void __init kgdb_hookup_irq(void)
+{
+       request_irq(kgdb_irq, kgdb_interrupt, SA_SHIRQ, "GDB-stub",
+                   &kgdb_amba_port);
+}
+
+struct kgdb_io kgdb_io_ops = {
+       .init = kgdb_serial_init,
+       .write_char = kgdb_serial_putchar,
+       .read_char = kgdb_serial_getchar,
+       .late_init = kgdb_hookup_irq,
+};
diff -puN arch/arm/mm/extable.c~arm-lite arch/arm/mm/extable.c
--- linux-2.6.13-rc3/arch/arm/mm/extable.c~arm-lite     2005-07-29 
11:55:32.000000000 -0700
+++ linux-2.6.13-rc3-trini/arch/arm/mm/extable.c        2005-07-29 
11:55:32.000000000 -0700
@@ -2,6 +2,7 @@
  *  linux/arch/arm/mm/extable.c
  */
 #include <linux/module.h>
+#include <linux/kgdb.h>
 #include <asm/uaccess.h>
 
 int fixup_exception(struct pt_regs *regs)
@@ -11,6 +12,12 @@ int fixup_exception(struct pt_regs *regs
        fixup = search_exception_tables(instruction_pointer(regs));
        if (fixup)
                regs->ARM_pc = fixup->fixup;
+#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 fixup != NULL;
 }
diff -puN drivers/serial/amba-pl011.c~arm-lite drivers/serial/amba-pl011.c
--- linux-2.6.13-rc3/drivers/serial/amba-pl011.c~arm-lite       2005-07-29 
11:55:32.000000000 -0700
+++ linux-2.6.13-rc3-trini/drivers/serial/amba-pl011.c  2005-07-29 
11:55:32.000000000 -0700
@@ -350,7 +350,7 @@ static int pl011_startup(struct uart_por
        /*
         * Allocate the IRQ
         */
-       retval = request_irq(uap->port.irq, pl011_int, 0, "uart-pl011", uap);
+       retval = request_irq(uap->port.irq, pl011_int, SA_SHIRQ, "uart-pl011", 
uap);
        if (retval)
                goto clk_dis;
 
diff -puN drivers/serial/kgdb_8250.c~arm-lite drivers/serial/kgdb_8250.c
--- linux-2.6.13-rc3/drivers/serial/kgdb_8250.c~arm-lite        2005-07-29 
11:55:32.000000000 -0700
+++ linux-2.6.13-rc3-trini/drivers/serial/kgdb_8250.c   2005-07-29 
11:55:32.000000000 -0700
@@ -319,6 +319,22 @@ static int kgdb8250_init(void)
 
        /* Disable UART interrupts, set DTR and RTS high and set speed. */
        cval = 0x3;
+#if    defined(CONFIG_ARCH_OMAP1510)
+       /* Workaround to enable 115200 baud on OMAP1510 internal ports */
+       if (cpu_is_omap1510() && is_omap_port((void *)kgdb8250_addr)) {
+               if (kgdb8250_baud == 115200) {
+                       base_baud = 1;
+                       kgdb8250_baud = 1;
+                       serial_outb(1, kgdb8250_addr +
+                                   (UART_OMAP_OSC_12M_SEL <<
+                                    KGDB8250_REG_SHIFT));
+               } else {
+                       serial_outb(0, kgdb8250_addr +
+                                   (UART_OMAP_OSC_12M_SEL <<
+                                    KGDB8250_REG_SHIFT));
+               }
+       }
+#endif
        /* set DLAB */
        serial_outb(cval | UART_LCR_DLAB, kgdb8250_addr +
                    (UART_LCR << KGDB8250_REG_SHIFT));
diff -puN /dev/null include/asm-arm/kgdb.h
--- /dev/null   2005-07-25 10:57:32.312383000 -0700
+++ linux-2.6.13-rc3-trini/include/asm-arm/kgdb.h       2005-07-29 
12:48:10.000000000 -0700
@@ -0,0 +1,90 @@
+/*
+ * include/asm-arm/kgdb.h
+ *
+ * ARM KGDB support
+ *
+ * Author: Deepak Saxena <[EMAIL PROTECTED]>
+ *
+ * Copyright (C) 2002 MontaVista Software Inc.
+ *
+ */
+
+#ifndef __ASM_KGDB_H__
+#define __ASM_KGDB_H__
+
+#include <linux/config.h>
+#include <asm/ptrace.h>
+
+
+/*
+ * GDB assumes that we're a user process being debugged, so
+ * it will send us an SWI command to write into memory as the
+ * debug trap. When an SWI occurs, the next instruction addr is
+ * placed into R14_svc before jumping to the vector trap.
+ * This doesn't work for kernel debugging as we are already in SVC
+ * we would loose the kernel's LR, which is a bad thing. This
+ * is  bad thing.
+ *
+ * By doing this as an undefined instruction trap, we force a mode
+ * switch from SVC to UND mode, allowing us to save full kernel state.
+ *
+ * We also define a KGDB_COMPILED_BREAK which can be used to compile
+ * in breakpoints. This is important for things like sysrq-G and for
+ * the initial breakpoint from trap_init().
+ *
+ * Note to ARM HW designers: Add real trap support like SH && PPC to
+ * make our lives much much simpler. :)
+ */
+#define        BREAK_INSTR_SIZE                4
+#define GDB_BREAKINST                   0xef9f0001
+#define KGDB_BREAKINST                  0xe7ffdefe
+#define KGDB_COMPILED_BREAK             0xe7ffdeff
+#define CACHE_FLUSH_IS_SAFE            1
+
+#ifndef        __ASSEMBLY__
+
+#define        BREAKPOINT()                    asm(".word      0xe7ffdeff")
+
+
+extern void kgdb_handle_bus_error(void);
+extern int kgdb_fault_expected;
+
+/*
+ * From Amit S. Kale:
+ *
+ * In the register packet, words 0-15 are R0 to R10, FP, IP, SP, LR, PC. But
+ * Register 16 isn't cpsr. GDB passes CPSR in word 25. There are 9 words in
+ * between which are unused. Passing only 26 words to gdb is sufficient.
+ * GDB can figure out that floating point registers are not passed.
+ * GDB_MAX_REGS should be 26.
+ */
+#define        GDB_MAX_REGS            (26)
+
+#define        KGDB_MAX_NO_CPUS        1
+#define        BUFMAX                  400
+#define        NUMREGBYTES             (GDB_MAX_REGS << 2)
+#define        NUMCRITREGBYTES         (32 << 2)
+#define        CHECK_EXCEPTION_STACK() 1
+
+#define        _R0             0
+#define        _R1             1
+#define        _R2             2
+#define        _R3             3
+#define        _R4             4
+#define        _R5             5
+#define        _R6             6
+#define        _R7             7
+#define        _R8             8
+#define        _R9             9
+#define        _R10            10
+#define        _FP             11
+#define        _IP             12
+#define        _SP             13
+#define        _LR             14
+#define        _PC             15
+#define        _CPSR           (GDB_MAX_REGS - 1)
+
+#define        CHECK_EXCEPTION_STACK() 1
+
+#endif // !__ASSEMBLY__
+#endif // __ASM_KGDB_H__
diff -puN include/asm-arm/system.h~arm-lite include/asm-arm/system.h
--- linux-2.6.13-rc3/include/asm-arm/system.h~arm-lite  2005-07-29 
11:55:32.000000000 -0700
+++ linux-2.6.13-rc3-trini/include/asm-arm/system.h     2005-07-29 
11:55:32.000000000 -0700
@@ -371,6 +371,47 @@ static inline unsigned long __xchg(unsig
        return ret;
 }
 
+#define        __HAVE_ARCH_CMPXCHG     1
+
+#include <asm/types.h>
+
+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);
+
+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))); \
+  })
 #endif /* __ASSEMBLY__ */
 
 #define arch_align_stack(x) (x)
diff -puN lib/Kconfig.debug~arm-lite lib/Kconfig.debug
--- linux-2.6.13-rc3/lib/Kconfig.debug~arm-lite 2005-07-29 11:55:32.000000000 
-0700
+++ linux-2.6.13-rc3-trini/lib/Kconfig.debug    2005-07-29 13:18:12.000000000 
-0700
@@ -163,7 +163,7 @@ config FRAME_POINTER
 
 config KGDB
        bool "KGDB: kernel debugging with remote gdb"
-       depends on DEBUG_KERNEL && (X86 || MIPS32 || (SUPERH && !SUPERH64) || 
IA64 || X86_64 || ((!SMP || BROKEN) && PPC32))
+       depends on DEBUG_KERNEL && (ARM || 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
@@ -189,8 +189,10 @@ choice
        prompt "Method for KGDB communication"
        depends on KGDB
        default KGDB_ONLY_MODULES
+       default KGDB_ARM_VERSATILE if ARCH_VERSATILE
        default KGDB_SIBYTE if SIBYTE_SB1xxx_SOC
        default KGDB_MPSC if SERIAL_MPSC
+       default KGDB_PXA_SERIAL if ARCH_PXA
        help
          There are a number of different ways in which you can communicate
          with KGDB.  The most common is via serial, with the 8250 driver
@@ -227,6 +229,16 @@ config KGDB_SIBYTE
        bool "KGDB: On the Broadcom SWARM serial port"
        depends on MIPS && SIBYTE_SB1xxx_SOC
 
+config KGDB_ARM_VERSATILE
+       bool "KGDB: On ARM Versatile"
+       depends on ARM && ARCH_VERSATILE
+       help
+         Enables the KGDB serial driver for the ARM Versatile
+
+config KGDB_PXA_SERIAL
+       bool "KGDB: On the PXA2xx serial port"
+       depends on ARCH_PXA
+
 config KGDB_SH_SCI
        bool "KGDB: On SH SCI(F) serial port"
        depends on SUPERH && SERIAL_SH_SCI
@@ -296,6 +308,27 @@ config KGDB_PORT_3
        bool "Third serial port"
 endchoice
 
+choice
+       prompt "PXA serial UART for KGDB"
+       depends on KGDB_PXA_SERIAL
+       default KGDB_PXA_FFUART
+
+config KGDB_PXA_FFUART
+       bool "FFUART"
+
+config KGDB_PXA_BTUART
+       bool "BTUART"
+
+config KGDB_PXA_STUART
+       bool "STUART"
+
+endchoice
+
+config KGDB_PXA_BAUDRATE
+       int "UART baudrate for KGDB"
+       depends on KGDB_PXA_SERIAL
+       default "115200"
+
 config KGDB_PORT
        hex "hex I/O port address of the debug serial port"
        depends on !KGDB_SIMPLE_SERIAL && KGDB_8250 && !IA64
_
-
To unsubscribe from this list: send the line "unsubscribe linux-kernel" in
the body of a message to [EMAIL PROTECTED]
More majordomo info at  http://vger.kernel.org/majordomo-info.html
Please read the FAQ at  http://www.tux.org/lkml/

Reply via email to