+diff -rupN -X ../client-cleanup/dontdiff linux-2.6.18/Documentation/DocBook/Makefile linux-2.6.18.kgdb/Documentation/DocBook/Makefile
+--- linux-2.6.18/Documentation/DocBook/Makefile 2006-09-20 07:42:06.000000000 +0400
++++ linux-2.6.18.kgdb/Documentation/DocBook/Makefile 2008-06-10 16:18:58.000000000 +0400
+@@ -11,7 +11,7 @@ DOCBOOKS := wanbook.xml z8530book.xml mc
+ procfs-guide.xml writing_usb_driver.xml \
+ kernel-api.xml journal-api.xml lsm.xml usb.xml \
+ gadget.xml libata.xml mtdnand.xml librs.xml rapidio.xml \
+- genericirq.xml
++ genericirq.xml kgdb.xml
+
+ ###
+ # The build process is as follows (targets):
+diff -rupN -X ../client-cleanup/dontdiff linux-2.6.18/Documentation/DocBook/kgdb.tmpl linux-2.6.18.kgdb/Documentation/DocBook/kgdb.tmpl
+--- linux-2.6.18/Documentation/DocBook/kgdb.tmpl 1970-01-01 03:00:00.000000000 +0300
++++ linux-2.6.18.kgdb/Documentation/DocBook/kgdb.tmpl 2008-06-10 16:19:47.000000000 +0400
+@@ -0,0 +1,250 @@
++<?xml version="1.0" encoding="UTF-8"?>
++<!DOCTYPE book PUBLIC "-//OASIS//DTD DocBook XML V4.1.2//EN"
++ "http://www.oasis-open.org/docbook/xml/4.1.2/docbookx.dtd" []>
++
++<book id="kgdbInternals">
++ <bookinfo>
++ <title>KGDB Internals</title>
++
++ <authorgroup>
++ <author>
++ <firstname>Tom</firstname>
++ <surname>Rini</surname>
++ <affiliation>
++ <address>
++ <email>trini@kernel.crashing.org</email>
++ </address>
++ </affiliation>
++ </author>
++ </authorgroup>
++
++ <authorgroup>
++ <author>
++ <firstname>Amit S.</firstname>
++ <surname>Kale</surname>
++ <affiliation>
++ <address>
++ <email>amitkale@linsyssoft.com</email>
++ </address>
++ </affiliation>
++ </author>
++ </authorgroup>
++
++ <copyright>
++ <year>2004-2005</year>
++ <holder>MontaVista Software, Inc.</holder>
++ </copyright>
++ <copyright>
++ <year>2004</year>
++ <holder>Amit S. Kale</holder>
++ </copyright>
++
++ <legalnotice>
++ <para>
++ 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.
++ </para>
++
++ </legalnotice>
++ </bookinfo>
++
++<toc></toc>
++ <chapter id="Introduction">
++ <title>Introduction</title>
++ <para>
++ kgdb is a source level debugger for linux kernel. It is used along
++ with gdb to debug a linux kernel. Kernel developers can debug a kernel
++ similar to application programs with the use of kgdb. It makes it
++ possible to place breakpoints in kernel code, step through the code
++ and observe variables.
++ </para>
++ <para>
++ Two machines are required for using kgdb. One of these machines is a
++ development machine and the other is a test machine. The machines are
++ typically connected through a serial line, a null-modem cable which
++ connects their serial ports. It is also possible however, to use an
++ ethernet connection between the machines. The kernel to be debugged
++ runs on the test machine. gdb runs on the development machine. The
++ serial line or ethernet connection is used by gdb to communicate to
++ the kernel being debugged.
++ </para>
++ </chapter>
++ <chapter id="CompilingAKernel">
++ <title>Compiling a kernel</title>
++ <para>
++ To enable <symbol>CONFIG_KGDB</symbol>, look under the "Kernel debugging"
++ and then select "KGDB: kernel debugging with remote gdb".
++ </para>
++ <para>
++ The first choice for I/O is <symbol>CONFIG_KGDB_ONLY_MODULES</symbol>.
++ This means that you will only be able to use KGDB after loading a
++ kernel module that defines how you want to be able to talk with
++ KGDB. There are two other choices (more on some architectures) that
++ can be enabled as modules later, if not picked here.
++ </para>
++ <para>The first of these is <symbol>CONFIG_KGDB_8250_NOMODULE</symbol>.
++ This has sub-options such as <symbol>CONFIG_KGDB_SIMPLE_SERIAL</symbol>
++ which toggles choosing the serial port by ttyS number or by specifying
++ a port and IRQ number.
++ </para>
++ <para>
++ The second of these choices on most systems for I/O is
++ <symbol>CONFIG_KGDBOE</symbol>. This requires that the machine to be
++ debugged has an ethernet card which supports the netpoll API, such as
++ the cards supported by <symbol>CONFIG_E100</symbol>. There are no
++ sub-options for this, but a kernel command line option is required.
++ </para>
++ </chapter>
++ <chapter id="BootingTheKernel">
++ <title>Booting the kernel</title>
++ <para>
++ The Kernel command line option <constant>kgdbwait</constant> makes kgdb
++ wait for gdb connection during booting of a kernel. If the
++ <symbol>CONFIG_KGDB_8250</symbol> driver is used (or if applicable,
++ another serial driver) this breakpoint will happen very early on, before
++ console output. If you wish to change serial port information and you
++ have enabled both <symbol>CONFIG_KGDB_8250</symbol> and
++ <symbol>CONFIG_KGDB_SIMPLE_SERIAL</symbol> then you must pass the option
++ <constant>kgdb8250=<io or mmio>,<address>,<baud
++ rate>,<irq></constant> before <constant>kgdbwait</constant>.
++ The values <constant>io</constant> or <constant>mmio</constant> refer to
++ if the address being passed next needs to be memory mapped
++ (<constant>mmio</constant>) or not. The <constant>address</constant> must
++ be passed in hex and is the hardware address and will be remapped if
++ passed as <constant>mmio</constant>. The value
++ <constant>baud rate</constant> and <constant>irq</constant> are base-10.
++ The supported values for <constant>baud rate</constant> are
++ <constant>9600</constant>, <constant>19200</constant>,
++ <constant>38400</constant>, <constant>57600</constant>, and
++ <constant>115200</constant>.
++ </para>
++ <para>
++ To have KGDB stop the kernel and wait, with the compiled values for the
++ serial driver, pass in: <constant>kgdbwait</constant>.
++ </para>
++ <para>
++ To specify the values of the SH SCI(F) serial port at boot:
++ <constant>kgdbsci=0,115200</constant>.
++ </para>
++ <para>
++ To specify the values of the serial port at boot:
++ <constant>kgdb8250=io,3f8,115200,3</constant>.
++ On IA64 this could also be:
++ <constant>kgdb8250=mmio,0xff5e0000,115200,74</constant>
++ And to have KGDB also stop the kernel and wait for GDB to connect, pass in
++ <constant>kgdbwait</constant> after this arguement.
++ </para>
++ <para>
++ To configure the <symbol>CONFIG_KGDBOE</symbol> driver, pass in
++ <constant>kgdboe=[src-port]@<src-ip>/[dev],[tgt-port]@<tgt-ip>/[tgt-macaddr]</constant>
++ where:
++ <itemizedlist>
++ <listitem><para>src-port (optional): source for UDP packets (defaults to <constant>6443</constant>)</para></listitem>
++ <listitem><para>src-ip: source IP to use (interface address)</para></listitem>
++ <listitem><para>dev (optional): network interface (<constant>eth0</constant>)</para></listitem>
++ <listitem><para>tgt-port (optional): port GDB will use (defaults to <constant>6442</constant>)</para></listitem>
++ <listitem><para>tgt-ip: IP address GDB will be connecting from</para></listitem>
++ <listitem><para>tgt-macaddr (optional): ethernet MAC address for logging agent (default is broadcast)</para></listitem>
++ </itemizedlist>
++ </para>
++ <para>
++ The <symbol>CONFIG_KGDBOE</symbol> driver can be reconfigured at run
++ time, if <symbol>CONFIG_SYSFS</symbol> and
++ <symbol>CONFIG_MODULES</symbol> by echo'ing a new config string to
++ <constant>/sys/module/kgdboe/parameter/kgdboe</constant>. The
++ driver can be unconfigured with the special string
++ <constant>not_configured</constant>.
++ </para>
++ </chapter>
++ <chapter id="ConnectingGDB">
++ <title>Connecting gdb</title>
++ <para>
++ If you have used any of the methods to have KGDB stop and create
++ an initial breakpoint described in the previous chapter, kgdb prints
++ the message "Waiting for connection from remote gdb..." on the console
++ and waits for connection from gdb. At this point you connect gdb to kgdb.
++ </para>
++ <para>
++ Example (serial):
++ </para>
++ <programlisting>
++ % gdb ./vmlinux
++ (gdb) set remotebaud 115200
++ (gdb) target remote /dev/ttyS0
++ </programlisting>
++ <para>
++ Example (ethernet):
++ </para>
++ <programlisting>
++ % gdb ./vmlinux
++ (gdb) target remote udp:192.168.2.2:6443
++ </programlisting>
++ <para>
++ Once connected, you can debug a kernel the way you would debug an
++ application program.
++ </para>
++ </chapter>
++ <chapter id="ArchitectureNotes">
++ <title>Architecture specific notes</title>
++ <para>
++ SuperH: The NMI switch found on some boards can be used to trigger an
++ initial breakpoint. Subsequent triggers do nothing. If console
++ is enabled on the SCI(F) serial port, and that is the port being used
++ for KGDB, then you must trigger a breakpoint via sysrq, NMI, or
++ some other method prior to connecting, or echo a control-c to the
++ serial port. Also, to use the SCI(F) port for KGDB, the
++ <symbol>CONFIG_SERIAL_SH_SCI</symbol> driver must be enabled.
++ </para>
++ </chapter>
++ <chapter id="CommonBackEndReq">
++ <title>The common backend (required)</title>
++ <para>
++ There are a few flags which must be set on every architecture in
++ their <asm/kgdb.h> file. These are:
++ <itemizedlist>
++ <listitem>
++ <para>
++ NUMREGBYTES: The size in bytes of all of the registers, so
++ that we can ensure they will all fit into a packet.
++ </para>
++ <para>
++ BUFMAX: The size in bytes of the buffer GDB will read into.
++ This must be larger than NUMREGBYTES.
++ </para>
++ <para>
++ CACHE_FLUSH_IS_SAFE: Set to one if it always safe to call
++ flush_cache_range or flush_icache_range. On some architectures,
++ these functions may not be safe to call on SMP since we keep other
++ CPUs in a holding pattern.
++ </para>
++ </listitem>
++ </itemizedlist>
++ </para>
++ <para>
++ There are also the following functions for the common backend,
++ found in kernel/kgdb.c that must be supplied by the
++ architecture-specific backend. No weak version of these is provided.
++ </para>
++!Iinclude/linux/kgdb.h
++ </chapter>
++ <chapter id="CommonBackEndOpt">
++ <title>The common backend (optional)</title>
++ <para>
++ These functions are part of the common backend, found in kernel/kgdb.c
++ and are optionally implemented. Some functions (with _hw_ in the name)
++ end up being required on arches which use hardware breakpoints.
++ </para>
++!Ikernel/kgdb.c
++ </chapter>
++ <chapter id="DriverSpecificFunctions">
++ <title>Driver-Specific Functions</title>
++ <para>
++ Some of the I/O drivers have additional functions that can be
++ called, that are specific to the driver. Calls from other places
++ to these functions must be wrapped in #ifdefs for the driver in
++ question.
++ </para>
++!Idrivers/serial/8250_kgdb.c
++ </chapter>
++</book>
+diff -rupN -X ../client-cleanup/dontdiff linux-2.6.18/MAINTAINERS linux-2.6.18.kgdb/MAINTAINERS
+--- linux-2.6.18/MAINTAINERS 2006-09-20 07:42:06.000000000 +0400
++++ linux-2.6.18.kgdb/MAINTAINERS 2008-06-10 16:18:58.000000000 +0400
+@@ -1685,6 +1685,15 @@ L: linux-kernel@vger.kernel.org
+ L: fastboot@osdl.org
+ S: Maintained
+
++KGDB
++P: Tom Rini
++P: Amit S. Kale
++M: trini@kernel.crashing.org
++M: amitkale@linsyssoft.com
++W: http://sourceforge.net/projects/kgdb
++L: kgdb-bugreport@lists.sourceforge.net
++S: Maintained
++
+ KPROBES
+ P: Prasanna S Panchamukhi
+ M: prasanna@in.ibm.com
+diff -rupN -X ../client-cleanup/dontdiff linux-2.6.18/Makefile linux-2.6.18.kgdb/Makefile
+--- linux-2.6.18/Makefile 2006-09-20 07:42:06.000000000 +0400
++++ linux-2.6.18.kgdb/Makefile 2008-06-10 16:19:57.000000000 +0400
+@@ -990,6 +990,7 @@ MRPROPER_DIRS += include/config include
+ MRPROPER_FILES += .config .config.old include/asm .version .old_version \
+ include/linux/autoconf.h include/linux/version.h \
+ include/linux/utsrelease.h \
++ include/linux/dwarf2-defs.h \
+ Module.symvers tags TAGS cscope*
+
+ # clean - Delete most, but leave enough to build external modules
+@@ -1416,7 +1417,11 @@ clean := -f $(if $(KBUILD_SRC),$(srctree
+ endif # skip-makefile
+
+ PHONY += FORCE
+-FORCE:
++include/linux/dwarf2-defs.h: $(srctree)/include/linux/dwarf2.h $(srctree)/scripts/dwarfh.awk
++ mkdir -p include/linux/
++ awk -f $(srctree)/scripts/dwarfh.awk $(srctree)/include/linux/dwarf2.h > include/linux/dwarf2-defs.h
++
++FORCE: include/linux/dwarf2-defs.h
+
+
+ # Declare the contents of the .PHONY variable as phony. We keep that
+diff -rupN -X ../client-cleanup/dontdiff linux-2.6.18/arch/arm/kernel/Makefile linux-2.6.18.kgdb/arch/arm/kernel/Makefile
+--- linux-2.6.18/arch/arm/kernel/Makefile 2006-09-20 07:42:06.000000000 +0400
++++ linux-2.6.18.kgdb/arch/arm/kernel/Makefile 2008-06-10 16:19:51.000000000 +0400
+@@ -20,6 +20,7 @@ obj-$(CONFIG_ISA_DMA) += dma-isa.o
+ obj-$(CONFIG_PCI) += bios32.o isa.o
+ obj-$(CONFIG_SMP) += smp.o
+ obj-$(CONFIG_OABI_COMPAT) += sys_oabi-compat.o
++obj-$(CONFIG_KGDB) += kgdb.o kgdb-jmp.o
+
+ obj-$(CONFIG_CRUNCH) += crunch.o crunch-bits.o
+ AFLAGS_crunch-bits.o := -Wa,-mcpu=ep9312
+diff -rupN -X ../client-cleanup/dontdiff linux-2.6.18/arch/arm/kernel/entry-armv.S linux-2.6.18.kgdb/arch/arm/kernel/entry-armv.S
+--- linux-2.6.18/arch/arm/kernel/entry-armv.S 2006-09-20 07:42:06.000000000 +0400
++++ linux-2.6.18.kgdb/arch/arm/kernel/entry-armv.S 2008-06-10 16:19:58.000000000 +0400
+@@ -15,6 +15,7 @@
+ * it to save wrong values... Be aware!
+ */
+
++#include <asm/kgdb.h>
+ #include <asm/memory.h>
+ #include <asm/glue.h>
+ #include <asm/vfpmacros.h>
+@@ -232,6 +233,7 @@ svc_preempt:
+ beq preempt_return @ go again
+ b 1b
+ #endif
++ CFI_END_FRAME(__irq_svc)
+
+ .align 5
+ __und_svc:
+diff -rupN -X ../client-cleanup/dontdiff linux-2.6.18/arch/arm/kernel/kgdb-jmp.S linux-2.6.18.kgdb/arch/arm/kernel/kgdb-jmp.S
+--- linux-2.6.18/arch/arm/kernel/kgdb-jmp.S 1970-01-01 03:00:00.000000000 +0300
++++ linux-2.6.18.kgdb/arch/arm/kernel/kgdb-jmp.S 2008-06-10 16:19:51.000000000 +0400
+@@ -0,0 +1,32 @@
++/*
++ * 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. <source@mvista.com>
++ * source@mvista.com
++ *
++ * 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]
++ ldr r1,[r0, #64]
++ msr spsr,r1
++ ldmia r0,{r0-pc}^
+diff -rupN -X ../client-cleanup/dontdiff linux-2.6.18/arch/arm/kernel/kgdb.c linux-2.6.18.kgdb/arch/arm/kernel/kgdb.c
+--- linux-2.6.18/arch/arm/kernel/kgdb.c 1970-01-01 03:00:00.000000000 +0300
++++ linux-2.6.18.kgdb/arch/arm/kernel/kgdb.c 2008-06-10 16:19:51.000000000 +0400
+@@ -0,0 +1,208 @@
++/*
++ * arch/arm/kernel/kgdb.c
++ *
++ * ARM KGDB support
++ *
++ * Copyright (c) 2002-2004 MontaVista Software, Inc
++ *
++ * Authors: George Davis <davis_g@mvista.com>
++ * Deepak Saxena <dsaxena@plexity.net>
++ */
++#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 -rupN -X ../client-cleanup/dontdiff linux-2.6.18/arch/arm/kernel/setup.c linux-2.6.18.kgdb/arch/arm/kernel/setup.c
+--- linux-2.6.18/arch/arm/kernel/setup.c 2006-09-20 07:42:06.000000000 +0400
++++ linux-2.6.18.kgdb/arch/arm/kernel/setup.c 2008-06-10 16:19:51.000000000 +0400
+@@ -829,6 +829,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 -rupN -X ../client-cleanup/dontdiff linux-2.6.18/arch/arm/kernel/traps.c linux-2.6.18.kgdb/arch/arm/kernel/traps.c
+--- linux-2.6.18/arch/arm/kernel/traps.c 2006-09-20 07:42:06.000000000 +0400
++++ linux-2.6.18.kgdb/arch/arm/kernel/traps.c 2008-06-10 16:19:51.000000000 +0400
+@@ -278,6 +278,7 @@ asmlinkage void do_undefinstr(struct pt_
+ unsigned int instr;
+ struct undef_hook *hook;
+ siginfo_t info;
++ mm_segment_t fs;
+ void __user *pc;
+
+ /*
+@@ -287,12 +288,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) {
+@@ -684,6 +688,13 @@ EXPORT_SYMBOL(abort);
+
+ void __init trap_init(void)
+ {
++#if defined(CONFIG_KGDB)
++ return;
++}
++
++void __init early_trap_init(void)
++{
++#endif
+ unsigned long vectors = CONFIG_VECTORS_BASE;
+ extern char __stubs_start[], __stubs_end[];
+ extern char __vectors_start[], __vectors_end[];
+diff -rupN -X ../client-cleanup/dontdiff linux-2.6.18/arch/arm/mach-ixp2000/core.c linux-2.6.18.kgdb/arch/arm/mach-ixp2000/core.c
+--- linux-2.6.18/arch/arm/mach-ixp2000/core.c 2006-09-20 07:42:06.000000000 +0400
++++ linux-2.6.18.kgdb/arch/arm/mach-ixp2000/core.c 2008-06-10 16:19:51.000000000 +0400
+@@ -34,6 +34,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>
+@@ -184,6 +185,9 @@ static struct platform_device ixp2000_se
+ void __init ixp2000_uart_init(void)
+ {
+ platform_device_register(&ixp2000_serial_device);
++#ifdef CONFIG_KGDB_8250
++ kgdb8250_add_port(0, &ixp2000_serial_port);
++#endif
+ }
+
+
+diff -rupN -X ../client-cleanup/dontdiff linux-2.6.18/arch/arm/mach-ixp2000/ixdp2x01.c linux-2.6.18.kgdb/arch/arm/mach-ixp2000/ixdp2x01.c
+--- linux-2.6.18/arch/arm/mach-ixp2000/ixdp2x01.c 2006-09-20 07:42:06.000000000 +0400
++++ linux-2.6.18.kgdb/arch/arm/mach-ixp2000/ixdp2x01.c 2008-06-10 16:19:51.000000000 +0400
+@@ -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>
+@@ -413,6 +414,11 @@ static void __init ixdp2x01_init_machine
+ platform_add_devices(ixdp2x01_devices, ARRAY_SIZE(ixdp2x01_devices));
+ ixp2000_uart_init();
+ ixdp2x01_uart_init();
++
++#ifdef CONFIG_KGDB_8250
++ kgdb8250_add_port(0, &ixdp425_serial_ports[0]);
++ kgdb8250_add_port(1, &ixdp425_serial_ports[1]);
++#endif
+ }
+
+
+diff -rupN -X ../client-cleanup/dontdiff linux-2.6.18/arch/arm/mach-ixp4xx/coyote-setup.c linux-2.6.18.kgdb/arch/arm/mach-ixp4xx/coyote-setup.c
+--- linux-2.6.18/arch/arm/mach-ixp4xx/coyote-setup.c 2006-09-20 07:42:06.000000000 +0400
++++ linux-2.6.18.kgdb/arch/arm/mach-ixp4xx/coyote-setup.c 2008-06-10 16:19:51.000000000 +0400
+@@ -96,6 +96,10 @@ static void __init coyote_init(void)
+ }
+
+ 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 -rupN -X ../client-cleanup/dontdiff linux-2.6.18/arch/arm/mach-ixp4xx/ixdp425-setup.c linux-2.6.18.kgdb/arch/arm/mach-ixp4xx/ixdp425-setup.c
+--- linux-2.6.18/arch/arm/mach-ixp4xx/ixdp425-setup.c 2006-09-20 07:42:06.000000000 +0400
++++ linux-2.6.18.kgdb/arch/arm/mach-ixp4xx/ixdp425-setup.c 2008-06-10 16:19:51.000000000 +0400
+@@ -24,6 +24,7 @@
+ #include <asm/irq.h>
+ #include <asm/mach/arch.h>
+ #include <asm/mach/flash.h>
++#include <asm/kgdb.h>
+
+ static struct flash_platform_data ixdp425_flash_data = {
+ .map_name = "cfi_probe",
+@@ -76,7 +77,8 @@ 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 | UPF_SKIP_TEST,
++ .flags = UPF_BOOT_AUTOCONF | UPF_SKIP_TEST |
++ UPF_SHARE_IRQ,
+ .iotype = UPIO_MEM,
+ .regshift = 2,
+ .uartclk = IXP4XX_UART_XTAL,
+@@ -85,7 +87,8 @@ static struct plat_serial8250_port ixdp4
+ .mapbase = IXP4XX_UART2_BASE_PHYS,
+ .membase = (char *)IXP4XX_UART2_BASE_VIRT + REG_OFFSET,
+ .irq = IRQ_IXP4XX_UART2,
+- .flags = UPF_BOOT_AUTOCONF | UPF_SKIP_TEST,
++ .flags = UPF_BOOT_AUTOCONF | UPF_SKIP_TEST |
++ UPF_SHARE_IRQ,
+ .iotype = UPIO_MEM,
+ .regshift = 2,
+ .uartclk = IXP4XX_UART_XTAL,
+@@ -116,6 +119,11 @@ static void __init ixdp425_init(void)
+ IXP4XX_EXP_BUS_BASE(0) + ixp4xx_exp_bus_size - 1;
+
+ 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
+ }
+
+ #ifdef CONFIG_ARCH_IXDP425
+diff -rupN -X ../client-cleanup/dontdiff linux-2.6.18/arch/arm/mach-omap1/serial.c linux-2.6.18.kgdb/arch/arm/mach-omap1/serial.c
+--- linux-2.6.18/arch/arm/mach-omap1/serial.c 2006-09-20 07:42:06.000000000 +0400
++++ linux-2.6.18.kgdb/arch/arm/mach-omap1/serial.c 2008-06-10 16:19:51.000000000 +0400
+@@ -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>
+ #include <linux/clk.h>
+@@ -199,6 +200,9 @@ void __init omap_serial_init(void)
+ break;
+ }
+ omap_serial_reset(&serial_platform_data[i]);
++#ifdef CONFIG_KGDB_8250
++ kgdb8250_add_platform_port(i, &serial_platform_data[i]);
++#endif
+ }
+ }
+
+diff -rupN -X ../client-cleanup/dontdiff linux-2.6.18/arch/arm/mach-pxa/Makefile linux-2.6.18.kgdb/arch/arm/mach-pxa/Makefile
+--- linux-2.6.18/arch/arm/mach-pxa/Makefile 2006-09-20 07:42:06.000000000 +0400
++++ linux-2.6.18.kgdb/arch/arm/mach-pxa/Makefile 2008-06-10 16:19:51.000000000 +0400
+@@ -31,6 +31,7 @@ obj-$(CONFIG_LEDS) += $(led-y)
+ # Misc features
+ obj-$(CONFIG_PM) += pm.o sleep.o
+ obj-$(CONFIG_PXA_SSP) += ssp.o
++obj-$(CONFIG_KGDB_PXA_SERIAL) += kgdb-serial.o
+
+ ifeq ($(CONFIG_PXA27x),y)
+ obj-$(CONFIG_PM) += standby.o
+diff -rupN -X ../client-cleanup/dontdiff linux-2.6.18/arch/arm/mach-pxa/kgdb-serial.c linux-2.6.18.kgdb/arch/arm/mach-pxa/kgdb-serial.c
+--- linux-2.6.18/arch/arm/mach-pxa/kgdb-serial.c 1970-01-01 03:00:00.000000000 +0300
++++ linux-2.6.18.kgdb/arch/arm/mach-pxa/kgdb-serial.c 2008-06-10 16:19:51.000000000 +0400
+@@ -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_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 -rupN -X ../client-cleanup/dontdiff linux-2.6.18/arch/arm/mach-versatile/kgdb_serial.c linux-2.6.18.kgdb/arch/arm/mach-versatile/kgdb_serial.c
+--- linux-2.6.18/arch/arm/mach-versatile/kgdb_serial.c 1970-01-01 03:00:00.000000000 +0300
++++ linux-2.6.18.kgdb/arch/arm/mach-versatile/kgdb_serial.c 2008-06-10 16:19:51.000000000 +0400
+@@ -0,0 +1,121 @@
++/*
++ * arch/arm/mach-versatile/kgdb_serial.c
++ *
++ * Author: Manish Lachwani, mlachwani@mvista.com
++ *
++ * 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 -rupN -X ../client-cleanup/dontdiff linux-2.6.18/arch/arm/mm/extable.c linux-2.6.18.kgdb/arch/arm/mm/extable.c
+--- linux-2.6.18/arch/arm/mm/extable.c 2006-09-20 07:42:06.000000000 +0400
++++ linux-2.6.18.kgdb/arch/arm/mm/extable.c 2008-06-10 16:19:51.000000000 +0400
+@@ -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 -rupN -X ../client-cleanup/dontdiff linux-2.6.18/arch/i386/kernel/Makefile linux-2.6.18.kgdb/arch/i386/kernel/Makefile
+--- linux-2.6.18/arch/i386/kernel/Makefile 2006-09-20 07:42:06.000000000 +0400
++++ linux-2.6.18.kgdb/arch/i386/kernel/Makefile 2008-06-10 16:19:17.000000000 +0400
+@@ -39,6 +39,7 @@ obj-$(CONFIG_VM86) += vm86.o
+ obj-$(CONFIG_EARLY_PRINTK) += early_printk.o
+ obj-$(CONFIG_HPET_TIMER) += hpet.o
+ obj-$(CONFIG_K8_NB) += k8.o
++obj-$(CONFIG_KGDB) += kgdb.o kgdb-jmp.o
+
+ EXTRA_AFLAGS := -traditional
+
+diff -rupN -X ../client-cleanup/dontdiff linux-2.6.18/arch/i386/kernel/entry.S linux-2.6.18.kgdb/arch/i386/kernel/entry.S
+--- linux-2.6.18/arch/i386/kernel/entry.S 2006-09-20 07:42:06.000000000 +0400
++++ linux-2.6.18.kgdb/arch/i386/kernel/entry.S 2008-06-10 16:19:58.000000000 +0400
+@@ -201,7 +201,7 @@ VM_MASK = 0x00020000
+ CFI_OFFSET ecx, ECX-OLDESP;\
+ CFI_OFFSET ebx, EBX-OLDESP
+
+-ENTRY(ret_from_fork)
++KPROBE_ENTRY(ret_from_fork)
+ CFI_STARTPROC
+ pushl %eax
+ CFI_ADJUST_CFA_OFFSET 4
+@@ -664,7 +664,7 @@ ENTRY(simd_coprocessor_error)
+ jmp error_code
+ CFI_ENDPROC
+
+-ENTRY(device_not_available)
++KPROBE_ENTRY(device_not_available)
+ RING0_INT_FRAME
+ pushl $-1 # mark this as an int
+ CFI_ADJUST_CFA_OFFSET 4
+@@ -909,7 +909,7 @@ ENTRY(machine_check)
+ CFI_ENDPROC
+ #endif
+
+-ENTRY(spurious_interrupt_bug)
++KPROBE_ENTRY(spurious_interrupt_bug)
+ RING0_INT_FRAME
+ pushl $0
+ CFI_ADJUST_CFA_OFFSET 4
+@@ -953,3 +953,108 @@ ENDPROC(arch_unwind_init_running)
+ #include "syscall_table.S"
+
+ syscall_table_size=(.-sys_call_table)
++
++# Here we do call frames. We cheat a bit as we only really need
++# correct frames at locations we can actually look at from a
++# debugger. Since the break instruction trap actually goes thru
++# some of this code, we don't really need info on those areas, but
++# only after the fact. I.e. if we can not step or break in a
++# location or end up with a return address pointing at the
++# location, we don't need a correct call frame for it.
++
++#ifdef CONFIG_KGDB
++
++#include <linux/dwarf2-lang.h>
++/*
++ * The register numbers as known by gdb
++ */
++
++#define _EAX 0
++#define _ECX 1
++#define _EDX 2
++#define _EBX 3
++#define _ESP 4
++#define _EBP 5
++#define _ESI 6
++#define _EDI 7
++#define _PC 8
++#define _EIP 8
++#define _PS 9
++#define _EFLAGS 9
++#define _CS 10
++#define _SS 11
++#define _DS 12
++#define _ES 13
++#define _FS 14
++#define _GS 15
++ /*
++ * This code uses macros defined in linux/dwarf2-lang.h
++ * They attempt to follow the dwarf2 naming conventions... sort of..
++ */
++ENTRY(end_of_stack_stop_unwind_function)
++ .long end_of_stack_stop_unwind_function+1
++
++ .text
++
++ CFI_preamble(c1,_PC,1,1)
++ CFA_define_reference(_ESP,OLDESP) /* Stack pointer */
++ CFA_expression(_EIP)
++ CFA_exp_OP_dup /* copy old esp */
++ CFA_exp_OP_consts(CS-OLDESP) /* offset to CS address */
++ CFA_exp_OP_plus /* should be CS address */
++ CFA_exp_OP_deref /* get the CS */
++ CFA_exp_OP_const4s(VM_MASK|3) /* prepare to mask it */
++ CFA_exp_OP_and /* mask it, zero means kernel */
++ CFA_exp_OP_bra(eip_user_rtn) /* branch if user */
++ CFA_exp_OP_const4s(EIP-OLDESP) /* offset to return address */
++ CFA_exp_OP_plus /* add that in */
++ CFA_exp_OP_skip(eip_end) /* done if kernel, skip out */
++eip_user_rtn:
++ CFA_exp_OP_addr(end_of_stack_stop_unwind_function)/*dummy function */
++eip_end:
++ CFA_expression_end
++ CFA_define_offset(_EBX,EBX-OLDESP)
++ CFA_define_offset(_ECX,ECX-OLDESP)
++ CFA_define_offset(_EDX,EDX-OLDESP)
++ CFA_define_offset(_ESI,ESI-OLDESP)
++ CFA_define_offset(_EDI,EDI-OLDESP)
++ CFA_define_offset(_EBP,EBP-OLDESP)
++ CFA_define_offset(_EAX,EAX-OLDESP)
++ CFA_define_offset(_EFLAGS,EFLAGS-OLDESP)
++ CFI_postamble()
++
++/*
++ * This provides an uwind for our dummy end of unwind function.
++ * Current convention is to provied an undefined return address.
++ */
++ CFI_preamble(c2,_PC,1,1)
++ CFA_define_reference(_ESP,0) /* Stack pointer */
++ CFA_undefine_reg(_EIP)
++ CFI_postamble()
++
++ FDE_preamble(c2,end_of_stack_stop_unwind_function, \
++ end_of_stack_stop_unwind_function+5)
++ FDE_postamble()
++ /*
++ * This is VERY sloppy. At this point all we want to do is get
++ * the frame right for back tracing. It will not be good if
++ * you try to single step. We use already defined labels.
++ * We want to cover all call outs.
++ * We could also recode this as just one FDE, but this works and
++ * I want to get it out.
++ */
++ FDE_preamble(c1,ret_from_fork,ret_from_exception)
++ CFA_define_cfa_offset(4) /* one extra word on stack */
++ FDE_postamble()
++
++ FDE_preamble(c1,ret_from_exception,device_not_available_emulate)
++ FDE_postamble()
++
++ FDE_preamble(c1,device_not_available_emulate,debug)
++ CFA_define_cfa_offset(4) /* one extra word on stack */
++ FDE_postamble()
++
++ FDE_preamble(c1, debug,spurious_interrupt_bug)
++ FDE_postamble()
++
++#endif
+diff -rupN -X ../client-cleanup/dontdiff linux-2.6.18/arch/i386/kernel/head.S linux-2.6.18.kgdb/arch/i386/kernel/head.S
+--- linux-2.6.18/arch/i386/kernel/head.S 2006-09-20 07:42:06.000000000 +0400
++++ linux-2.6.18.kgdb/arch/i386/kernel/head.S 2008-06-10 16:19:58.000000000 +0400
+@@ -10,6 +10,7 @@
+ .text
+ #include <linux/threads.h>
+ #include <linux/linkage.h>
++#include <asm/kgdb.h>
+ #include <asm/segment.h>
+ #include <asm/page.h>
+ #include <asm/pgtable.h>
+@@ -326,6 +327,10 @@ is386: movl $2,%ecx # set MP
+ #endif /* CONFIG_SMP */
+ jmp start_kernel
+
++ /* This dwarf code tells gdb that this is the end of the unwind */
++ /* This uses the CFA set up for pc=1 located in entry.S */
++ CFI_END_FRAME(is386)
++
+ /*
+ * We depend on ET to be correct. This checks for 287/387.
+ */
+diff -rupN -X ../client-cleanup/dontdiff linux-2.6.18/arch/i386/kernel/kgdb-jmp.S linux-2.6.18.kgdb/arch/i386/kernel/kgdb-jmp.S
+--- linux-2.6.18/arch/i386/kernel/kgdb-jmp.S 1970-01-01 03:00:00.000000000 +0300
++++ linux-2.6.18.kgdb/arch/i386/kernel/kgdb-jmp.S 2008-06-10 16:19:17.000000000 +0400
+@@ -0,0 +1,74 @@
++/*
++ * arch/i386/kernel/kgdb-jmp.S
++ *
++ * 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: George Anzinger <george@mvista.com>
++ *
++ * Cribbed from glibc, which carries the following:
++ * Copyright (C) 1996, 1996, 1997, 2000, 2001 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/linkage.h>
++
++#define PCOFF 0
++#define LINKAGE 4 /* just the return address */
++#define PTR_SIZE 4
++#define PARMS LINKAGE /* no space for saved regs */
++#define JMPBUF PARMS
++#define VAL JMPBUF+PTR_SIZE
++
++#define JB_BX 0
++#define JB_SI 1
++#define JB_DI 2
++#define JB_BP 3
++#define JB_SP 4
++#define JB_PC 5
++
++/* This must be called prior to kgdb_fault_longjmp and
++ * kgdb_fault_longjmp must not be called outside of the context of the
++ * last call to kgdb_fault_setjmp.
++ * kgdb_fault_setjmp(int *jmp_buf[6])
++ */
++ENTRY(kgdb_fault_setjmp)
++ movl JMPBUF(%esp), %eax
++
++ /* Save registers. */
++ movl %ebx, (JB_BX*4)(%eax)
++ movl %esi, (JB_SI*4)(%eax)
++ movl %edi, (JB_DI*4)(%eax)
++ /* Save SP as it will be after we return. */
++ leal JMPBUF(%esp), %ecx
++ movl %ecx, (JB_SP*4)(%eax)
++ movl PCOFF(%esp), %ecx /* Save PC we are returning to now. */
++ movl %ecx, (JB_PC*4)(%eax)
++ movl %ebp, (JB_BP*4)(%eax) /* Save caller's frame pointer. */
++
++ /* Restore state so we can now try the access. */
++ movl JMPBUF(%esp), %ecx /* User's jmp_buf in %ecx. */
++ /* Save the return address now. */
++ movl (JB_PC*4)(%ecx), %edx
++ /* Restore registers. */
++ movl $0, %eax
++ movl (JB_SP*4)(%ecx), %esp
++ jmp *%edx /* Jump to saved PC. */
++
++/* kgdb_fault_longjmp(int *jmp_buf[6]) */
++ENTRY(kgdb_fault_longjmp)
++ movl JMPBUF(%esp), %ecx /* User's jmp_buf in %ecx. */
++ /* Save the return address now. */
++ movl (JB_PC*4)(%ecx), %edx
++ /* Restore registers. */
++ movl (JB_BX*4)(%ecx), %ebx
++ movl (JB_SI*4)(%ecx), %esi
++ movl (JB_DI*4)(%ecx), %edi
++ movl (JB_BP*4)(%ecx), %ebp
++ movl $1, %eax
++ movl (JB_SP*4)(%ecx), %esp
++ jmp *%edx /* Jump to saved PC. */
+diff -rupN -X ../client-cleanup/dontdiff linux-2.6.18/arch/i386/kernel/kgdb.c linux-2.6.18.kgdb/arch/i386/kernel/kgdb.c
+--- linux-2.6.18/arch/i386/kernel/kgdb.c 1970-01-01 03:00:00.000000000 +0300
++++ linux-2.6.18.kgdb/arch/i386/kernel/kgdb.c 2008-06-10 16:20:15.000000000 +0400
+@@ -0,0 +1,363 @@
++/*
++ *
++ * 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, or (at your option) any
++ * later version.
++ *
++ * This program is distributed in the hope that it will be useful, but
++ * WITHOUT ANY WARRANTY; without even the implied warranty of
++ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
++ * General Public License for more details.
++ *
++ */
++
++/*
++ * Copyright (C) 2000-2001 VERITAS Software Corporation.
++ */
++/*
++ * Contributor: Lake Stevens Instrument Division$
++ * Written by: Glenn Engel $
++ * Updated by: Amit Kale<akale@veritas.com>
++ * Updated by: Tom Rini <trini@kernel.crashing.org>
++ * Modified for 386 by Jim Kingdon, Cygnus Support.
++ * Origianl kgdb, compatibility with 2.1.xx kernel by
++ * David Grothe <dave@gcom.com>
++ * Additional support from Tigran Aivazian <tigran@sco.com>
++ */
++
++#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/vm86.h>
++#include <asm/system.h>
++#include <asm/ptrace.h> /* for linux pt_regs struct */
++#include <linux/kgdb.h>
++#include <linux/init.h>
++#include <asm/apicdef.h>
++#include <asm/desc.h>
++#include <asm/kdebug.h>
++
++#include "mach_ipi.h"
++
++/* Put the error code here just in case the user cares. */
++int gdb_i386errcode;
++/* Likewise, the vector number here (since GDB only gets the signal
++ number through the usual means, and that's not very specific). */
++int gdb_i386vector = -1;
++
++extern atomic_t cpu_doing_single_step;
++
++void regs_to_gdb_regs(unsigned long *gdb_regs, struct pt_regs *regs)
++{
++ gdb_regs[_EAX] = regs->eax;
++ gdb_regs[_EBX] = regs->ebx;
++ gdb_regs[_ECX] = regs->ecx;
++ gdb_regs[_EDX] = regs->edx;
++ gdb_regs[_ESI] = regs->esi;
++ gdb_regs[_EDI] = regs->edi;
++ gdb_regs[_EBP] = regs->ebp;
++ gdb_regs[_DS] = regs->xds;
++ gdb_regs[_ES] = regs->xes;
++ gdb_regs[_PS] = regs->eflags;
++ gdb_regs[_CS] = regs->xcs;
++ gdb_regs[_PC] = regs->eip;
++ gdb_regs[_ESP] = (int)(®s->esp);
++ gdb_regs[_SS] = __KERNEL_DS;
++ gdb_regs[_FS] = 0xFFFF;
++ gdb_regs[_GS] = 0xFFFF;
++}
++
++/*
++ * Extracts ebp, esp and eip values understandable by gdb from the values
++ * saved by switch_to.
++ * thread.esp points to ebp. flags and ebp are pushed in switch_to hence esp
++ * prior to entering switch_to is 8 greater then the value that is saved.
++ * If switch_to changes, change following code appropriately.
++ */
++void sleeping_thread_to_gdb_regs(unsigned long *gdb_regs, struct task_struct *p)
++{
++ gdb_regs[_EAX] = 0;
++ gdb_regs[_EBX] = 0;
++ gdb_regs[_ECX] = 0;
++ gdb_regs[_EDX] = 0;
++ gdb_regs[_ESI] = 0;
++ gdb_regs[_EDI] = 0;
++ gdb_regs[_EBP] = *(unsigned long *)p->thread.esp;
++ gdb_regs[_DS] = __KERNEL_DS;
++ gdb_regs[_ES] = __KERNEL_DS;
++ gdb_regs[_PS] = 0;
++ gdb_regs[_CS] = __KERNEL_CS;
++ gdb_regs[_PC] = p->thread.eip;
++ gdb_regs[_ESP] = p->thread.esp;
++ gdb_regs[_SS] = __KERNEL_DS;
++ gdb_regs[_FS] = 0xFFFF;
++ gdb_regs[_GS] = 0xFFFF;
++}
++
++void gdb_regs_to_regs(unsigned long *gdb_regs, struct pt_regs *regs)
++{
++ regs->eax = gdb_regs[_EAX];
++ regs->ebx = gdb_regs[_EBX];
++ regs->ecx = gdb_regs[_ECX];
++ regs->edx = gdb_regs[_EDX];
++ regs->esi = gdb_regs[_ESI];
++ regs->edi = gdb_regs[_EDI];
++ regs->ebp = gdb_regs[_EBP];
++ regs->xds = gdb_regs[_DS];
++ regs->xes = gdb_regs[_ES];
++ regs->eflags = gdb_regs[_PS];
++ regs->xcs = gdb_regs[_CS];
++ regs->eip = gdb_regs[_PC];
++}
++
++static struct hw_breakpoint {
++ unsigned enabled;
++ unsigned type;
++ unsigned len;
++ unsigned addr;
++} breakinfo[4] = {
++ { .enabled = 0 },
++ { .enabled = 0 },
++ { .enabled = 0 },
++ { .enabled = 0 },
++};
++
++void kgdb_correct_hw_break(void)
++{
++ int breakno;
++ int correctit;
++ int breakbit;
++ unsigned dr7;
++
++ asm volatile ("movl %%db7, %0\n":"=r" (dr7)
++ :);
++ do {
++ unsigned addr0, addr1, addr2, addr3;
++ asm volatile ("movl %%db0, %0\n"
++ "movl %%db1, %1\n"
++ "movl %%db2, %2\n"
++ "movl %%db3, %3\n":"=r" (addr0), "=r"(addr1),
++ "=r"(addr2), "=r"(addr3):);
++ } while (0);
++ correctit = 0;
++ for (breakno = 0; breakno < 3; breakno++) {
++ breakbit = 2 << (breakno << 1);
++ if (!(dr7 & breakbit) && breakinfo[breakno].enabled) {
++ correctit = 1;
++ dr7 |= breakbit;
++ dr7 &= ~(0xf0000 << (breakno << 2));
++ dr7 |= (((breakinfo[breakno].len << 2) |
++ breakinfo[breakno].type) << 16) <<
++ (breakno << 2);
++ switch (breakno) {
++ case 0:
++ asm volatile ("movl %0, %%dr0\n"::"r"
++ (breakinfo[breakno].addr));
++ break;
++
++ case 1:
++ asm volatile ("movl %0, %%dr1\n"::"r"
++ (breakinfo[breakno].addr));
++ break;
++
++ case 2:
++ asm volatile ("movl %0, %%dr2\n"::"r"
++ (breakinfo[breakno].addr));
++ break;
++
++ case 3:
++ asm volatile ("movl %0, %%dr3\n"::"r"
++ (breakinfo[breakno].addr));
++ break;
++ }
++ } else if ((dr7 & breakbit) && !breakinfo[breakno].enabled) {
++ correctit = 1;
++ dr7 &= ~breakbit;
++ dr7 &= ~(0xf0000 << (breakno << 2));
++ }
++ }
++ if (correctit)
++ asm volatile ("movl %0, %%db7\n"::"r" (dr7));
++}
++
++int kgdb_remove_hw_break(unsigned long addr)
++{
++ int i, idx = -1;
++ for (i = 0; i < 4; i++) {
++ if (breakinfo[i].addr == addr && breakinfo[i].enabled) {
++ idx = i;
++ break;
++ }
++ }
++ if (idx == -1)
++ return -1;
++
++ breakinfo[idx].enabled = 0;
++ return 0;
++}
++
++void kgdb_remove_all_hw_break(void)
++{
++ int i;
++
++ for (i = 0; i < 4; i++) {
++ if (breakinfo[i].enabled) {
++ /* Do what? */
++ ;
++ }
++ memset(&breakinfo[i], 0, sizeof(struct hw_breakpoint));
++ }
++}
++
++int kgdb_set_hw_break(unsigned long addr)
++{
++ int i, idx = -1;
++ for (i = 0; i < 4; i++) {
++ if (!breakinfo[i].enabled) {
++ idx = i;
++ break;
++ }
++ }
++ if (idx == -1)
++ return -1;
++
++ breakinfo[idx].enabled = 1;
++ breakinfo[idx].type = 1;
++ breakinfo[idx].len = 1;
++ breakinfo[idx].addr = addr;
++ return 0;
++}
++
++void kgdb_disable_hw_debug(struct pt_regs *regs)
++{
++ /* Disable hardware debugging while we are in kgdb */
++ asm volatile ("movl %0,%%db7": /* no output */ :"r" (0));
++}
++
++void kgdb_post_master_code(struct pt_regs *regs, int e_vector, int err_code)
++{
++ /* Master processor is completely in the debugger */
++ gdb_i386vector = e_vector;
++ gdb_i386errcode = err_code;
++}
++
++void kgdb_roundup_cpus(unsigned long flags)
++{
++ send_IPI_allbutself(APIC_DM_NMI);
++}
++
++int kgdb_arch_handle_exception(int e_vector, int signo,
++ int err_code, char *remcom_in_buffer,
++ char *remcom_out_buffer,
++ struct pt_regs *linux_regs)
++{
++ long addr;
++ char *ptr;
++ int newPC, dr6;
++
++ switch (remcom_in_buffer[0]) {
++ case 'c':
++ case 's':
++ /* try to read optional parameter, pc unchanged if no parm */
++ ptr = &remcom_in_buffer[1];
++ if (kgdb_hex2long(&ptr, &addr))
++ linux_regs->eip = addr;
++ newPC = linux_regs->eip;
++
++ /* clear the trace bit */
++ linux_regs->eflags &= ~TF_MASK;
++ atomic_set(&cpu_doing_single_step, -1);
++
++ /* set the trace bit if we're stepping */
++ if (remcom_in_buffer[0] == 's') {
++ linux_regs->eflags |= TF_MASK;
++ debugger_step = 1;
++ atomic_set(&cpu_doing_single_step,smp_processor_id());
++ }
++
++ asm volatile ("movl %%db6, %0\n":"=r" (dr6));
++ if (!(dr6 & 0x4000)) {
++ long breakno;
++ for (breakno = 0; breakno < 4; ++breakno) {
++ if (dr6 & (1 << breakno) &&
++ breakinfo[breakno].type == 0) {
++ /* Set restore flag */
++ linux_regs->eflags |= X86_EFLAGS_RF;
++ break;
++ }
++ }
++ }
++ kgdb_correct_hw_break();
++ asm volatile ("movl %0, %%db6\n"::"r" (0));
++
++ return (0);
++ } /* switch */
++ /* this means that we do not want to exit from the handler */
++ return -1;
++}
++
++/* Register KGDB with the i386die_chain so that we hook into all of the right
++ * spots. */
++static int kgdb_notify(struct notifier_block *self, unsigned long cmd,
++ void *ptr)
++{
++ struct die_args *args = ptr;
++ struct pt_regs *regs = args->regs;
++
++ /* Bad memory access? */
++ if (cmd == DIE_PAGE_FAULT_NO_CONTEXT && atomic_read(&debugger_active)
++ && kgdb_may_fault) {
++ kgdb_fault_longjmp(kgdb_fault_jmp_regs);
++ return NOTIFY_STOP;
++ } else if (cmd == DIE_PAGE_FAULT)
++ /* A normal page fault, ignore. */
++ return NOTIFY_DONE;
++ else if ((cmd == DIE_NMI || cmd == DIE_NMI_IPI ||
++ cmd == DIE_NMIWATCHDOG) && atomic_read(&debugger_active)) {
++ /* CPU roundup */
++ kgdb_nmihook(smp_processor_id(), regs);
++ return NOTIFY_STOP;
++ } else if (cmd == DIE_NMI_IPI || cmd == DIE_NMI || user_mode(regs) ||
++ (cmd == DIE_DEBUG && atomic_read(&debugger_active)))
++ /* Normal watchdog event or userspace debugging, or spurious
++ * debug exception, ignore. */
++ return NOTIFY_DONE;
++
++ kgdb_handle_exception(args->trapnr, args->signr, args->err, regs);
++
++ return NOTIFY_STOP;
++}
++
++static struct notifier_block kgdb_notifier = {
++ .notifier_call = kgdb_notify,
++};
++
++int kgdb_arch_init(void)
++{
++ atomic_notifier_chain_register(&i386die_chain, &kgdb_notifier);
++ return 0;
++}
++
++/*
++ * Skip an int3 exception when it occurs after a breakpoint has been
++ * removed. Backtrack eip by 1 since the int3 would have caused it to
++ * increment by 1.
++ */
++
++int kgdb_skipexception(int exception, struct pt_regs *regs)
++{
++ if (exception == 3 && kgdb_isremovedbreak(regs->eip - 1)) {
++ regs->eip -= 1;
++ return 1;
++ }
++ return 0;
++}
++
++struct kgdb_arch arch_kgdb_ops = {
++ .gdb_bpt_instr = {0xcc},
++ .flags = KGDB_HW_BREAKPOINT,
++};
+diff -rupN -X ../client-cleanup/dontdiff linux-2.6.18/arch/i386/kernel/process.c linux-2.6.18.kgdb/arch/i386/kernel/process.c
+--- linux-2.6.18/arch/i386/kernel/process.c 2006-09-20 07:42:06.000000000 +0400
++++ linux-2.6.18.kgdb/arch/i386/kernel/process.c 2008-06-10 16:19:58.000000000 +0400
+@@ -328,7 +328,27 @@ __asm__(".section .text\n"
+ "call *%ebx\n\t"
+ "pushl %eax\n\t"
+ "call do_exit\n"
++ "kernel_thread_helper_end:\n\t"
+ ".previous");
++#ifdef CONFIG_KGDB
++#include <linux/dwarf2-lang.h>
++
++ /* This dwarf code tells gdb that this is the end of the unwind */
++ /* This uses the CFA set up for pc=1 located in entry.S */
++#define _ESP 4
++#define _PC 8
++#define _EIP 8
++__asm__(
++ QUOTE_THIS(
++ CFI_preamble(dwarf_4,_PC,1,1)
++ CFA_define_reference(_ESP,0) /* Stack pointer */
++ CFA_undefine_reg(_EIP)
++ CFI_postamble()
++
++ FDE_preamble(dwarf_4,kernel_thread_helper,kernel_thread_helper_end)
++ FDE_postamble()
++ ));
++#endif
+
+ /*
+ * Create a kernel thread
+diff -rupN -X ../client-cleanup/dontdiff linux-2.6.18/arch/i386/kernel/setup.c linux-2.6.18.kgdb/arch/i386/kernel/setup.c
+--- linux-2.6.18/arch/i386/kernel/setup.c 2006-09-20 07:42:06.000000000 +0400
++++ linux-2.6.18.kgdb/arch/i386/kernel/setup.c 2008-06-10 16:19:17.000000000 +0400
+@@ -148,6 +148,7 @@ EXPORT_SYMBOL(ist_info);
+ struct e820map e820;
+
+ extern void early_cpu_init(void);
++extern void early_trap_init(void);
+ extern void generic_apic_probe(char *);
+ extern int root_mountflags;
+
+@@ -1444,6 +1445,7 @@ void __init setup_arch(char **cmdline_p)
+ memcpy(&boot_cpu_data, &new_cpu_data, sizeof(new_cpu_data));
+ pre_setup_arch_hook();
+ early_cpu_init();
++ early_trap_init();
+
+ /*
+ * FIXME: This isn't an official loader_type right
+@@ -1500,6 +1502,7 @@ void __init setup_arch(char **cmdline_p)
+ data_resource.end = virt_to_phys(_edata)-1;
+
+ parse_cmdline_early(cmdline_p);
++ parse_early_param();
+
+ #ifdef CONFIG_EARLY_PRINTK
+ {
+diff -rupN -X ../client-cleanup/dontdiff linux-2.6.18/arch/i386/kernel/smpboot.c linux-2.6.18.kgdb/arch/i386/kernel/smpboot.c
+--- linux-2.6.18/arch/i386/kernel/smpboot.c 2006-09-20 07:42:06.000000000 +0400
++++ linux-2.6.18.kgdb/arch/i386/kernel/smpboot.c 2008-06-10 16:19:58.000000000 +0400
+@@ -592,6 +592,9 @@ void __devinit initialize_secondary(void
+
+ asm volatile(
+ "movl %0,%%esp\n\t"
++#ifdef CONFIG_KGDB
++ "pushl end_of_stack_stop_unwind_function\n\t"
++#endif
+ "jmp *%1"
+ :
+ :"r" (current->thread.esp),"r" (current->thread.eip));
+diff -rupN -X ../client-cleanup/dontdiff linux-2.6.18/arch/i386/kernel/traps.c linux-2.6.18.kgdb/arch/i386/kernel/traps.c
+--- linux-2.6.18/arch/i386/kernel/traps.c 2006-09-20 07:42:06.000000000 +0400
++++ linux-2.6.18.kgdb/arch/i386/kernel/traps.c 2008-06-10 16:19:17.000000000 +0400
+@@ -863,6 +863,7 @@ fastcall void __kprobes do_debug(struct
+ */
+ clear_dr7:
+ set_debugreg(0, 7);
++ notify_die(DIE_DEBUG, "debug2", regs, condition, error_code, SIGTRAP);
+ return;
+
+ debug_vm86:
+@@ -1167,6 +1168,12 @@ static void __init set_task_gate(unsigne
+ _set_gate(idt_table+n,5,0,0,(gdt_entry<<3));
+ }
+
++/* Some traps need to be set early. */
++void __init early_trap_init(void) {
++ set_intr_gate(1,&debug);
++ set_system_intr_gate(3, &int3); /* int3 can be called from all */
++ set_intr_gate(14,&page_fault);
++}
+
+ void __init trap_init(void)
+ {
+@@ -1183,10 +1190,8 @@ void __init trap_init(void)
+ #endif
+
+ set_trap_gate(0,÷_error);
+- set_intr_gate(1,&debug);
+ set_intr_gate(2,&nmi);
+- set_system_intr_gate(3, &int3); /* int3/4 can be called from all */
+- set_system_gate(4,&overflow);
++ set_system_gate(4,&overflow); /* int4/5 can be called from all */
+ set_trap_gate(5,&bounds);
+ set_trap_gate(6,&invalid_op);
+ set_trap_gate(7,&device_not_available);
+@@ -1196,7 +1201,6 @@ void __init trap_init(void)
+ set_trap_gate(11,&segment_not_present);
+ set_trap_gate(12,&stack_segment);
+ set_trap_gate(13,&general_protection);
+- set_intr_gate(14,&page_fault);
+ set_trap_gate(15,&spurious_interrupt_bug);
+ set_trap_gate(16,&coprocessor_error);
+ set_trap_gate(17,&alignment_check);
+diff -rupN -X ../client-cleanup/dontdiff linux-2.6.18/arch/i386/mm/fault.c linux-2.6.18.kgdb/arch/i386/mm/fault.c
+--- linux-2.6.18/arch/i386/mm/fault.c 2006-09-20 07:42:06.000000000 +0400
++++ linux-2.6.18.kgdb/arch/i386/mm/fault.c 2008-06-10 16:19:17.000000000 +0400
+@@ -539,6 +539,10 @@ no_context:
+ if (is_prefetch(regs, address, error_code))
+ return;
+
++ if (notify_die(DIE_PAGE_FAULT_NO_CONTEXT, "no context", regs,
++ error_code, 14, SIGSEGV) == NOTIFY_STOP)
++ return;
++
+ /*
+ * Oops. The kernel tried to access some bad page. We'll have to
+ * terminate things with extreme prejudice.
+diff -rupN -X ../client-cleanup/dontdiff linux-2.6.18/arch/ia64/kernel/Makefile linux-2.6.18.kgdb/arch/ia64/kernel/Makefile
+--- linux-2.6.18/arch/ia64/kernel/Makefile 2006-09-20 07:42:06.000000000 +0400
++++ linux-2.6.18.kgdb/arch/ia64/kernel/Makefile 2008-06-10 16:19:32.000000000 +0400
+@@ -31,6 +31,7 @@ obj-$(CONFIG_KPROBES) += kprobes.o jpro
+ obj-$(CONFIG_IA64_UNCACHED_ALLOCATOR) += uncached.o
+ obj-$(CONFIG_AUDIT) += audit.o
+ mca_recovery-y += mca_drv.o mca_drv_asm.o
++obj-$(CONFIG_KGDB) += kgdb.o kgdb-jmp.o
+
+ # The gate DSO image is built using a special linker script.
+ targets += gate.so gate-syms.o
+diff -rupN -X ../client-cleanup/dontdiff linux-2.6.18/arch/ia64/kernel/entry.S linux-2.6.18.kgdb/arch/ia64/kernel/entry.S
+--- linux-2.6.18/arch/ia64/kernel/entry.S 2006-09-20 07:42:06.000000000 +0400
++++ linux-2.6.18.kgdb/arch/ia64/kernel/entry.S 2008-06-10 16:20:23.000000000 +0400
+@@ -953,9 +953,9 @@ GLOBAL_ENTRY(ia64_leave_kernel)
+ shr.u r18=r19,16 // get byte size of existing "dirty" partition
+ ;;
+ mov r16=ar.bsp // get existing backing store pointer
+- addl r17=THIS_CPU(ia64_phys_stacked_size_p8),r0
++(pUStk) addl r17=THIS_CPU(ia64_phys_stacked_size_p8),r0
+ ;;
+- ld4 r17=[r17] // r17 = cpu_data->phys_stacked_size_p8
++(pUStk) ld4 r17=[r17] // r17 = cpu_data->phys_stacked_size_p8
+ (pKStk) br.cond.dpnt skip_rbs_switch
+
+ /*
+diff -rupN -X ../client-cleanup/dontdiff linux-2.6.18/arch/ia64/kernel/ivt.S linux-2.6.18.kgdb/arch/ia64/kernel/ivt.S
+--- linux-2.6.18/arch/ia64/kernel/ivt.S 2006-09-20 07:42:06.000000000 +0400
++++ linux-2.6.18.kgdb/arch/ia64/kernel/ivt.S 2008-06-10 16:20:23.000000000 +0400
+@@ -52,6 +52,14 @@
+ #include <asm/unistd.h>
+ #include <asm/errno.h>
+
++#ifdef CONFIG_KGDB
++#define KGDB_ENABLE_PSR_DB mov r31=psr;; movl r30=IA64_PSR_DB;; \
++ or r31=r31,r30;; \
++ mov psr.l=r31;; srlz.i;;
++#else
++#define KGDB_ENABLE_PSR_DB
++#endif
++
+ #if 1
+ # define PSR_DEFAULT_BITS psr.ac
+ #else
+@@ -519,6 +527,7 @@ ENTRY(page_fault)
+ movl r14=ia64_leave_kernel
+ ;;
+ SAVE_REST
++ KGDB_ENABLE_PSR_DB
+ mov rp=r14
+ ;;
+ adds out2=16,r12 // out2 = pointer to pt_regs
+@@ -863,6 +872,7 @@ ENTRY(interrupt)
+ srlz.i // ensure everybody knows psr.ic is back on
+ ;;
+ SAVE_REST
++ KGDB_ENABLE_PSR_DB
+ ;;
+ MCA_RECOVER_RANGE(interrupt)
+ alloc r14=ar.pfs,0,0,2,0 // must be first in an insn group
+@@ -1110,6 +1120,7 @@ ENTRY(non_syscall)
+ movl r15=ia64_leave_kernel
+ ;;
+ SAVE_REST
++ KGDB_ENABLE_PSR_DB
+ mov rp=r15
+ ;;
+ br.call.sptk.many b6=ia64_bad_break // avoid WAW on CFM and ignore return addr
+@@ -1143,6 +1154,7 @@ ENTRY(dispatch_unaligned_handler)
+ adds r3=8,r2 // set up second base pointer
+ ;;
+ SAVE_REST
++ KGDB_ENABLE_PSR_DB
+ movl r14=ia64_leave_kernel
+ ;;
+ mov rp=r14
+@@ -1185,6 +1197,10 @@ ENTRY(dispatch_to_fault_handler)
+ adds r3=8,r2 // set up second base pointer for SAVE_REST
+ ;;
+ SAVE_REST
++ cmp.eq p6,p0=29,out0
++(p6) br.cond.spnt 1f;; // debug_vector
++ KGDB_ENABLE_PSR_DB
++1:
+ movl r14=ia64_leave_kernel
+ ;;
+ mov rp=r14
+diff -rupN -X ../client-cleanup/dontdiff linux-2.6.18/arch/ia64/kernel/kgdb-jmp.S linux-2.6.18.kgdb/arch/ia64/kernel/kgdb-jmp.S
+--- linux-2.6.18/arch/ia64/kernel/kgdb-jmp.S 1970-01-01 03:00:00.000000000 +0300
++++ linux-2.6.18.kgdb/arch/ia64/kernel/kgdb-jmp.S 2008-06-10 16:19:32.000000000 +0400
+@@ -0,0 +1,238 @@
++/* setjmp() and longjmp() assembler support for kdb on ia64.
++
++ This code was copied from glibc CVS as of 2001-06-27 and modified where
++ necessary to fit the kernel.
++ Keith Owens <kaos@melbourne.sgi.com> 2001-06-27
++ */
++
++/* Copyright (C) 1999, 2000, 2001 Free Software Foundation, Inc.
++ Contributed by David Mosberger-Tang <davidm@hpl.hp.com>.
++
++ The GNU C Library is free software; you can redistribute it and/or
++ modify it under the terms of the GNU Library General Public License as
++ published by the Free Software Foundation; either version 2 of the
++ License, or (at your option) any later version.
++
++ The GNU C Library is distributed in the hope that it will be useful,
++ but WITHOUT ANY WARRANTY; without even the implied warranty of
++ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
++ Library General Public License for more details.
++
++ You should have received a copy of the GNU Library General Public
++ License along with the GNU C Library; see the file COPYING.LIB. If
++ not, write to the Free Software Foundation, Inc.,
++ 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
++*/
++
++#include <asm/asmmacro.h>
++GLOBAL_ENTRY(kgdb_fault_setjmp)
++ .prologue ASM_UNW_PRLG_RP|ASM_UNW_PRLG_PFS, ASM_UNW_PRLG_GRSAVE(2)
++ alloc loc1=ar.pfs,2,2,2,0
++ mov r16=ar.unat
++ ;;
++ mov r17=ar.fpsr
++ mov r2=in0
++ add r3=8,in0
++ ;;
++.mem.offset 0,0;
++ st8.spill.nta [r2]=sp,16 // r12 (sp)
++.mem.offset 8,0;
++ st8.spill.nta [r3]=gp,16 // r1 (gp)
++ ;;
++ st8.nta [r2]=r16,16 // save caller's unat
++ st8.nta [r3]=r17,16 // save fpsr
++ add r8=0xa0,in0
++ ;;
++.mem.offset 160,0;
++ st8.spill.nta [r2]=r4,16 // r4
++.mem.offset 168,0;
++ st8.spill.nta [r3]=r5,16 // r5
++ add r9=0xb0,in0
++ ;;
++ stf.spill.nta [r8]=f2,32
++ stf.spill.nta [r9]=f3,32
++ mov loc0=rp
++ .body
++ ;;
++ stf.spill.nta [r8]=f4,32
++ stf.spill.nta [r9]=f5,32
++ mov r17=b1
++ ;;
++ stf.spill.nta [r8]=f16,32
++ stf.spill.nta [r9]=f17,32
++ mov r18=b2
++ ;;
++ stf.spill.nta [r8]=f18,32
++ stf.spill.nta [r9]=f19,32
++ mov r19=b3
++ ;;
++ stf.spill.nta [r8]=f20,32
++ stf.spill.nta [r9]=f21,32
++ mov r20=b4
++ ;;
++ stf.spill.nta [r8]=f22,32
++ stf.spill.nta [r9]=f23,32
++ mov r21=b5
++ ;;
++ stf.spill.nta [r8]=f24,32
++ stf.spill.nta [r9]=f25,32
++ mov r22=ar.lc
++ ;;
++ stf.spill.nta [r8]=f26,32
++ stf.spill.nta [r9]=f27,32
++ mov r24=pr
++ ;;
++ stf.spill.nta [r8]=f28,32
++ stf.spill.nta [r9]=f29,32
++ ;;
++ stf.spill.nta [r8]=f30
++ stf.spill.nta [r9]=f31
++
++.mem.offset 0,0;
++ st8.spill.nta [r2]=r6,16 // r6
++.mem.offset 8,0;
++ st8.spill.nta [r3]=r7,16 // r7
++ ;;
++ mov r23=ar.bsp
++ mov r25=ar.unat
++ st8.nta [r2]=loc0,16 // b0
++ st8.nta [r3]=r17,16 // b1
++ ;;
++ st8.nta [r2]=r18,16 // b2
++ st8.nta [r3]=r19,16 // b3
++ ;;
++ st8.nta [r2]=r20,16 // b4
++ st8.nta [r3]=r21,16 // b5
++ ;;
++ st8.nta [r2]=loc1,16 // ar.pfs
++ st8.nta [r3]=r22,16 // ar.lc
++ ;;
++ st8.nta [r2]=r24,16 // pr
++ st8.nta [r3]=r23,16 // ar.bsp
++ ;;
++ st8.nta [r2]=r25 // ar.unat
++ st8.nta [r3]=in0 // &__jmp_buf
++ mov r8=0
++ mov rp=loc0
++ mov ar.pfs=loc1
++ br.ret.sptk.few rp
++END(kdba_setjmp)
++#define pPos p6 /* is rotate count positive? */
++#define pNeg p7 /* is rotate count negative? */
++GLOBAL_ENTRY(kgdb_fault_longjmp)
++ alloc r8=ar.pfs,2,1,0,0
++ mov r27=ar.rsc
++ add r2=0x98,in0 // r2 <- &jmpbuf.orig_jmp_buf_addr
++ ;;
++ ld8 r8=[r2],-16 // r8 <- orig_jmp_buf_addr
++ mov r10=ar.bsp
++ and r11=~0x3,r27 // clear ar.rsc.mode
++ ;;
++ flushrs // flush dirty regs to backing store (must be first in insn grp)
++ ld8 r23=[r2],8 // r23 <- jmpbuf.ar_bsp
++ sub r8=r8,in0 // r8 <- &orig_jmpbuf - &jmpbuf
++ ;;
++ ld8 r25=[r2] // r25 <- jmpbuf.ar_unat
++ extr.u r8=r8,3,6 // r8 <- (&orig_jmpbuf - &jmpbuf)/8 & 0x3f
++ ;;
++ cmp.lt pNeg,pPos=r8,r0
++ mov r2=in0
++ ;;
++(pPos) mov r16=r8
++(pNeg) add r16=64,r8
++(pPos) sub r17=64,r8
++(pNeg) sub r17=r0,r8
++ ;;
++ mov ar.rsc=r11 // put RSE in enforced lazy mode
++ shr.u r8=r25,r16
++ add r3=8,in0 // r3 <- &jmpbuf.r1
++ shl r9=r25,r17
++ ;;
++ or r25=r8,r9
++ ;;
++ mov r26=ar.rnat
++ mov ar.unat=r25 // setup ar.unat (NaT bits for r1, r4-r7, and r12)
++ ;;
++ ld8.fill.nta sp=[r2],16 // r12 (sp)
++ ld8.fill.nta gp=[r3],16 // r1 (gp)
++ dep r11=-1,r23,3,6 // r11 <- ia64_rse_rnat_addr(jmpbuf.ar_bsp)
++ ;;
++ ld8.nta r16=[r2],16 // caller's unat
++ ld8.nta r17=[r3],16 // fpsr
++ ;;
++ ld8.fill.nta r4=[r2],16 // r4
++ ld8.fill.nta r5=[r3],16 // r5 (gp)
++ cmp.geu p8,p0=r10,r11 // p8 <- (ar.bsp >= jmpbuf.ar_bsp)
++ ;;
++ ld8.fill.nta r6=[r2],16 // r6
++ ld8.fill.nta r7=[r3],16 // r7
++ ;;
++ mov ar.unat=r16 // restore caller's unat
++ mov ar.fpsr=r17 // restore fpsr
++ ;;
++ ld8.nta r16=[r2],16 // b0
++ ld8.nta r17=[r3],16 // b1
++ ;;
++(p8) ld8 r26=[r11] // r26 <- *ia64_rse_rnat_addr(jmpbuf.ar_bsp)
++ mov ar.bspstore=r23 // restore ar.bspstore
++ ;;
++ ld8.nta r18=[r2],16 // b2
++ ld8.nta r19=[r3],16 // b3
++ ;;
++ ld8.nta r20=[r2],16 // b4
++ ld8.nta r21=[r3],16 // b5
++ ;;
++ ld8.nta r11=[r2],16 // ar.pfs
++ ld8.nta r22=[r3],56 // ar.lc
++ ;;
++ ld8.nta r24=[r2],32 // pr
++ mov b0=r16
++ ;;
++ ldf.fill.nta f2=[r2],32
++ ldf.fill.nta f3=[r3],32
++ mov b1=r17
++ ;;
++ ldf.fill.nta f4=[r2],32
++ ldf.fill.nta f5=[r3],32
++ mov b2=r18
++ ;;
++ ldf.fill.nta f16=[r2],32
++ ldf.fill.nta f17=[r3],32
++ mov b3=r19
++ ;;
++ ldf.fill.nta f18=[r2],32
++ ldf.fill.nta f19=[r3],32
++ mov b4=r20
++ ;;
++ ldf.fill.nta f20=[r2],32
++ ldf.fill.nta f21=[r3],32
++ mov b5=r21
++ ;;
++ ldf.fill.nta f22=[r2],32
++ ldf.fill.nta f23=[r3],32
++ mov ar.lc=r22
++ ;;
++ ldf.fill.nta f24=[r2],32
++ ldf.fill.nta f25=[r3],32
++ cmp.eq p8,p9=0,in1
++ ;;
++ ldf.fill.nta f26=[r2],32
++ ldf.fill.nta f27=[r3],32
++ mov ar.pfs=r11
++ ;;
++ ldf.fill.nta f28=[r2],32
++ ldf.fill.nta f29=[r3],32
++ ;;
++ ldf.fill.nta f30=[r2]
++ ldf.fill.nta f31=[r3]
++(p8) mov r8=1
++
++ mov ar.rnat=r26 // restore ar.rnat
++ ;;
++ mov ar.rsc=r27 // restore ar.rsc
++(p9) mov r8=in1
++
++ invala // virt. -> phys. regnum mapping may change
++ mov pr=r24,-1
++ br.ret.sptk.few rp
++END(kgdb_fault_longjmp)
+diff -rupN -X ../client-cleanup/dontdiff linux-2.6.18/arch/ia64/kernel/kgdb.c linux-2.6.18.kgdb/arch/ia64/kernel/kgdb.c
+--- linux-2.6.18/arch/ia64/kernel/kgdb.c 1970-01-01 03:00:00.000000000 +0300
++++ linux-2.6.18.kgdb/arch/ia64/kernel/kgdb.c 2008-06-10 16:19:32.000000000 +0400
+@@ -0,0 +1,1131 @@
++/*
++ *
++ * 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, or (at your option) any
++ * later version.
++ *
++ * This program is distributed in the hope that it will be useful, but
++ * WITHOUT ANY WARRANTY; without even the implied warranty of
++ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
++ * General Public License for more details.
++ *
++ */
++
++/*
++ * Copyright (C) 2000-2001 VERITAS Software Corporation.
++ * (c) Copyright 2005 Hewlett-Packard Development Company, L.P.
++ * Bob Picco <bob.picco@hp.com>
++ */
++/*
++ * Contributor: Lake Stevens Instrument Division$
++ * Written by: Glenn Engel $
++ * Updated by: Amit Kale<akale@veritas.com>
++ * Modified for 386 by Jim Kingdon, Cygnus Support.
++ * Origianl kgdb, compatibility with 2.1.xx kernel by David Grothe <dave@gcom.com>
++ */
++
++#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 <asm/unwind.h>
++#include <asm/rse.h>
++#include <linux/kgdb.h>
++#include <linux/init.h>
++#include <asm/cacheflush.h>
++#include <asm/kdebug.h>
++
++#define NUM_REGS 590
++#define REGISTER_BYTES (NUM_REGS*8+128*8)
++#define REGISTER_BYTE(N) (((N) * 8) \
++ + ((N) <= IA64_FR0_REGNUM ? \
++ 0 : 8 * (((N) > IA64_FR127_REGNUM) ? 128 : (N) - IA64_FR0_REGNUM)))
++#define REGISTER_SIZE(N) \
++ (((N) >= IA64_FR0_REGNUM && (N) <= IA64_FR127_REGNUM) ? 16 : 8)
++#define IA64_GR0_REGNUM 0
++#define IA64_FR0_REGNUM 128
++#define IA64_FR127_REGNUM (IA64_FR0_REGNUM+127)
++#define IA64_PR0_REGNUM 256
++#define IA64_BR0_REGNUM 320
++#define IA64_VFP_REGNUM 328
++#define IA64_PR_REGNUM 330
++#define IA64_IP_REGNUM 331
++#define IA64_PSR_REGNUM 332
++#define IA64_CFM_REGNUM 333
++#define IA64_AR0_REGNUM 334
++#define IA64_NAT0_REGNUM 462
++#define IA64_NAT31_REGNUM (IA64_NAT0_REGNUM+31)
++#define IA64_NAT32_REGNUM (IA64_NAT0_REGNUM+32)
++#define IA64_RSC_REGNUM (IA64_AR0_REGNUM+16)
++#define IA64_BSP_REGNUM (IA64_AR0_REGNUM+17)
++#define IA64_BSPSTORE_REGNUM (IA64_AR0_REGNUM+18)
++#define IA64_RNAT_REGNUM (IA64_AR0_REGNUM+19)
++#define IA64_FCR_REGNUM (IA64_AR0_REGNUM+21)
++#define IA64_EFLAG_REGNUM (IA64_AR0_REGNUM+24)
++#define IA64_CSD_REGNUM (IA64_AR0_REGNUM+25)
++#define IA64_SSD_REGNUM (IA64_AR0_REGNUM+26)
++#define IA64_CFLG_REGNUM (IA64_AR0_REGNUM+27)
++#define IA64_FSR_REGNUM (IA64_AR0_REGNUM+28)
++#define IA64_FIR_REGNUM (IA64_AR0_REGNUM+29)
++#define IA64_FDR_REGNUM (IA64_AR0_REGNUM+30)
++#define IA64_CCV_REGNUM (IA64_AR0_REGNUM+32)
++#define IA64_UNAT_REGNUM (IA64_AR0_REGNUM+36)
++#define IA64_FPSR_REGNUM (IA64_AR0_REGNUM+40)
++#define IA64_ITC_REGNUM (IA64_AR0_REGNUM+44)
++#define IA64_PFS_REGNUM (IA64_AR0_REGNUM+64)
++#define IA64_LC_REGNUM (IA64_AR0_REGNUM+65)
++#define IA64_EC_REGNUM (IA64_AR0_REGNUM+66)
++
++#define REGISTER_INDEX(N) (REGISTER_BYTE(N) / sizeof (unsigned long))
++#define BREAK_INSTR_ALIGN (~0xfULL)
++
++#define ptoff(V) ((unsigned int) &((struct pt_regs *)0x0)->V)
++struct reg_to_ptreg_index {
++ unsigned int reg;
++ unsigned int ptregoff;
++};
++
++static struct reg_to_ptreg_index gr_reg_to_ptreg_index[] = {
++ {IA64_GR0_REGNUM + 1, ptoff(r1)},
++ {IA64_GR0_REGNUM + 2, ptoff(r2)},
++ {IA64_GR0_REGNUM + 3, ptoff(r3)},
++ {IA64_GR0_REGNUM + 8, ptoff(r8)},
++ {IA64_GR0_REGNUM + 9, ptoff(r9)},
++ {IA64_GR0_REGNUM + 10, ptoff(r10)},
++ {IA64_GR0_REGNUM + 11, ptoff(r11)},
++ {IA64_GR0_REGNUM + 12, ptoff(r12)},
++ {IA64_GR0_REGNUM + 13, ptoff(r13)},
++ {IA64_GR0_REGNUM + 14, ptoff(r14)},
++ {IA64_GR0_REGNUM + 15, ptoff(r15)},
++ {IA64_GR0_REGNUM + 16, ptoff(r16)},
++ {IA64_GR0_REGNUM + 17, ptoff(r17)},
++ {IA64_GR0_REGNUM + 18, ptoff(r18)},
++ {IA64_GR0_REGNUM + 19, ptoff(r19)},
++ {IA64_GR0_REGNUM + 20, ptoff(r20)},
++ {IA64_GR0_REGNUM + 21, ptoff(r21)},
++ {IA64_GR0_REGNUM + 22, ptoff(r22)},
++ {IA64_GR0_REGNUM + 23, ptoff(r23)},
++ {IA64_GR0_REGNUM + 24, ptoff(r24)},
++ {IA64_GR0_REGNUM + 25, ptoff(r25)},
++ {IA64_GR0_REGNUM + 26, ptoff(r26)},
++ {IA64_GR0_REGNUM + 27, ptoff(r27)},
++ {IA64_GR0_REGNUM + 28, ptoff(r28)},
++ {IA64_GR0_REGNUM + 29, ptoff(r29)},
++ {IA64_GR0_REGNUM + 30, ptoff(r30)},
++ {IA64_GR0_REGNUM + 31, ptoff(r31)},
++};
++
++static struct reg_to_ptreg_index br_reg_to_ptreg_index[] = {
++ {IA64_BR0_REGNUM, ptoff(b0)},
++ {IA64_BR0_REGNUM + 6, ptoff(b6)},
++ {IA64_BR0_REGNUM + 7, ptoff(b7)},
++};
++
++static struct reg_to_ptreg_index ar_reg_to_ptreg_index[] = {
++ {IA64_PFS_REGNUM, ptoff(ar_pfs)},
++ {IA64_UNAT_REGNUM, ptoff(ar_unat)},
++ {IA64_RNAT_REGNUM, ptoff(ar_rnat)},
++ {IA64_BSPSTORE_REGNUM, ptoff(ar_bspstore)},
++ {IA64_RSC_REGNUM, ptoff(ar_rsc)},
++ {IA64_CSD_REGNUM, ptoff(ar_csd)},
++ {IA64_SSD_REGNUM, ptoff(ar_ssd)},
++ {IA64_FPSR_REGNUM, ptoff(ar_fpsr)},
++ {IA64_CCV_REGNUM, ptoff(ar_ccv)},
++};
++
++extern atomic_t cpu_doing_single_step;
++
++static int kgdb_gr_reg(int regnum, struct unw_frame_info *info,
++ unsigned long *reg, int rw)
++{
++ char nat;
++
++ if ((regnum >= IA64_GR0_REGNUM && regnum <= (IA64_GR0_REGNUM + 1)) ||
++ (regnum >= (IA64_GR0_REGNUM + 4) &&
++ regnum <= (IA64_GR0_REGNUM + 7)))
++ return !unw_access_gr(info, regnum - IA64_GR0_REGNUM,
++ reg, &nat, rw);
++ else
++ return 0;
++}
++static int kgdb_gr_ptreg(int regnum, struct pt_regs * ptregs,
++ struct unw_frame_info *info, unsigned long *reg, int rw)
++{
++ int i, result = 1;
++ char nat;
++
++ if (!((regnum >= (IA64_GR0_REGNUM + 2) &&
++ regnum <= (IA64_GR0_REGNUM + 3)) ||
++ (regnum >= (IA64_GR0_REGNUM + 8) &&
++ regnum <= (IA64_GR0_REGNUM + 15)) ||
++ (regnum >= (IA64_GR0_REGNUM + 16) &&
++ regnum <= (IA64_GR0_REGNUM + 31))))
++ return 0;
++ else if (rw && ptregs) {
++ for (i = 0; i < ARRAY_SIZE(gr_reg_to_ptreg_index); i++)
++ if (gr_reg_to_ptreg_index[i].reg == regnum) {
++ *((unsigned long *)(((void *)ptregs) +
++ gr_reg_to_ptreg_index[i].ptregoff)) = *reg;
++ break;
++ }
++ } else if (!rw && ptregs) {
++ for (i = 0; i < ARRAY_SIZE(gr_reg_to_ptreg_index); i++)
++ if (gr_reg_to_ptreg_index[i].reg == regnum) {
++ *reg = *((unsigned long *)
++ (((void *)ptregs) +
++ gr_reg_to_ptreg_index[i].ptregoff));
++ break;
++ }
++ } else
++ result = !unw_access_gr(info, regnum - IA64_GR0_REGNUM,
++ reg, &nat, rw);
++ return result;
++}
++
++static int kgdb_br_reg(int regnum, struct pt_regs * ptregs,
++ struct unw_frame_info *info, unsigned long *reg, int rw)
++{
++ int i, result = 1;
++
++ if (!(regnum >= IA64_BR0_REGNUM && regnum <= (IA64_BR0_REGNUM + 7)))
++ return 0;
++
++ switch (regnum) {
++ case IA64_BR0_REGNUM:
++ case IA64_BR0_REGNUM + 6:
++ case IA64_BR0_REGNUM + 7:
++ if (rw) {
++ for (i = 0; i < ARRAY_SIZE(br_reg_to_ptreg_index); i++)
++ if (br_reg_to_ptreg_index[i].reg == regnum) {
++ *((unsigned long *)
++ (((void *)ptregs) +
++ br_reg_to_ptreg_index[i].ptregoff)) =
++ *reg;
++ break;
++ }
++ } else
++ for (i = 0; i < ARRAY_SIZE(br_reg_to_ptreg_index); i++)
++ if (br_reg_to_ptreg_index[i].reg == regnum) {
++ *reg = *((unsigned long *)
++ (((void *)ptregs) +
++ br_reg_to_ptreg_index[i].
++ ptregoff));
++ break;
++ }
++ break;
++ case IA64_BR0_REGNUM + 1:
++ case IA64_BR0_REGNUM + 2:
++ case IA64_BR0_REGNUM + 3:
++ case IA64_BR0_REGNUM + 4:
++ case IA64_BR0_REGNUM + 5:
++ result = !unw_access_br(info, regnum - IA64_BR0_REGNUM,
++ reg, rw);
++ break;
++ }
++
++ return result;
++}
++
++static int kgdb_fr_reg(int regnum, char *inbuffer, struct pt_regs * ptregs,
++ struct unw_frame_info *info, unsigned long *reg,
++ struct ia64_fpreg *freg, int rw)
++{
++ int result = 1;
++
++ if (!(regnum >= IA64_FR0_REGNUM && regnum <= (IA64_FR0_REGNUM + 127)))
++ return 0;
++
++ switch (regnum) {
++ case IA64_FR0_REGNUM + 6:
++ case IA64_FR0_REGNUM + 7:
++ case IA64_FR0_REGNUM + 8:
++ case IA64_FR0_REGNUM + 9:
++ case IA64_FR0_REGNUM + 10:
++ case IA64_FR0_REGNUM + 11:
++ case IA64_FR0_REGNUM + 12:
++ if (rw) {
++ char *ptr = inbuffer;
++
++ freg->u.bits[0] = *reg;
++ kgdb_hex2long(&ptr, &freg->u.bits[1]);
++ *(&ptregs->f6 + (regnum - (IA64_FR0_REGNUM + 6))) =
++ *freg;
++ break;
++ } else if (!ptregs)
++ result = !unw_access_fr(info, regnum - IA64_FR0_REGNUM,
++ freg, rw);
++ else
++ *freg =
++ *(&ptregs->f6 + (regnum - (IA64_FR0_REGNUM + 6)));
++ break;
++ default:
++ if (!rw)
++ result = !unw_access_fr(info, regnum - IA64_FR0_REGNUM,
++ freg, rw);
++ else
++ result = 0;
++ break;
++ }
++
++ return result;
++}
++
++static int kgdb_ar_reg(int regnum, struct pt_regs * ptregs,
++ struct unw_frame_info *info, unsigned long *reg, int rw)
++{
++ int result = 0, i;
++
++ if (!(regnum >= IA64_AR0_REGNUM && regnum <= IA64_EC_REGNUM))
++ return 0;
++
++ if (rw && ptregs) {
++ for (i = 0; i < ARRAY_SIZE(ar_reg_to_ptreg_index); i++)
++ if (ar_reg_to_ptreg_index[i].reg == regnum) {
++ *((unsigned long *) (((void *)ptregs) +
++ ar_reg_to_ptreg_index[i].ptregoff)) =
++ *reg;
++ result = 1;
++ break;
++ }
++ } else if (ptregs) {
++ for (i = 0; i < ARRAY_SIZE(ar_reg_to_ptreg_index); i++)
++ if (ar_reg_to_ptreg_index[i].reg == regnum) {
++ *reg = *((unsigned long *) (((void *)ptregs) +
++ ar_reg_to_ptreg_index[i].ptregoff));
++ result = 1;
++ break;
++ }
++ }
++
++ if (result)
++ return result;
++
++ result = 1;
++
++ switch (regnum) {
++ case IA64_CSD_REGNUM:
++ result = !unw_access_ar(info, UNW_AR_CSD, reg, rw);
++ break;
++ case IA64_SSD_REGNUM:
++ result = !unw_access_ar(info, UNW_AR_SSD, reg, rw);
++ break;
++ case IA64_UNAT_REGNUM:
++ result = !unw_access_ar(info, UNW_AR_RNAT, reg, rw);
++ break;
++ case IA64_RNAT_REGNUM:
++ result = !unw_access_ar(info, UNW_AR_RNAT, reg, rw);
++ break;
++ case IA64_BSPSTORE_REGNUM:
++ result = !unw_access_ar(info, UNW_AR_RNAT, reg, rw);
++ break;
++ case IA64_PFS_REGNUM:
++ result = !unw_access_ar(info, UNW_AR_RNAT, reg, rw);
++ break;
++ case IA64_LC_REGNUM:
++ result = !unw_access_ar(info, UNW_AR_LC, reg, rw);
++ break;
++ case IA64_EC_REGNUM:
++ result = !unw_access_ar(info, UNW_AR_EC, reg, rw);
++ break;
++ case IA64_FPSR_REGNUM:
++ result = !unw_access_ar(info, UNW_AR_FPSR, reg, rw);
++ break;
++ case IA64_RSC_REGNUM:
++ result = !unw_access_ar(info, UNW_AR_RSC, reg, rw);
++ break;
++ case IA64_CCV_REGNUM:
++ result = !unw_access_ar(info, UNW_AR_CCV, reg, rw);
++ break;
++ default:
++ result = 0;
++ }
++
++ return result;
++}
++
++void kgdb_get_reg(char *outbuffer, int regnum, struct unw_frame_info *info,
++ struct pt_regs *ptregs)
++{
++ unsigned long reg, size = 0, *mem = ®
++ struct ia64_fpreg freg;
++
++ if (kgdb_gr_reg(regnum, info, ®, 0) ||
++ kgdb_gr_ptreg(regnum, ptregs, info, ®, 0) ||
++ kgdb_br_reg(regnum, ptregs, info, ®, 0) ||
++ kgdb_ar_reg(regnum, ptregs, info, ®, 0))
++ size = sizeof(reg);
++ else if (kgdb_fr_reg(regnum, NULL, ptregs, info, ®, &freg, 0)) {
++ size = sizeof(freg);
++ mem = (unsigned long *)&freg;
++ } else if (regnum == IA64_IP_REGNUM) {
++ if (!ptregs) {
++ unw_get_ip(info, ®);
++ size = sizeof(reg);
++ } else {
++ reg = ptregs->cr_iip;
++ size = sizeof(reg);
++ }
++ } else if (regnum == IA64_CFM_REGNUM) {
++ if (!ptregs)
++ unw_get_cfm(info, ®);
++ else
++ reg = ptregs->cr_ifs;
++ size = sizeof(reg);
++ } else if (regnum == IA64_PSR_REGNUM) {
++ if (!ptregs && kgdb_usethread)
++ ptregs = (struct pt_regs *)
++ ((unsigned long)kgdb_usethread +
++ IA64_STK_OFFSET) - 1;
++ if (ptregs)
++ reg = ptregs->cr_ipsr;
++ size = sizeof(reg);
++ } else if (regnum == IA64_PR_REGNUM) {
++ if (ptregs)
++ reg = ptregs->pr;
++ else
++ unw_access_pr(info, ®, 0);
++ size = sizeof(reg);
++ } else if (regnum == IA64_BSP_REGNUM) {
++ unw_get_bsp(info, ®);
++ size = sizeof(reg);
++ }
++
++ if (size) {
++ kgdb_mem2hex((char *) mem, outbuffer, size);
++ outbuffer[size*2] = 0;
++ }
++ else
++ strcpy(outbuffer, "E0");
++
++ return;
++}
++
++void kgdb_put_reg(char *inbuffer, char *outbuffer, int regnum,
++ struct unw_frame_info *info, struct pt_regs *ptregs)
++{
++ unsigned long reg;
++ struct ia64_fpreg freg;
++ char *ptr = inbuffer;
++
++ kgdb_hex2long(&ptr, ®);
++ strcpy(outbuffer, "OK");
++
++ if (kgdb_gr_reg(regnum, info, ®, 1) ||
++ kgdb_gr_ptreg(regnum, ptregs, info, ®, 1) ||
++ kgdb_br_reg(regnum, ptregs, info, ®, 1) ||
++ kgdb_fr_reg(regnum, inbuffer, ptregs, info, ®, &freg, 1) ||
++ kgdb_ar_reg(regnum, ptregs, info, ®, 1)) ;
++ else if (regnum == IA64_IP_REGNUM)
++ ptregs->cr_iip = reg;
++ else if (regnum == IA64_CFM_REGNUM)
++ ptregs->cr_ifs = reg;
++ else if (regnum == IA64_PSR_REGNUM)
++ ptregs->cr_ipsr = reg;
++ else if (regnum == IA64_PR_REGNUM)
++ ptregs->pr = reg;
++ else
++ strcpy(outbuffer, "E01");
++ return;
++}
++
++void regs_to_gdb_regs(unsigned long *gdb_regs, struct pt_regs *regs)
++{
++}
++
++void sleeping_thread_to_gdb_regs(unsigned long *gdb_regs, struct task_struct *p)
++{
++}
++
++void gdb_regs_to_regs(unsigned long *gdb_regs, struct pt_regs *regs)
++{
++
++}
++
++#define MAX_HW_BREAKPOINT (20)
++long hw_break_total_dbr, hw_break_total_ibr;
++#define HW_BREAKPOINT (hw_break_total_dbr + hw_break_total_ibr)
++#define WATCH_INSTRUCTION 0x0
++#define WATCH_WRITE 0x1
++#define WATCH_READ 0x2
++#define WATCH_ACCESS 0x3
++
++#define HWCAP_DBR ((1 << WATCH_WRITE) | (1 << WATCH_READ))
++#define HWCAP_IBR (1 << WATCH_INSTRUCTION)
++struct hw_breakpoint {
++ unsigned enabled;
++ unsigned long capable;
++ unsigned long type;
++ unsigned long mask;
++ unsigned long addr;
++} *breakinfo;
++
++static struct hw_breakpoint hwbreaks[MAX_HW_BREAKPOINT];
++
++enum instruction_type { A, I, M, F, B, L, X, u };
++
++static enum instruction_type bundle_encoding[32][3] = {
++ {M, I, I}, /* 00 */
++ {M, I, I}, /* 01 */
++ {M, I, I}, /* 02 */
++ {M, I, I}, /* 03 */
++ {M, L, X}, /* 04 */
++ {M, L, X}, /* 05 */
++ {u, u, u}, /* 06 */
++ {u, u, u}, /* 07 */
++ {M, M, I}, /* 08 */
++ {M, M, I}, /* 09 */
++ {M, M, I}, /* 0A */
++ {M, M, I}, /* 0B */
++ {M, F, I}, /* 0C */
++ {M, F, I}, /* 0D */
++ {M, M, F}, /* 0E */
++ {M, M, F}, /* 0F */
++ {M, I, B}, /* 10 */
++ {M, I, B}, /* 11 */
++ {M, B, B}, /* 12 */
++ {M, B, B}, /* 13 */
++ {u, u, u}, /* 14 */
++ {u, u, u}, /* 15 */
++ {B, B, B}, /* 16 */
++ {B, B, B}, /* 17 */
++ {M, M, B}, /* 18 */
++ {M, M, B}, /* 19 */
++ {u, u, u}, /* 1A */
++ {u, u, u}, /* 1B */
++ {M, F, B}, /* 1C */
++ {M, F, B}, /* 1D */
++ {u, u, u}, /* 1E */
++ {u, u, u}, /* 1F */
++};
++
++int kgdb_validate_break_address(unsigned long addr)
++{
++ int error;
++ char tmp_variable[BREAK_INSTR_SIZE];
++ error = kgdb_get_mem((char *)(addr & BREAK_INSTR_ALIGN), tmp_variable,
++ BREAK_INSTR_SIZE);
++ return error;
++}
++
++int kgdb_arch_set_breakpoint(unsigned long addr, char *saved_instr)
++{
++ extern unsigned long _start[];
++ unsigned long slot = addr & BREAK_INSTR_ALIGN, bundle_addr;
++ unsigned long template;
++ struct bundle {
++ struct {
++ unsigned long long template:5;
++ unsigned long long slot0:41;
++ unsigned long long slot1_p0:64 - 46;
++ } quad0;
++ struct {
++ unsigned long long slot1_p1:41 - (64 - 46);
++ unsigned long long slot2:41;
++ } quad1;
++ } bundle;
++ int ret;
++
++ bundle_addr = addr & ~0xFULL;
++
++ if (bundle_addr == (unsigned long)_start)
++ return 0;
++
++ ret = kgdb_get_mem((char *)bundle_addr, (char *)&bundle,
++ BREAK_INSTR_SIZE);
++ if (ret < 0)
++ return ret;
++
++ if (slot > 2)
++ slot = 0;
++
++ memcpy(saved_instr, &bundle, BREAK_INSTR_SIZE);
++ template = bundle.quad0.template;
++
++ if (slot == 1 && bundle_encoding[template][1] == L)
++ slot = 2;
++
++ switch (slot) {
++ case 0:
++ bundle.quad0.slot0 = BREAKNUM;
++ break;
++ case 1:
++ bundle.quad0.slot1_p0 = BREAKNUM;
++ bundle.quad1.slot1_p1 = (BREAKNUM >> (64 - 46));
++ break;
++ case 2:
++ bundle.quad1.slot2 = BREAKNUM;
++ break;
++ }
++
++ return kgdb_set_mem((char *)bundle_addr, (char *)&bundle,
++ BREAK_INSTR_SIZE);
++}
++
++int kgdb_arch_remove_breakpoint(unsigned long addr, char *bundle)
++{
++ extern unsigned long _start[];
++
++ addr = addr & BREAK_INSTR_ALIGN;
++ if (addr == (unsigned long)_start)
++ return 0;
++ return kgdb_set_mem((char *)addr, (char *)bundle, BREAK_INSTR_SIZE);
++}
++
++static int hw_breakpoint_init;
++
++void do_init_hw_break(void)
++{
++ s64 status;
++ int i;
++
++ hw_breakpoint_init = 1;
++
++#ifdef CONFIG_IA64_HP_SIM
++ hw_break_total_ibr = 8;
++ hw_break_total_dbr = 8;
++ status = 0;
++#else
++ status = ia64_pal_debug_info(&hw_break_total_ibr, &hw_break_total_dbr);
++#endif
++
++ if (status) {
++ printk(KERN_INFO "do_init_hw_break: pal call failed %d\n",
++ (int)status);
++ return;
++ }
++
++ if (HW_BREAKPOINT > MAX_HW_BREAKPOINT) {
++ printk(KERN_INFO "do_init_hw_break: %d exceeds max %d\n",
++ (int)HW_BREAKPOINT, (int)MAX_HW_BREAKPOINT);
++
++ while ((HW_BREAKPOINT > MAX_HW_BREAKPOINT)
++ && hw_break_total_ibr != 1)
++ hw_break_total_ibr--;
++ while (HW_BREAKPOINT > MAX_HW_BREAKPOINT)
++ hw_break_total_dbr--;
++ }
++
++ breakinfo = hwbreaks;
++
++ memset(breakinfo, 0, HW_BREAKPOINT * sizeof(struct hw_breakpoint));
++
++ for (i = 0; i < hw_break_total_dbr; i++)
++ breakinfo[i].capable = HWCAP_DBR;
++
++ for (; i < HW_BREAKPOINT; i++)
++ breakinfo[i].capable = HWCAP_IBR;
++
++ return;
++}
++
++void kgdb_correct_hw_break(void)
++{
++ int breakno;
++
++ if (!breakinfo)
++ return;
++
++ for (breakno = 0; breakno < HW_BREAKPOINT; breakno++) {
++ if (breakinfo[breakno].enabled) {
++ if (breakinfo[breakno].capable & HWCAP_IBR) {
++ int ibreakno = breakno - hw_break_total_dbr;
++ ia64_set_ibr(ibreakno << 1,
++ breakinfo[breakno].addr);
++ ia64_set_ibr((ibreakno << 1) + 1,
++ (~breakinfo[breakno].mask &
++ ((1UL << 56UL) - 1)) |
++ (1UL << 56UL) | (1UL << 63UL));
++ } else {
++ ia64_set_dbr(breakno << 1,
++ breakinfo[breakno].addr);
++ ia64_set_dbr((breakno << 1) + 1,
++ (~breakinfo[breakno].
++ mask & ((1UL << 56UL) - 1)) |
++ (1UL << 56UL) |
++ (breakinfo[breakno].type << 62UL));
++ }
++ } else {
++ if (breakinfo[breakno].capable & HWCAP_IBR)
++ ia64_set_ibr(((breakno -
++ hw_break_total_dbr) << 1) + 1,
++ 0);
++ else
++ ia64_set_dbr((breakno << 1) + 1, 0);
++ }
++ }
++
++ return;
++}
++
++int hardware_breakpoint(unsigned long addr, int length, int type, int action)
++{
++ int breakno, found, watch;
++ unsigned long mask;
++ extern unsigned long _start[];
++
++ if (!hw_breakpoint_init)
++ do_init_hw_break();
++
++ if (!breakinfo)
++ return 0;
++ else if (addr == (unsigned long)_start)
++ return 1;
++
++ if (type == WATCH_ACCESS)
++ mask = HWCAP_DBR;
++ else
++ mask = 1UL << type;
++
++ for (watch = 0, found = 0, breakno = 0; breakno < HW_BREAKPOINT;
++ breakno++) {
++ if (action) {
++ if (breakinfo[breakno].enabled
++ || !(breakinfo[breakno].capable & mask))
++ continue;
++ breakinfo[breakno].enabled = 1;
++ breakinfo[breakno].type = type;
++ breakinfo[breakno].mask = length - 1;
++ breakinfo[breakno].addr = addr;
++ watch = breakno;
++ } else if (breakinfo[breakno].enabled &&
++ ((length < 0 && breakinfo[breakno].addr == addr) ||
++ ((breakinfo[breakno].capable & mask) &&
++ (breakinfo[breakno].mask == (length - 1)) &&
++ (breakinfo[breakno].addr == addr)))) {
++ breakinfo[breakno].enabled = 0;
++ breakinfo[breakno].type = 0UL;
++ } else
++ continue;
++ found++;
++ if (type != WATCH_ACCESS)
++ break;
++ else if (found == 2)
++ break;
++ else
++ mask = HWCAP_IBR;
++ }
++
++ if (type == WATCH_ACCESS && found == 1) {
++ breakinfo[watch].enabled = 0;
++ found = 0;
++ }
++
++ mb();
++ return found;
++}
++
++int kgdb_arch_set_hw_breakpoint(unsigned long addr, int len,
++ enum kgdb_bptype type)
++{
++ return hardware_breakpoint(addr, len, type - '1', 1);
++}
++
++int kgdb_arch_remove_hw_breakpoint(unsigned long addr, int len,
++ enum kgdb_bptype type)
++{
++ return hardware_breakpoint(addr, len, type - '1', 0);
++}
++
++int kgdb_remove_hw_break(unsigned long addr)
++{
++ return hardware_breakpoint(addr, 8, WATCH_INSTRUCTION, 0);
++
++}
++
++void kgdb_remove_all_hw_break(void)
++{
++ int i;
++
++ for (i = 0; i < HW_BREAKPOINT; i++)
++ memset(&breakinfo[i], 0, sizeof(struct hw_breakpoint));
++}
++
++int kgdb_set_hw_break(unsigned long addr)
++{
++ return hardware_breakpoint(addr, 8, WATCH_INSTRUCTION, 1);
++}
++
++void kgdb_disable_hw_debug(struct pt_regs *regs)
++{
++ unsigned long hw_breakpoint_status;
++
++ hw_breakpoint_status = ia64_getreg(_IA64_REG_PSR);
++ if (hw_breakpoint_status & IA64_PSR_DB)
++ ia64_setreg(_IA64_REG_PSR_L,
++ hw_breakpoint_status ^ IA64_PSR_DB);
++}
++
++volatile static struct smp_unw {
++ struct unw_frame_info *unw;
++ struct task_struct *task;
++} smp_unw[NR_CPUS];
++
++static int inline kgdb_get_blocked_state(struct task_struct *p,
++ struct unw_frame_info *unw)
++{
++ unsigned long ip;
++ int count = 0;
++
++ unw_init_from_blocked_task(unw, p);
++ ip = 0UL;
++ do {
++ if (unw_unwind(unw) < 0)
++ return -1;
++ unw_get_ip(unw, &ip);
++ if (!in_sched_functions(ip))
++ break;
++ } while (count++ < 16);
++
++ if (!ip)
++ return -1;
++ else
++ return 0;
++}
++
++static void inline kgdb_wait(struct pt_regs *regs)
++{
++ unsigned long hw_breakpoint_status = ia64_getreg(_IA64_REG_PSR);
++ if (hw_breakpoint_status & IA64_PSR_DB)
++ ia64_setreg(_IA64_REG_PSR_L,
++ hw_breakpoint_status ^ IA64_PSR_DB);
++ kgdb_nmihook(smp_processor_id(), regs);
++ if (hw_breakpoint_status & IA64_PSR_DB)
++ ia64_setreg(_IA64_REG_PSR_L, hw_breakpoint_status);
++
++ return;
++}
++
++static void inline normalize(struct unw_frame_info *running,
++ struct pt_regs *regs)
++{
++ unsigned long sp;
++
++ do {
++ unw_get_sp(running, &sp);
++ if ((sp + 0x10) >= (unsigned long)regs)
++ break;
++ } while (unw_unwind(running) >= 0);
++
++ return;
++}
++
++static void kgdb_init_running(struct unw_frame_info *unw, void *data)
++{
++ struct pt_regs *regs;
++
++ regs = data;
++ normalize(unw, regs);
++ smp_unw[smp_processor_id()].unw = unw;
++ kgdb_wait(regs);
++}
++
++void kgdb_wait_ipi(struct pt_regs *regs)
++{
++ struct unw_frame_info unw;
++
++ smp_unw[smp_processor_id()].task = current;
++
++ if (user_mode(regs)) {
++ smp_unw[smp_processor_id()].unw = (struct unw_frame_info *)1;
++ kgdb_wait(regs);
++ } else {
++ if (current->state == TASK_RUNNING)
++ unw_init_running(kgdb_init_running, regs);
++ else {
++ if (kgdb_get_blocked_state(current, &unw))
++ smp_unw[smp_processor_id()].unw =
++ (struct unw_frame_info *)1;
++ else
++ smp_unw[smp_processor_id()].unw = &unw;
++ kgdb_wait(regs);
++ }
++ }
++
++ smp_unw[smp_processor_id()].unw = NULL;
++ return;
++}
++
++void kgdb_roundup_cpus(unsigned long flags)
++{
++ if (num_online_cpus() > 1)
++ smp_send_nmi_allbutself();
++}
++
++static volatile int kgdb_hwbreak_sstep[NR_CPUS];
++
++static int kgdb_notify(struct notifier_block *self, unsigned long cmd,
++ void *ptr)
++{
++ struct die_args *args = ptr;
++ struct pt_regs *regs = args->regs;
++ unsigned long err = args->err;
++
++ switch (cmd) {
++ default:
++ return NOTIFY_DONE;
++ case DIE_PAGE_FAULT_NO_CONTEXT:
++ if (atomic_read(&debugger_active) && kgdb_may_fault) {
++ kgdb_fault_longjmp(kgdb_fault_jmp_regs);
++ return NOTIFY_STOP;
++ }
++ break;
++ case DIE_BREAK:
++ if (user_mode(regs) || err == 0x80001)
++ return NOTIFY_DONE;
++ break;
++ case DIE_FAULT:
++ if (user_mode(regs))
++ return NOTIFY_DONE;
++ else if (err == 36 && kgdb_hwbreak_sstep[smp_processor_id()]) {
++ kgdb_hwbreak_sstep[smp_processor_id()] = 0;
++ regs->cr_ipsr &= ~IA64_PSR_SS;
++ return NOTIFY_STOP;
++ }
++ case DIE_MCA_MONARCH_PROCESS:
++ case DIE_INIT_MONARCH_PROCESS:
++ break;
++ }
++
++ kgdb_handle_exception(args->trapnr, args->signr, args->err, regs);
++ return NOTIFY_STOP;
++}
++
++static struct notifier_block kgdb_notifier = {
++ .notifier_call = kgdb_notify,
++};
++
++int kgdb_arch_init(void)
++{
++ atomic_notifier_chain_register(&ia64die_chain, &kgdb_notifier);
++ return 0;
++}
++
++static void do_kgdb_handle_exception(struct unw_frame_info *, void *data);
++
++struct kgdb_state {
++ int e_vector;
++ int signo;
++ unsigned long err_code;
++ struct pt_regs *regs;
++ struct unw_frame_info *unw;
++ char *inbuf;
++ char *outbuf;
++ int unwind;
++ int ret;
++};
++
++static void inline kgdb_pc(struct pt_regs *regs, unsigned long pc)
++{
++ regs->cr_iip = pc & ~0xf;
++ ia64_psr(regs)->ri = pc & 0x3;
++ return;
++}
++
++int kgdb_arch_handle_exception(int e_vector, int signo,
++ int err_code, char *remcom_in_buffer,
++ char *remcom_out_buffer,
++ struct pt_regs *linux_regs)
++{
++ struct kgdb_state info;
++
++ info.e_vector = e_vector;
++ info.signo = signo;
++ info.err_code = err_code;
++ info.unw = (void *)0;
++ info.inbuf = remcom_in_buffer;
++ info.outbuf = remcom_out_buffer;
++ info.unwind = 0;
++ info.ret = -1;
++
++ if (remcom_in_buffer[0] == 'c' || remcom_in_buffer[0] == 's') {
++ info.regs = linux_regs;
++ do_kgdb_handle_exception(NULL, &info);
++ } else if (kgdb_usethread == current) {
++ info.regs = linux_regs;
++ info.unwind = 1;
++ unw_init_running(do_kgdb_handle_exception, &info);
++ } else if (kgdb_usethread->state != TASK_RUNNING) {
++ struct unw_frame_info unw_info;
++
++ if (kgdb_get_blocked_state(kgdb_usethread, &unw_info)) {
++ info.ret = 1;
++ goto bad;
++ }
++ info.regs = NULL;
++ do_kgdb_handle_exception(&unw_info, &info);
++ } else {
++ int i;
++
++ for (i = 0; i < NR_CPUS; i++)
++ if (smp_unw[i].task == kgdb_usethread && smp_unw[i].unw
++ && smp_unw[i].unw != (struct unw_frame_info *)1) {
++ info.regs = NULL;
++ do_kgdb_handle_exception(smp_unw[i].unw, &info);
++ break;
++ } else {
++ info.ret = 1;
++ goto bad;
++ }
++ }
++
++ bad:
++ if (info.ret != -1 && remcom_in_buffer[0] == 'p') {
++ unsigned long bad = 0xbad4badbadbadbadUL;
++
++ printk("kgdb_arch_handle_exception: p packet bad (%s)\n",
++ remcom_in_buffer);
++ kgdb_mem2hex((char *)&bad, remcom_out_buffer, sizeof(bad));
++ remcom_out_buffer[sizeof(bad) * 2] = 0;
++ info.ret = -1;
++ }
++ return info.ret;
++}
++
++/*
++ * This is done because I evidently made an incorrect 'p' encoding
++ * when my patch for gdb was committed. It was later corrected. This
++ * check supports both my wrong encoding of the register number and
++ * the correct encoding. Eventually this should be eliminated and
++ * kgdb_hex2long should be demarshalling the regnum.
++ */
++static inline int check_packet(unsigned int regnum, char *packet)
++{
++ static int check_done, swap;
++ unsigned long reglong;
++
++ if (likely(check_done)) {
++ if (swap) {
++ kgdb_hex2long(&packet, ®long);
++ regnum = (int) reglong;
++ }
++
++ } else {
++ if (regnum > NUM_REGS) {
++ kgdb_hex2long(&packet, ®long);
++ regnum = (int) reglong;
++ swap = 1;
++ }
++ check_done = 1;
++ }
++ return regnum;
++}
++
++static void do_kgdb_handle_exception(struct unw_frame_info *unw_info,
++ void *data)
++{
++ long addr;
++ char *ptr;
++ unsigned long newPC;
++ int e_vector, signo;
++ unsigned long err_code;
++ struct pt_regs *linux_regs;
++ struct kgdb_state *info;
++ char *remcom_in_buffer, *remcom_out_buffer;
++
++ info = data;
++ info->unw = unw_info;
++ e_vector = info->e_vector;
++ signo = info->signo;
++ err_code = info->err_code;
++ remcom_in_buffer = info->inbuf;
++ remcom_out_buffer = info->outbuf;
++ linux_regs = info->regs;
++
++ if (info->unwind)
++ normalize(unw_info, linux_regs);
++
++ switch (remcom_in_buffer[0]) {
++ case 'p':
++ {
++ unsigned int regnum;
++
++ kgdb_hex2mem(&remcom_in_buffer[1], (char *)®num,
++ sizeof(regnum));
++ regnum = check_packet(regnum, &remcom_in_buffer[1]);
++ if (regnum >= NUM_REGS) {
++ remcom_out_buffer[0] = 'E';
++ remcom_out_buffer[1] = 0;
++ } else
++ kgdb_get_reg(remcom_out_buffer, regnum,
++ unw_info, linux_regs);
++ break;
++ }
++ case 'P':
++ {
++ unsigned int regno;
++ long v;
++ char *ptr;
++
++ ptr = &remcom_in_buffer[1];
++ if ((!kgdb_usethread || kgdb_usethread == current) &&
++ kgdb_hex2long(&ptr, &v) &&
++ *ptr++ == '=' && (v >= 0)) {
++ regno = (unsigned int)v;
++ regno = (regno >= NUM_REGS ? 0 : regno);
++ kgdb_put_reg(ptr, remcom_out_buffer, regno,
++ unw_info, linux_regs);
++ } else
++ strcpy(remcom_out_buffer, "E01");
++ break;
++ }
++ case 'c':
++ case 's':
++ if (e_vector == TRAP_BRKPT && err_code == KGDBBREAKNUM) {
++ if (ia64_psr(linux_regs)->ri < 2)
++ kgdb_pc(linux_regs, linux_regs->cr_iip +
++ ia64_psr(linux_regs)->ri + 1);
++ else
++ kgdb_pc(linux_regs, linux_regs->cr_iip + 16);
++ }
++
++ /* try to read optional parameter, pc unchanged if no parm */
++ ptr = &remcom_in_buffer[1];
++ if (kgdb_hex2long(&ptr, &addr)) {
++ linux_regs->cr_iip = addr;
++ }
++ newPC = linux_regs->cr_iip;
++
++ /* clear the trace bit */
++ linux_regs->cr_ipsr &= ~IA64_PSR_SS;
++
++ atomic_set(&cpu_doing_single_step, -1);
++
++ /* set the trace bit if we're stepping or took a hardware break */
++ if (remcom_in_buffer[0] == 's' || e_vector == TRAP_HWBKPT) {
++ linux_regs->cr_ipsr |= IA64_PSR_SS;
++ debugger_step = 1;
++ if (kgdb_contthread)
++ atomic_set(&cpu_doing_single_step,
++ smp_processor_id());
++ }
++
++ kgdb_correct_hw_break();
++
++ /* if not hardware breakpoint, then reenable them */
++ if (e_vector != TRAP_HWBKPT)
++ linux_regs->cr_ipsr |= IA64_PSR_DB;
++ else {
++ kgdb_hwbreak_sstep[smp_processor_id()] = 1;
++ linux_regs->cr_ipsr &= ~IA64_PSR_DB;
++ }
++
++ info->ret = 0;
++ break;
++ default:
++ break;
++ }
++
++ return;
++}
++
++struct kgdb_arch arch_kgdb_ops = {
++ .set_hw_breakpoint = kgdb_arch_set_hw_breakpoint,
++ .remove_hw_breakpoint = kgdb_arch_remove_hw_breakpoint,
++ .gdb_bpt_instr = {0xcc},
++ .flags = KGDB_HW_BREAKPOINT,
++};
+diff -rupN -X ../client-cleanup/dontdiff linux-2.6.18/arch/ia64/kernel/process.c linux-2.6.18.kgdb/arch/ia64/kernel/process.c
+--- linux-2.6.18/arch/ia64/kernel/process.c 2006-09-20 07:42:06.000000000 +0400
++++ linux-2.6.18.kgdb/arch/ia64/kernel/process.c 2008-06-10 16:20:23.000000000 +0400
+@@ -458,6 +458,9 @@ copy_thread (int nr, unsigned long clone
+ */
+ child_ptregs->cr_ipsr = ((child_ptregs->cr_ipsr | IA64_PSR_BITS_TO_SET)
+ & ~(IA64_PSR_BITS_TO_CLEAR | IA64_PSR_PP | IA64_PSR_UP));
++#ifdef CONFIG_KGDB
++ child_ptregs->cr_ipsr |= IA64_PSR_DB;
++#endif
+
+ /*
+ * NOTE: The calling convention considers all floating point
+@@ -686,6 +689,9 @@ kernel_thread (int (*fn)(void *), void *
+ regs.pt.r11 = (unsigned long) arg; /* 2nd argument */
+ /* Preserve PSR bits, except for bits 32-34 and 37-45, which we can't read. */
+ regs.pt.cr_ipsr = ia64_getreg(_IA64_REG_PSR) | IA64_PSR_BN;
++#ifdef CONFIG_KGDB
++ regs.pt.cr_ipsr |= IA64_PSR_DB;
++#endif
+ regs.pt.cr_ifs = 1UL << 63; /* mark as valid, empty frame */
+ regs.sw.ar_fpsr = regs.pt.ar_fpsr = ia64_getreg(_IA64_REG_AR_FPSR);
+ regs.sw.ar_bspstore = (unsigned long) current + IA64_RBS_OFFSET;
+diff -rupN -X ../client-cleanup/dontdiff linux-2.6.18/arch/ia64/kernel/smp.c linux-2.6.18.kgdb/arch/ia64/kernel/smp.c
+--- linux-2.6.18/arch/ia64/kernel/smp.c 2006-09-20 07:42:06.000000000 +0400
++++ linux-2.6.18.kgdb/arch/ia64/kernel/smp.c 2008-06-10 16:19:32.000000000 +0400
+@@ -47,6 +47,7 @@
+ #include <asm/tlbflush.h>
+ #include <asm/unistd.h>
+ #include <asm/mca.h>
++#include <linux/kgdb.h>
+
+ /*
+ * Structure and data for smp_call_function(). This is designed to minimise static memory
+@@ -66,6 +67,9 @@ static volatile struct call_data_struct
+
+ #define IPI_CALL_FUNC 0
+ #define IPI_CPU_STOP 1
++#ifdef CONFIG_KGDB
++#define IPI_KGDB_INTERRUPT 2
++#endif
+
+ /* This needs to be cacheline aligned because it is written to by *other* CPUs. */
+ static DEFINE_PER_CPU(u64, ipi_operation) ____cacheline_aligned;
+@@ -155,6 +159,11 @@ handle_IPI (int irq, void *dev_id, struc
+ case IPI_CPU_STOP:
+ stop_this_cpu();
+ break;
++#ifdef CONFIG_KGDB
++ case IPI_KGDB_INTERRUPT:
++ kgdb_wait_ipi(regs);
++ break;
++#endif
+
+ default:
+ printk(KERN_CRIT "Unknown IPI on CPU %d: %lu\n", this_cpu, which);
+@@ -305,6 +314,14 @@ smp_call_function_single (int cpuid, voi
+ }
+ EXPORT_SYMBOL(smp_call_function_single);
+
++#ifdef CONFIG_KGDB
++void
++smp_send_nmi_allbutself(void)
++{
++ send_IPI_allbutself(IPI_KGDB_INTERRUPT);
++}
++#endif
++
+ /*
+ * this function sends a 'generic call function' IPI to all other CPUs
+ * in the system.
+diff -rupN -X ../client-cleanup/dontdiff linux-2.6.18/arch/ia64/kernel/traps.c linux-2.6.18.kgdb/arch/ia64/kernel/traps.c
+--- linux-2.6.18/arch/ia64/kernel/traps.c 2006-09-20 07:42:06.000000000 +0400
++++ linux-2.6.18.kgdb/arch/ia64/kernel/traps.c 2008-06-10 16:19:32.000000000 +0400
+@@ -200,8 +200,12 @@ __kprobes ia64_bad_break (unsigned long
+ break;
+
+ default:
+- if (break_num < 0x40000 || break_num > 0x100000)
++ if (break_num < 0x40000 || break_num > 0x100000) {
++ if (notify_die(DIE_BREAK, "bad break", regs,
++ break_num, TRAP_BRKPT, SIGTRAP) == NOTIFY_STOP)
++ return;
+ die_if_kernel("Bad break", regs, break_num);
++ }
+
+ if (break_num < 0x80000) {
+ sig = SIGILL; code = __ILL_BREAK;
+diff -rupN -X ../client-cleanup/dontdiff linux-2.6.18/arch/ia64/kernel/unwind.c linux-2.6.18.kgdb/arch/ia64/kernel/unwind.c
+--- linux-2.6.18/arch/ia64/kernel/unwind.c 2006-09-20 07:42:06.000000000 +0400
++++ linux-2.6.18.kgdb/arch/ia64/kernel/unwind.c 2008-06-10 16:20:23.000000000 +0400
+@@ -72,10 +72,68 @@
+ # define STAT(x...)
+ #endif
+
++#ifdef CONFIG_KGDB
++#define KGDB_EARLY_SIZE 100
++static struct unw_reg_state __initdata kgdb_reg_state[KGDB_EARLY_SIZE];
++static struct unw_labeled_state __initdata kgdb_labeled_state[KGDB_EARLY_SIZE];
++void __initdata *kgdb_reg_state_free, __initdata *kgdb_labeled_state_free;
++
++static void __init
++kgdb_malloc_init(void)
++{
++ int i;
++
++ kgdb_reg_state_free = kgdb_reg_state;
++ for (i = 1; i < KGDB_EARLY_SIZE; i++) {
++ *((unsigned long *) &kgdb_reg_state[i]) = (unsigned long) kgdb_reg_state_free;
++ kgdb_reg_state_free = &kgdb_reg_state[i];
++ }
++
++ kgdb_labeled_state_free = kgdb_labeled_state;
++ for (i = 1; i < KGDB_EARLY_SIZE; i++) {
++ *((unsigned long *) &kgdb_labeled_state[i]) =
++ (unsigned long) kgdb_labeled_state_free;
++ kgdb_labeled_state_free = &kgdb_labeled_state[i];
++ }
++
++}
++
++static void * __init
++kgdb_malloc(void **mem)
++{
++ void *p;
++
++ p = *mem;
++ *mem = *((void **) p);
++ return p;
++}
++
++static void __init
++kgdb_free(void **mem, void *p)
++{
++ *((void **)p) = *mem;
++ *mem = p;
++}
++
++#define alloc_reg_state() (!malloc_sizes[0].cs_cachep ? \
++ kgdb_malloc(&kgdb_reg_state_free) : \
++ kmalloc(sizeof(struct unw_reg_state), GFP_ATOMIC))
++#define free_reg_state(usr) (!malloc_sizes[0].cs_cachep ? \
++ kgdb_free(&kgdb_reg_state_free, usr) : \
++ kfree(usr))
++#define alloc_labeled_state() (!malloc_sizes[0].cs_cachep ? \
++ kgdb_malloc(&kgdb_labeled_state_free) : \
++ kmalloc(sizeof(struct unw_labeled_state), GFP_ATOMIC))
++#define free_labeled_state(usr) (!malloc_sizes[0].cs_cachep ? \
++ kgdb_free(&kgdb_labeled_state_free, usr) : \
++ kfree(usr))
++
++#else
+ #define alloc_reg_state() kmalloc(sizeof(struct unw_reg_state), GFP_ATOMIC)
+ #define free_reg_state(usr) kfree(usr)
+ #define alloc_labeled_state() kmalloc(sizeof(struct unw_labeled_state), GFP_ATOMIC)
+ #define free_labeled_state(usr) kfree(usr)
++#endif
+
+ typedef unsigned long unw_word;
+ typedef unsigned char unw_hash_index_t;
+@@ -238,6 +296,24 @@ static struct {
+ #endif
+ };
+
++#ifdef CONFIG_KGDB
++/*
++ * This makes it safe to call breakpoint() very early
++ * in setup_arch providing:
++ * 1) breakpoint isn't called between lines in cpu_init
++ * where init_mm.mm_count is incremented and ia64_mmu_init
++ * is called. Otherwise the test below is invalid.
++ * 2) the memory examined doesn't result in tlbmiss.
++ */
++static unsigned long inline kgdb_unimpl_va_mask(void)
++{
++ if (atomic_read(&init_mm.mm_count) > 1)
++ return local_cpu_data->unimpl_va_mask;
++ else
++ return 0UL;
++}
++#endif
++
+ static inline int
+ read_only (void *addr)
+ {
+@@ -1786,7 +1862,11 @@ run_script (struct unw_script *script, s
+
+ case UNW_INSN_LOAD:
+ #ifdef UNW_DEBUG
++#ifdef CONFIG_KGDB
++ if ((s[val] & (kgdb_unimpl_va_mask() | 0x7)) != 0
++#else
+ if ((s[val] & (local_cpu_data->unimpl_va_mask | 0x7)) != 0
++#endif
+ || s[val] < TASK_SIZE)
+ {
+ UNW_DPRINT(0, "unwind.%s: rejecting bad psp=0x%lx\n",
+@@ -1821,7 +1901,11 @@ find_save_locs (struct unw_frame_info *i
+ struct unw_script *scr;
+ unsigned long flags = 0;
+
++#ifdef CONFIG_KGDB
++ if ((info->ip & (kgdb_unimpl_va_mask() | 0xf)) || info->ip < TASK_SIZE) {
++#else
+ if ((info->ip & (local_cpu_data->unimpl_va_mask | 0xf)) || info->ip < TASK_SIZE) {
++#endif
+ /* don't let obviously bad addresses pollute the cache */
+ /* FIXME: should really be level 0 but it occurs too often. KAO */
+ UNW_DPRINT(1, "unwind.%s: rejecting bad ip=0x%lx\n", __FUNCTION__, info->ip);
+@@ -2249,6 +2333,9 @@ unw_init (void)
+
+ init_unwind_table(&unw.kernel_table, "kernel", KERNEL_START, (unsigned long) __gp,
+ __start_unwind, __end_unwind);
++#ifdef CONFIG_KGDB
++ kgdb_malloc_init();
++#endif
+ }
+
+ /*
+diff -rupN -X ../client-cleanup/dontdiff linux-2.6.18/arch/ia64/mm/extable.c linux-2.6.18.kgdb/arch/ia64/mm/extable.c
+--- linux-2.6.18/arch/ia64/mm/extable.c 2006-09-20 07:42:06.000000000 +0400
++++ linux-2.6.18.kgdb/arch/ia64/mm/extable.c 2008-06-10 16:19:32.000000000 +0400
+@@ -6,6 +6,7 @@
+ */
+
+ #include <linux/sort.h>
++#include <linux/kgdb.h>
+
+ #include <asm/uaccess.h>
+ #include <asm/module.h>
+@@ -73,6 +74,11 @@ search_extable (const struct exception_t
+ else
+ last = mid - 1;
+ }
++#ifdef CONFIG_KGDB
++ if (atomic_read(&debugger_active) && kgdb_may_fault)
++ kgdb_fault_longjmp(kgdb_fault_jmp_regs);
++ /* Not reached. */
++#endif
+ return NULL;
+ }
+
+diff -rupN -X ../client-cleanup/dontdiff linux-2.6.18/arch/ia64/mm/fault.c linux-2.6.18.kgdb/arch/ia64/mm/fault.c
+--- linux-2.6.18/arch/ia64/mm/fault.c 2006-09-20 07:42:06.000000000 +0400
++++ linux-2.6.18.kgdb/arch/ia64/mm/fault.c 2008-06-10 16:19:32.000000000 +0400
+@@ -266,6 +266,10 @@ ia64_do_page_fault (unsigned long addres
+ */
+ bust_spinlocks(1);
+
++ if (notify_die(DIE_PAGE_FAULT_NO_CONTEXT, "no context", regs,
++ isr, 14, SIGSEGV) == NOTIFY_STOP)
++ return;
++
+ if (address < PAGE_SIZE)
+ printk(KERN_ALERT "Unable to handle kernel NULL pointer dereference (address %016lx)\n", address);
+ else
+diff -rupN -X ../client-cleanup/dontdiff linux-2.6.18/arch/mips/Kconfig.debug linux-2.6.18.kgdb/arch/mips/Kconfig.debug
+--- linux-2.6.18/arch/mips/Kconfig.debug 2006-09-20 07:42:06.000000000 +0400
++++ linux-2.6.18.kgdb/arch/mips/Kconfig.debug 2008-06-10 16:19:28.000000000 +0400
+@@ -37,25 +37,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 -rupN -X ../client-cleanup/dontdiff linux-2.6.18/arch/mips/kernel/Makefile linux-2.6.18.kgdb/arch/mips/kernel/Makefile
+--- linux-2.6.18/arch/mips/kernel/Makefile 2006-09-20 07:42:06.000000000 +0400
++++ linux-2.6.18.kgdb/arch/mips/kernel/Makefile 2008-06-10 16:19:28.000000000 +0400
+@@ -59,7 +59,8 @@ obj-$(CONFIG_MIPS32_COMPAT) += linux32.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_64BIT) += cpu-bugs64.o
+diff -rupN -X ../client-cleanup/dontdiff linux-2.6.18/arch/mips/kernel/gdb-low.S linux-2.6.18.kgdb/arch/mips/kernel/gdb-low.S
+--- linux-2.6.18/arch/mips/kernel/gdb-low.S 2006-09-20 07:42:06.000000000 +0400
++++ linux-2.6.18.kgdb/arch/mips/kernel/gdb-low.S 1970-01-01 03:00:00.000000000 +0300
+@@ -1,394 +0,0 @@
+-/*
+- * gdb-low.S contains the low-level trap handler for the GDB stub.
+- *
+- * Copyright (C) 1995 Andreas Busse
+- */
+-#include <linux/sys.h>
+-
+-#include <asm/asm.h>
+-#include <asm/errno.h>
+-#include <asm/irqflags.h>
+-#include <asm/mipsregs.h>
+-#include <asm/regdef.h>
+-#include <asm/stackframe.h>
+-#include <asm/gdb-stub.h>
+-
+-#ifdef CONFIG_32BIT
+-#define DMFC0 mfc0
+-#define DMTC0 mtc0
+-#define LDC1 lwc1
+-#define SDC1 lwc1
+-#endif
+-#ifdef CONFIG_64BIT
+-#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.
+- */
+- mfc0 k0, CP0_CAUSE
+- andi k0, k0, 0x7c
+-#ifdef CONFIG_64BIT
+- dsll k0, k0, 1
+-#endif
+- PTR_L k1, saved_vectors(k0)
+- jr k1
+- nop
+-1:
+- move k0, sp
+- PTR_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 */
+- TRACE_IRQS_OFF
+-
+-/*
+- * 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:
+-#ifdef CONFIG_MIPS_MT_SMTC
+- /* Read-modify write of Status must be atomic */
+- mfc0 t2, CP0_TCSTATUS
+- ori t1, t2, TCSTATUS_IXMT
+- mtc0 t1, CP0_TCSTATUS
+- andi t2, t2, TCSTATUS_IXMT
+- _ehb
+- DMT 9 # dmt t1
+- jal mips_ihb
+- nop
+-#endif /* CONFIG_MIPS_MT_SMTC */
+- mfc0 t0, CP0_STATUS
+- ori t0, 0x1f
+- xori t0, 0x1f
+- mtc0 t0, CP0_STATUS
+-#ifdef CONFIG_MIPS_MT_SMTC
+- andi t1, t1, VPECONTROL_TE
+- beqz t1, 9f
+- nop
+- EMT # emt
+-9:
+- mfc0 t1, CP0_TCSTATUS
+- xori t1, t1, TCSTATUS_IXMT
+- or t1, t1, t2
+- mtc0 t1, CP0_TCSTATUS
+- _ehb
+-#endif /* CONFIG_MIPS_MT_SMTC */
+- 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 -rupN -X ../client-cleanup/dontdiff linux-2.6.18/arch/mips/kernel/gdb-stub.c linux-2.6.18.kgdb/arch/mips/kernel/gdb-stub.c
+--- linux-2.6.18/arch/mips/kernel/gdb-stub.c 2006-09-20 07:42:06.000000000 +0400
++++ linux-2.6.18.kgdb/arch/mips/kernel/gdb-stub.c 1970-01-01 03:00:00.000000000 +0300
+@@ -1,1154 +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/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>
+-#include <asm/smp.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 DEFINE_SPINLOCK(kgdb_lock);
+-static raw_spinlock_t kgdb_cpulock[NR_CPUS] = {
+- [0 ... NR_CPUS-1] = __RAW_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 = *(®s->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;
+-
+-#ifdef CONFIG_SMP
+- /* avoid deadlock if someone is make IPC */
+- if (spin_is_locked(&smp_call_lock))
+- return;
+-#endif
+-
+- async_bp.addr = *epc;
+- *epc = (unsigned long)async_breakpoint;
+-}
+-
+-static void kgdb_wait(void *arg)
+-{
+- unsigned flags;
+- int cpu = smp_processor_id();
+-
+- local_irq_save(flags);
+-
+- __raw_spin_lock(&kgdb_cpulock[cpu]);
+- __raw_spin_unlock(&kgdb_cpulock[cpu]);
+-
+- local_irq_restore(flags);
+-}
+-
+-/*
+- * GDB stub needs to call kgdb_wait on all processor with interrupts
+- * disabled, so it uses it's own special variant.
+- */
+-static int kgdb_smp_call_kgdb_wait(void)
+-{
+-#ifdef CONFIG_SMP
+- struct call_data_struct data;
+- int i, cpus = num_online_cpus() - 1;
+- int cpu = smp_processor_id();
+-
+- /*
+- * Can die spectacularly if this CPU isn't yet marked online
+- */
+- BUG_ON(!cpu_online(cpu));
+-
+- if (!cpus)
+- return 0;
+-
+- if (spin_is_locked(&smp_call_lock)) {
+- /*
+- * Some other processor is trying to make us do something
+- * but we're not going to respond... give up
+- */
+- return -1;
+- }
+-
+- /*
+- * We will continue here, accepting the fact that
+- * the kernel may deadlock if another CPU attempts
+- * to call smp_call_function now...
+- */
+-
+- data.func = kgdb_wait;
+- data.info = NULL;
+- atomic_set(&data.started, 0);
+- data.wait = 0;
+-
+- spin_lock(&smp_call_lock);
+- call_data = &data;
+- mb();
+-
+- /* Send a message to all other CPUs and wait for them to respond */
+- for (i = 0; i < NR_CPUS; i++)
+- if (cpu_online(i) && i != cpu)
+- core_send_ipi(i, SMP_CALL_FUNCTION);
+-
+- /* Wait for response */
+- /* FIXME: lock-up detection, backtrace on lock-up */
+- while (atomic_read(&data.started) != cpus)
+- barrier();
+-
+- call_data = NULL;
+- spin_unlock(&smp_call_lock);
+-#endif
+-
+- return 0;
+-}
+-
+-/*
+- * 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 (__raw_spin_trylock(&kgdb_cpulock[i]) == 0)
+- panic("kgdb: couldn't get cpulock %d\n", i);
+-
+- /*
+- * force other cpus to enter kgdb
+- */
+- kgdb_smp_call_kgdb_wait();
+-
+- /*
+- * 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 *)®s->cp0_epc, ptr, sizeof(long), 0);
+- *ptr++ = ';';
+-
+- /*
+- * Send frame pointer
+- */
+- *ptr++ = hexchars[REG_FP >> 4];
+- *ptr++ = hexchars[REG_FP & 0xf];
+- *ptr++ = ':';
+- ptr = mem2hex((char *)®s->reg30, ptr, sizeof(long), 0);
+- *ptr++ = ';';
+-
+- /*
+- * Send stack pointer
+- */
+- *ptr++ = hexchars[REG_SP >> 4];
+- *ptr++ = hexchars[REG_SP & 0xf];
+- *ptr++ = ':';
+- ptr = mem2hex((char *)®s->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 *)®s->reg0, ptr, 32*sizeof(long), 0); /* r0...r31 */
+- ptr = mem2hex((char *)®s->cp0_status, ptr, 6*sizeof(long), 0); /* cp0 */
+- ptr = mem2hex((char *)®s->fpr0, ptr, 32*sizeof(long), 0); /* f0...31 */
+- ptr = mem2hex((char *)®s->cp1_fsr, ptr, 2*sizeof(long), 0); /* cp1 */
+- ptr = mem2hex((char *)®s->frame_ptr, ptr, 2*sizeof(long), 0); /* frp */
+- ptr = mem2hex((char *)®s->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 *)®s->reg0, 32*sizeof(long), 0, 0);
+- ptr += 32*(2*sizeof(long));
+- hex2mem(ptr, (char *)®s->cp0_status, 6*sizeof(long), 0, 0);
+- ptr += 6*(2*sizeof(long));
+- hex2mem(ptr, (char *)®s->fpr0, 32*sizeof(long), 0, 0);
+- ptr += 32*(2*sizeof(long));
+- hex2mem(ptr, (char *)®s->cp1_fsr, 2*sizeof(long), 0, 0);
+- ptr += 2*(2*sizeof(long));
+- hex2mem(ptr, (char *)®s->frame_ptr, 2*sizeof(long), 0, 0);
+- ptr += 2*(2*sizeof(long));
+- hex2mem(ptr, (char *)®s->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--)
+- __raw_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 * __attribute_used__ malloc(size_t size)
+-{
+- return kmalloc(size, GFP_ATOMIC);
+-}
+-
+-static void __attribute_used__ 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 -rupN -X ../client-cleanup/dontdiff linux-2.6.18/arch/mips/kernel/irq.c linux-2.6.18.kgdb/arch/mips/kernel/irq.c
+--- linux-2.6.18/arch/mips/kernel/irq.c 2006-09-20 07:42:06.000000000 +0400
++++ linux-2.6.18.kgdb/arch/mips/kernel/irq.c 2008-06-10 16:19:28.000000000 +0400
+@@ -25,6 +25,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'.
+@@ -115,23 +119,13 @@ asmlinkage void spurious_interrupt(struc
+ atomic_inc(&irq_err_count);
+ }
+
+-#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;
+@@ -144,12 +138,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 -rupN -X ../client-cleanup/dontdiff linux-2.6.18/arch/mips/kernel/kgdb-jmp.c linux-2.6.18.kgdb/arch/mips/kernel/kgdb-jmp.c
+--- linux-2.6.18/arch/mips/kernel/kgdb-jmp.c 1970-01-01 03:00:00.000000000 +0300
++++ linux-2.6.18.kgdb/arch/mips/kernel/kgdb-jmp.c 2008-06-10 16:19:28.000000000 +0400
+@@ -0,0 +1,116 @@
++/*
++ * 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>
++ * Author: Manish Lachwani <mlachwani@mvista.com>
++ *
++ * 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>
++
++#ifdef CONFIG_MIPS64
++/*
++ * MIPS 64-bit
++ */
++
++int kgdb_fault_setjmp_aux(unsigned long *curr_context, int sp, int fp)
++{
++ __asm__ __volatile__ ("sd $gp, %0" : : "m" (curr_context[0]));
++ __asm__ __volatile__ ("sd $16, %0" : : "m" (curr_context[1]));
++ __asm__ __volatile__ ("sd $17, %0" : : "m" (curr_context[2]));
++ __asm__ __volatile__ ("sd $18, %0" : : "m" (curr_context[3]));
++ __asm__ __volatile__ ("sd $19, %0" : : "m" (curr_context[4]));
++ __asm__ __volatile__ ("sd $20, %0" : : "m" (curr_context[5]));
++ __asm__ __volatile__ ("sd $21, %0" : : "m" (curr_context[6]));
++ __asm__ __volatile__ ("sd $22, %0" : : "m" (curr_context[7]));
++ __asm__ __volatile__ ("sd $23, %0" : : "m" (curr_context[8]));
++ __asm__ __volatile__ ("sd $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__ ("ld $gp, %0" : : "m" (curr_context[0]));
++ __asm__ __volatile__ ("ld $16, %0" : : "m" (curr_context[1]));
++ __asm__ __volatile__ ("ld $17, %0" : : "m" (curr_context[2]));
++ __asm__ __volatile__ ("ld $18, %0" : : "m" (curr_context[3]));
++ __asm__ __volatile__ ("ld $19, %0" : : "m" (curr_context[4]));
++ __asm__ __volatile__ ("ld $20, %0" : : "m" (curr_context[5]));
++ __asm__ __volatile__ ("ld $21, %0" : : "m" (curr_context[6]));
++ __asm__ __volatile__ ("ld $22, %0" : : "m" (curr_context[7]));
++ __asm__ __volatile__ ("ld $23, %0" : : "m" (curr_context[8]));
++ __asm__ __volatile__ ("ld $25, %0" : : "m" (curr_context[9]));
++ sp_val = curr_context[10];
++ fp_val = curr_context[11];
++ __asm__ __volatile__ ("ld $29, %0\n\t"
++ "ld $30, %1\n\t" : : "m" (sp_val), "m" (fp_val));
++
++ __asm__ __volatile__ ("dli $2, 1");
++ __asm__ __volatile__ ("j $25");
++
++ for (;;);
++}
++#else
++/*
++ * MIPS 32-bit
++ */
++
++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 (;;);
++}
++#endif
+diff -rupN -X ../client-cleanup/dontdiff linux-2.6.18/arch/mips/kernel/kgdb-setjmp.S linux-2.6.18.kgdb/arch/mips/kernel/kgdb-setjmp.S
+--- linux-2.6.18/arch/mips/kernel/kgdb-setjmp.S 1970-01-01 03:00:00.000000000 +0300
++++ linux-2.6.18.kgdb/arch/mips/kernel/kgdb-setjmp.S 2008-06-10 16:19:28.000000000 +0400
+@@ -0,0 +1,28 @@
++/*
++ * 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.
++ * Author: Manish Lachwani (mlachwani@mvista.com)
++ *
++ * 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>
++
++ .ent kgdb_fault_setjmp,0
++ENTRY (kgdb_fault_setjmp)
++ move a1, sp
++ move a2, fp
++#ifdef CONFIG_MIPS64
++ nop
++#endif
++ j kgdb_fault_setjmp_aux
++ .end kgdb_fault_setjmp
+diff -rupN -X ../client-cleanup/dontdiff linux-2.6.18/arch/mips/kernel/kgdb.c linux-2.6.18.kgdb/arch/mips/kernel/kgdb.c
+--- linux-2.6.18/arch/mips/kernel/kgdb.c 1970-01-01 03:00:00.000000000 +0300
++++ linux-2.6.18.kgdb/arch/mips/kernel/kgdb.c 2008-06-10 16:19:28.000000000 +0400
+@@ -0,0 +1,297 @@
++/*
++ * 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 (fixup_exception(regs)) {
++ return;
++ }
++
++ 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;
++ gdb_reg_t *ptr = (gdb_reg_t*)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;
++ const gdb_reg_t *ptr = (gdb_reg_t*)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;
++ 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;
++ gdb_reg_t *ptr = (gdb_reg_t*)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 -rupN -X ../client-cleanup/dontdiff linux-2.6.18/arch/mips/kernel/kgdb_handler.S linux-2.6.18.kgdb/arch/mips/kernel/kgdb_handler.S
+--- linux-2.6.18/arch/mips/kernel/kgdb_handler.S 1970-01-01 03:00:00.000000000 +0300
++++ linux-2.6.18.kgdb/arch/mips/kernel/kgdb_handler.S 2008-06-10 16:19:28.000000000 +0400
+@@ -0,0 +1,57 @@
++/*
++ * arch/mips/kernel/kgdb_handler.S
++ *
++ * 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
++ * 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
++
++ /*
++ * 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
++ */
++ mfc0 k1, CP0_CAUSE
++ andi k1, k1, 0x7c
++ PTR_L k0, saved_vectors(k1)
++ jr k0
++ nop
++1:
++ SAVE_ALL
++ .set at
++ .set reorder
++ move a0, sp
++ jal handle_exception
++ j ret_from_exception
++ END(trap_low)
+diff -rupN -X ../client-cleanup/dontdiff linux-2.6.18/arch/mips/kernel/traps.c linux-2.6.18.kgdb/arch/mips/kernel/traps.c
+--- linux-2.6.18/arch/mips/kernel/traps.c 2006-09-20 07:42:06.000000000 +0400
++++ linux-2.6.18.kgdb/arch/mips/kernel/traps.c 2008-06-10 16:19:28.000000000 +0400
+@@ -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, 2005 Maciej W. Rozycki
++ *
++ * KGDB specific changes - Manish Lachwani (mlachwani@mvista.com)
+ */
+ #include <linux/init.h>
+ #include <linux/mm.h>
+@@ -20,6 +22,7 @@
+ #include <linux/spinlock.h>
+ #include <linux/kallsyms.h>
+ #include <linux/bootmem.h>
++#include <linux/kgdb.h>
+
+ #include <asm/bootinfo.h>
+ #include <asm/branch.h>
+@@ -40,6 +43,7 @@
+ #include <asm/mmu_context.h>
+ #include <asm/watch.h>
+ #include <asm/types.h>
++#include <asm/kdebug.h>
+
+ extern asmlinkage void handle_int(void);
+ extern asmlinkage void handle_tlbm(void);
+@@ -78,6 +82,21 @@ void (*board_bind_eic_interrupt)(int irq
+ */
+ #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 ...
+@@ -1387,6 +1406,11 @@ void __init trap_init(void)
+ extern char except_vec4;
+ unsigned long i;
+
++#if defined(CONFIG_KGDB)
++ if (kgdb_early_setup)
++ return; /* Already done */
++#endif
++
+ if (cpu_has_veic || cpu_has_vint)
+ ebase = (unsigned long) alloc_bootmem_low_pages (0x200 + VECTORSPACING*64);
+ else
+diff -rupN -X ../client-cleanup/dontdiff linux-2.6.18/arch/mips/mips-boards/generic/Makefile linux-2.6.18.kgdb/arch/mips/mips-boards/generic/Makefile
+--- linux-2.6.18/arch/mips/mips-boards/generic/Makefile 2006-09-20 07:42:06.000000000 +0400
++++ linux-2.6.18.kgdb/arch/mips/mips-boards/generic/Makefile 2008-06-10 16:19:28.000000000 +0400
+@@ -21,6 +21,5 @@
+ obj-y := 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 -rupN -X ../client-cleanup/dontdiff linux-2.6.18/arch/mips/mips-boards/generic/init.c linux-2.6.18.kgdb/arch/mips/mips-boards/generic/init.c
+--- linux-2.6.18/arch/mips/mips-boards/generic/init.c 2006-09-20 07:42:06.000000000 +0400
++++ linux-2.6.18.kgdb/arch/mips/mips-boards/generic/init.c 2008-06-10 16:19:28.000000000 +0400
+@@ -37,15 +37,6 @@
+
+ #include <asm/mips-boards/malta.h>
+
+-#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;
+
+@@ -172,58 +163,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++);
+- }
+-
+- /* Breakpoint is invoked after interrupts are initialised */
+- }
+-}
+-#endif
+-
+ void __init mips_nmi_setup (void)
+ {
+ void *base;
+diff -rupN -X ../client-cleanup/dontdiff linux-2.6.18/arch/mips/mips-boards/malta/malta_setup.c linux-2.6.18.kgdb/arch/mips/mips-boards/malta/malta_setup.c
+--- linux-2.6.18/arch/mips/mips-boards/malta/malta_setup.c 2006-09-20 07:42:06.000000000 +0400
++++ linux-2.6.18.kgdb/arch/mips/mips-boards/malta/malta_setup.c 2008-06-10 16:19:28.000000000 +0400
+@@ -46,10 +46,6 @@ extern void mips_reboot_setup(void);
+ extern void mips_time_init(void);
+ extern unsigned long mips_rtc_get_time(void);
+
+-#ifdef CONFIG_KGDB
+-extern void kgdb_config(void);
+-#endif
+-
+ struct resource standard_io_resources[] = {
+ { .name = "dma1", .start = 0x00, .end = 0x1f, .flags = IORESOURCE_BUSY },
+ { .name = "timer", .start = 0x40, .end = 0x5f, .flags = IORESOURCE_BUSY },
+@@ -124,10 +120,6 @@ void __init plat_mem_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 -rupN -X ../client-cleanup/dontdiff linux-2.6.18/arch/mips/mm/extable.c linux-2.6.18.kgdb/arch/mips/mm/extable.c
+--- linux-2.6.18/arch/mips/mm/extable.c 2006-09-20 07:42:06.000000000 +0400
++++ linux-2.6.18.kgdb/arch/mips/mm/extable.c 2008-06-10 16:19:28.000000000 +0400
+@@ -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 -rupN -X ../client-cleanup/dontdiff linux-2.6.18/arch/mips/sibyte/cfe/setup.c linux-2.6.18.kgdb/arch/mips/sibyte/cfe/setup.c
+--- linux-2.6.18/arch/mips/sibyte/cfe/setup.c 2006-09-20 07:42:06.000000000 +0400
++++ linux-2.6.18.kgdb/arch/mips/sibyte/cfe/setup.c 2008-06-10 16:19:28.000000000 +0400
+@@ -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 -rupN -X ../client-cleanup/dontdiff linux-2.6.18/arch/mips/sibyte/sb1250/Makefile linux-2.6.18.kgdb/arch/mips/sibyte/sb1250/Makefile
+--- linux-2.6.18/arch/mips/sibyte/sb1250/Makefile 2006-09-20 07:42:06.000000000 +0400
++++ linux-2.6.18.kgdb/arch/mips/sibyte/sb1250/Makefile 2008-06-10 16:19:28.000000000 +0400
+@@ -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 -rupN -X ../client-cleanup/dontdiff linux-2.6.18/arch/mips/sibyte/sb1250/irq.c linux-2.6.18.kgdb/arch/mips/sibyte/sb1250/irq.c
+--- linux-2.6.18/arch/mips/sibyte/sb1250/irq.c 2006-09-20 07:42:06.000000000 +0400
++++ linux-2.6.18.kgdb/arch/mips/sibyte/sb1250/irq.c 2008-06-10 16:19:28.000000000 +0400
+@@ -30,6 +30,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>
+@@ -59,16 +60,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 irq_chip sb1250_irq_type = {
+ .typename = "SB1250-IMR",
+ .startup = startup_sb1250_irq,
+@@ -324,6 +315,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 */
+ __raw_writeq(IMR_IP2_VAL,
+@@ -375,50 +371,6 @@ void __init arch_init_irq(void)
+ /* Enable necessary IPs, disable the rest */
+ change_c0_status(ST0_IM, imask);
+
+-#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 */
+- __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);
+- }
+-#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)))
+-
+-static 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(®s->cp0_epc);
+-}
+-
+-#endif /* CONFIG_KGDB */
+-
+ static inline int dclz(unsigned long long x)
+ {
+ int lz;
+@@ -473,7 +425,7 @@ asmlinkage void plat_irq_dispatch(struct
+ sb1250_mailbox_interrupt(regs);
+ #endif
+
+-#ifdef CONFIG_KGDB
++#ifdef CONFIG_KGDB_SIBYTE
+ else if (pending & CAUSEF_IP6) /* KGDB (uart 1) */
+ sb1250_kgdb_interrupt(regs);
+ #endif
+diff -rupN -X ../client-cleanup/dontdiff linux-2.6.18/arch/mips/sibyte/sb1250/kgdb_sibyte.c linux-2.6.18.kgdb/arch/mips/sibyte/sb1250/kgdb_sibyte.c
+--- linux-2.6.18/arch/mips/sibyte/sb1250/kgdb_sibyte.c 1970-01-01 03:00:00.000000000 +0300
++++ linux-2.6.18.kgdb/arch/mips/sibyte/sb1250/kgdb_sibyte.c 2008-06-10 16:19:28.000000000 +0400
+@@ -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 -rupN -X ../client-cleanup/dontdiff linux-2.6.18/arch/mips/sibyte/swarm/Makefile linux-2.6.18.kgdb/arch/mips/sibyte/swarm/Makefile
+--- linux-2.6.18/arch/mips/sibyte/swarm/Makefile 2006-09-20 07:42:06.000000000 +0400
++++ linux-2.6.18.kgdb/arch/mips/sibyte/swarm/Makefile 2008-06-10 16:19:28.000000000 +0400
+@@ -1,3 +1 @@
+ lib-y = setup.o rtc_xicor1241.o rtc_m41t81.o
+-
+-lib-$(CONFIG_KGDB) += dbg_io.o
+diff -rupN -X ../client-cleanup/dontdiff linux-2.6.18/arch/mips/sibyte/swarm/dbg_io.c linux-2.6.18.kgdb/arch/mips/sibyte/swarm/dbg_io.c
+--- linux-2.6.18/arch/mips/sibyte/swarm/dbg_io.c 2006-09-20 07:42:06.000000000 +0400
++++ linux-2.6.18.kgdb/arch/mips/sibyte/swarm/dbg_io.c 1970-01-01 03:00:00.000000000 +0300
+@@ -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 -rupN -X ../client-cleanup/dontdiff linux-2.6.18/arch/mips/tx4938/common/Makefile linux-2.6.18.kgdb/arch/mips/tx4938/common/Makefile
+--- linux-2.6.18/arch/mips/tx4938/common/Makefile 2006-09-20 07:42:06.000000000 +0400
++++ linux-2.6.18.kgdb/arch/mips/tx4938/common/Makefile 2008-06-10 16:19:28.000000000 +0400
+@@ -7,5 +7,5 @@
+ #
+
+ obj-y += prom.o setup.o irq.o rtc_rx5c348.o
+-obj-$(CONFIG_KGDB) += dbgio.o
++obj-$(CONFIG_KGDB_8250) += dbgio.o
+
+diff -rupN -X ../client-cleanup/dontdiff linux-2.6.18/arch/powerpc/Kconfig.debug linux-2.6.18.kgdb/arch/powerpc/Kconfig.debug
+--- linux-2.6.18/arch/powerpc/Kconfig.debug 2006-09-20 07:42:06.000000000 +0400
++++ linux-2.6.18.kgdb/arch/powerpc/Kconfig.debug 2008-06-10 16:19:22.000000000 +0400
+@@ -18,52 +18,9 @@ config DEBUG_STACK_USAGE
+
+ This option will slow down process creation somewhat.
+
+-config DEBUGGER
+- bool "Enable debugger hooks"
+- depends on DEBUG_KERNEL
+- help
+- Include in-kernel hooks for kernel debuggers. Unless you are
+- intending to debug the kernel, say N here.
+-
+-config KGDB
+- bool "Include kgdb kernel debugger"
+- depends on DEBUGGER && (BROKEN || PPC_GEN550 || 4xx)
+- select DEBUG_INFO
+- help
+- Include in-kernel hooks for kgdb, the Linux kernel source level
+- debugger. See <http://kgdb.sourceforge.net/> for more information.
+- Unless you are intending to debug the kernel, say N here.
+-
+-choice
+- prompt "Serial Port"
+- depends on KGDB
+- default KGDB_TTYS1
+-
+-config KGDB_TTYS0
+- bool "ttyS0"
+-
+-config KGDB_TTYS1
+- bool "ttyS1"
+-
+-config KGDB_TTYS2
+- bool "ttyS2"
+-
+-config KGDB_TTYS3
+- bool "ttyS3"
+-
+-endchoice
+-
+-config KGDB_CONSOLE
+- bool "Enable serial console thru kgdb port"
+- depends on KGDB && 8xx || CPM2
+- help
+- If you enable this, all serial console messages will be sent
+- over the gdb stub.
+- If unsure, say N.
+-
+ config XMON
+ bool "Include xmon kernel debugger"
+- depends on DEBUGGER && !PPC_ISERIES
++ depends on DEBUG_KERNEL && !PPC_ISERIES
+ help
+ Include in-kernel hooks for the xmon kernel monitor/debugger.
+ Unless you are intending to debug the kernel, say N here.
+@@ -82,6 +39,11 @@ config XMON_DEFAULT
+ xmon is normally disabled unless booted with 'xmon=on'.
+ Use 'xmon=off' to disable xmon init during runtime.
+
++config DEBUGGER
++ bool
++ depends on KGDB || XMON
++ default y
++
+ config IRQSTACKS
+ bool "Use separate kernel stacks when processing interrupts"
+ depends on PPC64
+diff -rupN -X ../client-cleanup/dontdiff linux-2.6.18/arch/powerpc/kernel/Makefile linux-2.6.18.kgdb/arch/powerpc/kernel/Makefile
+--- linux-2.6.18/arch/powerpc/kernel/Makefile 2006-09-20 07:42:06.000000000 +0400
++++ linux-2.6.18.kgdb/arch/powerpc/kernel/Makefile 2008-06-10 16:19:22.000000000 +0400
+@@ -60,6 +60,7 @@ obj-$(CONFIG_BOOTX_TEXT) += btext.o
+ obj-$(CONFIG_SMP) += smp.o
+ obj-$(CONFIG_KPROBES) += kprobes.o
+ obj-$(CONFIG_PPC_UDBG_16550) += legacy_serial.o udbg_16550.o
++obj-$(CONFIG_KGDB) += kgdb.o
+ module-$(CONFIG_PPC64) += module_64.o
+ obj-$(CONFIG_MODULES) += $(module-y)
+
+diff -rupN -X ../client-cleanup/dontdiff linux-2.6.18/arch/powerpc/kernel/kgdb.c linux-2.6.18.kgdb/arch/powerpc/kernel/kgdb.c
+--- linux-2.6.18/arch/powerpc/kernel/kgdb.c 1970-01-01 03:00:00.000000000 +0300
++++ linux-2.6.18.kgdb/arch/powerpc/kernel/kgdb.c 2008-06-10 16:19:22.000000000 +0400
+@@ -0,0 +1,568 @@
++/*
++ * arch/powerpc/kernel/kgdb.c
++ *
++ * PowerPC backend to the KGDB stub.
++ *
++ * Maintainer: Tom Rini <trini@kernel.crashing.org>
++ *
++ * Copied from arch/ppc/kernel/kgdb.c, updated for ppc64
++ *
++ * Copyright (C) 1996 Paul Mackerras (setjmp/longjmp)
++ * 1998 (c) Michael AK Tesch (tesch@cs.wisc.edu)
++ * Copyright (C) 2003 Timesys Corporation.
++ * Copyright (C) 2004-2006 MontaVista Software, Inc.
++ * PPC64 Mods (C) 2005 Frank Rowand (frowand@mvista.com)
++ * PPC32 support restored by Vitaly Wool <vwool@ru.mvista.com> and
++ * Sergei Shtylyov <sshtylyov@ru.mvista.com>
++ *
++ * 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/config.h>
++#include <linux/kernel.h>
++#include <linux/init.h>
++#include <linux/kgdb.h>
++#include <linux/smp.h>
++#include <linux/signal.h>
++#include <linux/ptrace.h>
++#include <asm/current.h>
++#include <asm/ptrace.h>
++#include <asm/processor.h>
++#include <asm/machdep.h>
++
++/*
++ * This table contains the mapping between PowerPC hardware trap types, and
++ * signals, which are primarily what GDB understands. GDB and the kernel
++ * don't always agree on values, so we use constants taken from gdb-6.2.
++ */
++static struct hard_trap_info
++{
++ unsigned int tt; /* Trap type code for powerpc */
++ unsigned char signo; /* Signal that we map this trap into */
++} hard_trap_info[] = {
++ { 0x0100, 0x02 /* SIGINT */ }, /* system reset */
++ { 0x0200, 0x0b /* SIGSEGV */ }, /* machine check */
++ { 0x0300, 0x0b /* SIGSEGV */ }, /* data access */
++ { 0x0400, 0x0b /* SIGSEGV */ }, /* instruction access */
++ { 0x0500, 0x02 /* SIGINT */ }, /* external interrupt */
++ { 0x0600, 0x0a /* SIGBUS */ }, /* alignment */
++ { 0x0700, 0x05 /* SIGTRAP */ }, /* program check */
++ { 0x0800, 0x08 /* SIGFPE */ }, /* fp unavailable */
++ { 0x0900, 0x0e /* SIGALRM */ }, /* decrementer */
++ { 0x0c00, 0x14 /* SIGCHLD */ }, /* system call */
++#if defined(CONFIG_40x) || defined(CONFIG_BOOKE)
++ { 0x2002, 0x05 /* SIGTRAP */ }, /* debug */
++#if defined(CONFIG_FSL_BOOKE)
++ { 0x2010, 0x08 /* SIGFPE */ }, /* spe unavailable */
++ { 0x2020, 0x08 /* SIGFPE */ }, /* spe unavailable */
++ { 0x2030, 0x08 /* SIGFPE */ }, /* spe fp data */
++ { 0x2040, 0x08 /* SIGFPE */ }, /* spe fp data */
++ { 0x2050, 0x08 /* SIGFPE */ }, /* spe fp round */
++ { 0x2060, 0x0e /* SIGILL */ }, /* performace monitor */
++ { 0x2900, 0x08 /* SIGFPE */ }, /* apu unavailable */
++ { 0x3100, 0x0e /* SIGALRM */ }, /* fixed interval timer */
++ { 0x3200, 0x02 /* SIGINT */ }, /* watchdog */
++#else
++ { 0x1000, 0x0e /* SIGALRM */ }, /* programmable interval timer */
++ { 0x1010, 0x0e /* SIGALRM */ }, /* fixed interval timer */
++ { 0x1020, 0x02 /* SIGINT */ }, /* watchdog */
++ { 0x2010, 0x08 /* SIGFPE */ }, /* fp unavailable */
++ { 0x2020, 0x08 /* SIGFPE */ }, /* ap unavailable */
++#endif
++#else
++ { 0x0d00, 0x05 /* SIGTRAP */ }, /* single-step */
++#if defined(CONFIG_8xx)
++ { 0x1000, 0x04 /* SIGILL */ }, /* software emulation */
++#else
++ { 0x0f00, 0x04 /* SIGILL */ }, /* performance monitor */
++ { 0x0f20, 0x08 /* SIGFPE */ }, /* altivec unavailable */
++ { 0x1300, 0x05 /* SIGTRAP */ }, /* instruction address break */
++#if defined(CONFIG_PPC64)
++ { 0x1200, 0x05 /* SIGILL */ }, /* system error */
++ { 0x1500, 0x04 /* SIGILL */ }, /* soft patch */
++ { 0x1600, 0x04 /* SIGILL */ }, /* maintenance */
++ { 0x1700, 0x08 /* SIGFPE */ }, /* altivec assist */
++ { 0x1800, 0x04 /* SIGILL */ }, /* thermal */
++#else
++ { 0x1400, 0x02 /* SIGINT */ }, /* SMI */
++ { 0x1600, 0x08 /* SIGFPE */ }, /* altivec assist */
++ { 0x1700, 0x04 /* SIGILL */ }, /* TAU */
++ { 0x2000, 0x05 /* SIGTRAP */ }, /* run mode */
++#endif
++#endif
++#endif
++ { 0x0000, 0x00 } /* Must be last */
++};
++
++extern atomic_t cpu_doing_single_step;
++
++static int computeSignal(unsigned 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 */
++}
++
++static int kgdb_call_nmi_hook(struct pt_regs *regs)
++{
++ kgdb_nmihook(smp_processor_id(), regs);
++ return 0;
++}
++
++#ifdef CONFIG_SMP
++void kgdb_roundup_cpus(unsigned long flags)
++{
++ smp_send_debugger_break(MSG_ALL_BUT_SELF);
++}
++#endif
++
++/* KGDB functions to use existing PowerPC64 hooks. */
++static int kgdb_debugger(struct pt_regs *regs)
++{
++ return kgdb_handle_exception(0, computeSignal(TRAP(regs)), 0, regs);
++}
++
++static int kgdb_breakpoint(struct pt_regs *regs)
++{
++ if (user_mode(regs))
++ return 0;
++
++ kgdb_handle_exception(0, SIGTRAP, 0, regs);
++
++ if (*(u32 *) (regs->nip) == *(u32 *) (&arch_kgdb_ops.gdb_bpt_instr))
++ regs->nip += 4;
++
++ return 1;
++}
++
++static int kgdb_singlestep(struct pt_regs *regs)
++{
++ struct thread_info *thread_info, *exception_thread_info;
++ if (user_mode(regs))
++ return 0;
++ /*
++ * On Book E and perhaps other processsors, singlestep is handled on
++ * the critical exception stack. This causes current_thread_info()
++ * to fail, since it it locates the thread_info by masking off
++ * the low bits of the current stack pointer. We work around
++ * this issue by copying the thread_info from the kernel stack
++ * before calling kgdb_handle_exception, and copying it back
++ * afterwards. On most processors the copy is avoided since
++ * exception_thread_info == thread_info.
++ */
++ thread_info = (struct thread_info *)(regs->gpr[1] & ~(THREAD_SIZE-1));
++ exception_thread_info = current_thread_info();
++
++ if (thread_info != exception_thread_info)
++ memcpy(exception_thread_info, thread_info, sizeof *thread_info);
++
++ kgdb_handle_exception(0, SIGTRAP, 0, regs);
++
++ if (thread_info != exception_thread_info)
++ memcpy(thread_info, exception_thread_info, sizeof *thread_info);
++
++ return 1;
++}
++
++int kgdb_iabr_match(struct pt_regs *regs)
++{
++ if (user_mode(regs))
++ return 0;
++
++ kgdb_handle_exception(0, computeSignal(TRAP(regs)), 0, regs);
++ return 1;
++}
++
++int kgdb_dabr_match(struct pt_regs *regs)
++{
++ if (user_mode(regs))
++ return 0;
++
++ kgdb_handle_exception(0, computeSignal(TRAP(regs)), 0, regs);
++ return 1;
++}
++
++#define PACK64(ptr,src) do { *(ptr++) = (src); } while(0)
++
++#define PACK32(ptr,src) do { \
++ u32 *ptr32; \
++ ptr32 = (u32 *)ptr; \
++ *(ptr32++) = (src); \
++ ptr = (unsigned long *)ptr32; \
++ } while(0)
++
++void regs_to_gdb_regs(unsigned long *gdb_regs, struct pt_regs *regs)
++{
++ unsigned long *ptr = gdb_regs;
++ int reg;
++
++ memset(gdb_regs, 0, NUMREGBYTES);
++
++ for (reg = 0; reg < 32; reg++)
++ PACK64(ptr, regs->gpr[reg]);
++
++#ifdef CONFIG_FSL_BOOKE
++#ifdef CONFIG_SPE
++ for (reg = 0; reg < 32; reg++)
++ PACK64(ptr, current->thread.evr[reg]);
++#else
++ ptr += 32;
++#endif
++#else
++ /* fp registers not used by kernel, leave zero */
++ ptr += 32 * 8 / sizeof(long);
++#endif
++
++ PACK64(ptr, regs->nip);
++ PACK64(ptr, regs->msr);
++ PACK32(ptr, regs->ccr);
++ PACK64(ptr, regs->link);
++ PACK64(ptr, regs->ctr);
++ PACK32(ptr, regs->xer);
++
++#if 0
++ Following are in struct thread_struct, not struct pt_regs,
++ ignoring for now since kernel does not use them. Would it
++ make sense to get them from the thread that kgdb is set to?
++
++ If this code is enabled, update the definition of NUMREGBYTES to
++ include the vector registers and vector state registers.
++
++ PACK32(ptr, current->thread->fpscr);
++
++ /* vr registers not used by kernel, leave zero */
++ ptr += 32 * 16 / sizeof(long);
++
++#ifdef CONFIG_ALTIVEC
++ PACK32(ptr, current->thread->vscr);
++ PACK32(ptr, current->thread->vrsave);
++#else
++ ptr += 2 * 4 / sizeof(long);
++#endif
++#else
++#ifdef CONFIG_FSL_BOOKE
++#ifdef CONFIG_SPE
++ /* u64 acc */
++ PACK32(ptr, current->thread.acc >> 32);
++ PACK32(ptr, current->thread.acc & 0xffffffff);
++ PACK64(ptr, current->thread.spefscr);
++#else
++ ptr += 2 + 1;
++#endif
++#else
++ /* fpscr not used by kernel, leave zero */
++ PACK32(ptr, 0);
++#endif
++#endif
++
++ BUG_ON((unsigned long)ptr >
++ (unsigned long)(((void *)gdb_regs) + NUMREGBYTES));
++}
++
++void sleeping_thread_to_gdb_regs(unsigned long *gdb_regs, struct task_struct *p)
++{
++ struct pt_regs *regs = (struct pt_regs *)(p->thread.ksp +
++ STACK_FRAME_OVERHEAD);
++ unsigned long *ptr = gdb_regs;
++ int reg;
++
++ memset(gdb_regs, 0, NUMREGBYTES);
++
++ /* Regs GPR0-2 */
++ for (reg = 0; reg < 3; reg++)
++ PACK64(ptr, regs->gpr[reg]);
++
++ /* Regs GPR3-13 are caller saved, not in regs->gpr[] */
++ ptr += 11;
++
++ /* Regs GPR14-31 */
++ for (reg = 14; reg < 32; reg++)
++ PACK64(ptr, regs->gpr[reg]);
++
++#ifdef CONFIG_FSL_BOOKE
++#ifdef CONFIG_SPE
++ for (reg = 0; reg < 32; reg++)
++ PACK64(ptr, p->thread.evr[reg]);
++#else
++ ptr += 32;
++#endif
++#else
++ /* fp registers not used by kernel, leave zero */
++ ptr += 32 * 8 / sizeof(long);
++#endif
++ PACK64(ptr, regs->nip);
++ PACK64(ptr, regs->msr);
++ PACK32(ptr, regs->ccr);
++ PACK64(ptr, regs->link);
++ PACK64(ptr, regs->ctr);
++ PACK32(ptr, regs->xer);
++
++#if 0
++ Following are in struct thread_struct, not struct pt_regs,
++ ignoring for now since kernel does not use them. Would it
++ make sense to get them from the thread that kgdb is set to?
++
++ If this code is enabled, update the definition of NUMREGBYTES to
++ include the vector registers and vector state registers.
++
++ PACK32(ptr, p->thread->fpscr);
++
++ /* vr registers not used by kernel, leave zero */
++ ptr += 32 * 16 / sizeof(long);
++
++#ifdef CONFIG_ALTIVEC
++ PACK32(ptr, p->thread->vscr);
++ PACK32(ptr, p->thread->vrsave);
++#else
++ ptr += 2 * 4 / sizeof(long);
++#endif
++#else
++#ifdef CONFIG_FSL_BOOKE
++#ifdef CONFIG_SPE
++ /* u64 acc */
++ PACK32(ptr, p->thread.acc >> 32);
++ PACK32(ptr, p->thread.acc & 0xffffffff);
++ PACK64(ptr, p->thread.spefscr);
++#else
++ ptr += 2 + 1;
++#endif
++#else
++ /* fpscr not used by kernel, leave zero */
++ PACK32(ptr, 0);
++#endif
++#endif
++
++ BUG_ON((unsigned long)ptr >
++ (unsigned long)(((void *)gdb_regs) + NUMREGBYTES));
++}
++
++#define UNPACK64(dest,ptr) do { dest = *(ptr++); } while(0)
++
++#define UNPACK32(dest,ptr) do { \
++ u32 *ptr32; \
++ ptr32 = (u32 *)ptr; \
++ dest = *(ptr32++); \
++ ptr = (unsigned long *)ptr32; \
++ } while(0)
++
++void gdb_regs_to_regs(unsigned long *gdb_regs, struct pt_regs *regs)
++{
++ unsigned long *ptr = gdb_regs;
++ int reg;
++
++#ifdef CONFIG_SPE
++ union {
++ u32 v32[2];
++ u64 v64;
++ } acc;
++#endif
++ for (reg = 0; reg < 32; reg++)
++ UNPACK64(regs->gpr[reg], ptr);
++
++#ifdef CONFIG_FSL_BOOKE
++#ifdef CONFIG_SPE
++ for (reg = 0; reg < 32; reg++)
++ UNPACK64(current->thread.evr[reg], ptr);
++#else
++ ptr += 32;
++#endif
++#else
++ /* fp registers not used by kernel, leave zero */
++ ptr += 32 * 8 / sizeof(int);
++#endif
++ UNPACK64(regs->nip, ptr);
++ UNPACK64(regs->msr, ptr);
++ UNPACK32(regs->ccr, ptr);
++ UNPACK64(regs->link, ptr);
++ UNPACK64(regs->ctr, ptr);
++ UNPACK32(regs->xer, ptr);
++
++#if 0
++ Following are in struct thread_struct, not struct pt_regs,
++ ignoring for now since kernel does not use them. Would it
++ make sense to get them from the thread that kgdb is set to?
++
++ If this code is enabled, update the definition of NUMREGBYTES to
++ include the vector registers and vector state registers.
++
++ /* fpscr, vscr, vrsave not used by kernel, leave unchanged */
++
++ UNPACK32(current->thread->fpscr, ptr);
++
++ /* vr registers not used by kernel, leave zero */
++ ptr += 32 * 16 / sizeof(long);
++
++ #ifdef CONFIG_ALTIVEC
++ UNPACK32(current->thread->vscr, ptr);
++ UNPACK32(current->thread->vrsave, ptr);
++#else
++ ptr += 2 * 4 / sizeof(long);
++#endif
++#else
++#ifdef CONFIG_FSL_BOOKE
++#ifdef CONFIG_SPE
++ /* u64 acc */
++ UNPACK32(acc.v32[0], ptr);
++ UNPACK32(acc.v32[1], ptr);
++ current->thread.acc = acc.v64;
++ UNPACK64(current->thread.spefscr, ptr);
++#else
++ ptr += 2 + 1;
++#endif
++#endif
++#endif
++
++ BUG_ON((unsigned long)ptr >
++ (unsigned long)(((void *)gdb_regs) + NUMREGBYTES));
++}
++
++/*
++ * This function does PowerPC specific procesing for interfacing to gdb.
++ */
++int kgdb_arch_handle_exception(int vector, int signo, int err_code,
++ char *remcom_in_buffer, char *remcom_out_buffer,
++ struct pt_regs *linux_regs)
++{
++ char *ptr = &remcom_in_buffer[1];
++ unsigned long addr;
++
++ switch (remcom_in_buffer[0]) {
++ /*
++ * sAA..AA Step one instruction from AA..AA
++ * This will return an error to gdb ..
++ */
++ case 's':
++ case 'c':
++ /* handle the optional parameter */
++ if (kgdb_hex2long(&ptr, &addr))
++ linux_regs->nip = addr;
++
++ atomic_set(&cpu_doing_single_step, -1);
++ /* set the trace bit if we're stepping */
++ if (remcom_in_buffer[0] == 's') {
++#if defined(CONFIG_40x) || defined(CONFIG_BOOKE)
++ mtspr(SPRN_DBCR0,
++ mfspr(SPRN_DBCR0) | DBCR0_IC | DBCR0_IDM);
++ linux_regs->msr |= MSR_DE;
++#else
++ linux_regs->msr |= MSR_SE;
++#endif
++ debugger_step = 1;
++ if (kgdb_contthread)
++ atomic_set(&cpu_doing_single_step,
++ smp_processor_id());
++ }
++ return 0;
++ }
++
++ return -1;
++}
++
++int kgdb_fault_setjmp(unsigned long *curr_context)
++{
++#ifdef CONFIG_PPC32
++ __asm__ __volatile__("mflr 0; stw 0,0(%0);\n\
++ stw 1,4(%0); stw 2,8(%0);\n\
++ mfcr 0; stw 0,12(%0);\n\
++ stmw 13,16(%0)\n" : : "r" (curr_context));
++#else
++ __asm__ __volatile__("mflr 0; std 0,0(%0)\n\
++ std 1,8(%0)\n\
++ std 2,16(%0)\n\
++ mfcr 0; std 0,24(%0)\n\
++ std 13,32(%0)\n\
++ std 14,40(%0)\n\
++ std 15,48(%0)\n\
++ std 16,56(%0)\n\
++ std 17,64(%0)\n\
++ std 18,72(%0)\n\
++ std 19,80(%0)\n\
++ std 20,88(%0)\n\
++ std 21,96(%0)\n\
++ std 22,104(%0)\n\
++ std 23,112(%0)\n\
++ std 24,120(%0)\n\
++ std 25,128(%0)\n\
++ std 26,136(%0)\n\
++ std 27,144(%0)\n\
++ std 28,152(%0)\n\
++ std 29,160(%0)\n\
++ std 30,168(%0)\n\
++ std 31,176(%0)\n" : : "r" (curr_context));
++#endif
++ return 0;
++}
++
++void kgdb_fault_longjmp(unsigned long *curr_context)
++{
++#ifdef CONFIG_PPC32
++ __asm__ __volatile__("lmw 13,16(%0);\n\
++ lwz 0,12(%0); mtcrf 0x38,0;\n\
++ lwz 0,0(%0); lwz 1,4(%0); lwz 2,8(%0);\n\
++ mtlr 0; mr 3,1\n" : : "r" (curr_context));
++#else
++ __asm__ __volatile__("ld 13,32(%0)\n\
++ ld 14,40(%0)\n\
++ ld 15,48(%0)\n\
++ ld 16,56(%0)\n\
++ ld 17,64(%0)\n\
++ ld 18,72(%0)\n\
++ ld 19,80(%0)\n\
++ ld 20,88(%0)\n\
++ ld 21,96(%0)\n\
++ ld 22,104(%0)\n\
++ ld 23,112(%0)\n\
++ ld 24,120(%0)\n\
++ ld 25,128(%0)\n\
++ ld 26,136(%0)\n\
++ ld 27,144(%0)\n\
++ ld 28,152(%0)\n\
++ ld 29,160(%0)\n\
++ ld 30,168(%0)\n\
++ ld 31,176(%0)\n\
++ ld 0,24(%0)\n\
++ mtcrf 0x38,0\n\
++ ld 0,0(%0)\n\
++ ld 1,8(%0)\n\
++ ld 2,16(%0)\n\
++ mtlr 0\n\
++ mr 3,1\n" : : "r" (curr_context));
++#endif
++}
++
++/*
++ * Global data
++ */
++struct kgdb_arch arch_kgdb_ops = {
++ .gdb_bpt_instr = {0x7d, 0x82, 0x10, 0x08},
++};
++
++int kgdb_not_implemented(struct pt_regs *regs)
++{
++ return 0;
++}
++
++int kgdb_arch_init(void)
++{
++#ifdef CONFIG_XMON
++#error Both XMON and KGDB selected in .config. Unselect one of them.
++#endif
++
++ __debugger_ipi = kgdb_call_nmi_hook;
++ __debugger = kgdb_debugger;
++ __debugger_bpt = kgdb_breakpoint;
++ __debugger_sstep = kgdb_singlestep;
++ __debugger_iabr_match = kgdb_iabr_match;
++ __debugger_dabr_match = kgdb_dabr_match;
++ __debugger_fault_handler = kgdb_not_implemented;
++
++ return 0;
++}
++
++arch_initcall(kgdb_arch_init);
+diff -rupN -X ../client-cleanup/dontdiff linux-2.6.18/arch/powerpc/kernel/legacy_serial.c linux-2.6.18.kgdb/arch/powerpc/kernel/legacy_serial.c
+--- linux-2.6.18/arch/powerpc/kernel/legacy_serial.c 2006-09-20 07:42:06.000000000 +0400
++++ linux-2.6.18.kgdb/arch/powerpc/kernel/legacy_serial.c 2008-06-10 16:19:22.000000000 +0400
+@@ -11,6 +11,9 @@
+ #include <asm/udbg.h>
+ #include <asm/pci-bridge.h>
+ #include <asm/ppc-pci.h>
++#ifdef CONFIG_KGDB_8250
++#include <linux/kgdb.h>
++#endif
+
+ #undef DEBUG
+
+@@ -470,6 +473,9 @@ static int __init serial_dev_init(void)
+ fixup_port_pio(i, np, port);
+ if ((port->iotype == UPIO_MEM) || (port->iotype == UPIO_TSI))
+ fixup_port_mmio(i, np, port);
++#ifdef CONFIG_KGDB_8250
++ kgdb8250_add_platform_port(i, port);
++#endif
+ }
+
+ DBG("Registering platform serial ports\n");
+diff -rupN -X ../client-cleanup/dontdiff linux-2.6.18/arch/powerpc/kernel/setup_32.c linux-2.6.18.kgdb/arch/powerpc/kernel/setup_32.c
+--- linux-2.6.18/arch/powerpc/kernel/setup_32.c 2006-09-20 07:42:06.000000000 +0400
++++ linux-2.6.18.kgdb/arch/powerpc/kernel/setup_32.c 2008-06-10 16:19:22.000000000 +0400
+@@ -45,10 +45,6 @@
+
+ #define DBG(fmt...)
+
+-#if defined CONFIG_KGDB
+-#include <asm/kgdb.h>
+-#endif
+-
+ extern void bootx_init(unsigned long r4, unsigned long phys);
+
+ struct ide_machdep_calls ppc_ide_md;
+@@ -248,18 +244,6 @@ void __init setup_arch(char **cmdline_p)
+ /* Register early console */
+ register_early_udbg_console();
+
+-#if defined(CONFIG_KGDB)
+- if (ppc_md.kgdb_map_scc)
+- ppc_md.kgdb_map_scc();
+- set_debug_traps();
+- if (strstr(cmd_line, "gdb")) {
+- if (ppc_md.progress)
+- ppc_md.progress("setup_arch: kgdb breakpoint", 0x4000);
+- printk("kgdb breakpoint activated\n");
+- breakpoint();
+- }
+-#endif
+-
+ /*
+ * Set cache line size based on type of cpu as a default.
+ * Systems with OF can look in the properties on the cpu node(s)
+diff -rupN -X ../client-cleanup/dontdiff linux-2.6.18/arch/powerpc/mm/fault.c linux-2.6.18.kgdb/arch/powerpc/mm/fault.c
+--- linux-2.6.18/arch/powerpc/mm/fault.c 2006-09-20 07:42:06.000000000 +0400
++++ linux-2.6.18.kgdb/arch/powerpc/mm/fault.c 2008-06-10 16:19:22.000000000 +0400
+@@ -28,6 +28,7 @@
+ #include <linux/highmem.h>
+ #include <linux/module.h>
+ #include <linux/kprobes.h>
++#include <linux/kgdb.h>
+
+ #include <asm/page.h>
+ #include <asm/pgtable.h>
+@@ -424,6 +425,13 @@ void bad_page_fault(struct pt_regs *regs
+ return;
+ }
+
++#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
++
+ /* kernel has accessed a bad area */
+
+ printk(KERN_ALERT "Unable to handle kernel paging request for ");
+diff -rupN -X ../client-cleanup/dontdiff linux-2.6.18/arch/powerpc/platforms/powermac/setup.c linux-2.6.18.kgdb/arch/powerpc/platforms/powermac/setup.c
+--- linux-2.6.18/arch/powerpc/platforms/powermac/setup.c 2006-09-20 07:42:06.000000000 +0400
++++ linux-2.6.18.kgdb/arch/powerpc/platforms/powermac/setup.c 2008-06-10 16:19:22.000000000 +0400
+@@ -98,8 +98,6 @@ extern struct machdep_calls pmac_md;
+ int sccdbg;
+ #endif
+
+-extern void zs_kgdb_hook(int tty_num);
+-
+ sys_ctrler_t sys_ctrler = SYS_CTRLER_UNKNOWN;
+ EXPORT_SYMBOL(sys_ctrler);
+
+@@ -319,10 +317,6 @@ static void __init pmac_setup_arch(void)
+ l2cr_init();
+ #endif /* CONFIG_PPC32 */
+
+-#ifdef CONFIG_KGDB
+- zs_kgdb_hook(0);
+-#endif
+-
+ find_via_cuda();
+ find_via_pmu();
+ smu_init();
+diff -rupN -X ../client-cleanup/dontdiff linux-2.6.18/arch/ppc/Kconfig.debug linux-2.6.18.kgdb/arch/ppc/Kconfig.debug
+--- linux-2.6.18/arch/ppc/Kconfig.debug 2006-09-20 07:42:06.000000000 +0400
++++ linux-2.6.18.kgdb/arch/ppc/Kconfig.debug 2008-06-10 16:19:22.000000000 +0400
+@@ -2,42 +2,6 @@ menu "Kernel hacking"
+
+ source "lib/Kconfig.debug"
+
+-config KGDB
+- bool "Include kgdb kernel debugger"
+- depends on DEBUG_KERNEL && (BROKEN || PPC_GEN550 || 4xx)
+- select DEBUG_INFO
+- help
+- Include in-kernel hooks for kgdb, the Linux kernel source level
+- debugger. See <http://kgdb.sourceforge.net/> for more information.
+- Unless you are intending to debug the kernel, say N here.
+-
+-choice
+- prompt "Serial Port"
+- depends on KGDB
+- default KGDB_TTYS1
+-
+-config KGDB_TTYS0
+- bool "ttyS0"
+-
+-config KGDB_TTYS1
+- bool "ttyS1"
+-
+-config KGDB_TTYS2
+- bool "ttyS2"
+-
+-config KGDB_TTYS3
+- bool "ttyS3"
+-
+-endchoice
+-
+-config KGDB_CONSOLE
+- bool "Enable serial console thru kgdb port"
+- depends on KGDB && 8xx || CPM2
+- help
+- If you enable this, all serial console messages will be sent
+- over the gdb stub.
+- If unsure, say N.
+-
+ config XMON
+ bool "Include xmon kernel debugger"
+ depends on DEBUG_KERNEL
+diff -rupN -X ../client-cleanup/dontdiff linux-2.6.18/arch/ppc/kernel/kgdb.c linux-2.6.18.kgdb/arch/ppc/kernel/kgdb.c
+--- linux-2.6.18/arch/ppc/kernel/kgdb.c 1970-01-01 03:00:00.000000000 +0300
++++ linux-2.6.18.kgdb/arch/ppc/kernel/kgdb.c 2008-06-10 16:20:19.000000000 +0400
+@@ -0,0 +1,350 @@
++/*
++ * arch/ppc/kernel/kgdb.c
++ *
++ * PowerPC backend to the KGDB stub.
++ *
++ * Maintainer: Tom Rini <trini@kernel.crashing.org>
++ *
++ * 1998 (c) Michael AK Tesch (tesch@cs.wisc.edu)
++ * Copyright (C) 2003 Timesys Corporation.
++ * 2004 (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/config.h>
++#include <linux/kernel.h>
++#include <linux/init.h>
++#include <linux/kgdb.h>
++#include <linux/smp.h>
++#include <linux/signal.h>
++#include <linux/ptrace.h>
++#include <asm/current.h>
++#include <asm/ptrace.h>
++#include <asm/processor.h>
++#include <asm/machdep.h>
++
++/*
++ * This table contains the mapping between PowerPC hardware trap types, and
++ * signals, which are primarily what GDB understands. GDB and the kernel
++ * don't always agree on values, so we use constants taken from gdb-6.2.
++ */
++static struct hard_trap_info
++{
++ unsigned int tt; /* Trap type code for powerpc */
++ unsigned char signo; /* Signal that we map this trap into */
++} hard_trap_info[] = {
++#if defined(CONFIG_40x) || defined(CONFIG_BOOKE)
++ { 0x0100, 0x02 /* SIGINT */ }, /* critical input interrupt */
++ { 0x0200, 0x0b /* SIGSEGV */ }, /* machine check */
++ { 0x0300, 0x0b /* SIGSEGV */ }, /* data storage */
++ { 0x0400, 0x0a /* SIGBUS */ }, /* instruction storage */
++ { 0x0500, 0x02 /* SIGINT */ }, /* interrupt */
++ { 0x0600, 0x0a /* SIGBUS */ }, /* alignment */
++ { 0x0700, 0x04 /* SIGILL */ }, /* program */
++ { 0x0800, 0x04 /* SIGILL */ }, /* reserved */
++ { 0x0900, 0x04 /* SIGILL */ }, /* reserved */
++ { 0x0a00, 0x04 /* SIGILL */ }, /* reserved */
++ { 0x0b00, 0x04 /* SIGILL */ }, /* reserved */
++ { 0x0c00, 0x14 /* SIGCHLD */ }, /* syscall */
++ { 0x0d00, 0x04 /* SIGILL */ }, /* reserved */
++ { 0x0e00, 0x04 /* SIGILL */ }, /* reserved */
++ { 0x0f00, 0x04 /* SIGILL */ }, /* reserved */
++ { 0x2002, 0x05 /* SIGTRAP */}, /* debug */
++#else
++ { 0x0200, 0x0b /* SIGSEGV */ }, /* machine check */
++ { 0x0300, 0x0b /* SIGSEGV */ }, /* address error (store) */
++ { 0x0400, 0x0a /* SIGBUS */ }, /* instruction bus error */
++ { 0x0500, 0x02 /* SIGINT */ }, /* interrupt */
++ { 0x0600, 0x0a /* SIGBUS */ }, /* alingment */
++ { 0x0700, 0x05 /* SIGTRAP */ }, /* breakpoint trap */
++ { 0x0800, 0x08 /* SIGFPE */}, /* fpu unavail */
++ { 0x0900, 0x0e /* SIGALRM */ }, /* decrementer */
++ { 0x0a00, 0x04 /* SIGILL */ }, /* reserved */
++ { 0x0b00, 0x04 /* SIGILL */ }, /* reserved */
++ { 0x0c00, 0x14 /* SIGCHLD */ }, /* syscall */
++ { 0x0d00, 0x05 /* SIGTRAP */ }, /* single-step/watch */
++ { 0x0e00, 0x08 /* SIGFPE */ }, /* fp assist */
++#endif
++ { 0x0000, 0x000 } /* Must be last */
++};
++
++extern atomic_t cpu_doing_single_step;
++
++static int computeSignal(unsigned 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 */
++}
++
++/* KGDB functions to use existing PowerPC hooks. */
++static void kgdb_debugger(struct pt_regs *regs)
++{
++ kgdb_handle_exception(0, computeSignal(TRAP(regs)), 0, regs);
++}
++
++static int kgdb_breakpoint(struct pt_regs *regs)
++{
++ if (user_mode(regs))
++ return 0;
++
++ kgdb_handle_exception(0, SIGTRAP, 0, regs);
++
++ if (*(u32 *) (regs->nip) == *(u32 *) (&arch_kgdb_ops.gdb_bpt_instr))
++ regs->nip += 4;
++
++ return 1;
++}
++
++static int kgdb_singlestep(struct pt_regs *regs)
++{
++ struct thread_info *thread_info, *exception_thread_info;
++
++ if (user_mode(regs))
++ return 0;
++ /*
++ * On Book E and perhaps other processsors, singlestep is handled on
++ * the critical exception stack. This causes current_thread_info()
++ * to fail, since it it locates the thread_info by masking off
++ * the low bits of the current stack pointer. We work around
++ * this issue by copying the thread_info from the kernel stack
++ * before calling kgdb_handle_exception, and copying it back
++ * afterwards. On most processors the copy is avoided since
++ * exception_thread_info == thread_info.
++ */
++ thread_info = (struct thread_info *)(regs->gpr[1] & ~(THREAD_SIZE-1));
++ exception_thread_info = current_thread_info();
++
++ if (thread_info != exception_thread_info)
++ memcpy(exception_thread_info, thread_info, sizeof *thread_info);
++
++ kgdb_handle_exception(0, SIGTRAP, 0, regs);
++
++ if (thread_info != exception_thread_info)
++ memcpy(thread_info, exception_thread_info, sizeof *thread_info);
++
++ return 1;
++}
++
++int kgdb_iabr_match(struct pt_regs *regs)
++{
++ if (user_mode(regs))
++ return 0;
++
++ kgdb_handle_exception(0, computeSignal(TRAP(regs)), 0, regs);
++ return 1;
++}
++
++int kgdb_dabr_match(struct pt_regs *regs)
++{
++ if (user_mode(regs))
++ return 0;
++
++ kgdb_handle_exception(0, computeSignal(TRAP(regs)), 0, regs);
++ return 1;
++}
++
++void regs_to_gdb_regs(unsigned long *gdb_regs, struct pt_regs *regs)
++{
++ int reg;
++ unsigned long *ptr = gdb_regs;
++
++ memset(gdb_regs, 0, MAXREG * 4);
++
++ for (reg = 0; reg < 32; reg++)
++ *(ptr++) = regs->gpr[reg];
++
++#ifndef CONFIG_E500
++ for (reg = 0; reg < 64; reg++)
++ *(ptr++) = 0;
++#else
++ for (reg = 0; reg < 32; reg++)
++ *(ptr++) = current->thread.evr[reg];
++#endif
++
++ *(ptr++) = regs->nip;
++ *(ptr++) = regs->msr;
++ *(ptr++) = regs->ccr;
++ *(ptr++) = regs->link;
++ *(ptr++) = regs->ctr;
++ *(ptr++) = regs->xer;
++
++#ifdef CONFIG_SPE
++ /* u64 acc */
++ *(ptr++) = (current->thread.acc >> 32);
++ *(ptr++) = (current->thread.acc & 0xffffffff);
++ *(ptr++) = current->thread.spefscr;
++#endif
++}
++
++void sleeping_thread_to_gdb_regs(unsigned long *gdb_regs, struct task_struct *p)
++{
++ struct pt_regs *regs = (struct pt_regs *)(p->thread.ksp +
++ STACK_FRAME_OVERHEAD);
++ int reg;
++ unsigned long *ptr = gdb_regs;
++
++ memset(gdb_regs, 0, MAXREG * 4);
++
++ /* Regs GPR0-2 */
++ for (reg = 0; reg < 3; reg++)
++ *(ptr++) = regs->gpr[reg];
++
++ /* Regs GPR3-13 are not saved */
++ for (reg = 3; reg < 14; reg++)
++ *(ptr++) = 0;
++
++ /* Regs GPR14-31 */
++ for (reg = 14; reg < 32; reg++)
++ *(ptr++) = regs->gpr[reg];
++
++#ifndef CONFIG_E500
++ for (reg = 0; reg < 64; reg++)
++ *(ptr++) = 0;
++#else
++ for (reg = 0; reg < 32; reg++)
++ *(ptr++) = current->thread.evr[reg];
++#endif
++
++ *(ptr++) = regs->nip;
++ *(ptr++) = regs->msr;
++ *(ptr++) = regs->ccr;
++ *(ptr++) = regs->link;
++ *(ptr++) = regs->ctr;
++ *(ptr++) = regs->xer;
++
++#ifdef CONFIG_SPE
++ /* u64 acc */
++ *(ptr++) = (current->thread.acc >> 32);
++ *(ptr++) = (current->thread.acc & 0xffffffff);
++ *(ptr++) = current->thread.spefscr;
++#endif
++}
++
++void gdb_regs_to_regs(unsigned long *gdb_regs, struct pt_regs *regs)
++{
++ int reg;
++ unsigned long *ptr = gdb_regs;
++#ifdef CONFIG_SPE
++ union {
++ u32 v32[2];
++ u64 v64;
++ } u;
++#endif
++
++ for (reg = 0; reg < 32; reg++)
++ regs->gpr[reg] = *(ptr++);
++
++#ifndef CONFIG_E500
++ for (reg = 0; reg < 64; reg++)
++ ptr++;
++#else
++ for (reg = 0; reg < 32; reg++)
++ current->thread.evr[reg] = *(ptr++);
++#endif
++
++ regs->nip = *(ptr++);
++ regs->msr = *(ptr++);
++ regs->ccr = *(ptr++);
++ regs->link = *(ptr++);
++ regs->ctr = *(ptr++);
++ regs->xer = *(ptr++);
++
++#ifdef CONFIG_SPE
++ /* u64 acc */
++ u.v32[0] = *(ptr++);
++ u.v32[1] = *(ptr++);
++ current->thread.acc = u.v64;
++ current->thread.spefscr = *(ptr++);
++#endif
++}
++
++/*
++ * Save/restore state in case a memory access causes a fault.
++ */
++int kgdb_fault_setjmp(unsigned long *curr_context)
++{
++ __asm__ __volatile__("mflr 0; stw 0,0(%0);"
++ "stw 1,4(%0); stw 2,8(%0);"
++ "mfcr 0; stw 0,12(%0);"
++ "stmw 13,16(%0)"::"r"(curr_context));
++ return 0;
++}
++
++void kgdb_fault_longjmp(unsigned long *curr_context)
++{
++ __asm__ __volatile__("lmw 13,16(%0);"
++ "lwz 0,12(%0); mtcrf 0x38,0;"
++ "lwz 0,0(%0); lwz 1,4(%0); lwz 2,8(%0);"
++ "mtlr 0; mr 3,1"::"r"(curr_context));
++}
++
++/*
++ * This function does PoerPC specific procesing for interfacing to gdb.
++ */
++int kgdb_arch_handle_exception(int vector, int signo, int err_code,
++ char *remcom_in_buffer, char *remcom_out_buffer,
++ struct pt_regs *linux_regs)
++{
++ char *ptr = &remcom_in_buffer[1];
++ unsigned long addr;
++
++ switch (remcom_in_buffer[0])
++ {
++ /*
++ * sAA..AA Step one instruction from AA..AA
++ * This will return an error to gdb ..
++ */
++ case 's':
++ case 'c':
++ /* handle the optional parameter */
++ if (kgdb_hex2long (&ptr, &addr))
++ linux_regs->nip = addr;
++
++ atomic_set(&cpu_doing_single_step, -1);
++ /* set the trace bit if we're stepping */
++ if (remcom_in_buffer[0] == 's') {
++#if defined (CONFIG_40x) || defined(CONFIG_BOOKE)
++ mtspr(SPRN_DBCR0, mfspr(SPRN_DBCR0) |
++ DBCR0_IC | DBCR0_IDM);
++ linux_regs->msr |= MSR_DE;
++#else
++ linux_regs->msr |= MSR_SE;
++#endif
++ debugger_step = 1;
++ if (kgdb_contthread)
++ atomic_set(&cpu_doing_single_step,
++ smp_processor_id());
++ }
++ return 0;
++ }
++
++ return -1;
++}
++
++/*
++ * Global data
++ */
++struct kgdb_arch arch_kgdb_ops = {
++ .gdb_bpt_instr = {0x7d, 0x82, 0x10, 0x08},
++};
++
++int kgdb_arch_init(void)
++{
++ debugger = kgdb_debugger;
++ debugger_bpt = kgdb_breakpoint;
++ debugger_sstep = kgdb_singlestep;
++ debugger_iabr_match = kgdb_iabr_match;
++ debugger_dabr_match = kgdb_dabr_match;
++
++ return 0;
++}
++
++arch_initcall(kgdb_arch_init);
+diff -rupN -X ../client-cleanup/dontdiff linux-2.6.18/arch/ppc/kernel/ppc-stub.c linux-2.6.18.kgdb/arch/ppc/kernel/ppc-stub.c
+--- linux-2.6.18/arch/ppc/kernel/ppc-stub.c 2006-09-20 07:42:06.000000000 +0400
++++ linux-2.6.18.kgdb/arch/ppc/kernel/ppc-stub.c 1970-01-01 03:00:00.000000000 +0300
+@@ -1,866 +0,0 @@
+-/*
+- * ppc-stub.c: KGDB support for the Linux kernel.
+- *
+- * adapted from arch/sparc/kernel/sparc-stub.c for the PowerPC
+- * some stuff borrowed from Paul Mackerras' xmon
+- * Copyright (C) 1998 Michael AK Tesch (tesch@cs.wisc.edu)
+- *
+- * Modifications to run under Linux
+- * Copyright (C) 1995 David S. Miller (davem@caip.rutgers.edu)
+- *
+- * This file originally came from the gdb sources, and the
+- * copyright notices have been retained below.
+- */
+-
+-/****************************************************************************
+-
+- THIS SOFTWARE IS NOT COPYRIGHTED
+-
+- HP offers the following for use in the public domain. HP makes no
+- warranty with regard to the software or its performance and the
+- user accepts the software "AS IS" with all faults.
+-
+- HP DISCLAIMS ANY WARRANTIES, EXPRESS OR IMPLIED, WITH REGARD
+- TO THIS SOFTWARE INCLUDING BUT NOT LIMITED TO THE WARRANTIES
+- OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE.
+-
+-****************************************************************************/
+-
+-/****************************************************************************
+- * Header: remcom.c,v 1.34 91/03/09 12:29:49 glenne Exp $
+- *
+- * Module name: remcom.c $
+- * Revision: 1.34 $
+- * Date: 91/03/09 12:29:49 $
+- * Contributor: Lake Stevens Instrument Division$
+- *
+- * Description: low level support for gdb debugger. $
+- *
+- * Considerations: only works on target hardware $
+- *
+- * Written by: Glenn Engel $
+- * ModuleState: Experimental $
+- *
+- * NOTES: See Below $
+- *
+- * Modified for SPARC by Stu Grossman, Cygnus Support.
+- *
+- * This code has been extensively tested on the Fujitsu SPARClite demo board.
+- *
+- * 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 trap #1.
+- *
+- *************
+- *
+- * 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
+- * qOffsets Get section offsets. Reply is Text=xxx;Data=yyy;Bss=zzz
+- *
+- * 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
+- *
+- ****************************************************************************/
+-
+-#include <linux/kernel.h>
+-#include <linux/string.h>
+-#include <linux/mm.h>
+-#include <linux/smp.h>
+-#include <linux/smp_lock.h>
+-#include <linux/init.h>
+-#include <linux/sysrq.h>
+-
+-#include <asm/cacheflush.h>
+-#include <asm/system.h>
+-#include <asm/signal.h>
+-#include <asm/kgdb.h>
+-#include <asm/pgtable.h>
+-#include <asm/ptrace.h>
+-
+-void breakinst(void);
+-
+-/*
+- * 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 remcomInBuffer[BUFMAX];
+-static char remcomOutBuffer[BUFMAX];
+-
+-static int initialized;
+-static int kgdb_active;
+-static int kgdb_started;
+-static u_int fault_jmp_buf[100];
+-static int kdebug;
+-
+-
+-static const char hexchars[]="0123456789abcdef";
+-
+-/* Place where we save old trap entries for restoration - sparc*/
+-/* struct tt_entry kgdb_savettable[256]; */
+-/* typedef void (*trapfunc_t)(void); */
+-
+-static void kgdb_fault_handler(struct pt_regs *regs);
+-static int handle_exception (struct pt_regs *regs);
+-
+-#if 0
+-/* Install an exception handler for kgdb */
+-static void exceptionHandler(int tnum, unsigned int *tfunc)
+-{
+- /* We are dorking with a live trap table, all irqs off */
+-}
+-#endif
+-
+-int
+-kgdb_setjmp(long *buf)
+-{
+- asm ("mflr 0; stw 0,0(%0);"
+- "stw 1,4(%0); stw 2,8(%0);"
+- "mfcr 0; stw 0,12(%0);"
+- "stmw 13,16(%0)"
+- : : "r" (buf));
+- /* XXX should save fp regs as well */
+- return 0;
+-}
+-void
+-kgdb_longjmp(long *buf, int val)
+-{
+- if (val == 0)
+- val = 1;
+- asm ("lmw 13,16(%0);"
+- "lwz 0,12(%0); mtcrf 0x38,0;"
+- "lwz 0,0(%0); lwz 1,4(%0); lwz 2,8(%0);"
+- "mtlr 0; mr 3,%1"
+- : : "r" (buf), "r" (val));
+-}
+-/* 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;
+-}
+-
+-/* 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.
+- */
+-static unsigned char *
+-mem2hex(const char *mem, char *buf, int count)
+-{
+- unsigned char ch;
+- unsigned short tmp_s;
+- unsigned long tmp_l;
+-
+- if (kgdb_setjmp((long*)fault_jmp_buf) == 0) {
+- debugger_fault_handler = kgdb_fault_handler;
+-
+- /* Accessing 16 bit and 32 bit objects in a single
+- ** load instruction is required to avoid bad side
+- ** effects for some IO registers.
+- */
+-
+- if ((count == 2) && (((long)mem & 1) == 0)) {
+- tmp_s = *(unsigned short *)mem;
+- mem += 2;
+- *buf++ = hexchars[(tmp_s >> 12) & 0xf];
+- *buf++ = hexchars[(tmp_s >> 8) & 0xf];
+- *buf++ = hexchars[(tmp_s >> 4) & 0xf];
+- *buf++ = hexchars[tmp_s & 0xf];
+-
+- } else if ((count == 4) && (((long)mem & 3) == 0)) {
+- tmp_l = *(unsigned int *)mem;
+- mem += 4;
+- *buf++ = hexchars[(tmp_l >> 28) & 0xf];
+- *buf++ = hexchars[(tmp_l >> 24) & 0xf];
+- *buf++ = hexchars[(tmp_l >> 20) & 0xf];
+- *buf++ = hexchars[(tmp_l >> 16) & 0xf];
+- *buf++ = hexchars[(tmp_l >> 12) & 0xf];
+- *buf++ = hexchars[(tmp_l >> 8) & 0xf];
+- *buf++ = hexchars[(tmp_l >> 4) & 0xf];
+- *buf++ = hexchars[tmp_l & 0xf];
+-
+- } else {
+- while (count-- > 0) {
+- ch = *mem++;
+- *buf++ = hexchars[ch >> 4];
+- *buf++ = hexchars[ch & 0xf];
+- }
+- }
+-
+- } else {
+- /* error condition */
+- }
+- debugger_fault_handler = NULL;
+- *buf = 0;
+- return buf;
+-}
+-
+-/* convert the hex array pointed to by buf into binary to be placed in mem
+- * return a pointer to the character AFTER the last byte written.
+-*/
+-static char *
+-hex2mem(char *buf, char *mem, int count)
+-{
+- unsigned char ch;
+- int i;
+- char *orig_mem;
+- unsigned short tmp_s;
+- unsigned long tmp_l;
+-
+- orig_mem = mem;
+-
+- if (kgdb_setjmp((long*)fault_jmp_buf) == 0) {
+- debugger_fault_handler = kgdb_fault_handler;
+-
+- /* Accessing 16 bit and 32 bit objects in a single
+- ** store instruction is required to avoid bad side
+- ** effects for some IO registers.
+- */
+-
+- if ((count == 2) && (((long)mem & 1) == 0)) {
+- tmp_s = hex(*buf++) << 12;
+- tmp_s |= hex(*buf++) << 8;
+- tmp_s |= hex(*buf++) << 4;
+- tmp_s |= hex(*buf++);
+-
+- *(unsigned short *)mem = tmp_s;
+- mem += 2;
+-
+- } else if ((count == 4) && (((long)mem & 3) == 0)) {
+- tmp_l = hex(*buf++) << 28;
+- tmp_l |= hex(*buf++) << 24;
+- tmp_l |= hex(*buf++) << 20;
+- tmp_l |= hex(*buf++) << 16;
+- tmp_l |= hex(*buf++) << 12;
+- tmp_l |= hex(*buf++) << 8;
+- tmp_l |= hex(*buf++) << 4;
+- tmp_l |= hex(*buf++);
+-
+- *(unsigned long *)mem = tmp_l;
+- mem += 4;
+-
+- } else {
+- for (i=0; i<count; i++) {
+- ch = hex(*buf++) << 4;
+- ch |= hex(*buf++);
+- *mem++ = ch;
+- }
+- }
+-
+-
+- /*
+- ** Flush the data cache, invalidate the instruction cache.
+- */
+- flush_icache_range((int)orig_mem, (int)orig_mem + count - 1);
+-
+- } else {
+- /* error condition */
+- }
+- debugger_fault_handler = NULL;
+- return mem;
+-}
+-
+-/*
+- * 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;
+-
+- if (kgdb_setjmp((long*)fault_jmp_buf) == 0) {
+- debugger_fault_handler = kgdb_fault_handler;
+- while (**ptr) {
+- hexValue = hex(**ptr);
+- if (hexValue < 0)
+- break;
+-
+- *intValue = (*intValue << 4) | hexValue;
+- numChars ++;
+-
+- (*ptr)++;
+- }
+- } else {
+- /* error condition */
+- }
+- debugger_fault_handler = NULL;
+-
+- return (numChars);
+-}
+-
+-/* 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() & 0x7f;
+- 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 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(unsigned char *buffer)
+-{
+- unsigned char checksum;
+- int count;
+- unsigned char ch, recv;
+-
+- /* $<packet info>#<checksum>. */
+- do {
+- putDebugChar('$');
+- checksum = 0;
+- count = 0;
+-
+- while ((ch = buffer[count])) {
+- putDebugChar(ch);
+- checksum += ch;
+- count += 1;
+- }
+-
+- putDebugChar('#');
+- putDebugChar(hexchars[checksum >> 4]);
+- putDebugChar(hexchars[checksum & 0xf]);
+- recv = getDebugChar();
+- } while ((recv & 0x7f) != '+');
+-}
+-
+-static void kgdb_flush_cache_all(void)
+-{
+- flush_instruction_cache();
+-}
+-
+-/* Set up exception handlers for tracing and breakpoints
+- * [could be called kgdb_init()]
+- */
+-void set_debug_traps(void)
+-{
+-#if 0
+- unsigned char c;
+-
+- save_and_cli(flags);
+-
+- /* In case GDB is started before us, ack any packets (presumably
+- * "$?#xx") sitting there.
+- *
+- * I've found this code causes more problems than it solves,
+- * so that's why it's commented out. GDB seems to work fine
+- * now starting either before or after the kernel -bwb
+- */
+-
+- while((c = getDebugChar()) != '$');
+- while((c = getDebugChar()) != '#');
+- c = getDebugChar(); /* eat first csum byte */
+- c = getDebugChar(); /* eat second csum byte */
+- putDebugChar('+'); /* ack it */
+-#endif
+- debugger = kgdb;
+- debugger_bpt = kgdb_bpt;
+- debugger_sstep = kgdb_sstep;
+- debugger_iabr_match = kgdb_iabr_match;
+- debugger_dabr_match = kgdb_dabr_match;
+-
+- initialized = 1;
+-}
+-
+-static void kgdb_fault_handler(struct pt_regs *regs)
+-{
+- kgdb_longjmp((long*)fault_jmp_buf, 1);
+-}
+-
+-int kgdb_bpt(struct pt_regs *regs)
+-{
+- return handle_exception(regs);
+-}
+-
+-int kgdb_sstep(struct pt_regs *regs)
+-{
+- return handle_exception(regs);
+-}
+-
+-void kgdb(struct pt_regs *regs)
+-{
+- handle_exception(regs);
+-}
+-
+-int kgdb_iabr_match(struct pt_regs *regs)
+-{
+- printk(KERN_ERR "kgdb doesn't support iabr, what?!?\n");
+- return handle_exception(regs);
+-}
+-
+-int kgdb_dabr_match(struct pt_regs *regs)
+-{
+- printk(KERN_ERR "kgdb doesn't support dabr, what?!?\n");
+- return handle_exception(regs);
+-}
+-
+-/* Convert the hardware trap type code to a unix signal number. */
+-/*
+- * This table contains the mapping between PowerPC hardware trap types, and
+- * signals, which are primarily what GDB understands.
+- */
+-static struct hard_trap_info
+-{
+- unsigned int tt; /* Trap type code for powerpc */
+- unsigned char signo; /* Signal that we map this trap into */
+-} hard_trap_info[] = {
+-#if defined(CONFIG_40x) || defined(CONFIG_BOOKE)
+- { 0x100, SIGINT }, /* critical input interrupt */
+- { 0x200, SIGSEGV }, /* machine check */
+- { 0x300, SIGSEGV }, /* data storage */
+- { 0x400, SIGBUS }, /* instruction storage */
+- { 0x500, SIGINT }, /* interrupt */
+- { 0x600, SIGBUS }, /* alignment */
+- { 0x700, SIGILL }, /* program */
+- { 0x800, SIGILL }, /* reserved */
+- { 0x900, SIGILL }, /* reserved */
+- { 0xa00, SIGILL }, /* reserved */
+- { 0xb00, SIGILL }, /* reserved */
+- { 0xc00, SIGCHLD }, /* syscall */
+- { 0xd00, SIGILL }, /* reserved */
+- { 0xe00, SIGILL }, /* reserved */
+- { 0xf00, SIGILL }, /* reserved */
+- /*
+- ** 0x1000 PIT
+- ** 0x1010 FIT
+- ** 0x1020 watchdog
+- ** 0x1100 data TLB miss
+- ** 0x1200 instruction TLB miss
+- */
+- { 0x2002, SIGTRAP}, /* debug */
+-#else
+- { 0x200, SIGSEGV }, /* machine check */
+- { 0x300, SIGSEGV }, /* address error (store) */
+- { 0x400, SIGBUS }, /* instruction bus error */
+- { 0x500, SIGINT }, /* interrupt */
+- { 0x600, SIGBUS }, /* alingment */
+- { 0x700, SIGTRAP }, /* breakpoint trap */
+- { 0x800, SIGFPE }, /* fpu unavail */
+- { 0x900, SIGALRM }, /* decrementer */
+- { 0xa00, SIGILL }, /* reserved */
+- { 0xb00, SIGILL }, /* reserved */
+- { 0xc00, SIGCHLD }, /* syscall */
+- { 0xd00, SIGTRAP }, /* single-step/watch */
+- { 0xe00, SIGFPE }, /* fp assist */
+-#endif
+- { 0, 0} /* Must be last */
+-
+-};
+-
+-static int computeSignal(unsigned 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 */
+-}
+-
+-#define PC_REGNUM 64
+-#define SP_REGNUM 1
+-
+-/*
+- * This function does all command processing for interfacing to gdb.
+- */
+-static int
+-handle_exception (struct pt_regs *regs)
+-{
+- int sigval;
+- int addr;
+- int length;
+- char *ptr;
+- unsigned int msr;
+-
+- /* We don't handle user-mode breakpoints. */
+- if (user_mode(regs))
+- return 0;
+-
+- if (debugger_fault_handler) {
+- debugger_fault_handler(regs);
+- panic("kgdb longjump failed!\n");
+- }
+- if (kgdb_active) {
+- printk(KERN_ERR "interrupt while in kgdb, returning\n");
+- return 0;
+- }
+-
+- kgdb_active = 1;
+- kgdb_started = 1;
+-
+-#ifdef KGDB_DEBUG
+- printk("kgdb: entering handle_exception; trap [0x%x]\n",
+- (unsigned int)regs->trap);
+-#endif
+-
+- kgdb_interruptible(0);
+- lock_kernel();
+- msr = mfmsr();
+- mtmsr(msr & ~MSR_EE); /* disable interrupts */
+-
+- if (regs->nip == (unsigned long)breakinst) {
+- /* Skip over breakpoint trap insn */
+- regs->nip += 4;
+- }
+-
+- /* reply to host that an exception has occurred */
+- sigval = computeSignal(regs->trap);
+- ptr = remcomOutBuffer;
+-
+- *ptr++ = 'T';
+- *ptr++ = hexchars[sigval >> 4];
+- *ptr++ = hexchars[sigval & 0xf];
+- *ptr++ = hexchars[PC_REGNUM >> 4];
+- *ptr++ = hexchars[PC_REGNUM & 0xf];
+- *ptr++ = ':';
+- ptr = mem2hex((char *)®s->nip, ptr, 4);
+- *ptr++ = ';';
+- *ptr++ = hexchars[SP_REGNUM >> 4];
+- *ptr++ = hexchars[SP_REGNUM & 0xf];
+- *ptr++ = ':';
+- ptr = mem2hex(((char *)regs) + SP_REGNUM*4, ptr, 4);
+- *ptr++ = ';';
+- *ptr++ = 0;
+-
+- putpacket(remcomOutBuffer);
+- if (kdebug)
+- printk("remcomOutBuffer: %s\n", remcomOutBuffer);
+-
+- /* XXX We may want to add some features dealing with poking the
+- * XXX page tables, ... (look at sparc-stub.c for more info)
+- * XXX also required hacking to the gdb sources directly...
+- */
+-
+- while (1) {
+- remcomOutBuffer[0] = 0;
+-
+- getpacket(remcomInBuffer);
+- switch (remcomInBuffer[0]) {
+- case '?': /* report most recent signal */
+- remcomOutBuffer[0] = 'S';
+- remcomOutBuffer[1] = hexchars[sigval >> 4];
+- remcomOutBuffer[2] = hexchars[sigval & 0xf];
+- remcomOutBuffer[3] = 0;
+- break;
+-#if 0
+- case 'q': /* this screws up gdb for some reason...*/
+- {
+- extern long _start, sdata, __bss_start;
+-
+- ptr = &remcomInBuffer[1];
+- if (strncmp(ptr, "Offsets", 7) != 0)
+- break;
+-
+- ptr = remcomOutBuffer;
+- sprintf(ptr, "Text=%8.8x;Data=%8.8x;Bss=%8.8x",
+- &_start, &sdata, &__bss_start);
+- break;
+- }
+-#endif
+- case 'd':
+- /* toggle debug flag */
+- kdebug ^= 1;
+- break;
+-
+- case 'g': /* return the value of the CPU registers.
+- * some of them are non-PowerPC names :(
+- * they are stored in gdb like:
+- * struct {
+- * u32 gpr[32];
+- * f64 fpr[32];
+- * u32 pc, ps, cnd, lr; (ps=msr)
+- * u32 cnt, xer, mq;
+- * }
+- */
+- {
+- int i;
+- ptr = remcomOutBuffer;
+- /* General Purpose Regs */
+- ptr = mem2hex((char *)regs, ptr, 32 * 4);
+- /* Floating Point Regs - FIXME */
+- /*ptr = mem2hex((char *), ptr, 32 * 8);*/
+- for(i=0; i<(32*8*2); i++) { /* 2chars/byte */
+- ptr[i] = '0';
+- }
+- ptr += 32*8*2;
+- /* pc, msr, cr, lr, ctr, xer, (mq is unused) */
+- ptr = mem2hex((char *)®s->nip, ptr, 4);
+- ptr = mem2hex((char *)®s->msr, ptr, 4);
+- ptr = mem2hex((char *)®s->ccr, ptr, 4);
+- ptr = mem2hex((char *)®s->link, ptr, 4);
+- ptr = mem2hex((char *)®s->ctr, ptr, 4);
+- ptr = mem2hex((char *)®s->xer, ptr, 4);
+- }
+- break;
+-
+- case 'G': /* set the value of the CPU registers */
+- {
+- ptr = &remcomInBuffer[1];
+-
+- /*
+- * If the stack pointer has moved, you should pray.
+- * (cause only god can help you).
+- */
+-
+- /* General Purpose Regs */
+- hex2mem(ptr, (char *)regs, 32 * 4);
+-
+- /* Floating Point Regs - FIXME?? */
+- /*ptr = hex2mem(ptr, ??, 32 * 8);*/
+- ptr += 32*8*2;
+-
+- /* pc, msr, cr, lr, ctr, xer, (mq is unused) */
+- ptr = hex2mem(ptr, (char *)®s->nip, 4);
+- ptr = hex2mem(ptr, (char *)®s->msr, 4);
+- ptr = hex2mem(ptr, (char *)®s->ccr, 4);
+- ptr = hex2mem(ptr, (char *)®s->link, 4);
+- ptr = hex2mem(ptr, (char *)®s->ctr, 4);
+- ptr = hex2mem(ptr, (char *)®s->xer, 4);
+-
+- strcpy(remcomOutBuffer,"OK");
+- }
+- break;
+- case 'H':
+- /* don't do anything, yet, just acknowledge */
+- hexToInt(&ptr, &addr);
+- strcpy(remcomOutBuffer,"OK");
+- break;
+-
+- case 'm': /* mAA..AA,LLLL Read LLLL bytes at address AA..AA */
+- /* Try to read %x,%x. */
+-
+- ptr = &remcomInBuffer[1];
+-
+- if (hexToInt(&ptr, &addr) && *ptr++ == ','
+- && hexToInt(&ptr, &length)) {
+- if (mem2hex((char *)addr, remcomOutBuffer,
+- length))
+- break;
+- strcpy(remcomOutBuffer, "E03");
+- } else
+- strcpy(remcomOutBuffer, "E01");
+- break;
+-
+- case 'M': /* MAA..AA,LLLL: Write LLLL bytes at address AA.AA return OK */
+- /* Try to read '%x,%x:'. */
+-
+- ptr = &remcomInBuffer[1];
+-
+- if (hexToInt(&ptr, &addr) && *ptr++ == ','
+- && hexToInt(&ptr, &length)
+- && *ptr++ == ':') {
+- if (hex2mem(ptr, (char *)addr, length))
+- strcpy(remcomOutBuffer, "OK");
+- else
+- strcpy(remcomOutBuffer, "E03");
+- flush_icache_range(addr, addr+length);
+- } else
+- strcpy(remcomOutBuffer, "E02");
+- break;
+-
+-
+- case 'k': /* kill the program, actually just continue */
+- case 'c': /* cAA..AA Continue; address AA..AA optional */
+- /* try to read optional parameter, pc unchanged if no parm */
+-
+- ptr = &remcomInBuffer[1];
+- if (hexToInt(&ptr, &addr))
+- regs->nip = addr;
+-
+-/* Need to flush the instruction cache here, as we may have deposited a
+- * breakpoint, and the icache probably has no way of knowing that a data ref to
+- * some location may have changed something that is in the instruction cache.
+- */
+- kgdb_flush_cache_all();
+- mtmsr(msr);
+-
+- kgdb_interruptible(1);
+- unlock_kernel();
+- kgdb_active = 0;
+- if (kdebug) {
+- printk("remcomInBuffer: %s\n", remcomInBuffer);
+- printk("remcomOutBuffer: %s\n", remcomOutBuffer);
+- }
+- return 1;
+-
+- case 's':
+- kgdb_flush_cache_all();
+-#if defined(CONFIG_40x) || defined(CONFIG_BOOKE)
+- mtspr(SPRN_DBCR0, mfspr(SPRN_DBCR0) | DBCR0_IC);
+- regs->msr |= MSR_DE;
+-#else
+- regs->msr |= MSR_SE;
+-#endif
+- unlock_kernel();
+- kgdb_active = 0;
+- if (kdebug) {
+- printk("remcomInBuffer: %s\n", remcomInBuffer);
+- printk("remcomOutBuffer: %s\n", remcomOutBuffer);
+- }
+- return 1;
+-
+- case 'r': /* Reset (if user process..exit ???)*/
+- panic("kgdb reset.");
+- break;
+- } /* switch */
+- if (remcomOutBuffer[0] && kdebug) {
+- printk("remcomInBuffer: %s\n", remcomInBuffer);
+- printk("remcomOutBuffer: %s\n", remcomOutBuffer);
+- }
+- /* reply to the request */
+- putpacket(remcomOutBuffer);
+- } /* while(1) */
+-}
+-
+-/* 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) {
+- printk("breakpoint() called b4 kgdb init\n");
+- return;
+- }
+-
+- asm(" .globl breakinst \n\
+- breakinst: .long 0x7d821008");
+-}
+-
+-#ifdef CONFIG_KGDB_CONSOLE
+-/* Output string in GDB O-packet format if GDB has connected. If nothing
+- output, returns 0 (caller must then handle output). */
+-int
+-kgdb_output_string (const char* s, unsigned int count)
+-{
+- char buffer[512];
+-
+- if (!kgdb_started)
+- return 0;
+-
+- count = (count <= (sizeof(buffer) / 2 - 2))
+- ? count : (sizeof(buffer) / 2 - 2);
+-
+- buffer[0] = 'O';
+- mem2hex (s, &buffer[1], count);
+- putpacket(buffer);
+-
+- return 1;
+-}
+-#endif
+-
+-static void sysrq_handle_gdb(int key, struct pt_regs *pt_regs,
+- struct tty_struct *tty)
+-{
+- printk("Entering GDB stub\n");
+- breakpoint();
+-}
+-static struct sysrq_key_op sysrq_gdb_op = {
+- .handler = sysrq_handle_gdb,
+- .help_msg = "Gdb",
+- .action_msg = "GDB",
+-};
+-
+-static int gdb_register_sysrq(void)
+-{
+- printk("Registering GDB sysrq handler\n");
+- register_sysrq_key('g', &sysrq_gdb_op);
+- return 0;
+-}
+-module_init(gdb_register_sysrq);
+diff -rupN -X ../client-cleanup/dontdiff linux-2.6.18/arch/ppc/kernel/setup.c linux-2.6.18.kgdb/arch/ppc/kernel/setup.c
+--- linux-2.6.18/arch/ppc/kernel/setup.c 2006-09-20 07:42:06.000000000 +0400
++++ linux-2.6.18.kgdb/arch/ppc/kernel/setup.c 2008-06-10 16:19:22.000000000 +0400
+@@ -47,10 +47,6 @@
+ #include <asm/ppc_sys.h>
+ #endif
+
+-#if defined CONFIG_KGDB
+-#include <asm/kgdb.h>
+-#endif
+-
+ extern void platform_init(unsigned long r3, unsigned long r4,
+ unsigned long r5, unsigned long r6, unsigned long r7);
+ extern void identify_cpu(unsigned long offset, unsigned long cpu);
+@@ -504,18 +500,6 @@ void __init setup_arch(char **cmdline_p)
+ #endif /* CONFIG_XMON */
+ if ( ppc_md.progress ) ppc_md.progress("setup_arch: enter", 0x3eab);
+
+-#if defined(CONFIG_KGDB)
+- if (ppc_md.kgdb_map_scc)
+- ppc_md.kgdb_map_scc();
+- set_debug_traps();
+- if (strstr(cmd_line, "gdb")) {
+- if (ppc_md.progress)
+- ppc_md.progress("setup_arch: kgdb breakpoint", 0x4000);
+- printk("kgdb breakpoint activated\n");
+- breakpoint();
+- }
+-#endif
+-
+ /*
+ * Set cache line size based on type of cpu as a default.
+ * Systems with OF can look in the properties on the cpu node(s)
+diff -rupN -X ../client-cleanup/dontdiff linux-2.6.18/arch/ppc/mm/fault.c linux-2.6.18.kgdb/arch/ppc/mm/fault.c
+--- linux-2.6.18/arch/ppc/mm/fault.c 2006-09-20 07:42:06.000000000 +0400
++++ linux-2.6.18.kgdb/arch/ppc/mm/fault.c 2008-06-10 16:19:22.000000000 +0400
+@@ -25,6 +25,7 @@
+ #include <linux/interrupt.h>
+ #include <linux/highmem.h>
+ #include <linux/module.h>
++#include <linux/kgdb.h>
+
+ #include <asm/page.h>
+ #include <asm/pgtable.h>
+@@ -329,6 +330,14 @@ bad_page_fault(struct pt_regs *regs, uns
+ return;
+ }
+
++#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
++
+ /* kernel has accessed a bad area */
+ #if defined(CONFIG_XMON) || defined(CONFIG_KGDB)
+ if (debugger_kernel_faults)
+diff -rupN -X ../client-cleanup/dontdiff linux-2.6.18/arch/ppc/platforms/4xx/bubinga.c linux-2.6.18.kgdb/arch/ppc/platforms/4xx/bubinga.c
+--- linux-2.6.18/arch/ppc/platforms/4xx/bubinga.c 2006-09-20 07:42:06.000000000 +0400
++++ linux-2.6.18.kgdb/arch/ppc/platforms/4xx/bubinga.c 2008-06-10 16:19:22.000000000 +0400
+@@ -4,7 +4,7 @@
+ * Author: SAW (IBM), derived from walnut.c.
+ * Maintained by MontaVista Software <source@mvista.com>
+ *
+- * 2003 (c) MontaVista Softare Inc. This file is licensed under the
++ * 2003-2004 (c) MontaVista Softare 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.
+@@ -100,17 +100,26 @@ bubinga_early_serial_map(void)
+ port.flags = UPF_BOOT_AUTOCONF | UPF_SKIP_TEST;
+ port.line = 0;
+
+- if (early_serial_setup(&port) != 0) {
++#ifdef CONFIG_SERIAL_8250
++ if (early_serial_setup(&port) != 0)
+ printk("Early serial init of port 0 failed\n");
+- }
++#endif
++
++#ifdef CONFIG_KGDB_8250
++ kgdb8250_add_port(0, &port);
++#endif
+
+ port.membase = (void*)ACTING_UART1_IO_BASE;
+ port.irq = ACTING_UART1_INT;
+ port.line = 1;
+
+- if (early_serial_setup(&port) != 0) {
++#ifdef CONFIG_SERIAL_8250
++ if (early_serial_setup(&port) != 0)
+ printk("Early serial init of port 1 failed\n");
+- }
++#endif
++#ifdef CONFIG_KGDB_8250
++ kgdb8250_add_port(1, &port);
++#endif
+ }
+
+ void __init
+@@ -255,8 +264,4 @@ platform_init(unsigned long r3, unsigned
+ ppc_md.nvram_read_val = todc_direct_read_val;
+ ppc_md.nvram_write_val = todc_direct_write_val;
+ #endif
+-#ifdef CONFIG_KGDB
+- ppc_md.early_serial_map = bubinga_early_serial_map;
+-#endif
+ }
+-
+diff -rupN -X ../client-cleanup/dontdiff linux-2.6.18/arch/ppc/platforms/4xx/ebony.c linux-2.6.18.kgdb/arch/ppc/platforms/4xx/ebony.c
+--- linux-2.6.18/arch/ppc/platforms/4xx/ebony.c 2006-09-20 07:42:06.000000000 +0400
++++ linux-2.6.18.kgdb/arch/ppc/platforms/4xx/ebony.c 2008-06-10 16:19:22.000000000 +0400
+@@ -32,6 +32,7 @@
+ #include <linux/tty.h>
+ #include <linux/serial.h>
+ #include <linux/serial_core.h>
++#include <linux/kgdb.h>
+
+ #include <asm/system.h>
+ #include <asm/pgtable.h>
+@@ -226,14 +227,20 @@ ebony_early_serial_map(void)
+ port.flags = UPF_BOOT_AUTOCONF | UPF_SKIP_TEST;
+ port.line = 0;
+
+- if (early_serial_setup(&port) != 0) {
++#ifdef CONFIG_SERIAL_8250
++ if (early_serial_setup(&port) != 0)
+ printk("Early serial init of port 0 failed\n");
+- }
++#endif
+
+-#if defined(CONFIG_SERIAL_TEXT_DEBUG) || defined(CONFIG_KGDB)
++#ifdef CONFIG_SERIAL_TEXT_DEBUG
+ /* Configure debug serial access */
+ gen550_init(0, &port);
++#endif
++#ifdef CONFIG_KGDB_8250
++ kgdb8250_add_port(0, &port);
++#endif
+
++#if defined(CONFIG_SERIAL_TEXT_DEBUG) || defined(CONFIG_KGDB_8250)
+ /* Purge TLB entry added in head_44x.S for early serial access */
+ _tlbie(UART0_IO_BASE);
+ #endif
+@@ -243,14 +250,18 @@ ebony_early_serial_map(void)
+ port.uartclk = clocks.uart1;
+ port.line = 1;
+
+- if (early_serial_setup(&port) != 0) {
++#ifdef CONFIG_SERIAL_8250
++ if (early_serial_setup(&port) != 1)
+ printk("Early serial init of port 1 failed\n");
+- }
++#endif
+
+-#if defined(CONFIG_SERIAL_TEXT_DEBUG) || defined(CONFIG_KGDB)
++#ifdef CONFIG_SERIAL_TEXT_DEBUG
+ /* Configure debug serial access */
+ gen550_init(1, &port);
+ #endif
++#ifdef CONFIG_KGDB_8250
++ kgdb8250_add_port(1, &port);
++#endif
+ }
+
+ static void __init
+@@ -327,8 +338,4 @@ void __init platform_init(unsigned long
+
+ ppc_md.nvram_read_val = todc_direct_read_val;
+ ppc_md.nvram_write_val = todc_direct_write_val;
+-#ifdef CONFIG_KGDB
+- ppc_md.early_serial_map = ebony_early_serial_map;
+-#endif
+ }
+-
+diff -rupN -X ../client-cleanup/dontdiff linux-2.6.18/arch/ppc/platforms/4xx/ocotea.c linux-2.6.18.kgdb/arch/ppc/platforms/4xx/ocotea.c
+--- linux-2.6.18/arch/ppc/platforms/4xx/ocotea.c 2006-09-20 07:42:06.000000000 +0400
++++ linux-2.6.18.kgdb/arch/ppc/platforms/4xx/ocotea.c 2008-06-10 16:19:22.000000000 +0400
+@@ -30,6 +30,7 @@
+ #include <linux/tty.h>
+ #include <linux/serial.h>
+ #include <linux/serial_core.h>
++#include <linux/kgdb.h>
+
+ #include <asm/system.h>
+ #include <asm/pgtable.h>
+@@ -249,14 +250,20 @@ ocotea_early_serial_map(void)
+ port.flags = UPF_BOOT_AUTOCONF | UPF_SKIP_TEST;
+ port.line = 0;
+
+- if (early_serial_setup(&port) != 0) {
++#ifdef CONFIG_SERIAL_8250
++ if (early_serial_setup(&port) != 0)
+ printk("Early serial init of port 0 failed\n");
+- }
++#endif
+
+-#if defined(CONFIG_SERIAL_TEXT_DEBUG) || defined(CONFIG_KGDB)
++#ifdef CONFIG_SERIAL_TEXT_DEBUG
+ /* Configure debug serial access */
+ gen550_init(0, &port);
++#endif
++#ifdef CONFIG_KGDB_8250
++ kgdb8250_add_port(0, &port);
++#endif
+
++#if defined(CONFIG_SERIAL_TEXT_DEBUG) || defined(CONFIG_KGDB_8250)
+ /* Purge TLB entry added in head_44x.S for early serial access */
+ _tlbie(UART0_IO_BASE);
+ #endif
+@@ -266,14 +273,18 @@ ocotea_early_serial_map(void)
+ port.uartclk = clocks.uart1;
+ port.line = 1;
+
+- if (early_serial_setup(&port) != 0) {
++#ifdef CONFIG_SERIAL_8250
++ if (early_serial_setup(&port) != 1)
+ printk("Early serial init of port 1 failed\n");
+- }
++#endif
+
+-#if defined(CONFIG_SERIAL_TEXT_DEBUG) || defined(CONFIG_KGDB)
++#ifdef CONFIG_SERIAL_TEXT_DEBUG
+ /* Configure debug serial access */
+ gen550_init(1, &port);
+ #endif
++#ifdef CONFIG_KGDB_8250
++ kgdb8250_add_port(1, &port);
++#endif
+ }
+
+ static void __init
+@@ -343,8 +354,5 @@ void __init platform_init(unsigned long
+
+ ppc_md.nvram_read_val = todc_direct_read_val;
+ ppc_md.nvram_write_val = todc_direct_write_val;
+-#ifdef CONFIG_KGDB
+- ppc_md.early_serial_map = ocotea_early_serial_map;
+-#endif
+ ppc_md.init = ocotea_init;
+ }
+diff -rupN -X ../client-cleanup/dontdiff linux-2.6.18/arch/ppc/platforms/4xx/xilinx_ml300.c linux-2.6.18.kgdb/arch/ppc/platforms/4xx/xilinx_ml300.c
+--- linux-2.6.18/arch/ppc/platforms/4xx/xilinx_ml300.c 2006-09-20 07:42:06.000000000 +0400
++++ linux-2.6.18.kgdb/arch/ppc/platforms/4xx/xilinx_ml300.c 2008-06-10 16:19:22.000000000 +0400
+@@ -41,9 +41,6 @@
+ * ppc4xx_map_io arch/ppc/syslib/ppc4xx_setup.c
+ * start_kernel init/main.c
+ * setup_arch arch/ppc/kernel/setup.c
+- * #if defined(CONFIG_KGDB)
+- * *ppc_md.kgdb_map_scc() == gen550_kgdb_map_scc
+- * #endif
+ * *ppc_md.setup_arch == ml300_setup_arch this file
+ * ppc4xx_setup_arch arch/ppc/syslib/ppc4xx_setup.c
+ * ppc4xx_find_bridges arch/ppc/syslib/ppc405_pci.c
+@@ -117,7 +114,6 @@ ml300_early_serial_init(int num, struct
+ void __init
+ ml300_early_serial_map(void)
+ {
+-#ifdef CONFIG_SERIAL_8250
+ struct plat_serial8250_port *pdata;
+ int i = 0;
+
+@@ -129,7 +125,14 @@ ml300_early_serial_map(void)
+ pdata++;
+ i++;
+ }
+-#endif /* CONFIG_SERIAL_8250 */
++#ifdef CONFIG_SERIAL_8250
++ if (early_serial_setup(&port) != 0)
++ printk("Early serial init of port %d failed\n", i);
++#endif
++
++#ifdef CONFIG_KGDB_8250
++ kgdb8250_add_port(i, &port)
++#endif
+ }
+
+ void __init
+@@ -165,9 +168,4 @@ platform_init(unsigned long r3, unsigned
+ #if defined(XPAR_POWER_0_POWERDOWN_BASEADDR)
+ ppc_md.power_off = xilinx_power_off;
+ #endif
+-
+-#ifdef CONFIG_KGDB
+- ppc_md.early_serial_map = ml300_early_serial_map;
+-#endif
+ }
+-
+diff -rupN -X ../client-cleanup/dontdiff linux-2.6.18/arch/ppc/platforms/85xx/sbc8560.c linux-2.6.18.kgdb/arch/ppc/platforms/85xx/sbc8560.c
+--- linux-2.6.18/arch/ppc/platforms/85xx/sbc8560.c 2006-09-20 07:42:06.000000000 +0400
++++ linux-2.6.18.kgdb/arch/ppc/platforms/85xx/sbc8560.c 2008-06-10 16:19:22.000000000 +0400
+@@ -50,7 +50,6 @@
+ #include <syslib/ppc85xx_common.h>
+ #include <syslib/ppc85xx_setup.h>
+
+-#ifdef CONFIG_SERIAL_8250
+ static void __init
+ sbc8560_early_serial_map(void)
+ {
+@@ -66,12 +65,16 @@ sbc8560_early_serial_map(void)
+ uart_req.membase = ioremap(uart_req.mapbase, MPC85xx_UART0_SIZE);
+ uart_req.type = PORT_16650;
+
+-#if defined(CONFIG_SERIAL_TEXT_DEBUG) || defined(CONFIG_KGDB)
+- gen550_init(0, &uart_req);
++#ifdef CONFIG_SERIAL_8250
++ if (early_serial_setup(&uart_req) != 0)
++ printk("Early serial init of port 0 failed\n");
++#endif
++#ifdef CONFIG_SERIAL_TEXT_DEBUG
++ gen550_init(0, &uart_req);
++#endif
++#ifdef CONFIG_KGDB_8250
++ kgdb8250_add_port(0, &uart_req);
+ #endif
+-
+- if (early_serial_setup(&uart_req) != 0)
+- printk("Early serial init of port 0 failed\n");
+
+ /* Assume early_serial_setup() doesn't modify uart_req */
+ uart_req.line = 1;
+@@ -79,14 +82,17 @@ sbc8560_early_serial_map(void)
+ uart_req.membase = ioremap(uart_req.mapbase, MPC85xx_UART1_SIZE);
+ uart_req.irq = MPC85xx_IRQ_EXT10;
+
+-#if defined(CONFIG_SERIAL_TEXT_DEBUG) || defined(CONFIG_KGDB)
+- gen550_init(1, &uart_req);
++#ifdef CONFIG_SERIAL_8250
++ if (early_serial_setup(&uart_req) != 0)
++ printk("Early serial init of port 0 failed\n");
+ #endif
+-
+- if (early_serial_setup(&uart_req) != 0)
+- printk("Early serial init of port 1 failed\n");
+-}
++#ifdef CONFIG_SERIAL_TEXT_DEBUG
++ gen550_init(0, &uart_req);
++#endif
++#ifdef CONFIG_KGDB_8250
++ kgdb8250_add_port(0, &uart_req);
+ #endif
++}
+
+ /* ************************************************************************
+ *
+@@ -115,9 +121,7 @@ sbc8560_setup_arch(void)
+ /* setup PCI host bridges */
+ mpc85xx_setup_hose();
+ #endif
+-#ifdef CONFIG_SERIAL_8250
+ sbc8560_early_serial_map();
+-#endif
+ #ifdef CONFIG_SERIAL_TEXT_DEBUG
+ /* Invalidate the entry we stole earlier the serial ports
+ * should be properly mapped */
+diff -rupN -X ../client-cleanup/dontdiff linux-2.6.18/arch/ppc/platforms/chestnut.c linux-2.6.18.kgdb/arch/ppc/platforms/chestnut.c
+--- linux-2.6.18/arch/ppc/platforms/chestnut.c 2006-09-20 07:42:06.000000000 +0400
++++ linux-2.6.18.kgdb/arch/ppc/platforms/chestnut.c 2008-06-10 16:19:22.000000000 +0400
+@@ -492,7 +492,7 @@ chestnut_power_off(void)
+ static void __init
+ chestnut_map_io(void)
+ {
+-#if defined(CONFIG_SERIAL_TEXT_DEBUG) || defined(CONFIG_KGDB)
++#if defined(CONFIG_SERIAL_TEXT_DEBUG) || defined(CONFIG_KGDB_8250)
+ io_block_mapping(CHESTNUT_UART_BASE, CHESTNUT_UART_BASE, 0x100000,
+ _PAGE_IO);
+ #endif
+@@ -566,9 +566,6 @@ platform_init(unsigned long r3, unsigned
+ #if defined(CONFIG_SERIAL_TEXT_DEBUG)
+ ppc_md.progress = gen550_progress;
+ #endif
+-#if defined(CONFIG_KGDB)
+- ppc_md.kgdb_map_scc = gen550_kgdb_map_scc;
+-#endif
+
+ if (ppc_md.progress)
+ ppc_md.progress("chestnut_init(): exit", 0);
+diff -rupN -X ../client-cleanup/dontdiff linux-2.6.18/arch/ppc/platforms/pplus.c linux-2.6.18.kgdb/arch/ppc/platforms/pplus.c
+--- linux-2.6.18/arch/ppc/platforms/pplus.c 2006-09-20 07:42:06.000000000 +0400
++++ linux-2.6.18.kgdb/arch/ppc/platforms/pplus.c 2008-06-10 16:19:22.000000000 +0400
+@@ -893,9 +893,6 @@ platform_init(unsigned long r3, unsigned
+ #ifdef CONFIG_SERIAL_TEXT_DEBUG
+ ppc_md.progress = gen550_progress;
+ #endif /* CONFIG_SERIAL_TEXT_DEBUG */
+-#ifdef CONFIG_KGDB
+- ppc_md.kgdb_map_scc = gen550_kgdb_map_scc;
+-#endif
+ #ifdef CONFIG_SMP
+ smp_ops = &pplus_smp_ops;
+ #endif /* CONFIG_SMP */
+diff -rupN -X ../client-cleanup/dontdiff linux-2.6.18/arch/ppc/platforms/sandpoint.c linux-2.6.18.kgdb/arch/ppc/platforms/sandpoint.c
+--- linux-2.6.18/arch/ppc/platforms/sandpoint.c 2006-09-20 07:42:06.000000000 +0400
++++ linux-2.6.18.kgdb/arch/ppc/platforms/sandpoint.c 2008-06-10 16:19:22.000000000 +0400
+@@ -730,9 +730,6 @@ platform_init(unsigned long r3, unsigned
+ ppc_md.nvram_read_val = todc_mc146818_read_val;
+ ppc_md.nvram_write_val = todc_mc146818_write_val;
+
+-#ifdef CONFIG_KGDB
+- ppc_md.kgdb_map_scc = gen550_kgdb_map_scc;
+-#endif
+ #ifdef CONFIG_SERIAL_TEXT_DEBUG
+ ppc_md.progress = gen550_progress;
+ #endif
+diff -rupN -X ../client-cleanup/dontdiff linux-2.6.18/arch/ppc/platforms/spruce.c linux-2.6.18.kgdb/arch/ppc/platforms/spruce.c
+--- linux-2.6.18/arch/ppc/platforms/spruce.c 2006-09-20 07:42:06.000000000 +0400
++++ linux-2.6.18.kgdb/arch/ppc/platforms/spruce.c 2008-06-10 16:19:22.000000000 +0400
+@@ -178,26 +178,32 @@ spruce_early_serial_map(void)
+ serial_req.membase = (u_char *)UART0_IO_BASE;
+ serial_req.regshift = 0;
+
+-#if defined(CONFIG_KGDB) || defined(CONFIG_SERIAL_TEXT_DEBUG)
+- gen550_init(0, &serial_req);
+-#endif
+ #ifdef CONFIG_SERIAL_8250
+ if (early_serial_setup(&serial_req) != 0)
+ printk("Early serial init of port 0 failed\n");
+ #endif
++#ifdef CONFIG_SERIAL_TEXT_DEBUG
++ gen550_init(0, &serial_req);
++#endif
++#ifdef CONFIG_KGDB_8250
++ kgdb8250_add_port(0, &port);
++#endif
+
+ /* Assume early_serial_setup() doesn't modify serial_req */
+ serial_req.line = 1;
+ serial_req.irq = UART1_INT;
+ serial_req.membase = (u_char *)UART1_IO_BASE;
+
+-#if defined(CONFIG_KGDB) || defined(CONFIG_SERIAL_TEXT_DEBUG)
+- gen550_init(1, &serial_req);
+-#endif
+ #ifdef CONFIG_SERIAL_8250
+ if (early_serial_setup(&serial_req) != 0)
+ printk("Early serial init of port 1 failed\n");
+ #endif
++#ifdef CONFIG_SERIAL_TEXT_DEBUG
++ gen550_init(1, &serial_req);
++#endif
++#ifdef CONFIG_KGDB_8250
++ kgdb8250_add_port(1, &serial_req);
++#endif
+ }
+
+ TODC_ALLOC();
+@@ -316,7 +322,4 @@ platform_init(unsigned long r3, unsigned
+ #ifdef CONFIG_SERIAL_TEXT_DEBUG
+ ppc_md.progress = gen550_progress;
+ #endif /* CONFIG_SERIAL_TEXT_DEBUG */
+-#ifdef CONFIG_KGDB
+- ppc_md.kgdb_map_scc = gen550_kgdb_map_scc;
+-#endif
+ }
+diff -rupN -X ../client-cleanup/dontdiff linux-2.6.18/arch/ppc/syslib/Makefile linux-2.6.18.kgdb/arch/ppc/syslib/Makefile
+--- linux-2.6.18/arch/ppc/syslib/Makefile 2006-09-20 07:42:06.000000000 +0400
++++ linux-2.6.18.kgdb/arch/ppc/syslib/Makefile 2008-06-10 16:19:22.000000000 +0400
+@@ -76,7 +76,6 @@ obj-$(CONFIG_PCI_8260) += m82xx_pci.o p
+ obj-$(CONFIG_8260_PCI9) += m8260_pci_erratum9.o
+ obj-$(CONFIG_CPM2) += cpm2_common.o cpm2_pic.o
+ ifeq ($(CONFIG_PPC_GEN550),y)
+-obj-$(CONFIG_KGDB) += gen550_kgdb.o gen550_dbg.o
+ obj-$(CONFIG_SERIAL_TEXT_DEBUG) += gen550_dbg.o
+ endif
+ ifeq ($(CONFIG_SERIAL_MPSC_CONSOLE),y)
+diff -rupN -X ../client-cleanup/dontdiff linux-2.6.18/arch/ppc/syslib/gen550.h linux-2.6.18.kgdb/arch/ppc/syslib/gen550.h
+--- linux-2.6.18/arch/ppc/syslib/gen550.h 2006-09-20 07:42:06.000000000 +0400
++++ linux-2.6.18.kgdb/arch/ppc/syslib/gen550.h 2008-06-10 16:19:22.000000000 +0400
+@@ -11,4 +11,3 @@
+
+ extern void gen550_progress(char *, unsigned short);
+ extern void gen550_init(int, struct uart_port *);
+-extern void gen550_kgdb_map_scc(void);
+diff -rupN -X ../client-cleanup/dontdiff linux-2.6.18/arch/ppc/syslib/ibm44x_common.c linux-2.6.18.kgdb/arch/ppc/syslib/ibm44x_common.c
+--- linux-2.6.18/arch/ppc/syslib/ibm44x_common.c 2006-09-20 07:42:06.000000000 +0400
++++ linux-2.6.18.kgdb/arch/ppc/syslib/ibm44x_common.c 2008-06-10 16:19:22.000000000 +0400
+@@ -192,9 +192,6 @@ void __init ibm44x_platform_init(unsigne
+ #ifdef CONFIG_SERIAL_TEXT_DEBUG
+ ppc_md.progress = gen550_progress;
+ #endif /* CONFIG_SERIAL_TEXT_DEBUG */
+-#ifdef CONFIG_KGDB
+- ppc_md.kgdb_map_scc = gen550_kgdb_map_scc;
+-#endif
+
+ /*
+ * The Abatron BDI JTAG debugger does not tolerate others
+diff -rupN -X ../client-cleanup/dontdiff linux-2.6.18/arch/ppc/syslib/mv64x60.c linux-2.6.18.kgdb/arch/ppc/syslib/mv64x60.c
+--- linux-2.6.18/arch/ppc/syslib/mv64x60.c 2006-09-20 07:42:06.000000000 +0400
++++ linux-2.6.18.kgdb/arch/ppc/syslib/mv64x60.c 2008-06-10 16:19:22.000000000 +0400
+@@ -241,6 +241,12 @@ static struct resource mv64x60_mpsc0_res
+ .end = MV64x60_IRQ_SDMA_0,
+ .flags = IORESOURCE_IRQ,
+ },
++ [4] = {
++ .name = "mpsc 0 irq",
++ .start = MV64x60_IRQ_MPSC_0,
++ .end = MV64x60_IRQ_MPSC_0,
++ .flags = IORESOURCE_IRQ,
++ },
+ };
+
+ static struct platform_device mpsc0_device = {
+@@ -298,6 +304,12 @@ static struct resource mv64x60_mpsc1_res
+ .end = MV64360_IRQ_SDMA_1,
+ .flags = IORESOURCE_IRQ,
+ },
++ [4] = {
++ .name = "mpsc 1 irq",
++ .start = MV64360_IRQ_MPSC_1,
++ .end = MV64360_IRQ_MPSC_1,
++ .flags = IORESOURCE_IRQ,
++ },
+ };
+
+ static struct platform_device mpsc1_device = {
+@@ -1426,12 +1438,46 @@ mv64x60_pd_fixup(struct mv64x60_handle *
+ static int __init
+ mv64x60_add_pds(void)
+ {
+- return platform_add_devices(mv64x60_pd_devs,
+- ARRAY_SIZE(mv64x60_pd_devs));
++ int i, ret = 0;
++
++ for (i = 0; i < ARRAY_SIZE(mv64x60_pd_devs); i++) {
++ if (mv64x60_pd_devs[i]) {
++ ret = platform_device_register(mv64x60_pd_devs[i]);
++ }
++ if (ret) {
++ while (--i >= 0)
++ platform_device_unregister(mv64x60_pd_devs[i]);
++ break;
++ }
++ }
++ return ret;
+ }
+ arch_initcall(mv64x60_add_pds);
+
+ /*
++ * mv64x60_early_get_pdev_data()
++ *
++ * Get the data associated with a platform device by name and number.
++ */
++struct platform_device * __init
++mv64x60_early_get_pdev_data(const char *name, int id, int remove)
++{
++ int i;
++ struct platform_device *pdev;
++
++ for (i = 0; i <ARRAY_SIZE(mv64x60_pd_devs); i++) {
++ if ((pdev = mv64x60_pd_devs[i]) &&
++ pdev->id == id &&
++ !strcmp(pdev->name, name)) {
++ if (remove)
++ mv64x60_pd_devs[i] = NULL;
++ return pdev;
++ }
++ }
++ return NULL;
++}
++
++/*
+ *****************************************************************************
+ *
+ * GT64260-Specific Routines
+@@ -1764,6 +1810,11 @@ gt64260a_chip_specific_init(struct mv64x
+ r->start = MV64x60_IRQ_SDMA_0;
+ r->end = MV64x60_IRQ_SDMA_0;
+ }
++ if ((r = platform_get_resource(&mpsc1_device, IORESOURCE_IRQ, 1))
++ != NULL) {
++ r->start = GT64260_IRQ_MPSC_1;
++ r->end = GT64260_IRQ_MPSC_1;
++ }
+ #endif
+ }
+
+diff -rupN -X ../client-cleanup/dontdiff linux-2.6.18/arch/ppc/syslib/mv64x60_dbg.c linux-2.6.18.kgdb/arch/ppc/syslib/mv64x60_dbg.c
+--- linux-2.6.18/arch/ppc/syslib/mv64x60_dbg.c 2006-09-20 07:42:06.000000000 +0400
++++ linux-2.6.18.kgdb/arch/ppc/syslib/mv64x60_dbg.c 2008-06-10 16:19:22.000000000 +0400
+@@ -34,7 +34,7 @@ static struct mv64x60_handle mv64x60_dbg
+ void
+ mv64x60_progress_init(u32 base)
+ {
+- mv64x60_dbg_bh.v_base = base;
++ mv64x60_dbg_bh.v_base = (void*)base;
+ return;
+ }
+
+@@ -69,53 +69,3 @@ mv64x60_mpsc_progress(char *s, unsigned
+ return;
+ }
+ #endif /* CONFIG_SERIAL_TEXT_DEBUG */
+-
+-
+-#if defined(CONFIG_KGDB)
+-
+-#if defined(CONFIG_KGDB_TTYS0)
+-#define KGDB_PORT 0
+-#elif defined(CONFIG_KGDB_TTYS1)
+-#define KGDB_PORT 1
+-#else
+-#error "Invalid kgdb_tty port"
+-#endif
+-
+-void
+-putDebugChar(unsigned char c)
+-{
+- mv64x60_polled_putc(KGDB_PORT, (char)c);
+-}
+-
+-int
+-getDebugChar(void)
+-{
+- unsigned char c;
+-
+- while (!mv64x60_polled_getc(KGDB_PORT, &c));
+- return (int)c;
+-}
+-
+-void
+-putDebugString(char* str)
+-{
+- while (*str != '\0') {
+- putDebugChar(*str);
+- str++;
+- }
+- putDebugChar('\r');
+- return;
+-}
+-
+-void
+-kgdb_interruptible(int enable)
+-{
+-}
+-
+-void
+-kgdb_map_scc(void)
+-{
+- if (ppc_md.early_serial_map)
+- ppc_md.early_serial_map();
+-}
+-#endif /* CONFIG_KGDB */
+diff -rupN -X ../client-cleanup/dontdiff linux-2.6.18/arch/ppc/syslib/ppc85xx_setup.c linux-2.6.18.kgdb/arch/ppc/syslib/ppc85xx_setup.c
+--- linux-2.6.18/arch/ppc/syslib/ppc85xx_setup.c 2006-09-20 07:42:06.000000000 +0400
++++ linux-2.6.18.kgdb/arch/ppc/syslib/ppc85xx_setup.c 2008-06-10 16:19:22.000000000 +0400
+@@ -69,7 +69,6 @@ mpc85xx_calibrate_decr(void)
+ mtspr(SPRN_TCR, TCR_DIE);
+ }
+
+-#ifdef CONFIG_SERIAL_8250
+ void __init
+ mpc85xx_early_serial_map(void)
+ {
+@@ -85,7 +84,7 @@ mpc85xx_early_serial_map(void)
+ pdata[0].mapbase += binfo->bi_immr_base;
+ pdata[0].membase = ioremap(pdata[0].mapbase, MPC85xx_UART0_SIZE);
+
+-#if defined(CONFIG_SERIAL_TEXT_DEBUG) || defined(CONFIG_KGDB)
++#if defined(CONFIG_SERIAL_TEXT_DEBUG) || defined(CONFIG_KGDB_8250)
+ memset(&serial_req, 0, sizeof (serial_req));
+ serial_req.iotype = UPIO_MEM;
+ serial_req.mapbase = pdata[0].mapbase;
+@@ -93,18 +92,24 @@ mpc85xx_early_serial_map(void)
+ serial_req.regshift = 0;
+
+ gen550_init(0, &serial_req);
++#ifdef CONFIG_KGDB_8250
++ kgdb8250_add_port(0, &serial_req);
++#endif
+ #endif
+
+ pdata[1].uartclk = binfo->bi_busfreq;
+ pdata[1].mapbase += binfo->bi_immr_base;
+ pdata[1].membase = ioremap(pdata[1].mapbase, MPC85xx_UART0_SIZE);
+
+-#if defined(CONFIG_SERIAL_TEXT_DEBUG) || defined(CONFIG_KGDB)
++#if defined(CONFIG_SERIAL_TEXT_DEBUG) || defined(CONFIG_KGDB_8250)
+ /* Assume gen550_init() doesn't modify serial_req */
+ serial_req.mapbase = pdata[1].mapbase;
+ serial_req.membase = pdata[1].membase;
+
+ gen550_init(1, &serial_req);
++#ifdef CONFIG_KGDB_8250
++ kgdb8250_add_port(1, &serial_req);
++#endif
+ #endif
+ }
+ #endif
+@@ -363,5 +368,3 @@ mpc85xx_setup_hose(void)
+ return;
+ }
+ #endif /* CONFIG_PCI */
+-
+-
+diff -rupN -X ../client-cleanup/dontdiff linux-2.6.18/arch/sh/Kconfig.debug linux-2.6.18.kgdb/arch/sh/Kconfig.debug
+--- linux-2.6.18/arch/sh/Kconfig.debug 2006-09-20 07:42:06.000000000 +0400
++++ linux-2.6.18.kgdb/arch/sh/Kconfig.debug 2008-06-10 16:19:47.000000000 +0400
+@@ -29,96 +29,4 @@ config EARLY_PRINTK
+ This option is only useful porting the kernel to a new machine,
+ when the kernel may crash or hang before the serial console is
+ initialised. If unsure, say N.
+-
+-config KGDB
+- bool "Include KGDB kernel debugger"
+- help
+- Include in-kernel hooks for kgdb, the Linux kernel source level
+- debugger. See <http://kgdb.sourceforge.net/> for more information.
+- Unless you are intending to debug the kernel, say N here.
+-
+-menu "KGDB configuration options"
+- depends on KGDB
+-
+-config MORE_COMPILE_OPTIONS
+- bool "Add any additional compile options"
+- help
+- If you want to add additional CFLAGS to the kernel build, enable this
+- option and then enter what you would like to add in the next question.
+- Note however that -g is already appended with the selection of KGDB.
+-
+-config COMPILE_OPTIONS
+- string "Additional compile arguments"
+- depends on MORE_COMPILE_OPTIONS
+-
+-config KGDB_NMI
+- bool "Enter KGDB on NMI"
+- default n
+-
+-config KGDB_THREAD
+- bool "Include KGDB thread support"
+- default y
+-
+-config SH_KGDB_CONSOLE
+- bool "Console messages through GDB"
+- default n
+-
+-config KGDB_SYSRQ
+- bool "Allow SysRq 'G' to enter KGDB"
+- default y
+-
+-config KGDB_KERNEL_ASSERTS
+- bool "Include KGDB kernel assertions"
+- default n
+-
+-comment "Serial port setup"
+-
+-config KGDB_DEFPORT
+- int "Port number (ttySCn)"
+- default "1"
+-
+-config KGDB_DEFBAUD
+- int "Baud rate"
+- default "115200"
+-
+-choice
+- prompt "Parity"
+- depends on KGDB
+- default KGDB_DEFPARITY_N
+-
+-config KGDB_DEFPARITY_N
+- bool "None"
+-
+-config KGDB_DEFPARITY_E
+- bool "Even"
+-
+-config KGDB_DEFPARITY_O
+- bool "Odd"
+-
+-endchoice
+-
+-choice
+- prompt "Data bits"
+- depends on KGDB
+- default KGDB_DEFBITS_8
+-
+-config KGDB_DEFBITS_8
+- bool "8"
+-
+-config KGDB_DEFBITS_7
+- bool "7"
+-
+-endchoice
+-
+-endmenu
+-
+-config FRAME_POINTER
+- bool "Compile the kernel with frame pointers"
+- default y if KGDB
+- help
+- If you say Y here the resulting kernel image will be slightly larger
+- and slower, but it will give very useful debugging information.
+- If you don't debug the kernel, you can say N, but we may not be able
+- to solve problems without frame pointers.
+-
+ endmenu
+diff -rupN -X ../client-cleanup/dontdiff linux-2.6.18/arch/sh/Makefile linux-2.6.18.kgdb/arch/sh/Makefile
+--- linux-2.6.18/arch/sh/Makefile 2006-09-20 07:42:06.000000000 +0400
++++ linux-2.6.18.kgdb/arch/sh/Makefile 2008-06-10 16:19:47.000000000 +0400
+@@ -43,7 +43,6 @@ cflags-$(CONFIG_CPU_SH4) += -m4 \
+ cflags-$(CONFIG_CPU_SH4A) += $(call cc-option,-m4a-nofpu,)
+
+ cflags-$(CONFIG_SH_DSP) += -Wa,-dsp
+-cflags-$(CONFIG_SH_KGDB) += -g
+
+ cflags-$(CONFIG_MORE_COMPILE_OPTIONS) += \
+ $(shell echo $(CONFIG_COMPILE_OPTIONS) | sed -e 's/"//g')
+diff -rupN -X ../client-cleanup/dontdiff linux-2.6.18/arch/sh/boards/se/7751/setup.c linux-2.6.18.kgdb/arch/sh/boards/se/7751/setup.c
+--- linux-2.6.18/arch/sh/boards/se/7751/setup.c 2006-09-20 07:42:06.000000000 +0400
++++ linux-2.6.18.kgdb/arch/sh/boards/se/7751/setup.c 2008-06-10 16:19:47.000000000 +0400
+@@ -17,10 +17,6 @@
+ #include <asm/io.h>
+ #include <asm/se7751/se7751.h>
+
+-#ifdef CONFIG_SH_KGDB
+-#include <asm/kgdb.h>
+-#endif
+-
+ /*
+ * Configure the Super I/O chip
+ */
+@@ -82,12 +78,6 @@ const char *get_system_type(void)
+ return "7751 SolutionEngine";
+ }
+
+-#ifdef CONFIG_SH_KGDB
+-static int kgdb_uart_setup(void);
+-static struct kgdb_sermap kgdb_uart_sermap =
+-{ "ttyS", 0, kgdb_uart_setup, NULL };
+-#endif
+-
+ /*
+ * Initialize the board
+ */
+@@ -95,133 +85,4 @@ void __init platform_setup(void)
+ {
+ /* Call init_smsc() replacement to set up SuperIO. */
+ /* XXX: RTC setting comes here */
+-#ifdef CONFIG_SH_KGDB
+- kgdb_register_sermap(&kgdb_uart_sermap);
+-#endif
+-}
+-
+-/*********************************************************************
+- * Currently a hack (e.g. does not interact well w/serial.c, lots of *
+- * hardcoded stuff) but may be useful if SCI/F needs debugging. *
+- * Mostly copied from x86 code (see files asm-i386/kgdb_local.h and *
+- * arch/i386/lib/kgdb_serial.c). *
+- *********************************************************************/
+-
+-#ifdef CONFIG_SH_KGDB
+-#include <linux/types.h>
+-#include <linux/serial.h>
+-#include <linux/serialP.h>
+-#include <linux/serial_reg.h>
+-
+-#define COM1_PORT 0x3f8 /* Base I/O address */
+-#define COM1_IRQ 4 /* IRQ not used yet */
+-#define COM2_PORT 0x2f8 /* Base I/O address */
+-#define COM2_IRQ 3 /* IRQ not used yet */
+-
+-#define SB_CLOCK 1843200 /* Serial baud clock */
+-#define SB_BASE (SB_CLOCK/16)
+-#define SB_MCR UART_MCR_OUT2 | UART_MCR_DTR | UART_MCR_RTS
+-
+-struct uart_port {
+- int base;
+-};
+-#define UART_NPORTS 2
+-struct uart_port uart_ports[] = {
+- { COM1_PORT },
+- { COM2_PORT },
+-};
+-struct uart_port *kgdb_uart_port;
+-
+-#define UART_IN(reg) inb_p(kgdb_uart_port->base + reg)
+-#define UART_OUT(reg,v) outb_p((v), kgdb_uart_port->base + reg)
+-
+-/* Basic read/write functions for the UART */
+-#define UART_LSR_RXCERR (UART_LSR_BI | UART_LSR_FE | UART_LSR_PE)
+-static int kgdb_uart_getchar(void)
+-{
+- int lsr;
+- int c = -1;
+-
+- while (c == -1) {
+- lsr = UART_IN(UART_LSR);
+- if (lsr & UART_LSR_DR)
+- c = UART_IN(UART_RX);
+- if ((lsr & UART_LSR_RXCERR))
+- c = -1;
+- }
+- return c;
+-}
+-
+-static void kgdb_uart_putchar(int c)
+-{
+- while ((UART_IN(UART_LSR) & UART_LSR_THRE) == 0)
+- ;
+- UART_OUT(UART_TX, c);
+-}
+-
+-/*
+- * Initialize UART to configured/requested values.
+- * (But we don't interrupts yet, or interact w/serial.c)
+- */
+-static int kgdb_uart_setup(void)
+-{
+- int port;
+- int lcr = 0;
+- int bdiv = 0;
+-
+- if (kgdb_portnum >= UART_NPORTS) {
+- KGDB_PRINTK("uart port %d invalid.\n", kgdb_portnum);
+- return -1;
+- }
+-
+- kgdb_uart_port = &uart_ports[kgdb_portnum];
+-
+- /* Init sequence from gdb_hook_interrupt */
+- UART_IN(UART_RX);
+- UART_OUT(UART_IER, 0);
+-
+- UART_IN(UART_RX); /* Serial driver comments say */
+- UART_IN(UART_IIR); /* this clears interrupt regs */
+- UART_IN(UART_MSR);
+-
+- /* Figure basic LCR values */
+- switch (kgdb_bits) {
+- case '7':
+- lcr |= UART_LCR_WLEN7;
+- break;
+- default: case '8':
+- lcr |= UART_LCR_WLEN8;
+- break;
+- }
+- switch (kgdb_parity) {
+- case 'O':
+- lcr |= UART_LCR_PARITY;
+- break;
+- case 'E':
+- lcr |= (UART_LCR_PARITY | UART_LCR_EPAR);
+- break;
+- default: break;
+- }
+-
+- /* Figure the baud rate divisor */
+- bdiv = (SB_BASE/kgdb_baud);
+-
+- /* Set the baud rate and LCR values */
+- UART_OUT(UART_LCR, (lcr | UART_LCR_DLAB));
+- UART_OUT(UART_DLL, (bdiv & 0xff));
+- UART_OUT(UART_DLM, ((bdiv >> 8) & 0xff));
+- UART_OUT(UART_LCR, lcr);
+-
+- /* Set the MCR */
+- UART_OUT(UART_MCR, SB_MCR);
+-
+- /* Turn off FIFOs for now */
+- UART_OUT(UART_FCR, 0);
+-
+- /* Setup complete: initialize function pointers */
+- kgdb_getchar = kgdb_uart_getchar;
+- kgdb_putchar = kgdb_uart_putchar;
+-
+- return 0;
+ }
+-#endif /* CONFIG_SH_KGDB */
+diff -rupN -X ../client-cleanup/dontdiff linux-2.6.18/arch/sh/kernel/Makefile linux-2.6.18.kgdb/arch/sh/kernel/Makefile
+--- linux-2.6.18/arch/sh/kernel/Makefile 2006-09-20 07:42:06.000000000 +0400
++++ linux-2.6.18.kgdb/arch/sh/kernel/Makefile 2008-06-10 16:19:47.000000000 +0400
+@@ -13,7 +13,7 @@ obj-y += cpu/ timers/
+ obj-$(CONFIG_SMP) += smp.o
+ obj-$(CONFIG_CF_ENABLER) += cf-enabler.o
+ obj-$(CONFIG_SH_STANDARD_BIOS) += sh_bios.o
+-obj-$(CONFIG_SH_KGDB) += kgdb_stub.o kgdb_jmp.o
++obj-$(CONFIG_KGDB) += kgdb.o kgdb-jmp.o
+ obj-$(CONFIG_SH_CPU_FREQ) += cpufreq.o
+ obj-$(CONFIG_MODULES) += module.o
+ obj-$(CONFIG_EARLY_PRINTK) += early_printk.o
+diff -rupN -X ../client-cleanup/dontdiff linux-2.6.18/arch/sh/kernel/cpu/sh3/ex.S linux-2.6.18.kgdb/arch/sh/kernel/cpu/sh3/ex.S
+--- linux-2.6.18/arch/sh/kernel/cpu/sh3/ex.S 2006-09-20 07:42:06.000000000 +0400
++++ linux-2.6.18.kgdb/arch/sh/kernel/cpu/sh3/ex.S 2008-06-10 16:19:47.000000000 +0400
+@@ -42,7 +42,7 @@ ENTRY(exception_handling_table)
+ .long exception_error ! reserved_instruction (filled by trap_init) /* 180 */
+ .long exception_error ! illegal_slot_instruction (filled by trap_init) /*1A0*/
+ ENTRY(nmi_slot)
+-#if defined (CONFIG_KGDB_NMI)
++#if defined (CONFIG_KGDB)
+ .long debug_enter /* 1C0 */ ! Allow trap to debugger
+ #else
+ .long exception_none /* 1C0 */ ! Not implemented yet
+diff -rupN -X ../client-cleanup/dontdiff linux-2.6.18/arch/sh/kernel/cpu/sh4/ex.S linux-2.6.18.kgdb/arch/sh/kernel/cpu/sh4/ex.S
+--- linux-2.6.18/arch/sh/kernel/cpu/sh4/ex.S 2006-09-20 07:42:06.000000000 +0400
++++ linux-2.6.18.kgdb/arch/sh/kernel/cpu/sh4/ex.S 2008-06-10 16:19:47.000000000 +0400
+@@ -46,7 +46,7 @@ ENTRY(exception_handling_table)
+ .long exception_error ! reserved_instruction (filled by trap_init) /* 180 */
+ .long exception_error ! illegal_slot_instruction (filled by trap_init) /*1A0*/
+ ENTRY(nmi_slot)
+-#if defined (CONFIG_KGDB_NMI)
++#if defined (CONFIG_KGDB)
+ .long debug_enter /* 1C0 */ ! Allow trap to debugger
+ #else
+ .long exception_none /* 1C0 */ ! Not implemented yet
+diff -rupN -X ../client-cleanup/dontdiff linux-2.6.18/arch/sh/kernel/entry.S linux-2.6.18.kgdb/arch/sh/kernel/entry.S
+--- linux-2.6.18/arch/sh/kernel/entry.S 2006-09-20 07:42:06.000000000 +0400
++++ linux-2.6.18.kgdb/arch/sh/kernel/entry.S 2008-06-10 16:19:47.000000000 +0400
+@@ -75,7 +75,7 @@
+ ENOSYS = 38
+ EINVAL = 22
+
+-#if defined(CONFIG_KGDB_NMI)
++#if defined(CONFIG_KGDB)
+ NMI_VEC = 0x1c0 ! Must catch early for debounce
+ #endif
+
+@@ -227,31 +227,33 @@ call_dae:
+ 2: .long do_address_error
+ #endif /* CONFIG_MMU */
+
+-#if defined(CONFIG_SH_STANDARD_BIOS) || defined(CONFIG_SH_KGDB)
++#if defined(CONFIG_SH_STANDARD_BIOS) || defined(CONFIG_KGDB)
+ ! Handle kernel debug if either kgdb (SW) or gdb-stub (FW) is present.
+ ! If both are configured, handle the debug traps (breakpoints) in SW,
+ ! but still allow BIOS traps to FW.
+
+ .align 2
+ debug_kernel:
+-#if defined(CONFIG_SH_STANDARD_BIOS) && defined(CONFIG_SH_KGDB)
++#if defined(CONFIG_SH_STANDARD_BIOS) && defined(CONFIG_KGDB)
+ /* Force BIOS call to FW (debug_trap put TRA in r8) */
+ mov r8,r0
+ shlr2 r0
+ cmp/eq #0x3f,r0
+ bt debug_kernel_fw
+-#endif /* CONFIG_SH_STANDARD_BIOS && CONFIG_SH_KGDB */
++#endif /* CONFIG_SH_STANDARD_BIOS && CONFIG_KGDB */
+
+-debug_enter:
+-#if defined(CONFIG_SH_KGDB)
++ .align 2
++ .globl debug_enter
++debug_enter:
++#if defined(CONFIG_KGDB)
+ /* Jump to kgdb, pass stacked regs as arg */
+ debug_kernel_sw:
+ mov.l 3f, r0
+ jmp @r0
+ mov r15, r4
+ .align 2
+-3: .long kgdb_handle_exception
+-#endif /* CONFIG_SH_KGDB */
++3: .long kgdb_exception_handler
++#endif /* CONFIG_KGDB */
+
+ #if defined(CONFIG_SH_STANDARD_BIOS)
+ /* Unwind the stack and jmp to the debug entry */
+@@ -293,12 +295,12 @@ debug_kernel_fw:
+ 2: .long gdb_vbr_vector
+ #endif /* CONFIG_SH_STANDARD_BIOS */
+
+-#endif /* CONFIG_SH_STANDARD_BIOS || CONFIG_SH_KGDB */
++#endif /* CONFIG_SH_STANDARD_BIOS || CONFIG_KGDB */
+
+
+ .align 2
+-debug_trap:
+-#if defined(CONFIG_SH_STANDARD_BIOS) || defined(CONFIG_SH_KGDB)
++debug_trap:
++#if defined(CONFIG_SH_STANDARD_BIOS) || defined(CONFIG_KGDB)
+ mov #OFF_SR, r0
+ mov.l @(r0,r15), r0 ! get status register
+ shll r0
+@@ -642,7 +644,7 @@ skip_restore:
+ 6: or k0, k2 ! Set the IMASK-bits
+ ldc k2, ssr
+ !
+-#if defined(CONFIG_KGDB_NMI)
++#if defined(CONFIG_KGDB)
+ ! Clear in_nmi
+ mov.l 4f, k0
+ mov #0, k1
+@@ -694,7 +696,7 @@ tlb_miss:
+ interrupt:
+ mov.l 2f, k2
+ mov.l 3f, k3
+-#if defined(CONFIG_KGDB_NMI)
++#if defined(CONFIG_KGDB)
+ ! Debounce (filter nested NMI)
+ mov.l @k2, k0
+ mov.l 5f, k1
+@@ -709,7 +711,7 @@ interrupt:
+ 5: .long NMI_VEC
+ 6: .long in_nmi
+ 0:
+-#endif /* defined(CONFIG_KGDB_NMI) */
++#endif /* defined(CONFIG_KGDB) */
+ bra handle_exception
+ mov.l @k2, k2
+
+diff -rupN -X ../client-cleanup/dontdiff linux-2.6.18/arch/sh/kernel/kgdb-jmp.S linux-2.6.18.kgdb/arch/sh/kernel/kgdb-jmp.S
+--- linux-2.6.18/arch/sh/kernel/kgdb-jmp.S 1970-01-01 03:00:00.000000000 +0300
++++ linux-2.6.18.kgdb/arch/sh/kernel/kgdb-jmp.S 2008-06-10 16:19:47.000000000 +0400
+@@ -0,0 +1,32 @@
++#include <linux/linkage.h>
++
++ENTRY(kgdb_fault_setjmp)
++ add #(9*4), r4
++ sts.l pr, @-r4
++ mov.l r15, @-r4
++ mov.l r14, @-r4
++ mov.l r13, @-r4
++ mov.l r12, @-r4
++ mov.l r11, @-r4
++ mov.l r10, @-r4
++ mov.l r9, @-r4
++ mov.l r8, @-r4
++ rts
++ mov #0, r0
++
++ENTRY(kgdb_fault_longjmp)
++ mov.l @r4+, r8
++ mov.l @r4+, r9
++ mov.l @r4+, r10
++ mov.l @r4+, r11
++ mov.l @r4+, r12
++ mov.l @r4+, r13
++ mov.l @r4+, r14
++ mov.l @r4+, r15
++ lds.l @r4+, pr
++ mov r5, r0
++ tst r0, r0
++ bf 1f
++ mov #1, r0
++1: rts
++ nop
+diff -rupN -X ../client-cleanup/dontdiff linux-2.6.18/arch/sh/kernel/kgdb.c linux-2.6.18.kgdb/arch/sh/kernel/kgdb.c
+--- linux-2.6.18/arch/sh/kernel/kgdb.c 1970-01-01 03:00:00.000000000 +0300
++++ linux-2.6.18.kgdb/arch/sh/kernel/kgdb.c 2008-06-10 16:19:47.000000000 +0400
+@@ -0,0 +1,363 @@
++/*
++ * arch/sh/kernel/kgdb.c
++ *
++ * Contains SH-specific low-level support for KGDB.
++ *
++ * Containes extracts from code by Glenn Engel, Jim Kingdon,
++ * David Grothe <dave@gcom.com>, Tigran Aivazian <tigran@sco.com>,
++ * Amit S. Kale <akale@veritas.com>, William Gatliff <bgat@open-widgets.com>,
++ * Ben Lee, Steve Chamberlain and Benoit Miller <fulg@iname.com>,
++ * Henry Bell <henry.bell@st.com> and Jeremy Siegel <jsiegel@mvista.com>
++ *
++ * Maintainer: Tom Rini <trini@kernel.crashing.org>
++ *
++ * 2004 (c) MontaVista Software, Inc. This file is licensed under
++ * the terms of the GNU General Public License version 2. This program
++ * is licensed "as is" without any warranty of any kind, whether express
++ * or implied.
++ */
++
++#include <linux/string.h>
++#include <linux/kernel.h>
++#include <linux/sched.h>
++#include <linux/smp.h>
++#include <linux/spinlock.h>
++#include <linux/delay.h>
++#include <linux/linkage.h>
++#include <linux/init.h>
++#include <linux/kgdb.h>
++
++#include <asm/system.h>
++#include <asm/current.h>
++#include <asm/signal.h>
++#include <asm/pgtable.h>
++#include <asm/ptrace.h>
++
++extern void per_cpu_trap_init(void);
++extern atomic_t cpu_doing_single_step;
++
++/* Function pointers for linkage */
++static struct kgdb_regs trap_registers;
++
++/* Globals. */
++char in_nmi; /* Set during NMI to prevent reentry */
++
++/* TRA differs sh3/4 */
++#if defined(CONFIG_CPU_SH3)
++#define TRA 0xffffffd0
++#elif defined(CONFIG_CPU_SH4)
++#define TRA 0xff000020
++#endif
++
++/* Macros for single step instruction identification */
++#define OPCODE_BT(op) (((op) & 0xff00) == 0x8900)
++#define OPCODE_BF(op) (((op) & 0xff00) == 0x8b00)
++#define OPCODE_BTF_DISP(op) (((op) & 0x80) ? (((op) | 0xffffff80) << 1) : \
++ (((op) & 0x7f ) << 1))
++#define OPCODE_BFS(op) (((op) & 0xff00) == 0x8f00)
++#define OPCODE_BTS(op) (((op) & 0xff00) == 0x8d00)
++#define OPCODE_BRA(op) (((op) & 0xf000) == 0xa000)
++#define OPCODE_BRA_DISP(op) (((op) & 0x800) ? (((op) | 0xfffff800) << 1) : \
++ (((op) & 0x7ff) << 1))
++#define OPCODE_BRAF(op) (((op) & 0xf0ff) == 0x0023)
++#define OPCODE_BRAF_REG(op) (((op) & 0x0f00) >> 8)
++#define OPCODE_BSR(op) (((op) & 0xf000) == 0xb000)
++#define OPCODE_BSR_DISP(op) (((op) & 0x800) ? (((op) | 0xfffff800) << 1) : \
++ (((op) & 0x7ff) << 1))
++#define OPCODE_BSRF(op) (((op) & 0xf0ff) == 0x0003)
++#define OPCODE_BSRF_REG(op) (((op) >> 8) & 0xf)
++#define OPCODE_JMP(op) (((op) & 0xf0ff) == 0x402b)
++#define OPCODE_JMP_REG(op) (((op) >> 8) & 0xf)
++#define OPCODE_JSR(op) (((op) & 0xf0ff) == 0x400b)
++#define OPCODE_JSR_REG(op) (((op) >> 8) & 0xf)
++#define OPCODE_RTS(op) ((op) == 0xb)
++#define OPCODE_RTE(op) ((op) == 0x2b)
++
++#define SR_T_BIT_MASK 0x1
++#define STEP_OPCODE 0xc320
++#define BIOS_CALL_TRAP 0x3f
++
++/* Exception codes as per SH-4 core manual */
++#define ADDRESS_ERROR_LOAD_VEC 7
++#define ADDRESS_ERROR_STORE_VEC 8
++#define TRAP_VEC 11
++#define INVALID_INSN_VEC 12
++#define INVALID_SLOT_VEC 13
++#define NMI_VEC 14
++#define SERIAL_BREAK_VEC 58
++
++/* Misc static */
++static int stepped_address;
++static short stepped_opcode;
++
++/* Translate SH-3/4 exception numbers to unix-like signal values */
++static int compute_signal(const int excep_code)
++{
++ switch (excep_code) {
++ case INVALID_INSN_VEC:
++ case INVALID_SLOT_VEC:
++ return SIGILL;
++ case ADDRESS_ERROR_LOAD_VEC:
++ case ADDRESS_ERROR_STORE_VEC:
++ return SIGSEGV;
++ case SERIAL_BREAK_VEC:
++ case NMI_VEC:
++ return SIGINT;
++ default:
++ /* Act like it was a break/trap. */
++ return SIGTRAP;
++ }
++}
++
++/*
++ * Translate the registers of the system into the format that GDB wants. Since
++ * we use a local structure to store things, instead of getting them out
++ * of pt_regs, we can just do a memcpy.
++ */
++void regs_to_gdb_regs(unsigned long *gdb_regs, struct pt_regs *ign)
++{
++ memcpy(gdb_regs, &trap_registers, sizeof(trap_registers));
++}
++
++/*
++ * On SH we save: r1 (prev->thread.sp) r2 (prev->thread.pc) r4 (prev) r5 (next)
++ * r6 (next->thread.sp) r7 (next->thread.pc)
++ */
++void sleeping_thread_to_gdb_regs(unsigned long *gdb_regs, struct task_struct *p)
++{
++ int count;
++
++ for (count = 0; count < 16; count++)
++ *(gdb_regs++) = 0;
++ *(gdb_regs++) = p->thread.pc;
++ *(gdb_regs++) = 0;
++ *(gdb_regs++) = 0;
++ *(gdb_regs++) = 0;
++ *(gdb_regs++) = 0;
++ *(gdb_regs++) = 0;
++ *(gdb_regs++) = 0;
++}
++
++/*
++ * Translate the registers values that GDB has given us back into the
++ * format of the system. See the comment above about memcpy.
++ */
++void gdb_regs_to_regs(unsigned long *gdb_regs, struct pt_regs *ign)
++{
++ memcpy(&trap_registers, gdb_regs, sizeof(trap_registers));
++}
++
++/* Calculate the new address for after a step */
++static short *get_step_address(void)
++{
++ short op = *(short *)trap_registers.pc;
++ long addr;
++
++ /* BT */
++ if (OPCODE_BT(op)) {
++ if (trap_registers.sr & SR_T_BIT_MASK)
++ addr = trap_registers.pc + 4 + OPCODE_BTF_DISP(op);
++ else
++ addr = trap_registers.pc + 2;
++ }
++
++ /* BTS */
++ else if (OPCODE_BTS(op)) {
++ if (trap_registers.sr & SR_T_BIT_MASK)
++ addr = trap_registers.pc + 4 + OPCODE_BTF_DISP(op);
++ else
++ addr = trap_registers.pc + 4; /* Not in delay slot */
++ }
++
++ /* BF */
++ else if (OPCODE_BF(op)) {
++ if (!(trap_registers.sr & SR_T_BIT_MASK))
++ addr = trap_registers.pc + 4 + OPCODE_BTF_DISP(op);
++ else
++ addr = trap_registers.pc + 2;
++ }
++
++ /* BFS */
++ else if (OPCODE_BFS(op)) {
++ if (!(trap_registers.sr & SR_T_BIT_MASK))
++ addr = trap_registers.pc + 4 + OPCODE_BTF_DISP(op);
++ else
++ addr = trap_registers.pc + 4; /* Not in delay slot */
++ }
++
++ /* BRA */
++ else if (OPCODE_BRA(op))
++ addr = trap_registers.pc + 4 + OPCODE_BRA_DISP(op);
++
++ /* BRAF */
++ else if (OPCODE_BRAF(op))
++ addr = trap_registers.pc + 4
++ + trap_registers.regs[OPCODE_BRAF_REG(op)];
++
++ /* BSR */
++ else if (OPCODE_BSR(op))
++ addr = trap_registers.pc + 4 + OPCODE_BSR_DISP(op);
++
++ /* BSRF */
++ else if (OPCODE_BSRF(op))
++ addr = trap_registers.pc + 4
++ + trap_registers.regs[OPCODE_BSRF_REG(op)];
++
++ /* JMP */
++ else if (OPCODE_JMP(op))
++ addr = trap_registers.regs[OPCODE_JMP_REG(op)];
++
++ /* JSR */
++ else if (OPCODE_JSR(op))
++ addr = trap_registers.regs[OPCODE_JSR_REG(op)];
++
++ /* RTS */
++ else if (OPCODE_RTS(op))
++ addr = trap_registers.pr;
++
++ /* RTE */
++ else if (OPCODE_RTE(op))
++ addr = trap_registers.regs[15];
++
++ /* Other */
++ else
++ addr = trap_registers.pc + 2;
++
++ kgdb_flush_icache_range(addr, addr + 2);
++ return (short *)addr;
++}
++
++/* The command loop, read and act on requests */
++int kgdb_arch_handle_exception(int e_vector, int signo, int err_code,
++ char *remcom_in_buffer, char *remcom_out_buffer,
++ struct pt_regs *ign)
++{
++ unsigned long addr;
++ char *ptr = &remcom_in_buffer[1];
++
++ /* Examine first char of buffer to see what we need to do */
++ switch (remcom_in_buffer[0]) {
++ case 'c': /* Continue at address AA..AA (optional) */
++ case 's': /* Step one instruction from AA..AA */
++ /* Try to read optional parameter, PC unchanged if none */
++ if (kgdb_hex2long(&ptr, &addr))
++ trap_registers.pc = addr;
++
++ atomic_set(&cpu_doing_single_step, -1);
++ if (remcom_in_buffer[0] == 's') {
++ /* Replace the instruction immediately after the
++ * current instruction (i.e. next in the expected
++ * flow of control) with a trap instruction, so that
++ * returning will cause only a single instruction to
++ * be executed. Note that this model is slightly
++ * broken for instructions with delay slots
++ * (e.g. B[TF]S, BSR, BRA etc), where both the branch
++ * and the instruction in the delay slot will be
++ * executed.
++ */
++ /* Determine where the target instruction will send
++ * us to */
++ unsigned short *next_addr = get_step_address();
++ stepped_address = (int)next_addr;
++
++ /* Replace it */
++ stepped_opcode = *(short *)next_addr;
++ *next_addr = STEP_OPCODE;
++
++ /* Flush and return */
++ kgdb_flush_icache_range((long)next_addr,
++ (long)next_addr + 2);
++ if (kgdb_contthread)
++ atomic_set(&cpu_doing_single_step,
++ smp_processor_id());
++ }
++ return 0;
++ }
++ return -1;
++}
++
++/*
++ * When an exception has occured, we are called. We need to set things
++ * up so that we can call kgdb_handle_exception to handle requests from
++ * the remote GDB.
++ */
++void kgdb_exception_handler(struct pt_regs *regs)
++{
++ int excep_code, vbr_val;
++ int count;
++
++ /* Copy kernel regs (from stack) */
++ for (count = 0; count < 16; count++)
++ trap_registers.regs[count] = regs->regs[count];
++ trap_registers.pc = regs->pc;
++ trap_registers.pr = regs->pr;
++ trap_registers.sr = regs->sr;
++ trap_registers.gbr = regs->gbr;
++ trap_registers.mach = regs->mach;
++ trap_registers.macl = regs->macl;
++
++ __asm__ __volatile__("stc vbr, %0":"=r"(vbr_val));
++ trap_registers.vbr = vbr_val;
++
++ /* Get the execption code. */
++ __asm__ __volatile__("stc r2_bank, %0":"=r"(excep_code));
++
++ excep_code >>= 5;
++
++ /* If we got an NMI, and KGDB is not yet initialized, call
++ * breakpoint() to try and initialize everything for us. */
++ if (excep_code == NMI_VEC && !kgdb_initialized) {
++ breakpoint();
++ return;
++ }
++
++ /* TRAP_VEC exception indicates a software trap inserted in place of
++ * code by GDB so back up PC by one instruction, as this instruction
++ * will later be replaced by its original one. Do NOT do this for
++ * trap 0xff, since that indicates a compiled-in breakpoint which
++ * will not be replaced (and we would retake the trap forever) */
++ if (excep_code == TRAP_VEC &&
++ (*(volatile unsigned long *)TRA != (0xff << 2)))
++ trap_registers.pc -= 2;
++
++ /* If we have been single-stepping, put back the old instruction.
++ * We use stepped_address in case we have stopped more than one
++ * instruction away. */
++ if (stepped_opcode != 0) {
++ *(short *)stepped_address = stepped_opcode;
++ kgdb_flush_icache_range(stepped_address, stepped_address + 2);
++ }
++ stepped_opcode = 0;
++
++ /* Call the stub to do the processing. Note that not everything we
++ * need to send back and forth lives in pt_regs. */
++ kgdb_handle_exception(excep_code, compute_signal(excep_code), 0, regs);
++
++ /* Copy back the (maybe modified) registers */
++ for (count = 0; count < 16; count++)
++ regs->regs[count] = trap_registers.regs[count];
++ regs->pc = trap_registers.pc;
++ regs->pr = trap_registers.pr;
++ regs->sr = trap_registers.sr;
++ regs->gbr = trap_registers.gbr;
++ regs->mach = trap_registers.mach;
++ regs->macl = trap_registers.macl;
++
++ vbr_val = trap_registers.vbr;
++ __asm__ __volatile__("ldc %0, vbr": :"r"(vbr_val));
++}
++
++int __init kgdb_arch_init(void)
++{
++ per_cpu_trap_init();
++
++ return 0;
++}
++
++struct kgdb_arch arch_kgdb_ops = {
++#ifdef CONFIG_CPU_LITTLE_ENDIAN
++ .gdb_bpt_instr = {0xff, 0xc3},
++#else
++ .gdb_bpt_instr = {0xc3, 0xff},
++#endif
++};
+diff -rupN -X ../client-cleanup/dontdiff linux-2.6.18/arch/sh/kernel/kgdb_jmp.S linux-2.6.18.kgdb/arch/sh/kernel/kgdb_jmp.S
+--- linux-2.6.18/arch/sh/kernel/kgdb_jmp.S 2006-09-20 07:42:06.000000000 +0400
++++ linux-2.6.18.kgdb/arch/sh/kernel/kgdb_jmp.S 1970-01-01 03:00:00.000000000 +0300
+@@ -1,33 +0,0 @@
+-#include <linux/linkage.h>
+-
+-ENTRY(setjmp)
+- add #(9*4), r4
+- sts.l pr, @-r4
+- mov.l r15, @-r4
+- mov.l r14, @-r4
+- mov.l r13, @-r4
+- mov.l r12, @-r4
+- mov.l r11, @-r4
+- mov.l r10, @-r4
+- mov.l r9, @-r4
+- mov.l r8, @-r4
+- rts
+- mov #0, r0
+-
+-ENTRY(longjmp)
+- mov.l @r4+, r8
+- mov.l @r4+, r9
+- mov.l @r4+, r10
+- mov.l @r4+, r11
+- mov.l @r4+, r12
+- mov.l @r4+, r13
+- mov.l @r4+, r14
+- mov.l @r4+, r15
+- lds.l @r4+, pr
+- mov r5, r0
+- tst r0, r0
+- bf 1f
+- mov #1, r0 ! in case val==0
+-1: rts
+- nop
+-
+diff -rupN -X ../client-cleanup/dontdiff linux-2.6.18/arch/sh/kernel/kgdb_stub.c linux-2.6.18.kgdb/arch/sh/kernel/kgdb_stub.c
+--- linux-2.6.18/arch/sh/kernel/kgdb_stub.c 2006-09-20 07:42:06.000000000 +0400
++++ linux-2.6.18.kgdb/arch/sh/kernel/kgdb_stub.c 1970-01-01 03:00:00.000000000 +0300
+@@ -1,1491 +0,0 @@
+-/*
+- * May be copied or modified under the terms of the GNU General Public
+- * License. See linux/COPYING for more information.
+- *
+- * Containes extracts from code by Glenn Engel, Jim Kingdon,
+- * David Grothe <dave@gcom.com>, Tigran Aivazian <tigran@sco.com>,
+- * Amit S. Kale <akale@veritas.com>, William Gatliff <bgat@open-widgets.com>,
+- * Ben Lee, Steve Chamberlain and Benoit Miller <fulg@iname.com>.
+- *
+- * This version by Henry Bell <henry.bell@st.com>
+- * Minor modifications by Jeremy Siegel <jsiegel@mvista.com>
+- *
+- * Contains low-level support for remote debug using GDB.
+- *
+- * To enable debugger support, two things need to happen. A call to
+- * set_debug_traps() is necessary in order to allow any breakpoints
+- * or error conditions to be properly intercepted and reported to gdb.
+- * A breakpoint also needs to be generated to begin communication. This
+- * is most easily accomplished by a call to breakpoint() which does
+- * a trapa if the initialisation phase has been successfully completed.
+- *
+- * In this case, set_debug_traps() is not used to "take over" exceptions;
+- * other kernel code is modified instead to enter the kgdb functions here
+- * when appropriate (see entry.S for breakpoint traps and NMI interrupts,
+- * see traps.c for kernel error exceptions).
+- *
+- * The following gdb commands are supported:
+- *
+- * Command Function Return value
+- *
+- * g return the value of the CPU registers hex data or ENN
+- * G set the value of the CPU registers OK or ENN
+- *
+- * mAA..AA,LLLL Read LLLL bytes at address AA..AA hex data or ENN
+- * MAA..AA,LLLL: Write LLLL bytes at address AA.AA OK or ENN
+- * XAA..AA,LLLL: Same, but data is binary (not hex) OK or ENN
+- *
+- * c Resume at current address SNN ( signal NN)
+- * cAA..AA Continue at address AA..AA SNN
+- * CNN; Resume at current address with signal SNN
+- * CNN;AA..AA Resume at address AA..AA with signal SNN
+- *
+- * s Step one instruction SNN
+- * sAA..AA Step one instruction from AA..AA SNN
+- * SNN; Step one instruction with signal SNN
+- * SNNAA..AA Step one instruction from AA..AA w/NN SNN
+- *
+- * k kill (Detach GDB)
+- *
+- * d Toggle debug flag
+- * D Detach GDB
+- *
+- * Hct Set thread t for operations, OK or ENN
+- * c = 'c' (step, cont), c = 'g' (other
+- * operations)
+- *
+- * qC Query current thread ID QCpid
+- * qfThreadInfo Get list of current threads (first) m<id>
+- * qsThreadInfo " " " " " (subsequent)
+- * qOffsets Get section offsets Text=x;Data=y;Bss=z
+- *
+- * TXX Find if thread XX is alive OK or ENN
+- * ? What was the last sigval ? SNN (signal NN)
+- * O Output to GDB console
+- *
+- * Remote communication protocol.
+- *
+- * A debug packet whose contents are <data> is encapsulated for
+- * transmission in the form:
+- *
+- * $ <data> # CSUM1 CSUM2
+- *
+- * <data> must be ASCII alphanumeric and cannot include characters
+- * '$' or '#'. If <data> starts with two characters followed by
+- * ':', then the existing stubs interpret this as a sequence number.
+- *
+- * CSUM1 and CSUM2 are ascii hex representation of an 8-bit
+- * checksum of <data>, the most significant nibble is sent first.
+- * the hex digits 0-9,a-f are used.
+- *
+- * Receiver responds with:
+- *
+- * + - if CSUM is correct and ready for next packet
+- * - - if CSUM is incorrect
+- *
+- * Responses can be run-length encoded to save space. A '*' means that
+- * the next character is an ASCII encoding giving a repeat count which
+- * stands for that many repititions of the character preceding the '*'.
+- * The encoding is n+29, yielding a printable character where n >=3
+- * (which is where RLE starts to win). Don't use an n > 126.
+- *
+- * So "0* " means the same as "0000".
+- */
+-
+-#include <linux/string.h>
+-#include <linux/kernel.h>
+-#include <linux/sched.h>
+-#include <linux/smp.h>
+-#include <linux/spinlock.h>
+-#include <linux/delay.h>
+-#include <linux/linkage.h>
+-#include <linux/init.h>
+-
+-#include <asm/system.h>
+-#include <asm/current.h>
+-#include <asm/signal.h>
+-#include <asm/pgtable.h>
+-#include <asm/ptrace.h>
+-#include <asm/kgdb.h>
+-
+-#ifdef CONFIG_SH_KGDB_CONSOLE
+-#include <linux/console.h>
+-#endif
+-
+-/* Function pointers for linkage */
+-kgdb_debug_hook_t *kgdb_debug_hook;
+-kgdb_bus_error_hook_t *kgdb_bus_err_hook;
+-
+-int (*kgdb_getchar)(void);
+-void (*kgdb_putchar)(int);
+-
+-static void put_debug_char(int c)
+-{
+- if (!kgdb_putchar)
+- return;
+- (*kgdb_putchar)(c);
+-}
+-static int get_debug_char(void)
+-{
+- if (!kgdb_getchar)
+- return -1;
+- return (*kgdb_getchar)();
+-}
+-
+-/* Num chars in in/out bound buffers, register packets need NUMREGBYTES * 2 */
+-#define BUFMAX 1024
+-#define NUMREGBYTES (MAXREG*4)
+-#define OUTBUFMAX (NUMREGBYTES*2+512)
+-
+-enum regs {
+- R0 = 0, R1, R2, R3, R4, R5, R6, R7,
+- R8, R9, R10, R11, R12, R13, R14, R15,
+- PC, PR, GBR, VBR, MACH, MACL, SR,
+- /* */
+- MAXREG
+-};
+-
+-static unsigned int registers[MAXREG];
+-struct kgdb_regs trap_registers;
+-
+-char kgdb_in_gdb_mode;
+-char in_nmi; /* Set during NMI to prevent reentry */
+-int kgdb_nofault; /* Boolean to ignore bus errs (i.e. in GDB) */
+-int kgdb_enabled = 1; /* Default to enabled, cmdline can disable */
+-int kgdb_halt;
+-
+-/* Exposed for user access */
+-struct task_struct *kgdb_current;
+-unsigned int kgdb_g_imask;
+-int kgdb_trapa_val;
+-int kgdb_excode;
+-
+-/* Default values for SCI (can override via kernel args in setup.c) */
+-#ifndef CONFIG_KGDB_DEFPORT
+-#define CONFIG_KGDB_DEFPORT 1
+-#endif
+-
+-#ifndef CONFIG_KGDB_DEFBAUD
+-#define CONFIG_KGDB_DEFBAUD 115200
+-#endif
+-
+-#if defined(CONFIG_KGDB_DEFPARITY_E)
+-#define CONFIG_KGDB_DEFPARITY 'E'
+-#elif defined(CONFIG_KGDB_DEFPARITY_O)
+-#define CONFIG_KGDB_DEFPARITY 'O'
+-#else /* CONFIG_KGDB_DEFPARITY_N */
+-#define CONFIG_KGDB_DEFPARITY 'N'
+-#endif
+-
+-#ifdef CONFIG_KGDB_DEFBITS_7
+-#define CONFIG_KGDB_DEFBITS '7'
+-#else /* CONFIG_KGDB_DEFBITS_8 */
+-#define CONFIG_KGDB_DEFBITS '8'
+-#endif
+-
+-/* SCI/UART settings, used in kgdb_console_setup() */
+-int kgdb_portnum = CONFIG_KGDB_DEFPORT;
+-int kgdb_baud = CONFIG_KGDB_DEFBAUD;
+-char kgdb_parity = CONFIG_KGDB_DEFPARITY;
+-char kgdb_bits = CONFIG_KGDB_DEFBITS;
+-
+-/* Jump buffer for setjmp/longjmp */
+-static jmp_buf rem_com_env;
+-
+-/* TRA differs sh3/4 */
+-#if defined(CONFIG_CPU_SH3)
+-#define TRA 0xffffffd0
+-#elif defined(CONFIG_CPU_SH4)
+-#define TRA 0xff000020
+-#endif
+-
+-/* Macros for single step instruction identification */
+-#define OPCODE_BT(op) (((op) & 0xff00) == 0x8900)
+-#define OPCODE_BF(op) (((op) & 0xff00) == 0x8b00)
+-#define OPCODE_BTF_DISP(op) (((op) & 0x80) ? (((op) | 0xffffff80) << 1) : \
+- (((op) & 0x7f ) << 1))
+-#define OPCODE_BFS(op) (((op) & 0xff00) == 0x8f00)
+-#define OPCODE_BTS(op) (((op) & 0xff00) == 0x8d00)
+-#define OPCODE_BRA(op) (((op) & 0xf000) == 0xa000)
+-#define OPCODE_BRA_DISP(op) (((op) & 0x800) ? (((op) | 0xfffff800) << 1) : \
+- (((op) & 0x7ff) << 1))
+-#define OPCODE_BRAF(op) (((op) & 0xf0ff) == 0x0023)
+-#define OPCODE_BRAF_REG(op) (((op) & 0x0f00) >> 8)
+-#define OPCODE_BSR(op) (((op) & 0xf000) == 0xb000)
+-#define OPCODE_BSR_DISP(op) (((op) & 0x800) ? (((op) | 0xfffff800) << 1) : \
+- (((op) & 0x7ff) << 1))
+-#define OPCODE_BSRF(op) (((op) & 0xf0ff) == 0x0003)
+-#define OPCODE_BSRF_REG(op) (((op) >> 8) & 0xf)
+-#define OPCODE_JMP(op) (((op) & 0xf0ff) == 0x402b)
+-#define OPCODE_JMP_REG(op) (((op) >> 8) & 0xf)
+-#define OPCODE_JSR(op) (((op) & 0xf0ff) == 0x400b)
+-#define OPCODE_JSR_REG(op) (((op) >> 8) & 0xf)
+-#define OPCODE_RTS(op) ((op) == 0xb)
+-#define OPCODE_RTE(op) ((op) == 0x2b)
+-
+-#define SR_T_BIT_MASK 0x1
+-#define STEP_OPCODE 0xc320
+-#define BIOS_CALL_TRAP 0x3f
+-
+-/* Exception codes as per SH-4 core manual */
+-#define ADDRESS_ERROR_LOAD_VEC 7
+-#define ADDRESS_ERROR_STORE_VEC 8
+-#define TRAP_VEC 11
+-#define INVALID_INSN_VEC 12
+-#define INVALID_SLOT_VEC 13
+-#define NMI_VEC 14
+-#define USER_BREAK_VEC 15
+-#define SERIAL_BREAK_VEC 58
+-
+-/* Misc static */
+-static int stepped_address;
+-static short stepped_opcode;
+-static const char hexchars[] = "0123456789abcdef";
+-static char in_buffer[BUFMAX];
+-static char out_buffer[OUTBUFMAX];
+-
+-static void kgdb_to_gdb(const char *s);
+-
+-#ifdef CONFIG_KGDB_THREAD
+-static struct task_struct *trapped_thread;
+-static struct task_struct *current_thread;
+-typedef unsigned char threadref[8];
+-#define BUF_THREAD_ID_SIZE 16
+-#endif
+-
+-/* Return addr as a real volatile address */
+-static inline unsigned int ctrl_inl(const unsigned long addr)
+-{
+- return *(volatile unsigned long *) addr;
+-}
+-
+-/* Correctly set *addr using volatile */
+-static inline void ctrl_outl(const unsigned int b, unsigned long addr)
+-{
+- *(volatile unsigned long *) addr = b;
+-}
+-
+-/* Get high hex bits */
+-static char highhex(const int x)
+-{
+- return hexchars[(x >> 4) & 0xf];
+-}
+-
+-/* Get low hex bits */
+-static char lowhex(const int x)
+-{
+- return hexchars[x & 0xf];
+-}
+-
+-/* Convert ch to hex */
+-static int hex(const char ch)
+-{
+- if ((ch >= 'a') && (ch <= 'f'))
+- return (ch - 'a' + 10);
+- if ((ch >= '0') && (ch <= '9'))
+- return (ch - '0');
+- if ((ch >= 'A') && (ch <= 'F'))
+- return (ch - 'A' + 10);
+- return (-1);
+-}
+-
+-/* Convert the memory pointed to by mem into hex, placing result in buf.
+- Returns a pointer to the last char put in buf (null) */
+-static char *mem_to_hex(const char *mem, char *buf, const int count)
+-{
+- int i;
+- int ch;
+- unsigned short s_val;
+- unsigned long l_val;
+-
+- /* Check for 16 or 32 */
+- if (count == 2 && ((long) mem & 1) == 0) {
+- s_val = *(unsigned short *) mem;
+- mem = (char *) &s_val;
+- } else if (count == 4 && ((long) mem & 3) == 0) {
+- l_val = *(unsigned long *) mem;
+- mem = (char *) &l_val;
+- }
+- for (i = 0; i < count; i++) {
+- ch = *mem++;
+- *buf++ = highhex(ch);
+- *buf++ = lowhex(ch);
+- }
+- *buf = 0;
+- return (buf);
+-}
+-
+-/* Convert the hex array pointed to by buf into binary, to be placed in mem.
+- Return a pointer to the character after the last byte written */
+-static char *hex_to_mem(const char *buf, char *mem, const int count)
+-{
+- int i;
+- unsigned char ch;
+-
+- for (i = 0; i < count; i++) {
+- ch = hex(*buf++) << 4;
+- ch = ch + hex(*buf++);
+- *mem++ = ch;
+- }
+- return (mem);
+-}
+-
+-/* While finding valid hex chars, convert to an integer, then return it */
+-static int hex_to_int(char **ptr, int *int_value)
+-{
+- int num_chars = 0;
+- int hex_value;
+-
+- *int_value = 0;
+-
+- while (**ptr) {
+- hex_value = hex(**ptr);
+- if (hex_value >= 0) {
+- *int_value = (*int_value << 4) | hex_value;
+- num_chars++;
+- } else
+- break;
+- (*ptr)++;
+- }
+- return num_chars;
+-}
+-
+-/* Copy the binary array pointed to by buf into mem. Fix $, #,
+- and 0x7d escaped with 0x7d. Return a pointer to the character
+- after the last byte written. */
+-static char *ebin_to_mem(const char *buf, char *mem, int count)
+-{
+- for (; count > 0; count--, buf++) {
+- if (*buf == 0x7d)
+- *mem++ = *(++buf) ^ 0x20;
+- else
+- *mem++ = *buf;
+- }
+- return mem;
+-}
+-
+-/* Pack a hex byte */
+-static char *pack_hex_byte(char *pkt, int byte)
+-{
+- *pkt++ = hexchars[(byte >> 4) & 0xf];
+- *pkt++ = hexchars[(byte & 0xf)];
+- return pkt;
+-}
+-
+-#ifdef CONFIG_KGDB_THREAD
+-
+-/* Pack a thread ID */
+-static char *pack_threadid(char *pkt, threadref * id)
+-{
+- char *limit;
+- unsigned char *altid;
+-
+- altid = (unsigned char *) id;
+-
+- limit = pkt + BUF_THREAD_ID_SIZE;
+- while (pkt < limit)
+- pkt = pack_hex_byte(pkt, *altid++);
+- return pkt;
+-}
+-
+-/* Convert an integer into our threadref */
+-static void int_to_threadref(threadref * id, const int value)
+-{
+- unsigned char *scan = (unsigned char *) id;
+- int i = 4;
+-
+- while (i--)
+- *scan++ = 0;
+-
+- *scan++ = (value >> 24) & 0xff;
+- *scan++ = (value >> 16) & 0xff;
+- *scan++ = (value >> 8) & 0xff;
+- *scan++ = (value & 0xff);
+-}
+-
+-/* Return a task structure ptr for a particular pid */
+-static struct task_struct *get_thread(int pid)
+-{
+- struct task_struct *thread;
+-
+- /* Use PID_MAX w/gdb for pid 0 */
+- if (pid == PID_MAX) pid = 0;
+-
+- /* First check via PID */
+- thread = find_task_by_pid(pid);
+-
+- if (thread)
+- return thread;
+-
+- /* Start at the start */
+- thread = init_tasks[0];
+-
+- /* Walk along the linked list of tasks */
+- do {
+- if (thread->pid == pid)
+- return thread;
+- thread = thread->next_task;
+- } while (thread != init_tasks[0]);
+-
+- return NULL;
+-}
+-
+-#endif /* CONFIG_KGDB_THREAD */
+-
+-/* Scan for the start char '$', read the packet and check the checksum */
+-static void get_packet(char *buffer, int buflen)
+-{
+- unsigned char checksum;
+- unsigned char xmitcsum;
+- int i;
+- int count;
+- char ch;
+-
+- do {
+- /* Ignore everything until the start character */
+- while ((ch = get_debug_char()) != '$');
+-
+- checksum = 0;
+- xmitcsum = -1;
+- count = 0;
+-
+- /* Now, read until a # or end of buffer is found */
+- while (count < (buflen - 1)) {
+- ch = get_debug_char();
+-
+- if (ch == '#')
+- break;
+-
+- checksum = checksum + ch;
+- buffer[count] = ch;
+- count = count + 1;
+- }
+-
+- buffer[count] = 0;
+-
+- /* Continue to read checksum following # */
+- if (ch == '#') {
+- xmitcsum = hex(get_debug_char()) << 4;
+- xmitcsum += hex(get_debug_char());
+-
+- /* Checksum */
+- if (checksum != xmitcsum)
+- put_debug_char('-'); /* Failed checksum */
+- else {
+- /* Ack successful transfer */
+- put_debug_char('+');
+-
+- /* If a sequence char is present, reply
+- the sequence ID */
+- if (buffer[2] == ':') {
+- put_debug_char(buffer[0]);
+- put_debug_char(buffer[1]);
+-
+- /* Remove sequence chars from buffer */
+- count = strlen(buffer);
+- for (i = 3; i <= count; i++)
+- buffer[i - 3] = buffer[i];
+- }
+- }
+- }
+- }
+- while (checksum != xmitcsum); /* Keep trying while we fail */
+-}
+-
+-/* Send the packet in the buffer with run-length encoding */
+-static void put_packet(char *buffer)
+-{
+- int checksum;
+- char *src;
+- int runlen;
+- int encode;
+-
+- do {
+- src = buffer;
+- put_debug_char('$');
+- checksum = 0;
+-
+- /* Continue while we still have chars left */
+- while (*src) {
+- /* Check for runs up to 99 chars long */
+- for (runlen = 1; runlen < 99; runlen++) {
+- if (src[0] != src[runlen])
+- break;
+- }
+-
+- if (runlen > 3) {
+- /* Got a useful amount, send encoding */
+- encode = runlen + ' ' - 4;
+- put_debug_char(*src); checksum += *src;
+- put_debug_char('*'); checksum += '*';
+- put_debug_char(encode); checksum += encode;
+- src += runlen;
+- } else {
+- /* Otherwise just send the current char */
+- put_debug_char(*src); checksum += *src;
+- src += 1;
+- }
+- }
+-
+- /* '#' Separator, put high and low components of checksum */
+- put_debug_char('#');
+- put_debug_char(highhex(checksum));
+- put_debug_char(lowhex(checksum));
+- }
+- while ((get_debug_char()) != '+'); /* While no ack */
+-}
+-
+-/* A bus error has occurred - perform a longjmp to return execution and
+- allow handling of the error */
+-static void kgdb_handle_bus_error(void)
+-{
+- longjmp(rem_com_env, 1);
+-}
+-
+-/* Translate SH-3/4 exception numbers to unix-like signal values */
+-static int compute_signal(const int excep_code)
+-{
+- int sigval;
+-
+- switch (excep_code) {
+-
+- case INVALID_INSN_VEC:
+- case INVALID_SLOT_VEC:
+- sigval = SIGILL;
+- break;
+- case ADDRESS_ERROR_LOAD_VEC:
+- case ADDRESS_ERROR_STORE_VEC:
+- sigval = SIGSEGV;
+- break;
+-
+- case SERIAL_BREAK_VEC:
+- case NMI_VEC:
+- sigval = SIGINT;
+- break;
+-
+- case USER_BREAK_VEC:
+- case TRAP_VEC:
+- sigval = SIGTRAP;
+- break;
+-
+- default:
+- sigval = SIGBUS; /* "software generated" */
+- break;
+- }
+-
+- return (sigval);
+-}
+-
+-/* Make a local copy of the registers passed into the handler (bletch) */
+-static void kgdb_regs_to_gdb_regs(const struct kgdb_regs *regs,
+- int *gdb_regs)
+-{
+- gdb_regs[R0] = regs->regs[R0];
+- gdb_regs[R1] = regs->regs[R1];
+- gdb_regs[R2] = regs->regs[R2];
+- gdb_regs[R3] = regs->regs[R3];
+- gdb_regs[R4] = regs->regs[R4];
+- gdb_regs[R5] = regs->regs[R5];
+- gdb_regs[R6] = regs->regs[R6];
+- gdb_regs[R7] = regs->regs[R7];
+- gdb_regs[R8] = regs->regs[R8];
+- gdb_regs[R9] = regs->regs[R9];
+- gdb_regs[R10] = regs->regs[R10];
+- gdb_regs[R11] = regs->regs[R11];
+- gdb_regs[R12] = regs->regs[R12];
+- gdb_regs[R13] = regs->regs[R13];
+- gdb_regs[R14] = regs->regs[R14];
+- gdb_regs[R15] = regs->regs[R15];
+- gdb_regs[PC] = regs->pc;
+- gdb_regs[PR] = regs->pr;
+- gdb_regs[GBR] = regs->gbr;
+- gdb_regs[MACH] = regs->mach;
+- gdb_regs[MACL] = regs->macl;
+- gdb_regs[SR] = regs->sr;
+- gdb_regs[VBR] = regs->vbr;
+-}
+-
+-/* Copy local gdb registers back to kgdb regs, for later copy to kernel */
+-static void gdb_regs_to_kgdb_regs(const int *gdb_regs,
+- struct kgdb_regs *regs)
+-{
+- regs->regs[R0] = gdb_regs[R0];
+- regs->regs[R1] = gdb_regs[R1];
+- regs->regs[R2] = gdb_regs[R2];
+- regs->regs[R3] = gdb_regs[R3];
+- regs->regs[R4] = gdb_regs[R4];
+- regs->regs[R5] = gdb_regs[R5];
+- regs->regs[R6] = gdb_regs[R6];
+- regs->regs[R7] = gdb_regs[R7];
+- regs->regs[R8] = gdb_regs[R8];
+- regs->regs[R9] = gdb_regs[R9];
+- regs->regs[R10] = gdb_regs[R10];
+- regs->regs[R11] = gdb_regs[R11];
+- regs->regs[R12] = gdb_regs[R12];
+- regs->regs[R13] = gdb_regs[R13];
+- regs->regs[R14] = gdb_regs[R14];
+- regs->regs[R15] = gdb_regs[R15];
+- regs->pc = gdb_regs[PC];
+- regs->pr = gdb_regs[PR];
+- regs->gbr = gdb_regs[GBR];
+- regs->mach = gdb_regs[MACH];
+- regs->macl = gdb_regs[MACL];
+- regs->sr = gdb_regs[SR];
+- regs->vbr = gdb_regs[VBR];
+-}
+-
+-#ifdef CONFIG_KGDB_THREAD
+-/* Make a local copy of registers from the specified thread */
+-asmlinkage void ret_from_fork(void);
+-static void thread_regs_to_gdb_regs(const struct task_struct *thread,
+- int *gdb_regs)
+-{
+- int regno;
+- int *tregs;
+-
+- /* Initialize to zero */
+- for (regno = 0; regno < MAXREG; regno++)
+- gdb_regs[regno] = 0;
+-
+- /* Just making sure... */
+- if (thread == NULL)
+- return;
+-
+- /* A new fork has pt_regs on the stack from a fork() call */
+- if (thread->thread.pc == (unsigned long)ret_from_fork) {
+-
+- int vbr_val;
+- struct pt_regs *kregs;
+- kregs = (struct pt_regs*)thread->thread.sp;
+-
+- gdb_regs[R0] = kregs->regs[R0];
+- gdb_regs[R1] = kregs->regs[R1];
+- gdb_regs[R2] = kregs->regs[R2];
+- gdb_regs[R3] = kregs->regs[R3];
+- gdb_regs[R4] = kregs->regs[R4];
+- gdb_regs[R5] = kregs->regs[R5];
+- gdb_regs[R6] = kregs->regs[R6];
+- gdb_regs[R7] = kregs->regs[R7];
+- gdb_regs[R8] = kregs->regs[R8];
+- gdb_regs[R9] = kregs->regs[R9];
+- gdb_regs[R10] = kregs->regs[R10];
+- gdb_regs[R11] = kregs->regs[R11];
+- gdb_regs[R12] = kregs->regs[R12];
+- gdb_regs[R13] = kregs->regs[R13];
+- gdb_regs[R14] = kregs->regs[R14];
+- gdb_regs[R15] = kregs->regs[R15];
+- gdb_regs[PC] = kregs->pc;
+- gdb_regs[PR] = kregs->pr;
+- gdb_regs[GBR] = kregs->gbr;
+- gdb_regs[MACH] = kregs->mach;
+- gdb_regs[MACL] = kregs->macl;
+- gdb_regs[SR] = kregs->sr;
+-
+- asm("stc vbr, %0":"=r"(vbr_val));
+- gdb_regs[VBR] = vbr_val;
+- return;
+- }
+-
+- /* Otherwise, we have only some registers from switch_to() */
+- tregs = (int *)thread->thread.sp;
+- gdb_regs[R15] = (int)tregs;
+- gdb_regs[R14] = *tregs++;
+- gdb_regs[R13] = *tregs++;
+- gdb_regs[R12] = *tregs++;
+- gdb_regs[R11] = *tregs++;
+- gdb_regs[R10] = *tregs++;
+- gdb_regs[R9] = *tregs++;
+- gdb_regs[R8] = *tregs++;
+- gdb_regs[PR] = *tregs++;
+- gdb_regs[GBR] = *tregs++;
+- gdb_regs[PC] = thread->thread.pc;
+-}
+-#endif /* CONFIG_KGDB_THREAD */
+-
+-/* Calculate the new address for after a step */
+-static short *get_step_address(void)
+-{
+- short op = *(short *) trap_registers.pc;
+- long addr;
+-
+- /* BT */
+- if (OPCODE_BT(op)) {
+- if (trap_registers.sr & SR_T_BIT_MASK)
+- addr = trap_registers.pc + 4 + OPCODE_BTF_DISP(op);
+- else
+- addr = trap_registers.pc + 2;
+- }
+-
+- /* BTS */
+- else if (OPCODE_BTS(op)) {
+- if (trap_registers.sr & SR_T_BIT_MASK)
+- addr = trap_registers.pc + 4 + OPCODE_BTF_DISP(op);
+- else
+- addr = trap_registers.pc + 4; /* Not in delay slot */
+- }
+-
+- /* BF */
+- else if (OPCODE_BF(op)) {
+- if (!(trap_registers.sr & SR_T_BIT_MASK))
+- addr = trap_registers.pc + 4 + OPCODE_BTF_DISP(op);
+- else
+- addr = trap_registers.pc + 2;
+- }
+-
+- /* BFS */
+- else if (OPCODE_BFS(op)) {
+- if (!(trap_registers.sr & SR_T_BIT_MASK))
+- addr = trap_registers.pc + 4 + OPCODE_BTF_DISP(op);
+- else
+- addr = trap_registers.pc + 4; /* Not in delay slot */
+- }
+-
+- /* BRA */
+- else if (OPCODE_BRA(op))
+- addr = trap_registers.pc + 4 + OPCODE_BRA_DISP(op);
+-
+- /* BRAF */
+- else if (OPCODE_BRAF(op))
+- addr = trap_registers.pc + 4
+- + trap_registers.regs[OPCODE_BRAF_REG(op)];
+-
+- /* BSR */
+- else if (OPCODE_BSR(op))
+- addr = trap_registers.pc + 4 + OPCODE_BSR_DISP(op);
+-
+- /* BSRF */
+- else if (OPCODE_BSRF(op))
+- addr = trap_registers.pc + 4
+- + trap_registers.regs[OPCODE_BSRF_REG(op)];
+-
+- /* JMP */
+- else if (OPCODE_JMP(op))
+- addr = trap_registers.regs[OPCODE_JMP_REG(op)];
+-
+- /* JSR */
+- else if (OPCODE_JSR(op))
+- addr = trap_registers.regs[OPCODE_JSR_REG(op)];
+-
+- /* RTS */
+- else if (OPCODE_RTS(op))
+- addr = trap_registers.pr;
+-
+- /* RTE */
+- else if (OPCODE_RTE(op))
+- addr = trap_registers.regs[15];
+-
+- /* Other */
+- else
+- addr = trap_registers.pc + 2;
+-
+- kgdb_flush_icache_range(addr, addr + 2);
+- return (short *) addr;
+-}
+-
+-/* Set up a single-step. Replace the instruction immediately after the
+- current instruction (i.e. next in the expected flow of control) with a
+- trap instruction, so that returning will cause only a single instruction
+- to be executed. Note that this model is slightly broken for instructions
+- with delay slots (e.g. B[TF]S, BSR, BRA etc), where both the branch
+- and the instruction in the delay slot will be executed. */
+-static void do_single_step(void)
+-{
+- unsigned short *addr = 0;
+-
+- /* Determine where the target instruction will send us to */
+- addr = get_step_address();
+- stepped_address = (int)addr;
+-
+- /* Replace it */
+- stepped_opcode = *(short *)addr;
+- *addr = STEP_OPCODE;
+-
+- /* Flush and return */
+- kgdb_flush_icache_range((long) addr, (long) addr + 2);
+- return;
+-}
+-
+-/* Undo a single step */
+-static void undo_single_step(void)
+-{
+- /* If we have stepped, put back the old instruction */
+- /* Use stepped_address in case we stopped elsewhere */
+- if (stepped_opcode != 0) {
+- *(short*)stepped_address = stepped_opcode;
+- kgdb_flush_icache_range(stepped_address, stepped_address + 2);
+- }
+- stepped_opcode = 0;
+-}
+-
+-/* Send a signal message */
+-static void send_signal_msg(const int signum)
+-{
+-#ifndef CONFIG_KGDB_THREAD
+- out_buffer[0] = 'S';
+- out_buffer[1] = highhex(signum);
+- out_buffer[2] = lowhex(signum);
+- out_buffer[3] = 0;
+- put_packet(out_buffer);
+-#else /* CONFIG_KGDB_THREAD */
+- int threadid;
+- threadref thref;
+- char *out = out_buffer;
+- const char *tstring = "thread";
+-
+- *out++ = 'T';
+- *out++ = highhex(signum);
+- *out++ = lowhex(signum);
+-
+- while (*tstring) {
+- *out++ = *tstring++;
+- }
+- *out++ = ':';
+-
+- threadid = trapped_thread->pid;
+- if (threadid == 0) threadid = PID_MAX;
+- int_to_threadref(&thref, threadid);
+- pack_threadid(out, &thref);
+- out += BUF_THREAD_ID_SIZE;
+- *out++ = ';';
+-
+- *out = 0;
+- put_packet(out_buffer);
+-#endif /* CONFIG_KGDB_THREAD */
+-}
+-
+-/* Reply that all was well */
+-static void send_ok_msg(void)
+-{
+- strcpy(out_buffer, "OK");
+- put_packet(out_buffer);
+-}
+-
+-/* Reply that an error occurred */
+-static void send_err_msg(void)
+-{
+- strcpy(out_buffer, "E01");
+- put_packet(out_buffer);
+-}
+-
+-/* Empty message indicates unrecognised command */
+-static void send_empty_msg(void)
+-{
+- put_packet("");
+-}
+-
+-/* Read memory due to 'm' message */
+-static void read_mem_msg(void)
+-{
+- char *ptr;
+- int addr;
+- int length;
+-
+- /* Jmp, disable bus error handler */
+- if (setjmp(rem_com_env) == 0) {
+-
+- kgdb_nofault = 1;
+-
+- /* Walk through, have m<addr>,<length> */
+- ptr = &in_buffer[1];
+- if (hex_to_int(&ptr, &addr) && (*ptr++ == ','))
+- if (hex_to_int(&ptr, &length)) {
+- ptr = 0;
+- if (length * 2 > OUTBUFMAX)
+- length = OUTBUFMAX / 2;
+- mem_to_hex((char *) addr, out_buffer, length);
+- }
+- if (ptr)
+- send_err_msg();
+- else
+- put_packet(out_buffer);
+- } else
+- send_err_msg();
+-
+- /* Restore bus error handler */
+- kgdb_nofault = 0;
+-}
+-
+-/* Write memory due to 'M' or 'X' message */
+-static void write_mem_msg(int binary)
+-{
+- char *ptr;
+- int addr;
+- int length;
+-
+- if (setjmp(rem_com_env) == 0) {
+-
+- kgdb_nofault = 1;
+-
+- /* Walk through, have M<addr>,<length>:<data> */
+- ptr = &in_buffer[1];
+- if (hex_to_int(&ptr, &addr) && (*ptr++ == ','))
+- if (hex_to_int(&ptr, &length) && (*ptr++ == ':')) {
+- if (binary)
+- ebin_to_mem(ptr, (char*)addr, length);
+- else
+- hex_to_mem(ptr, (char*)addr, length);
+- kgdb_flush_icache_range(addr, addr + length);
+- ptr = 0;
+- send_ok_msg();
+- }
+- if (ptr)
+- send_err_msg();
+- } else
+- send_err_msg();
+-
+- /* Restore bus error handler */
+- kgdb_nofault = 0;
+-}
+-
+-/* Continue message */
+-static void continue_msg(void)
+-{
+- /* Try to read optional parameter, PC unchanged if none */
+- char *ptr = &in_buffer[1];
+- int addr;
+-
+- if (hex_to_int(&ptr, &addr))
+- trap_registers.pc = addr;
+-}
+-
+-/* Continue message with signal */
+-static void continue_with_sig_msg(void)
+-{
+- int signal;
+- char *ptr = &in_buffer[1];
+- int addr;
+-
+- /* Report limitation */
+- kgdb_to_gdb("Cannot force signal in kgdb, continuing anyway.\n");
+-
+- /* Signal */
+- hex_to_int(&ptr, &signal);
+- if (*ptr == ';')
+- ptr++;
+-
+- /* Optional address */
+- if (hex_to_int(&ptr, &addr))
+- trap_registers.pc = addr;
+-}
+-
+-/* Step message */
+-static void step_msg(void)
+-{
+- continue_msg();
+- do_single_step();
+-}
+-
+-/* Step message with signal */
+-static void step_with_sig_msg(void)
+-{
+- continue_with_sig_msg();
+- do_single_step();
+-}
+-
+-/* Send register contents */
+-static void send_regs_msg(void)
+-{
+-#ifdef CONFIG_KGDB_THREAD
+- if (!current_thread)
+- kgdb_regs_to_gdb_regs(&trap_registers, registers);
+- else
+- thread_regs_to_gdb_regs(current_thread, registers);
+-#else
+- kgdb_regs_to_gdb_regs(&trap_registers, registers);
+-#endif
+-
+- mem_to_hex((char *) registers, out_buffer, NUMREGBYTES);
+- put_packet(out_buffer);
+-}
+-
+-/* Set register contents - currently can't set other thread's registers */
+-static void set_regs_msg(void)
+-{
+-#ifdef CONFIG_KGDB_THREAD
+- if (!current_thread) {
+-#endif
+- kgdb_regs_to_gdb_regs(&trap_registers, registers);
+- hex_to_mem(&in_buffer[1], (char *) registers, NUMREGBYTES);
+- gdb_regs_to_kgdb_regs(registers, &trap_registers);
+- send_ok_msg();
+-#ifdef CONFIG_KGDB_THREAD
+- } else
+- send_err_msg();
+-#endif
+-}
+-
+-
+-#ifdef CONFIG_KGDB_THREAD
+-
+-/* Set the status for a thread */
+-void set_thread_msg(void)
+-{
+- int threadid;
+- struct task_struct *thread = NULL;
+- char *ptr;
+-
+- switch (in_buffer[1]) {
+-
+- /* To select which thread for gG etc messages, i.e. supported */
+- case 'g':
+-
+- ptr = &in_buffer[2];
+- hex_to_int(&ptr, &threadid);
+- thread = get_thread(threadid);
+-
+- /* If we haven't found it */
+- if (!thread) {
+- send_err_msg();
+- break;
+- }
+-
+- /* Set current_thread (or not) */
+- if (thread == trapped_thread)
+- current_thread = NULL;
+- else
+- current_thread = thread;
+- send_ok_msg();
+- break;
+-
+- /* To select which thread for cCsS messages, i.e. unsupported */
+- case 'c':
+- send_ok_msg();
+- break;
+-
+- default:
+- send_empty_msg();
+- break;
+- }
+-}
+-
+-/* Is a thread alive? */
+-static void thread_status_msg(void)
+-{
+- char *ptr;
+- int threadid;
+- struct task_struct *thread = NULL;
+-
+- ptr = &in_buffer[1];
+- hex_to_int(&ptr, &threadid);
+- thread = get_thread(threadid);
+- if (thread)
+- send_ok_msg();
+- else
+- send_err_msg();
+-}
+-/* Send the current thread ID */
+-static void thread_id_msg(void)
+-{
+- int threadid;
+- threadref thref;
+-
+- out_buffer[0] = 'Q';
+- out_buffer[1] = 'C';
+-
+- if (current_thread)
+- threadid = current_thread->pid;
+- else if (trapped_thread)
+- threadid = trapped_thread->pid;
+- else /* Impossible, but just in case! */
+- {
+- send_err_msg();
+- return;
+- }
+-
+- /* Translate pid 0 to PID_MAX for gdb */
+- if (threadid == 0) threadid = PID_MAX;
+-
+- int_to_threadref(&thref, threadid);
+- pack_threadid(out_buffer + 2, &thref);
+- out_buffer[2 + BUF_THREAD_ID_SIZE] = '\0';
+- put_packet(out_buffer);
+-}
+-
+-/* Send thread info */
+-static void thread_info_msg(void)
+-{
+- struct task_struct *thread = NULL;
+- int threadid;
+- char *pos;
+- threadref thref;
+-
+- /* Start with 'm' */
+- out_buffer[0] = 'm';
+- pos = &out_buffer[1];
+-
+- /* For all possible thread IDs - this will overrun if > 44 threads! */
+- /* Start at 1 and include PID_MAX (since GDB won't use pid 0...) */
+- for (threadid = 1; threadid <= PID_MAX; threadid++) {
+-
+- read_lock(&tasklist_lock);
+- thread = get_thread(threadid);
+- read_unlock(&tasklist_lock);
+-
+- /* If it's a valid thread */
+- if (thread) {
+- int_to_threadref(&thref, threadid);
+- pack_threadid(pos, &thref);
+- pos += BUF_THREAD_ID_SIZE;
+- *pos++ = ',';
+- }
+- }
+- *--pos = 0; /* Lose final comma */
+- put_packet(out_buffer);
+-
+-}
+-
+-/* Return printable info for gdb's 'info threads' command */
+-static void thread_extra_info_msg(void)
+-{
+- int threadid;
+- struct task_struct *thread = NULL;
+- char buffer[20], *ptr;
+- int i;
+-
+- /* Extract thread ID */
+- ptr = &in_buffer[17];
+- hex_to_int(&ptr, &threadid);
+- thread = get_thread(threadid);
+-
+- /* If we don't recognise it, say so */
+- if (thread == NULL)
+- strcpy(buffer, "(unknown)");
+- else
+- strcpy(buffer, thread->comm);
+-
+- /* Construct packet */
+- for (i = 0, ptr = out_buffer; buffer[i]; i++)
+- ptr = pack_hex_byte(ptr, buffer[i]);
+-
+- if (thread->thread.pc == (unsigned long)ret_from_fork) {
+- strcpy(buffer, "<new fork>");
+- for (i = 0; buffer[i]; i++)
+- ptr = pack_hex_byte(ptr, buffer[i]);
+- }
+-
+- *ptr = '\0';
+- put_packet(out_buffer);
+-}
+-
+-/* Handle all qFooBarBaz messages - have to use an if statement as
+- opposed to a switch because q messages can have > 1 char id. */
+-static void query_msg(void)
+-{
+- const char *q_start = &in_buffer[1];
+-
+- /* qC = return current thread ID */
+- if (strncmp(q_start, "C", 1) == 0)
+- thread_id_msg();
+-
+- /* qfThreadInfo = query all threads (first) */
+- else if (strncmp(q_start, "fThreadInfo", 11) == 0)
+- thread_info_msg();
+-
+- /* qsThreadInfo = query all threads (subsequent). We know we have sent
+- them all after the qfThreadInfo message, so there are no to send */
+- else if (strncmp(q_start, "sThreadInfo", 11) == 0)
+- put_packet("l"); /* el = last */
+-
+- /* qThreadExtraInfo = supply printable information per thread */
+- else if (strncmp(q_start, "ThreadExtraInfo", 15) == 0)
+- thread_extra_info_msg();
+-
+- /* Unsupported - empty message as per spec */
+- else
+- send_empty_msg();
+-}
+-#endif /* CONFIG_KGDB_THREAD */
+-
+-/*
+- * Bring up the ports..
+- */
+-static int kgdb_serial_setup(void)
+-{
+- extern int kgdb_console_setup(struct console *co, char *options);
+- struct console dummy;
+-
+- kgdb_console_setup(&dummy, 0);
+-
+- return 0;
+-}
+-
+-/* The command loop, read and act on requests */
+-static void kgdb_command_loop(const int excep_code, const int trapa_value)
+-{
+- int sigval;
+-
+- if (excep_code == NMI_VEC) {
+-#ifndef CONFIG_KGDB_NMI
+- KGDB_PRINTK("Ignoring unexpected NMI?\n");
+- return;
+-#else /* CONFIG_KGDB_NMI */
+- if (!kgdb_enabled) {
+- kgdb_enabled = 1;
+- kgdb_init();
+- }
+-#endif /* CONFIG_KGDB_NMI */
+- }
+-
+- /* Ignore if we're disabled */
+- if (!kgdb_enabled)
+- return;
+-
+-#ifdef CONFIG_KGDB_THREAD
+- /* Until GDB specifies a thread */
+- current_thread = NULL;
+- trapped_thread = current;
+-#endif
+-
+- /* Enter GDB mode (e.g. after detach) */
+- if (!kgdb_in_gdb_mode) {
+- /* Do serial setup, notify user, issue preemptive ack */
+- kgdb_serial_setup();
+- KGDB_PRINTK("Waiting for GDB (on %s%d at %d baud)\n",
+- (kgdb_porttype ? kgdb_porttype->name : ""),
+- kgdb_portnum, kgdb_baud);
+- kgdb_in_gdb_mode = 1;
+- put_debug_char('+');
+- }
+-
+- /* Reply to host that an exception has occurred */
+- sigval = compute_signal(excep_code);
+- send_signal_msg(sigval);
+-
+- /* TRAP_VEC exception indicates a software trap inserted in place of
+- code by GDB so back up PC by one instruction, as this instruction
+- will later be replaced by its original one. Do NOT do this for
+- trap 0xff, since that indicates a compiled-in breakpoint which
+- will not be replaced (and we would retake the trap forever) */
+- if ((excep_code == TRAP_VEC) && (trapa_value != (0xff << 2))) {
+- trap_registers.pc -= 2;
+- }
+-
+- /* Undo any stepping we may have done */
+- undo_single_step();
+-
+- while (1) {
+-
+- out_buffer[0] = 0;
+- get_packet(in_buffer, BUFMAX);
+-
+- /* Examine first char of buffer to see what we need to do */
+- switch (in_buffer[0]) {
+-
+- case '?': /* Send which signal we've received */
+- send_signal_msg(sigval);
+- break;
+-
+- case 'g': /* Return the values of the CPU registers */
+- send_regs_msg();
+- break;
+-
+- case 'G': /* Set the value of the CPU registers */
+- set_regs_msg();
+- break;
+-
+- case 'm': /* Read LLLL bytes address AA..AA */
+- read_mem_msg();
+- break;
+-
+- case 'M': /* Write LLLL bytes address AA..AA, ret OK */
+- write_mem_msg(0); /* 0 = data in hex */
+- break;
+-
+- case 'X': /* Write LLLL bytes esc bin address AA..AA */
+- if (kgdb_bits == '8')
+- write_mem_msg(1); /* 1 = data in binary */
+- else
+- send_empty_msg();
+- break;
+-
+- case 'C': /* Continue, signum included, we ignore it */
+- continue_with_sig_msg();
+- return;
+-
+- case 'c': /* Continue at address AA..AA (optional) */
+- continue_msg();
+- return;
+-
+- case 'S': /* Step, signum included, we ignore it */
+- step_with_sig_msg();
+- return;
+-
+- case 's': /* Step one instruction from AA..AA */
+- step_msg();
+- return;
+-
+-#ifdef CONFIG_KGDB_THREAD
+-
+- case 'H': /* Task related */
+- set_thread_msg();
+- break;
+-
+- case 'T': /* Query thread status */
+- thread_status_msg();
+- break;
+-
+- case 'q': /* Handle query - currently thread-related */
+- query_msg();
+- break;
+-#endif
+-
+- case 'k': /* 'Kill the program' with a kernel ? */
+- break;
+-
+- case 'D': /* Detach from program, send reply OK */
+- kgdb_in_gdb_mode = 0;
+- send_ok_msg();
+- get_debug_char();
+- return;
+-
+- default:
+- send_empty_msg();
+- break;
+- }
+- }
+-}
+-
+-/* There has been an exception, most likely a breakpoint. */
+-void kgdb_handle_exception(struct pt_regs *regs)
+-{
+- int excep_code, vbr_val;
+- int count;
+- int trapa_value = ctrl_inl(TRA);
+-
+- /* Copy kernel regs (from stack) */
+- for (count = 0; count < 16; count++)
+- trap_registers.regs[count] = regs->regs[count];
+- trap_registers.pc = regs->pc;
+- trap_registers.pr = regs->pr;
+- trap_registers.sr = regs->sr;
+- trap_registers.gbr = regs->gbr;
+- trap_registers.mach = regs->mach;
+- trap_registers.macl = regs->macl;
+-
+- asm("stc vbr, %0":"=r"(vbr_val));
+- trap_registers.vbr = vbr_val;
+-
+- /* Get excode for command loop call, user access */
+- asm("stc r2_bank, %0":"=r"(excep_code));
+- kgdb_excode = excep_code;
+-
+- /* Other interesting environment items for reference */
+- asm("stc r6_bank, %0":"=r"(kgdb_g_imask));
+- kgdb_current = current;
+- kgdb_trapa_val = trapa_value;
+-
+- /* Act on the exception */
+- kgdb_command_loop(excep_code >> 5, trapa_value);
+-
+- kgdb_current = NULL;
+-
+- /* Copy back the (maybe modified) registers */
+- for (count = 0; count < 16; count++)
+- regs->regs[count] = trap_registers.regs[count];
+- regs->pc = trap_registers.pc;
+- regs->pr = trap_registers.pr;
+- regs->sr = trap_registers.sr;
+- regs->gbr = trap_registers.gbr;
+- regs->mach = trap_registers.mach;
+- regs->macl = trap_registers.macl;
+-
+- vbr_val = trap_registers.vbr;
+- asm("ldc %0, vbr": :"r"(vbr_val));
+-
+- return;
+-}
+-
+-/* Trigger a breakpoint by function */
+-void breakpoint(void)
+-{
+- if (!kgdb_enabled) {
+- kgdb_enabled = 1;
+- kgdb_init();
+- }
+- BREAKPOINT();
+-}
+-
+-/* Initialise the KGDB data structures and serial configuration */
+-int kgdb_init(void)
+-{
+- if (!kgdb_enabled)
+- return 1;
+-
+- in_nmi = 0;
+- kgdb_nofault = 0;
+- stepped_opcode = 0;
+- kgdb_in_gdb_mode = 0;
+-
+- if (kgdb_serial_setup() != 0) {
+- KGDB_PRINTK("serial setup error\n");
+- return -1;
+- }
+-
+- /* Init ptr to exception handler */
+- kgdb_debug_hook = kgdb_handle_exception;
+- kgdb_bus_err_hook = kgdb_handle_bus_error;
+-
+- /* Enter kgdb now if requested, or just report init done */
+- if (kgdb_halt) {
+- kgdb_in_gdb_mode = 1;
+- put_debug_char('+');
+- breakpoint();
+- }
+- else
+- {
+- KGDB_PRINTK("stub is initialized.\n");
+- }
+-
+- return 0;
+-}
+-
+-/* Make function available for "user messages"; console will use it too. */
+-
+-char gdbmsgbuf[BUFMAX];
+-#define MAXOUT ((BUFMAX-2)/2)
+-
+-static void kgdb_msg_write(const char *s, unsigned count)
+-{
+- int i;
+- int wcount;
+- char *bufptr;
+-
+- /* 'O'utput */
+- gdbmsgbuf[0] = 'O';
+-
+- /* Fill and send buffers... */
+- while (count > 0) {
+- bufptr = gdbmsgbuf + 1;
+-
+- /* Calculate how many this time */
+- wcount = (count > MAXOUT) ? MAXOUT : count;
+-
+- /* Pack in hex chars */
+- for (i = 0; i < wcount; i++)
+- bufptr = pack_hex_byte(bufptr, s[i]);
+- *bufptr = '\0';
+-
+- /* Move up */
+- s += wcount;
+- count -= wcount;
+-
+- /* Write packet */
+- put_packet(gdbmsgbuf);
+- }
+-}
+-
+-static void kgdb_to_gdb(const char *s)
+-{
+- kgdb_msg_write(s, strlen(s));
+-}
+-
+-#ifdef CONFIG_SH_KGDB_CONSOLE
+-void kgdb_console_write(struct console *co, const char *s, unsigned count)
+-{
+- /* Bail if we're not talking to GDB */
+- if (!kgdb_in_gdb_mode)
+- return;
+-
+- kgdb_msg_write(s, count);
+-}
+-#endif
+diff -rupN -X ../client-cleanup/dontdiff linux-2.6.18/arch/sh/kernel/setup.c linux-2.6.18.kgdb/arch/sh/kernel/setup.c
+--- linux-2.6.18/arch/sh/kernel/setup.c 2006-09-20 07:42:06.000000000 +0400
++++ linux-2.6.18.kgdb/arch/sh/kernel/setup.c 2008-06-10 16:19:47.000000000 +0400
+@@ -28,10 +28,6 @@
+ #include <asm/setup.h>
+ #include <asm/clock.h>
+
+-#ifdef CONFIG_SH_KGDB
+-#include <asm/kgdb.h>
+-static int kgdb_parse_options(char *options);
+-#endif
+ extern void * __rd_start, * __rd_end;
+ /*
+ * Machine setup..
+@@ -528,93 +524,3 @@ struct seq_operations cpuinfo_op = {
+ .show = show_cpuinfo,
+ };
+ #endif /* CONFIG_PROC_FS */
+-
+-#ifdef CONFIG_SH_KGDB
+-/*
+- * Parse command-line kgdb options. By default KGDB is enabled,
+- * entered on error (or other action) using default serial info.
+- * The command-line option can include a serial port specification
+- * and an action to override default or configured behavior.
+- */
+-struct kgdb_sermap kgdb_sci_sermap =
+-{ "ttySC", 5, kgdb_sci_setup, NULL };
+-
+-struct kgdb_sermap *kgdb_serlist = &kgdb_sci_sermap;
+-struct kgdb_sermap *kgdb_porttype = &kgdb_sci_sermap;
+-
+-void kgdb_register_sermap(struct kgdb_sermap *map)
+-{
+- struct kgdb_sermap *last;
+-
+- for (last = kgdb_serlist; last->next; last = last->next)
+- ;
+- last->next = map;
+- if (!map->namelen) {
+- map->namelen = strlen(map->name);
+- }
+-}
+-
+-static int __init kgdb_parse_options(char *options)
+-{
+- char c;
+- int baud;
+-
+- /* Check for port spec (or use default) */
+-
+- /* Determine port type and instance */
+- if (!memcmp(options, "tty", 3)) {
+- struct kgdb_sermap *map = kgdb_serlist;
+-
+- while (map && memcmp(options, map->name, map->namelen))
+- map = map->next;
+-
+- if (!map) {
+- KGDB_PRINTK("unknown port spec in %s\n", options);
+- return -1;
+- }
+-
+- kgdb_porttype = map;
+- kgdb_serial_setup = map->setup_fn;
+- kgdb_portnum = options[map->namelen] - '0';
+- options += map->namelen + 1;
+-
+- options = (*options == ',') ? options+1 : options;
+-
+- /* Read optional parameters (baud/parity/bits) */
+- baud = simple_strtoul(options, &options, 10);
+- if (baud != 0) {
+- kgdb_baud = baud;
+-
+- c = toupper(*options);
+- if (c == 'E' || c == 'O' || c == 'N') {
+- kgdb_parity = c;
+- options++;
+- }
+-
+- c = *options;
+- if (c == '7' || c == '8') {
+- kgdb_bits = c;
+- options++;
+- }
+- options = (*options == ',') ? options+1 : options;
+- }
+- }
+-
+- /* Check for action specification */
+- if (!memcmp(options, "halt", 4)) {
+- kgdb_halt = 1;
+- options += 4;
+- } else if (!memcmp(options, "disabled", 8)) {
+- kgdb_enabled = 0;
+- options += 8;
+- }
+-
+- if (*options) {
+- KGDB_PRINTK("ignored unknown options: %s\n", options);
+- return 0;
+- }
+- return 1;
+-}
+-__setup("kgdb=", kgdb_parse_options);
+-#endif /* CONFIG_SH_KGDB */
+-
+diff -rupN -X ../client-cleanup/dontdiff linux-2.6.18/arch/sh/kernel/time.c linux-2.6.18.kgdb/arch/sh/kernel/time.c
+--- linux-2.6.18/arch/sh/kernel/time.c 2006-09-20 07:42:06.000000000 +0400
++++ linux-2.6.18.kgdb/arch/sh/kernel/time.c 2008-06-10 16:19:47.000000000 +0400
+@@ -184,12 +184,4 @@ void __init time_init(void)
+ */
+ sys_timer = get_sys_timer();
+ printk(KERN_INFO "Using %s for system timer\n", sys_timer->name);
+-
+-#if defined(CONFIG_SH_KGDB)
+- /*
+- * Set up kgdb as requested. We do it here because the serial
+- * init uses the timer vars we just set up for figuring baud.
+- */
+- kgdb_init();
+-#endif
+ }
+diff -rupN -X ../client-cleanup/dontdiff linux-2.6.18/arch/sh/kernel/traps.c linux-2.6.18.kgdb/arch/sh/kernel/traps.c
+--- linux-2.6.18/arch/sh/kernel/traps.c 2006-09-20 07:42:06.000000000 +0400
++++ linux-2.6.18.kgdb/arch/sh/kernel/traps.c 2008-06-10 16:19:47.000000000 +0400
+@@ -26,6 +26,7 @@
+ #include <linux/spinlock.h>
+ #include <linux/module.h>
+ #include <linux/kallsyms.h>
++#include <linux/kgdb.h>
+
+ #include <asm/system.h>
+ #include <asm/uaccess.h>
+@@ -34,17 +35,8 @@
+ #include <asm/processor.h>
+ #include <asm/sections.h>
+
+-#ifdef CONFIG_SH_KGDB
+-#include <asm/kgdb.h>
+-#define CHK_REMOTE_DEBUG(regs) \
+-{ \
+- if ((kgdb_debug_hook != (kgdb_debug_hook_t *) NULL) && (!user_mode(regs))) \
+- { \
+- (*kgdb_debug_hook)(regs); \
+- } \
+-}
+-#else
+-#define CHK_REMOTE_DEBUG(regs)
++#ifndef CONFIG_KGDB
++#define kgdb_handle_exception(t, s, e, r)
+ #endif
+
+ #define DO_ERROR(trapnr, signr, str, name, tsk) \
+@@ -65,7 +57,7 @@ asmlinkage void do_##name(unsigned long
+ local_irq_enable(); \
+ tsk->thread.error_code = error_code; \
+ tsk->thread.trap_no = trapnr; \
+- CHK_REMOTE_DEBUG(®s); \
++ kgdb_handle_exception(trapnr, signr, error_code, ®s); \
+ force_sig(signr, tsk); \
+ die_if_no_fixup(str,®s,error_code); \
+ }
+@@ -92,10 +84,12 @@ void die(const char * str, struct pt_reg
+ {
+ static int die_counter;
+
++#ifdef CONFIG_KGDB
++ kgdb_handle_exception(1, SIGTRAP, err, regs);
++#endif
+ console_verbose();
+ spin_lock_irq(&die_lock);
+ printk("%s: %04lx [#%d]\n", str, err & 0xffff, ++die_counter);
+- CHK_REMOTE_DEBUG(regs);
+ show_regs(regs);
+ spin_unlock_irq(&die_lock);
+ do_exit(SIGSEGV);
+diff -rupN -X ../client-cleanup/dontdiff linux-2.6.18/arch/sh/mm/extable.c linux-2.6.18.kgdb/arch/sh/mm/extable.c
+--- linux-2.6.18/arch/sh/mm/extable.c 2006-09-20 07:42:06.000000000 +0400
++++ linux-2.6.18.kgdb/arch/sh/mm/extable.c 2008-06-10 16:19:47.000000000 +0400
+@@ -5,6 +5,7 @@
+ */
+
+ #include <linux/module.h>
++#include <linux/kgdb.h>
+ #include <asm/uaccess.h>
+
+ int fixup_exception(struct pt_regs *regs)
+@@ -16,6 +17,12 @@ int fixup_exception(struct pt_regs *regs
+ regs->pc = fixup->fixup;
+ return 1;
+ }
++#ifdef CONFIG_KGDB
++ if (atomic_read(&debugger_active) && kgdb_may_fault)
++ /* Restore our previous state. */
++ kgdb_fault_longjmp(kgdb_fault_jmp_regs);
++ /* Never reached. */
++#endif
+
+ return 0;
+ }
+diff -rupN -X ../client-cleanup/dontdiff linux-2.6.18/arch/sh/mm/fault-nommu.c linux-2.6.18.kgdb/arch/sh/mm/fault-nommu.c
+--- linux-2.6.18/arch/sh/mm/fault-nommu.c 2006-09-20 07:42:06.000000000 +0400
++++ linux-2.6.18.kgdb/arch/sh/mm/fault-nommu.c 2008-06-10 16:19:47.000000000 +0400
+@@ -29,10 +29,6 @@
+ #include <asm/mmu_context.h>
+ #include <asm/cacheflush.h>
+
+-#if defined(CONFIG_SH_KGDB)
+-#include <asm/kgdb.h>
+-#endif
+-
+ extern void die(const char *,struct pt_regs *,long);
+
+ /*
+@@ -43,11 +39,6 @@ extern void die(const char *,struct pt_r
+ asmlinkage void do_page_fault(struct pt_regs *regs, unsigned long writeaccess,
+ unsigned long address)
+ {
+-#if defined(CONFIG_SH_KGDB)
+- if (kgdb_nofault && kgdb_bus_err_hook)
+- kgdb_bus_err_hook();
+-#endif
+-
+ /*
+ * Oops. The kernel tried to access some bad page. We'll have to
+ * terminate things with extreme prejudice.
+@@ -69,11 +60,6 @@ asmlinkage void do_page_fault(struct pt_
+ asmlinkage int __do_page_fault(struct pt_regs *regs, unsigned long writeaccess,
+ unsigned long address)
+ {
+-#if defined(CONFIG_SH_KGDB)
+- if (kgdb_nofault && kgdb_bus_err_hook)
+- kgdb_bus_err_hook();
+-#endif
+-
+ if (address >= TASK_SIZE)
+ return 1;
+
+diff -rupN -X ../client-cleanup/dontdiff linux-2.6.18/arch/sh/mm/fault.c linux-2.6.18.kgdb/arch/sh/mm/fault.c
+--- linux-2.6.18/arch/sh/mm/fault.c 2006-09-20 07:42:06.000000000 +0400
++++ linux-2.6.18.kgdb/arch/sh/mm/fault.c 2008-06-10 16:19:47.000000000 +0400
+@@ -28,7 +28,6 @@
+ #include <asm/pgalloc.h>
+ #include <asm/mmu_context.h>
+ #include <asm/cacheflush.h>
+-#include <asm/kgdb.h>
+
+ extern void die(const char *,struct pt_regs *,long);
+
+@@ -45,11 +44,6 @@ asmlinkage void do_page_fault(struct pt_
+ struct vm_area_struct * vma;
+ unsigned long page;
+
+-#ifdef CONFIG_SH_KGDB
+- if (kgdb_nofault && kgdb_bus_err_hook)
+- kgdb_bus_err_hook();
+-#endif
+-
+ tsk = current;
+ mm = tsk->mm;
+
+@@ -153,6 +147,7 @@ no_context:
+ }
+ die("Oops", regs, writeaccess);
+ do_exit(SIGKILL);
++ dump_stack();
+
+ /*
+ * We ran out of memory, or some other thing happened to us that made
+@@ -202,11 +197,6 @@ asmlinkage int __do_page_fault(struct pt
+ spinlock_t *ptl;
+ int ret = 1;
+
+-#ifdef CONFIG_SH_KGDB
+- if (kgdb_nofault && kgdb_bus_err_hook)
+- kgdb_bus_err_hook();
+-#endif
+-
+ #ifdef CONFIG_SH_STORE_QUEUES
+ addrmax = P4SEG_STORE_QUE + 0x04000000;
+ #endif
+diff -rupN -X ../client-cleanup/dontdiff linux-2.6.18/arch/x86_64/Kconfig.debug linux-2.6.18.kgdb/arch/x86_64/Kconfig.debug
+--- linux-2.6.18/arch/x86_64/Kconfig.debug 2006-09-20 07:42:06.000000000 +0400
++++ linux-2.6.18.kgdb/arch/x86_64/Kconfig.debug 2008-06-10 16:19:41.000000000 +0400
+@@ -55,7 +55,4 @@ config DEBUG_STACK_USAGE
+
+ This option will slow down process creation somewhat.
+
+-#config X86_REMOTE_DEBUG
+-# bool "kgdb debugging stub"
+-
+ endmenu
+diff -rupN -X ../client-cleanup/dontdiff linux-2.6.18/arch/x86_64/kernel/Makefile linux-2.6.18.kgdb/arch/x86_64/kernel/Makefile
+--- linux-2.6.18/arch/x86_64/kernel/Makefile 2006-09-20 07:42:06.000000000 +0400
++++ linux-2.6.18.kgdb/arch/x86_64/kernel/Makefile 2008-06-10 16:19:41.000000000 +0400
+@@ -33,6 +33,7 @@ obj-$(CONFIG_IOMMU) += pci-gart.o apert
+ obj-$(CONFIG_CALGARY_IOMMU) += pci-calgary.o tce.o
+ obj-$(CONFIG_SWIOTLB) += pci-swiotlb.o
+ obj-$(CONFIG_KPROBES) += kprobes.o
++obj-$(CONFIG_KGDB) += kgdb.o kgdb-jmp.o
+ obj-$(CONFIG_X86_PM_TIMER) += pmtimer.o
+ obj-$(CONFIG_X86_VSMP) += vsmp.o
+ obj-$(CONFIG_K8_NB) += k8.o
+diff -rupN -X ../client-cleanup/dontdiff linux-2.6.18/arch/x86_64/kernel/entry.S linux-2.6.18.kgdb/arch/x86_64/kernel/entry.S
+--- linux-2.6.18/arch/x86_64/kernel/entry.S 2006-09-20 07:42:06.000000000 +0400
++++ linux-2.6.18.kgdb/arch/x86_64/kernel/entry.S 2008-06-10 16:19:58.000000000 +0400
+@@ -42,6 +42,7 @@
+ #include <asm/hw_irq.h>
+ #include <asm/page.h>
+ #include <asm/irqflags.h>
++#include <asm/kgdb.h>
+
+ .code64
+
+@@ -881,6 +882,7 @@ error_exit:
+ RESTORE_ARGS 0,8,0
+ jmp iret_label
+ CFI_ENDPROC
++ CFI_END_FRAME(kernel_thread)
+
+ error_kernelspace:
+ incl %ebx
+diff -rupN -X ../client-cleanup/dontdiff linux-2.6.18/arch/x86_64/kernel/kgdb-jmp.S linux-2.6.18.kgdb/arch/x86_64/kernel/kgdb-jmp.S
+--- linux-2.6.18/arch/x86_64/kernel/kgdb-jmp.S 1970-01-01 03:00:00.000000000 +0300
++++ linux-2.6.18.kgdb/arch/x86_64/kernel/kgdb-jmp.S 2008-06-10 16:19:41.000000000 +0400
+@@ -0,0 +1,65 @@
++/*
++ * arch/x86_64/kernel/kgdb-jmp.S
++ *
++ * 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) 2001, 2003, 2004 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/linkage.h>
++
++#define JB_RBX 0
++#define JB_RBP 1
++#define JB_R12 2
++#define JB_R13 3
++#define JB_R14 4
++#define JB_R15 5
++#define JB_RSP 6
++#define JB_PC 7
++
++ .code64
++
++/* This must be called prior to kgdb_fault_longjmp and
++ * kgdb_fault_longjmp must not be called outside of the context of the
++ * last call to kgdb_fault_setjmp.
++ */
++ENTRY(kgdb_fault_setjmp)
++ /* Save registers. */
++ movq %rbx, (JB_RBX*8)(%rdi)
++ movq %rbp, (JB_RBP*8)(%rdi)
++ movq %r12, (JB_R12*8)(%rdi)
++ movq %r13, (JB_R13*8)(%rdi)
++ movq %r14, (JB_R14*8)(%rdi)
++ movq %r15, (JB_R15*8)(%rdi)
++ leaq 8(%rsp), %rdx /* Save SP as it will be after we return. */
++ movq %rdx, (JB_RSP*8)(%rdi)
++ movq (%rsp), %rax /* Save PC we are returning to now. */
++ movq %rax, (JB_PC*8)(%rdi)
++ /* Set return value for setjmp. */
++ mov $0,%eax
++ movq (JB_PC*8)(%rdi),%rdx
++ movq (JB_RSP*8)(%rdi),%rsp
++ jmpq *%rdx
++
++ENTRY(kgdb_fault_longjmp)
++ /* Restore registers. */
++ movq (JB_RBX*8)(%rdi),%rbx
++ movq (JB_RBP*8)(%rdi),%rbp
++ movq (JB_R12*8)(%rdi),%r12
++ movq (JB_R13*8)(%rdi),%r13
++ movq (JB_R14*8)(%rdi),%r14
++ movq (JB_R15*8)(%rdi),%r15
++ /* Set return value for setjmp. */
++ movq (JB_PC*8)(%rdi),%rdx
++ movq (JB_RSP*8)(%rdi),%rsp
++ mov $1,%eax
++ jmpq *%rdx
+diff -rupN -X ../client-cleanup/dontdiff linux-2.6.18/arch/x86_64/kernel/kgdb.c linux-2.6.18.kgdb/arch/x86_64/kernel/kgdb.c
+--- linux-2.6.18/arch/x86_64/kernel/kgdb.c 1970-01-01 03:00:00.000000000 +0300
++++ linux-2.6.18.kgdb/arch/x86_64/kernel/kgdb.c 2008-06-10 16:19:41.000000000 +0400
+@@ -0,0 +1,474 @@
++/*
++ *
++ * 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, or (at your option) any
++ * later version.
++ *
++ * This program is distributed in the hope that it will be useful, but
++ * WITHOUT ANY WARRANTY; without even the implied warranty of
++ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
++ * General Public License for more details.
++ *
++ */
++
++/*
++ * Copyright (C) 2004 Amit S. Kale <amitkale@linsyssoft.com>
++ * Copyright (C) 2000-2001 VERITAS Software Corporation.
++ * Copyright (C) 2002 Andi Kleen, SuSE Labs
++ * Copyright (C) 2004 LinSysSoft Technologies Pvt. Ltd.
++ */
++/****************************************************************************
++ * Contributor: Lake Stevens Instrument Division$
++ * Written by: Glenn Engel $
++ * Updated by: Amit Kale<akale@veritas.com>
++ * Modified for 386 by Jim Kingdon, Cygnus Support.
++ * Origianl kgdb, compatibility with 2.1.xx kernel by
++ * David Grothe <dave@gcom.com>
++ * Integrated into 2.2.5 kernel by Tigran Aivazian <tigran@sco.com>
++ * X86_64 changes from Andi Kleen's patch merged by Jim Houston
++ */
++
++#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/apicdef.h>
++#include <asm/mach_apic.h>
++#include <asm/kdebug.h>
++#include <asm/debugreg.h>
++
++/* Put the error code here just in case the user cares. */
++int gdb_x86_64errcode;
++/* Likewise, the vector number here (since GDB only gets the signal
++ number through the usual means, and that's not very specific). */
++int gdb_x86_64vector = -1;
++
++extern atomic_t cpu_doing_single_step;
++
++void regs_to_gdb_regs(unsigned long *gdb_regs, struct pt_regs *regs)
++{
++ gdb_regs[_RAX] = regs->rax;
++ gdb_regs[_RBX] = regs->rbx;
++ gdb_regs[_RCX] = regs->rcx;
++ gdb_regs[_RDX] = regs->rdx;
++ gdb_regs[_RSI] = regs->rsi;
++ gdb_regs[_RDI] = regs->rdi;
++ gdb_regs[_RBP] = regs->rbp;
++ gdb_regs[_PS] = regs->eflags;
++ gdb_regs[_PC] = regs->rip;
++ gdb_regs[_R8] = regs->r8;
++ gdb_regs[_R9] = regs->r9;
++ gdb_regs[_R10] = regs->r10;
++ gdb_regs[_R11] = regs->r11;
++ gdb_regs[_R12] = regs->r12;
++ gdb_regs[_R13] = regs->r13;
++ gdb_regs[_R14] = regs->r14;
++ gdb_regs[_R15] = regs->r15;
++ gdb_regs[_RSP] = regs->rsp;
++}
++
++extern void thread_return(void);
++void sleeping_thread_to_gdb_regs(unsigned long *gdb_regs, struct task_struct *p)
++{
++ gdb_regs[_RAX] = 0;
++ gdb_regs[_RBX] = 0;
++ gdb_regs[_RCX] = 0;
++ gdb_regs[_RDX] = 0;
++ gdb_regs[_RSI] = 0;
++ gdb_regs[_RDI] = 0;
++ gdb_regs[_RBP] = *(unsigned long *)p->thread.rsp;
++ gdb_regs[_PS] = *(unsigned long *)(p->thread.rsp + 8);
++ gdb_regs[_PC] = (unsigned long)&thread_return;
++ gdb_regs[_R8] = 0;
++ gdb_regs[_R9] = 0;
++ gdb_regs[_R10] = 0;
++ gdb_regs[_R11] = 0;
++ gdb_regs[_R12] = 0;
++ gdb_regs[_R13] = 0;
++ gdb_regs[_R14] = 0;
++ gdb_regs[_R15] = 0;
++ gdb_regs[_RSP] = p->thread.rsp;
++}
++
++void gdb_regs_to_regs(unsigned long *gdb_regs, struct pt_regs *regs)
++{
++ regs->rax = gdb_regs[_RAX];
++ regs->rbx = gdb_regs[_RBX];
++ regs->rcx = gdb_regs[_RCX];
++ regs->rdx = gdb_regs[_RDX];
++ regs->rsi = gdb_regs[_RSI];
++ regs->rdi = gdb_regs[_RDI];
++ regs->rbp = gdb_regs[_RBP];
++ regs->eflags = gdb_regs[_PS];
++ regs->rip = gdb_regs[_PC];
++ regs->r8 = gdb_regs[_R8];
++ regs->r9 = gdb_regs[_R9];
++ regs->r10 = gdb_regs[_R10];
++ regs->r11 = gdb_regs[_R11];
++ regs->r12 = gdb_regs[_R12];
++ regs->r13 = gdb_regs[_R13];
++ regs->r14 = gdb_regs[_R14];
++ regs->r15 = gdb_regs[_R15];
++#if 0 /* can't change these */
++ regs->rsp = gdb_regs[_RSP];
++ regs->ss = gdb_regs[_SS];
++ regs->fs = gdb_regs[_FS];
++ regs->gs = gdb_regs[_GS];
++#endif
++
++} /* gdb_regs_to_regs */
++
++struct hw_breakpoint {
++ unsigned enabled;
++ unsigned type;
++ unsigned len;
++ unsigned long addr;
++} breakinfo[4] = { {
++enabled:0}, {
++enabled:0}, {
++enabled:0}, {
++enabled:0}};
++
++void kgdb_correct_hw_break(void)
++{
++ int breakno;
++ int correctit;
++ int breakbit;
++ unsigned long dr7;
++
++ asm volatile ("movq %%db7, %0\n":"=r" (dr7):);
++ do {
++ unsigned long addr0, addr1, addr2, addr3;
++ asm volatile ("movq %%db0, %0\n"
++ "movq %%db1, %1\n"
++ "movq %%db2, %2\n"
++ "movq %%db3, %3\n":"=r" (addr0), "=r"(addr1),
++ "=r"(addr2), "=r"(addr3):);
++ } while (0);
++ correctit = 0;
++ for (breakno = 0; breakno < 3; breakno++) {
++ breakbit = 2 << (breakno << 1);
++ if (!(dr7 & breakbit) && breakinfo[breakno].enabled) {
++ correctit = 1;
++ dr7 |= breakbit;
++ dr7 &= ~(0xf0000 << (breakno << 2));
++ dr7 |= (((breakinfo[breakno].len << 2) |
++ breakinfo[breakno].type) << 16) <<
++ (breakno << 2);
++ switch (breakno) {
++ case 0:
++ asm volatile ("movq %0, %%dr0\n"::"r"
++ (breakinfo[breakno].addr));
++ break;
++
++ case 1:
++ asm volatile ("movq %0, %%dr1\n"::"r"
++ (breakinfo[breakno].addr));
++ break;
++
++ case 2:
++ asm volatile ("movq %0, %%dr2\n"::"r"
++ (breakinfo[breakno].addr));
++ break;
++
++ case 3:
++ asm volatile ("movq %0, %%dr3\n"::"r"
++ (breakinfo[breakno].addr));
++ break;
++ }
++ } else if ((dr7 & breakbit) && !breakinfo[breakno].enabled) {
++ correctit = 1;
++ dr7 &= ~breakbit;
++ dr7 &= ~(0xf0000 << (breakno << 2));
++ }
++ }
++ if (correctit) {
++ asm volatile ("movq %0, %%db7\n"::"r" (dr7));
++ }
++}
++
++int kgdb_remove_hw_break(unsigned long addr)
++{
++ int i, idx = -1;
++ for (i = 0; i < 4; i++) {
++ if (breakinfo[i].addr == addr && breakinfo[i].enabled) {
++ idx = i;
++ break;
++ }
++ }
++ if (idx == -1)
++ return -1;
++
++ breakinfo[idx].enabled = 0;
++ return 0;
++}
++
++int kgdb_set_hw_break(unsigned long addr)
++{
++ int i, idx = -1;
++ for (i = 0; i < 4; i++) {
++ if (!breakinfo[i].enabled) {
++ idx = i;
++ break;
++ }
++ }
++ if (idx == -1)
++ return -1;
++
++ breakinfo[idx].enabled = 1;
++ breakinfo[idx].type = 1;
++ breakinfo[idx].len = 1;
++ breakinfo[idx].addr = addr;
++ return 0;
++}
++
++int remove_hw_break(unsigned breakno)
++{
++ if (!breakinfo[breakno].enabled) {
++ return -1;
++ }
++ breakinfo[breakno].enabled = 0;
++ return 0;
++}
++
++int set_hw_break(unsigned breakno, unsigned type, unsigned len, unsigned addr)
++{
++ if (breakinfo[breakno].enabled) {
++ return -1;
++ }
++ breakinfo[breakno].enabled = 1;
++ breakinfo[breakno].type = type;
++ breakinfo[breakno].len = len;
++ breakinfo[breakno].addr = addr;
++ return 0;
++}
++
++void kgdb_disable_hw_debug(struct pt_regs *regs)
++{
++ /* Disable hardware debugging while we are in kgdb */
++ asm volatile ("movq %0,%%db7": /* no output */ :"r" (0UL));
++}
++
++void kgdb_post_master_code(struct pt_regs *regs, int e_vector, int err_code)
++{
++ /* Master processor is completely in the debugger */
++ gdb_x86_64vector = e_vector;
++ gdb_x86_64errcode = err_code;
++}
++
++void kgdb_roundup_cpus(unsigned long flags)
++{
++ send_IPI_allbutself(APIC_DM_NMI);
++}
++
++int kgdb_arch_handle_exception(int e_vector, int signo, int err_code,
++ char *remcomInBuffer, char *remcomOutBuffer,
++ struct pt_regs *linux_regs)
++{
++ unsigned long addr, length;
++ unsigned long breakno, breaktype;
++ char *ptr;
++ int newPC;
++ unsigned long dr6;
++
++ switch (remcomInBuffer[0]) {
++ case 'c':
++ case 's':
++ /* try to read optional parameter, pc unchanged if no parm */
++ ptr = &remcomInBuffer[1];
++ if (kgdb_hex2long(&ptr, &addr))
++ linux_regs->rip = addr;
++ newPC = linux_regs->rip;
++
++ /* clear the trace bit */
++ linux_regs->eflags &= ~TF_MASK;
++
++ atomic_set(&cpu_doing_single_step, -1);
++ /* set the trace bit if we're stepping */
++ if (remcomInBuffer[0] == 's') {
++ linux_regs->eflags |= TF_MASK;
++ debugger_step = 1;
++ if (kgdb_contthread)
++ atomic_set(&cpu_doing_single_step,
++ smp_processor_id());
++
++ }
++
++ asm volatile ("movq %%db6, %0\n":"=r" (dr6));
++ if (!(dr6 & 0x4000)) {
++ for (breakno = 0; breakno < 4; ++breakno) {
++ if (dr6 & (1 << breakno)) {
++ if (breakinfo[breakno].type == 0) {
++ /* Set restore flag */
++ linux_regs->eflags |=
++ X86_EFLAGS_RF;
++ break;
++ }
++ }
++ }
++ }
++ kgdb_correct_hw_break();
++ asm volatile ("movq %0, %%db6\n"::"r" (0UL));
++
++ return (0);
++
++ case 'Y':
++ ptr = &remcomInBuffer[1];
++ kgdb_hex2long(&ptr, &breakno);
++ ptr++;
++ kgdb_hex2long(&ptr, &breaktype);
++ ptr++;
++ kgdb_hex2long(&ptr, &length);
++ ptr++;
++ kgdb_hex2long(&ptr, &addr);
++ if (set_hw_break(breakno & 0x3, breaktype & 0x3,
++ length & 0x3, addr) == 0)
++ strcpy(remcomOutBuffer, "OK");
++ else
++ strcpy(remcomOutBuffer, "ERROR");
++ break;
++
++ /* Remove hardware breakpoint */
++ case 'y':
++ ptr = &remcomInBuffer[1];
++ kgdb_hex2long(&ptr, &breakno);
++ if (remove_hw_break(breakno & 0x3) == 0)
++ strcpy(remcomOutBuffer, "OK");
++ else
++ strcpy(remcomOutBuffer, "ERROR");
++ break;
++
++ } /* switch */
++ return -1;
++}
++
++static struct pt_regs *in_interrupt_stack(unsigned long rsp, int cpu)
++{
++ struct pt_regs *regs;
++ unsigned long end = (unsigned long)cpu_pda(cpu)->irqstackptr;
++ if (rsp <= end && rsp >= end - IRQSTACKSIZE + 8) {
++ regs = *(((struct pt_regs **)end) - 1);
++ return regs;
++ }
++ return NULL;
++}
++
++static struct pt_regs *in_exception_stack(unsigned long rsp, int cpu)
++{
++ int i;
++ struct tss_struct *init_tss = &__get_cpu_var(init_tss);
++ for (i = 0; i < N_EXCEPTION_STACKS; i++)
++ if (rsp >= init_tss[cpu].ist[i] &&
++ rsp <= init_tss[cpu].ist[i] + EXCEPTION_STKSZ) {
++ struct pt_regs *r =
++ (void *)init_tss[cpu].ist[i] + EXCEPTION_STKSZ;
++ return r - 1;
++ }
++ return NULL;
++}
++
++void kgdb_shadowinfo(struct pt_regs *regs, char *buffer, unsigned threadid)
++{
++ static char intr_desc[] = "Stack at interrupt entrypoint";
++ static char exc_desc[] = "Stack at exception entrypoint";
++ struct pt_regs *stregs;
++ int cpu = hard_smp_processor_id();
++
++ if ((stregs = in_interrupt_stack(regs->rsp, cpu)))
++ kgdb_mem2hex(intr_desc, buffer, strlen(intr_desc));
++ else if ((stregs = in_exception_stack(regs->rsp, cpu)))
++ kgdb_mem2hex(exc_desc, buffer, strlen(exc_desc));
++}
++
++struct task_struct *kgdb_get_shadow_thread(struct pt_regs *regs, int threadid)
++{
++ struct pt_regs *stregs;
++ int cpu = hard_smp_processor_id();
++
++ if ((stregs = in_interrupt_stack(regs->rsp, cpu)))
++ return current;
++ else if ((stregs = in_exception_stack(regs->rsp, cpu)))
++ return current;
++
++ return NULL;
++}
++
++struct pt_regs *kgdb_shadow_regs(struct pt_regs *regs, int threadid)
++{
++ struct pt_regs *stregs;
++ int cpu = hard_smp_processor_id();
++
++ if ((stregs = in_interrupt_stack(regs->rsp, cpu)))
++ return stregs;
++ else if ((stregs = in_exception_stack(regs->rsp, cpu)))
++ return stregs;
++
++ return NULL;
++}
++
++/* Register KGDB with the die_chain so that we hook into all of the right
++ * spots. */
++static int kgdb_notify(struct notifier_block *self, unsigned long cmd,
++ void *ptr)
++{
++ struct die_args *args = ptr;
++ struct pt_regs *regs = args->regs;
++
++ if (cmd == DIE_PAGE_FAULT_NO_CONTEXT && atomic_read(&debugger_active)
++ && kgdb_may_fault) {
++ kgdb_fault_longjmp(kgdb_fault_jmp_regs);
++ return NOTIFY_STOP;
++ /* CPU roundup? */
++ } else if (atomic_read(&debugger_active) && cmd == DIE_NMI_IPI) {
++ kgdb_nmihook(smp_processor_id(), regs);
++ return NOTIFY_STOP;
++ /* See if KGDB is interested. */
++ } else if (cmd == DIE_PAGE_FAULT || user_mode(regs) ||
++ cmd == DIE_NMI_IPI || (cmd == DIE_DEBUG &&
++ atomic_read(&debugger_active)))
++ /* Userpace events, normal watchdog event, or spurious
++ * debug exception. Ignore. */
++ return NOTIFY_DONE;
++
++ kgdb_handle_exception(args->trapnr, args->signr, args->err, regs);
++
++ return NOTIFY_STOP;
++}
++
++static struct notifier_block kgdb_notifier = {
++ .notifier_call = kgdb_notify,
++ .priority = 0x7fffffff, /* we need to notified first */
++};
++
++int kgdb_arch_init(void)
++{
++ atomic_notifier_chain_register(&die_chain, &kgdb_notifier);
++ return 0;
++}
++/*
++ * Skip an int3 exception when it occurs after a breakpoint has been
++ * removed. Backtrack eip by 1 since the int3 would have caused it to
++ * increment by 1.
++ */
++
++int kgdb_skipexception(int exception, struct pt_regs *regs)
++{
++ if (exception == 3 && kgdb_isremovedbreak(regs->rip - 1)) {
++ regs->rip -= 1;
++ return 1;
++ }
++ return 0;
++}
++
++struct kgdb_arch arch_kgdb_ops = {
++ .gdb_bpt_instr = {0xcc},
++ .flags = KGDB_HW_BREAKPOINT,
++ .shadowth = 1,
++};
+diff -rupN -X ../client-cleanup/dontdiff linux-2.6.18/arch/x86_64/mm/fault.c linux-2.6.18.kgdb/arch/x86_64/mm/fault.c
+--- linux-2.6.18/arch/x86_64/mm/fault.c 2006-09-20 07:42:06.000000000 +0400
++++ linux-2.6.18.kgdb/arch/x86_64/mm/fault.c 2008-06-10 16:19:36.000000000 +0400
+@@ -557,6 +557,10 @@ no_context:
+ if (is_errata93(regs, address))
+ return;
+
++ if (notify_die(DIE_PAGE_FAULT_NO_CONTEXT, "no context", regs,
++ error_code, 14, SIGSEGV) == NOTIFY_STOP)
++ return;
++
+ /*
+ * Oops. The kernel tried to access some bad page. We'll have to
+ * terminate things with extreme prejudice.
+diff -rupN -X ../client-cleanup/dontdiff linux-2.6.18/drivers/char/keyboard.c linux-2.6.18.kgdb/drivers/char/keyboard.c
+--- linux-2.6.18/drivers/char/keyboard.c 2006-09-20 07:42:06.000000000 +0400
++++ linux-2.6.18.kgdb/drivers/char/keyboard.c 2008-06-10 16:20:02.000000000 +0400
+@@ -1174,6 +1174,7 @@ static void kbd_keycode(unsigned int key
+ sysrq_down = 0;
+ if (sysrq_down && down && !rep) {
+ handle_sysrq(kbd_sysrq_xlate[keycode], regs, tty);
++ sysrq_down = 0; /* In case we miss the 'up' event. */
+ return;
+ }
+ #endif
+diff -rupN -X ../client-cleanup/dontdiff linux-2.6.18/drivers/net/Makefile linux-2.6.18.kgdb/drivers/net/Makefile
+--- linux-2.6.18/drivers/net/Makefile 2006-09-20 07:42:06.000000000 +0400
++++ linux-2.6.18.kgdb/drivers/net/Makefile 2008-06-10 16:19:13.000000000 +0400
+@@ -216,6 +216,7 @@ obj-$(CONFIG_ETRAX_ETHERNET) += cris/
+ obj-$(CONFIG_ENP2611_MSF_NET) += ixp2000/
+
+ obj-$(CONFIG_NETCONSOLE) += netconsole.o
++obj-$(CONFIG_KGDBOE) += kgdboe.o
+
+ obj-$(CONFIG_FS_ENET) += fs_enet/
+
+diff -rupN -X ../client-cleanup/dontdiff linux-2.6.18/drivers/net/kgdboe.c linux-2.6.18.kgdb/drivers/net/kgdboe.c
+--- linux-2.6.18/drivers/net/kgdboe.c 1970-01-01 03:00:00.000000000 +0300
++++ linux-2.6.18.kgdb/drivers/net/kgdboe.c 2008-06-10 16:19:13.000000000 +0400
+@@ -0,0 +1,294 @@
++/*
++ * drivers/net/kgdboe.c
++ *
++ * A network interface for GDB.
++ * Based upon 'gdbserial' by David Grothe <dave@gcom.com>
++ * and Scott Foehner <sfoehner@engr.sgi.com>
++ *
++ * Maintainers: Amit S. Kale <amitkale@linsyssoft.com> and
++ * Tom Rini <trini@kernel.crashing.org>
++ *
++ * 2004 (c) Amit S. Kale <amitkale@linsyssoft.com>
++ * 2004-2005 (c) MontaVista Software, Inc.
++ * 2005 (c) Wind River Systems, Inc.
++ *
++ * Contributors at various stages not listed above:
++ * San Mehat <nettwerk@biodome.org>, Robert Walsh <rjwalsh@durables.org>,
++ * wangdi <wangdi@clusterfs.com>, Matt Mackall <mpm@selenic.com>,
++ * Pavel Machek <pavel@suse.cz>, Jason Wessel <jason.wessel@windriver.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/kernel.h>
++#include <linux/interrupt.h>
++#include <linux/string.h>
++#include <linux/kgdb.h>
++#include <linux/netpoll.h>
++#include <linux/init.h>
++
++#include <asm/atomic.h>
++
++#define IN_BUF_SIZE 512 /* power of 2, please */
++#define NOT_CONFIGURED_STRING "not_configured"
++#define OUT_BUF_SIZE 30 /* We don't want to send too big of a packet. */
++#define MAX_KGDBOE_CONFIG_STR 256
++
++static char in_buf[IN_BUF_SIZE], out_buf[OUT_BUF_SIZE];
++static int in_head, in_tail, out_count;
++static atomic_t in_count;
++/* 0 = unconfigured, 1 = netpoll options parsed, 2 = fully configured. */
++static int configured;
++static struct kgdb_io local_kgdb_io_ops;
++static int use_dynamic_mac;
++
++MODULE_DESCRIPTION("KGDB driver for network interfaces");
++MODULE_LICENSE("GPL");
++static char config[MAX_KGDBOE_CONFIG_STR] = NOT_CONFIGURED_STRING;
++static struct kparam_string kps = {
++ .string = config,
++ .maxlen = MAX_KGDBOE_CONFIG_STR,
++};
++
++static void rx_hook(struct netpoll *np, int port, char *msg, int len,
++ struct sk_buff *skb)
++{
++ int i;
++
++ np->remote_port = port;
++
++ /* Copy the MAC address if we need to. */
++ if (use_dynamic_mac) {
++ memcpy(np->remote_mac, eth_hdr(skb)->h_source,
++ sizeof(np->remote_mac));
++ use_dynamic_mac = 0;
++ }
++
++ /*
++ * This could be GDB trying to attach. But it could also be GDB
++ * finishing up a session, with kgdb_connected=0 but GDB sending
++ * an ACK for the final packet. To make sure we don't try and
++ * make a breakpoint when GDB is leaving, make sure that if
++ * !kgdb_connected the only len == 1 packet we allow is ^C.
++ */
++ if (!kgdb_connected && (len != 1 || msg[0] == 3) &&
++ !atomic_read(&kgdb_setting_breakpoint)) {
++ tasklet_schedule(&kgdb_tasklet_breakpoint);
++ }
++
++ for (i = 0; i < len; i++) {
++ if (msg[i] == 3)
++ tasklet_schedule(&kgdb_tasklet_breakpoint);
++
++ if (atomic_read(&in_count) >= IN_BUF_SIZE) {
++ /* buffer overflow, clear it */
++ in_head = in_tail = 0;
++ atomic_set(&in_count, 0);
++ break;
++ }
++ in_buf[in_head++] = msg[i];
++ in_head &= (IN_BUF_SIZE - 1);
++ atomic_inc(&in_count);
++ }
++}
++
++static struct netpoll np = {
++ .dev_name = "eth0",
++ .name = "kgdboe",
++ .rx_hook = rx_hook,
++ .local_port = 6443,
++ .remote_port = 6442,
++ .remote_mac = { 0xff, 0xff, 0xff, 0xff, 0xff, 0xff },
++};
++
++static void eth_pre_exception_handler(void)
++{
++ /* Increment the module count when the debugger is active */
++ if (!kgdb_connected)
++ try_module_get(THIS_MODULE);
++ netpoll_set_trap(1);
++}
++
++static void eth_post_exception_handler(void)
++{
++ /* decrement the module count when the debugger detaches */
++ if (!kgdb_connected)
++ module_put(THIS_MODULE);
++ netpoll_set_trap(0);
++}
++
++static int eth_get_char(void)
++{
++ int chr;
++
++ while (atomic_read(&in_count) == 0)
++ netpoll_poll(&np);
++
++ chr = in_buf[in_tail++];
++ in_tail &= (IN_BUF_SIZE - 1);
++ atomic_dec(&in_count);
++ return chr;
++}
++
++static void eth_flush_buf(void)
++{
++ if (out_count && np.dev) {
++ netpoll_send_udp(&np, out_buf, out_count);
++ memset(out_buf, 0, sizeof(out_buf));
++ out_count = 0;
++ }
++}
++
++static void eth_put_char(u8 chr)
++{
++ out_buf[out_count++] = chr;
++ if (out_count == OUT_BUF_SIZE)
++ eth_flush_buf();
++}
++
++static int option_setup(char *opt)
++{
++ char opt_scratch[MAX_KGDBOE_CONFIG_STR];
++
++ /* If we're being given a new configuration, copy it in. */
++ if (opt != config)
++ strcpy(config, opt);
++ /* But work on a copy as netpoll_parse_options will eat it. */
++ strcpy(opt_scratch, opt);
++ configured = !netpoll_parse_options(&np, opt_scratch);
++
++ use_dynamic_mac = 1;
++
++ return 0;
++}
++__setup("kgdboe=", option_setup);
++
++/* With our config string set by some means, configure kgdboe. */
++static int configure_kgdboe(void)
++{
++ /* Try out the string. */
++ option_setup(config);
++
++ if (!configured) {
++ printk(KERN_ERR "kgdboe: configuration incorrect - kgdboe not "
++ "loaded.\n");
++ printk(KERN_ERR " Usage: kgdboe=[src-port]@[src-ip]/[dev],"
++ "[tgt-port]@<tgt-ip>/<tgt-macaddr>\n");
++ return -EINVAL;
++ }
++
++ /* Bring it up. */
++ if (netpoll_setup(&np)) {
++ printk(KERN_ERR "kgdboe: netpoll_setup failed kgdboe failed\n");
++ return -EINVAL;
++ }
++
++ if (kgdb_register_io_module(&local_kgdb_io_ops)) {
++ netpoll_cleanup(&np);
++ return -EINVAL;
++ }
++
++ configured = 2;
++
++ return 0;
++}
++
++static int init_kgdboe(void)
++{
++ int ret;
++
++ /* Already done? */
++ if (configured == 2)
++ return 0;
++
++ /* OK, go ahead and do it. */
++ ret = configure_kgdboe();
++
++ if (configured == 2)
++ printk(KERN_INFO "kgdboe: debugging over ethernet enabled\n");
++
++ return ret;
++}
++
++static void cleanup_kgdboe(void)
++{
++ netpoll_cleanup(&np);
++ configured = 0;
++ kgdb_unregister_io_module(&local_kgdb_io_ops);
++}
++
++static int param_set_kgdboe_var(const char *kmessage, struct kernel_param *kp)
++{
++ char kmessage_save[MAX_KGDBOE_CONFIG_STR];
++ int msg_len = strlen(kmessage);
++
++ if (msg_len + 1 > MAX_KGDBOE_CONFIG_STR) {
++ printk(KERN_ERR "%s: string doesn't fit in %u chars.\n",
++ kp->name, MAX_KGDBOE_CONFIG_STR - 1);
++ return -ENOSPC;
++ }
++
++ if (kgdb_connected) {
++ printk(KERN_ERR "kgdboe: Cannot reconfigure while KGDB is "
++ "connected.\n");
++ return 0;
++ }
++
++ /* Start the reconfiguration process by saving the old string */
++ strncpy(kmessage_save, config, sizeof(kmessage_save));
++
++
++ /* Copy in the new param and strip out invalid characters so we
++ * can optionally specify the MAC.
++ */
++ strncpy(config, kmessage, sizeof(config));
++ msg_len--;
++ while (msg_len > 0 &&
++ (config[msg_len] < ',' || config[msg_len] > 'f')) {
++ config[msg_len] = '\0';
++ msg_len--;
++ }
++
++ /* Check to see if we are unconfiguring the io module and that it
++ * was in a fully configured state, as this is the only time that
++ * netpoll_cleanup should get called
++ */
++ if (configured == 2 && strcmp(config, NOT_CONFIGURED_STRING) == 0) {
++ printk(KERN_INFO "kgdboe: reverting to unconfigured state\n");
++ cleanup_kgdboe();
++ return 0;
++ } else
++ /* Go and configure with the new params. */
++ configure_kgdboe();
++
++ if (configured == 2)
++ return 0;
++
++ /* If the new string was invalid, revert to the previous state, which
++ * is at a minimum not_configured. */
++ strncpy(config, kmessage_save, sizeof(config));
++ if (strcmp(kmessage_save, NOT_CONFIGURED_STRING) != 0) {
++ printk(KERN_INFO "kgdboe: reverting to prior configuration\n");
++ /* revert back to the original config */
++ strncpy(config, kmessage_save, sizeof(config));
++ configure_kgdboe();
++ }
++ return 0;
++}
++
++static struct kgdb_io local_kgdb_io_ops = {
++ .read_char = eth_get_char,
++ .write_char = eth_put_char,
++ .init = init_kgdboe,
++ .flush = eth_flush_buf,
++ .pre_exception = eth_pre_exception_handler,
++ .post_exception = eth_post_exception_handler
++};
++
++module_init(init_kgdboe);
++module_exit(cleanup_kgdboe);
++module_param_call(kgdboe, param_set_kgdboe_var, param_get_string, &kps, 0644);
++MODULE_PARM_DESC(kgdboe, " kgdboe=[src-port]@[src-ip]/[dev],"
++ "[tgt-port]@<tgt-ip>/<tgt-macaddr>\n");
+diff -rupN -X ../client-cleanup/dontdiff linux-2.6.18/drivers/serial/8250.c linux-2.6.18.kgdb/drivers/serial/8250.c
+--- linux-2.6.18/drivers/serial/8250.c 2006-09-20 07:42:06.000000000 +0400
++++ linux-2.6.18.kgdb/drivers/serial/8250.c 2008-06-10 16:19:03.000000000 +0400
+@@ -2628,6 +2628,25 @@ void serial8250_unregister_port(int line
+ }
+ EXPORT_SYMBOL(serial8250_unregister_port);
+
++/**
++ * serial8250_unregister_by_port - remove a 16x50 serial port
++ * at runtime.
++ * @port: A &struct uart_port that describes the port to remove.
++ *
++ * Remove one serial port. This may not be called from interrupt
++ * context. We hand the port back to the our control.
++ */
++void serial8250_unregister_by_port(struct uart_port *port)
++{
++ struct uart_8250_port *uart;
++
++ uart = serial8250_find_match_or_unused(port);
++
++ if (uart)
++ serial8250_unregister_port(uart->port.line);
++}
++EXPORT_SYMBOL(serial8250_unregister_by_port);
++
+ static int __init serial8250_init(void)
+ {
+ int ret, i;
+diff -rupN -X ../client-cleanup/dontdiff linux-2.6.18/drivers/serial/8250_kgdb.c linux-2.6.18.kgdb/drivers/serial/8250_kgdb.c
+--- linux-2.6.18/drivers/serial/8250_kgdb.c 1970-01-01 03:00:00.000000000 +0300
++++ linux-2.6.18.kgdb/drivers/serial/8250_kgdb.c 2008-06-10 16:19:03.000000000 +0400
+@@ -0,0 +1,516 @@
++/*
++ * 8250 interface for kgdb.
++ *
++ * This is a merging of many different drivers, and all of the people have
++ * had an impact in some form or another:
++ *
++ * 2004-2005 (c) MontaVista Software, Inc.
++ * 2005-2006 (c) Wind River Systems, Inc.
++ *
++ * Amit Kale <amitkale@emsyssoft.com>, David Grothe <dave@gcom.com>,
++ * Scott Foehner <sfoehner@engr.sgi.com>, George Anzinger <george@mvista.com>,
++ * Robert Walsh <rjwalsh@durables.org>, wangdi <wangdi@clusterfs.com>,
++ * San Mehat, Tom Rini <trini@mvista.com>,
++ * Jason Wessel <jason.wessel@windriver.com>
++ */
++
++#include <linux/config.h>
++#include <linux/kernel.h>
++#include <linux/init.h>
++#include <linux/kgdb.h>
++#include <linux/interrupt.h>
++#include <linux/tty.h>
++#include <linux/serial.h>
++#include <linux/serial_reg.h>
++#include <linux/serialP.h>
++#include <linux/ioport.h>
++
++#include <asm/io.h>
++#include <asm/serial.h> /* For BASE_BAUD and SERIAL_PORT_DFNS */
++
++#include "8250.h"
++
++#define GDB_BUF_SIZE 512 /* power of 2, please */
++
++MODULE_DESCRIPTION("KGDB driver for the 8250");
++MODULE_LICENSE("GPL");
++/* These will conflict with early_param otherwise. */
++#ifdef CONFIG_KGDB_8250_MODULE
++static char config[256];
++module_param_string(kgdb8250, config, 256, 0);
++MODULE_PARM_DESC(kgdb8250,
++ " kgdb8250=<io or mmio>,<address>,<baud rate>,<irq>\n");
++static struct kgdb_io local_kgdb_io_ops;
++#endif /* CONFIG_KGDB_8250_MODULE */
++
++/* Speed of the UART. */
++static int kgdb8250_baud;
++
++/* Flag for if we need to call request_mem_region */
++static int kgdb8250_needs_request_mem_region;
++
++static char kgdb8250_buf[GDB_BUF_SIZE];
++static atomic_t kgdb8250_buf_in_cnt;
++static int kgdb8250_buf_out_inx;
++
++/* Old-style serial definitions, if existant, and a counter. */
++#ifdef CONFIG_KGDB_SIMPLE_SERIAL
++static int __initdata should_copy_rs_table = 1;
++static struct serial_state old_rs_table[] __initdata = {
++#ifdef SERIAL_PORT_DFNS
++ SERIAL_PORT_DFNS
++#endif
++};
++#endif
++
++/* Our internal table of UARTS. */
++#define UART_NR CONFIG_SERIAL_8250_NR_UARTS
++static struct uart_port kgdb8250_ports[UART_NR];
++
++static struct uart_port *current_port;
++
++/* Base of the UART. */
++static void *kgdb8250_addr;
++
++/* Forward declarations. */
++static int kgdb8250_uart_init(void);
++static int __init kgdb_init_io(void);
++static int __init kgdb8250_opt(char *str);
++
++/* These are much shorter calls to ioread8/iowrite8 that take into
++ * account our shifts, etc. */
++static inline unsigned int kgdb_ioread(u8 mask)
++{
++ return ioread8(kgdb8250_addr + (mask << current_port->regshift));
++}
++
++static inline void kgdb_iowrite(u8 val, u8 mask)
++{
++ iowrite8(val, kgdb8250_addr + (mask << current_port->regshift));
++}
++
++/*
++ * Wait until the interface can accept a char, then write it.
++ */
++static void kgdb_put_debug_char(u8 chr)
++{
++ while (!(kgdb_ioread(UART_LSR) & UART_LSR_THRE)) ;
++
++ kgdb_iowrite(chr, UART_TX);
++}
++
++/*
++ * Get a byte from the hardware data buffer and return it
++ */
++static int read_data_bfr(void)
++{
++ char it = kgdb_ioread(UART_LSR);
++
++ if (it & UART_LSR_DR)
++ return kgdb_ioread(UART_RX);
++
++ /*
++ * If we have a framing error assume somebody messed with
++ * our uart. Reprogram it and send '-' both ways...
++ */
++ if (it & 0xc) {
++ kgdb8250_uart_init();
++ kgdb_put_debug_char('-');
++ return '-';
++ }
++
++ return -1;
++}
++
++/*
++ * Get a char if available, return -1 if nothing available.
++ * Empty the receive buffer first, then look at the interface hardware.
++ */
++static int kgdb_get_debug_char(void)
++{
++ int retchr;
++
++ /* intr routine has q'd chars */
++ if (atomic_read(&kgdb8250_buf_in_cnt) != 0) {
++ retchr = kgdb8250_buf[kgdb8250_buf_out_inx++];
++ kgdb8250_buf_out_inx &= (GDB_BUF_SIZE - 1);
++ atomic_dec(&kgdb8250_buf_in_cnt);
++ return retchr;
++ }
++
++ do {
++ retchr = read_data_bfr();
++ } while (retchr < 0);
++
++ return retchr;
++}
++
++/*
++ * This is the receiver interrupt routine for the GDB stub.
++ * All that we need to do is verify that the interrupt happened on the
++ * line we're in charge of. If this is true, schedule a breakpoint and
++ * return.
++ */
++static irqreturn_t
++kgdb8250_interrupt(int irq, void *dev_id, struct pt_regs *regs)
++{
++ if (kgdb_ioread(UART_IIR) & UART_IIR_RDI) {
++ /* Throw away the data if another I/O routine is active. */
++ if (kgdb_io_ops.read_char != kgdb_get_debug_char &&
++ (kgdb_ioread(UART_LSR) & UART_LSR_DR))
++ kgdb_ioread(UART_RX);
++ else
++ breakpoint();
++ }
++
++ return IRQ_HANDLED;
++}
++
++/*
++ * Initializes the UART.
++ * Returns:
++ * 0 on success, 1 on failure.
++ */
++static int
++kgdb8250_uart_init (void)
++{
++ unsigned int ier, base_baud = current_port->uartclk ?
++ current_port->uartclk / 16 : BASE_BAUD;
++
++ /* test uart existance */
++ if(kgdb_ioread(UART_LSR) == 0xff)
++ return -1;
++
++ /* disable interrupts */
++ kgdb_iowrite(0, UART_IER);
++
++#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;
++ kgdb_iowrite(1, UART_OMAP_OSC_12M_SEL);
++ } else
++ kgdb_iowrite(0, UART_OMAP_OSC_12M_SEL);
++ }
++#endif
++ /* set DLAB */
++ kgdb_iowrite(UART_LCR_DLAB, UART_LCR);
++
++ /* set baud */
++ kgdb_iowrite((base_baud / kgdb8250_baud) & 0xff, UART_DLL);
++ kgdb_iowrite((base_baud / kgdb8250_baud) >> 8, UART_DLM);
++
++ /* reset DLAB, set LCR */
++ kgdb_iowrite(UART_LCR_WLEN8, UART_LCR);
++
++ /* set DTR and RTS */
++ kgdb_iowrite(UART_MCR_OUT2 | UART_MCR_DTR | UART_MCR_RTS, UART_MCR);
++
++ /* setup fifo */
++ kgdb_iowrite(UART_FCR_ENABLE_FIFO | UART_FCR_CLEAR_RCVR
++ | UART_FCR_CLEAR_XMIT | UART_FCR_TRIGGER_8,
++ UART_FCR);
++
++ /* clear pending interrupts */
++ kgdb_ioread(UART_IIR);
++ kgdb_ioread(UART_RX);
++ kgdb_ioread(UART_LSR);
++ kgdb_ioread(UART_MSR);
++
++ /* turn on RX interrupt only */
++ kgdb_iowrite(UART_IER_RDI, UART_IER);
++
++ /*
++ * Borrowed from the main 8250 driver.
++ * Try writing and reading the UART_IER_UUE bit (b6).
++ * If it works, this is probably one of the Xscale platform's
++ * internal UARTs.
++ * We're going to explicitly set the UUE bit to 0 before
++ * trying to write and read a 1 just to make sure it's not
++ * already a 1 and maybe locked there before we even start start.
++ */
++ ier = kgdb_ioread(UART_IER);
++ kgdb_iowrite(ier & ~UART_IER_UUE, UART_IER);
++ if (!(kgdb_ioread(UART_IER) & UART_IER_UUE)) {
++ /*
++ * OK it's in a known zero state, try writing and reading
++ * without disturbing the current state of the other bits.
++ */
++ kgdb_iowrite(ier | UART_IER_UUE, UART_IER);
++ if (kgdb_ioread(UART_IER) & UART_IER_UUE)
++ /*
++ * It's an Xscale.
++ */
++ ier |= UART_IER_UUE | UART_IER_RTOIE;
++ }
++ kgdb_iowrite(ier, UART_IER);
++ return 0;
++}
++
++/*
++ * Copy the old serial_state table to our uart_port table if we haven't
++ * had values specifically configured in. We need to make sure this only
++ * happens once.
++ */
++static void __init kgdb8250_copy_rs_table(void)
++{
++#ifdef CONFIG_KGDB_SIMPLE_SERIAL
++ int i;
++
++ if (!should_copy_rs_table)
++ return;
++
++ for (i = 0; i < ARRAY_SIZE(old_rs_table); i++) {
++ kgdb8250_ports[i].iobase = old_rs_table[i].port;
++ kgdb8250_ports[i].irq = irq_canonicalize(old_rs_table[i].irq);
++ kgdb8250_ports[i].uartclk = old_rs_table[i].baud_base * 16;
++ kgdb8250_ports[i].membase = old_rs_table[i].iomem_base;
++ kgdb8250_ports[i].iotype = old_rs_table[i].io_type;
++ kgdb8250_ports[i].regshift = old_rs_table[i].iomem_reg_shift;
++ kgdb8250_ports[i].line = i;
++ }
++
++ should_copy_rs_table = 0;
++#endif
++}
++
++/*
++ * Hookup our IRQ line now that it is safe to do so, after we grab any
++ * memory regions we might need to. If we haven't been initialized yet,
++ * go ahead and copy the old_rs_table in.
++ */
++static void __init kgdb8250_late_init(void)
++{
++ /* Try and copy the old_rs_table. */
++ kgdb8250_copy_rs_table();
++
++#if defined(CONFIG_SERIAL_8250) || defined(CONFIG_SERIAL_8250_MODULE)
++ /* Take the port away from the main driver. */
++ serial8250_unregister_by_port(current_port);
++
++ /* Now reinit the port as the above has disabled things. */
++ kgdb8250_uart_init();
++#endif
++ /* We may need to call request_mem_region() first. */
++ if (kgdb8250_needs_request_mem_region)
++ request_mem_region(current_port->mapbase,
++ 8 << current_port->regshift, "kgdb");
++ if (request_irq(current_port->irq, kgdb8250_interrupt, SA_SHIRQ,
++ "GDB-stub", current_port) < 0)
++ printk(KERN_ERR "KGDB failed to request the serial IRQ (%d)\n",
++ current_port->irq);
++}
++
++static __init int kgdb_init_io(void)
++{
++ /* Give us the basic table of uarts. */
++ kgdb8250_copy_rs_table();
++
++ /* We're either a module and parse a config string, or we have a
++ * semi-static config. */
++#ifdef CONFIG_KGDB_8250_MODULE
++ if (strlen(config)) {
++ if (kgdb8250_opt(config))
++ return -EINVAL;
++ } else {
++ printk(KERN_ERR "kgdb8250: argument error, usage: "
++ "kgdb8250=<io or mmio>,<address>,<baud rate>,<irq>\n");
++ return -EINVAL;
++ }
++#elif defined(CONFIG_KGDB_SIMPLE_SERIAL)
++ kgdb8250_baud = CONFIG_KGDB_BAUDRATE;
++
++ /* Setup our pointer to the serial port now. */
++ current_port = &kgdb8250_ports[CONFIG_KGDB_PORT_NUM];
++#else
++ if (kgdb8250_opt(CONFIG_KGDB_8250_CONF_STRING))
++ return -EINVAL;
++#endif
++
++
++ /* Internal driver setup. */
++ switch (current_port->iotype) {
++ case UPIO_MEM:
++ if (current_port->mapbase)
++ kgdb8250_needs_request_mem_region = 1;
++ if (current_port->flags & UPF_IOREMAP) {
++ current_port->membase = ioremap(current_port->mapbase,
++ 8 << current_port->regshift);
++ if (!current_port->membase)
++ return -EIO; /* Failed. */
++ }
++ kgdb8250_addr = current_port->membase;
++ break;
++ case UPIO_PORT:
++ default:
++ kgdb8250_addr = ioport_map(current_port->iobase,
++ 8 << current_port->regshift);
++ if (!kgdb8250_addr)
++ return -EIO; /* Failed. */
++ }
++
++ if (kgdb8250_uart_init() == -1) {
++ printk(KERN_ERR "kgdb8250: init failed\n");
++ return -EIO;
++ }
++#ifdef CONFIG_KGDB_8250_MODULE
++ /* Attach the kgdb irq. When this is built into the kernel, it
++ * is called as a part of late_init sequence.
++ */
++ kgdb8250_late_init();
++ if (kgdb_register_io_module(&local_kgdb_io_ops))
++ return -EINVAL;
++
++ printk(KERN_INFO "kgdb8250: debugging enabled\n");
++#endif /* CONFIG_KGD_8250_MODULE */
++
++ return 0;
++}
++
++#ifdef CONFIG_KGDB_8250_MODULE
++/* If it is a module the kgdb_io_ops should be a static which
++ * is passed to the KGDB I/O initialization
++ */
++static struct kgdb_io local_kgdb_io_ops = {
++#else /* ! CONFIG_KGDB_8250_MODULE */
++struct kgdb_io kgdb_io_ops = {
++#endif /* ! CONFIG_KGD_8250_MODULE */
++ .read_char = kgdb_get_debug_char,
++ .write_char = kgdb_put_debug_char,
++ .init = kgdb_init_io,
++ .late_init = kgdb8250_late_init,
++};
++
++/**
++ * kgdb8250_add_port - Define a serial port for use with KGDB
++ * @i: The index of the port being added
++ * @serial_req: The &struct uart_port describing the port
++ *
++ * On platforms where we must register the serial device
++ * dynamically, this is the best option if a platform also normally
++ * calls early_serial_setup().
++ */
++void __init kgdb8250_add_port(int i, struct uart_port *serial_req)
++{
++ /* Make sure we've got the built-in data before we override. */
++ kgdb8250_copy_rs_table();
++
++ /* Copy the whole thing over. */
++ if (current_port != &kgdb8250_ports[i])
++ memcpy(&kgdb8250_ports[i], serial_req, sizeof(struct uart_port));
++}
++
++/**
++ * kgdb8250_add_platform_port - Define a serial port for use with KGDB
++ * @i: The index of the port being added
++ * @p: The &struct plat_serial8250_port describing the port
++ *
++ * On platforms where we must register the serial device
++ * dynamically, this is the best option if a platform normally
++ * handles uart setup with an array of &struct plat_serial8250_port.
++ */
++void __init kgdb8250_add_platform_port(int i, struct plat_serial8250_port *p)
++{
++ /* Make sure we've got the built-in data before we override. */
++ kgdb8250_copy_rs_table();
++
++ kgdb8250_ports[i].iobase = p->iobase;
++ kgdb8250_ports[i].membase = p->membase;
++ kgdb8250_ports[i].irq = p->irq;
++ kgdb8250_ports[i].uartclk = p->uartclk;
++ kgdb8250_ports[i].regshift = p->regshift;
++ kgdb8250_ports[i].iotype = p->iotype;
++ kgdb8250_ports[i].flags = p->flags;
++ kgdb8250_ports[i].mapbase = p->mapbase;
++}
++
++/*
++ * Syntax for this cmdline option is:
++ * kgdb8250=<io or mmio>,<address>,<baud rate>,<irq>"
++ */
++static int __init kgdb8250_opt(char *str)
++{
++ /* We'll fill out and use the first slot. */
++ current_port = &kgdb8250_ports[0];
++
++ if (!strncmp(str, "io", 2)) {
++ current_port->iotype = UPIO_PORT;
++ str += 2;
++ } else if (!strncmp(str, "mmap", 4)) {
++ current_port->iotype = UPIO_MEM;
++ current_port->flags |= UPF_IOREMAP;
++ str += 4;
++ } else if (!strncmp(str, "mmio", 4)) {
++ current_port->iotype = UPIO_MEM;
++ current_port->flags &= ~UPF_IOREMAP;
++ str += 4;
++ } else
++ goto errout;
++
++ if (*str != ',')
++ goto errout;
++ str++;
++
++ if (current_port->iotype == UPIO_PORT)
++ current_port->iobase = simple_strtoul(str, &str, 16);
++ else {
++ if (current_port->flags & UPF_IOREMAP)
++ current_port->mapbase =
++ (unsigned long) simple_strtoul(str, &str, 16);
++ else
++ current_port->membase =
++ (void *) simple_strtoul(str, &str, 16);
++ }
++
++ if (*str != ',')
++ goto errout;
++ str++;
++
++ kgdb8250_baud = simple_strtoul(str, &str, 10);
++ if (!kgdb8250_baud)
++ goto errout;
++
++ if (*str != ',')
++ goto errout;
++ str++;
++
++ current_port->irq = simple_strtoul(str, &str, 10);
++
++#ifdef CONFIG_KGDB_SIMPLE_SERIAL
++ should_copy_rs_table = 0;
++#endif
++
++ return 0;
++
++ errout:
++ printk(KERN_ERR "Invalid syntax for option kgdb8250=\n");
++ return 1;
++}
++
++#ifdef CONFIG_KGDB_8250_MODULE
++static void cleanup_kgdb8250(void)
++{
++ kgdb_unregister_io_module(&local_kgdb_io_ops);
++
++ /* Clean up the irq and memory */
++ free_irq(current_port->irq, current_port);
++
++ if (kgdb8250_needs_request_mem_region)
++ release_mem_region(current_port->mapbase,
++ 8 << current_port->regshift);
++ /* Hook up the serial port back to what it was previously
++ * hooked up to.
++ */
++#if defined(CONFIG_SERIAL_8250) || defined(CONFIG_SERIAL_8250_MODULE)
++ /* Give the port back to the 8250 driver. */
++ serial8250_register_port(current_port);
++#endif
++}
++
++module_init(kgdb_init_io);
++module_exit(cleanup_kgdb8250);
++#else /* ! CONFIG_KGDB_8250_MODULE */
++early_param("kgdb8250", kgdb8250_opt);
++#endif /* ! CONFIG_KGDB_8250_MODULE */
+diff -rupN -X ../client-cleanup/dontdiff linux-2.6.18/drivers/serial/Kconfig linux-2.6.18.kgdb/drivers/serial/Kconfig
+--- linux-2.6.18/drivers/serial/Kconfig 2006-09-20 07:42:06.000000000 +0400
++++ linux-2.6.18.kgdb/drivers/serial/Kconfig 2008-06-10 16:19:03.000000000 +0400
+@@ -106,7 +106,7 @@ config SERIAL_8250_CS
+
+ config SERIAL_8250_NR_UARTS
+ int "Maximum number of 8250/16550 serial ports"
+- depends on SERIAL_8250
++ depends on SERIAL_8250 || KGDB_8250
+ default "4"
+ help
+ Set this to the number of serial ports you want the driver
+diff -rupN -X ../client-cleanup/dontdiff linux-2.6.18/drivers/serial/Makefile linux-2.6.18.kgdb/drivers/serial/Makefile
+--- linux-2.6.18/drivers/serial/Makefile 2006-09-20 07:42:06.000000000 +0400
++++ linux-2.6.18.kgdb/drivers/serial/Makefile 2008-06-10 16:19:22.000000000 +0400
+@@ -47,6 +47,7 @@ obj-$(CONFIG_SERIAL_IMX) += imx.o
+ obj-$(CONFIG_SERIAL_MPC52xx) += mpc52xx_uart.o
+ obj-$(CONFIG_SERIAL_ICOM) += icom.o
+ obj-$(CONFIG_SERIAL_M32R_SIO) += m32r_sio.o
++obj-$(CONFIG_KGDB_MPSC) += mpsc_kgdb.o
+ obj-$(CONFIG_SERIAL_MPSC) += mpsc.o
+ obj-$(CONFIG_ETRAX_SERIAL) += crisv10.o
+ obj-$(CONFIG_SERIAL_JSM) += jsm/
+@@ -56,3 +57,4 @@ obj-$(CONFIG_SERIAL_SGI_IOC4) += ioc4_se
+ obj-$(CONFIG_SERIAL_SGI_IOC3) += ioc3_serial.o
+ obj-$(CONFIG_SERIAL_AT91) += at91_serial.o
+ obj-$(CONFIG_SERIAL_NETX) += netx-serial.o
++obj-$(CONFIG_KGDB_8250) += 8250_kgdb.o
+diff -rupN -X ../client-cleanup/dontdiff linux-2.6.18/drivers/serial/amba-pl011.c linux-2.6.18.kgdb/drivers/serial/amba-pl011.c
+--- linux-2.6.18/drivers/serial/amba-pl011.c 2006-09-20 07:42:06.000000000 +0400
++++ linux-2.6.18.kgdb/drivers/serial/amba-pl011.c 2008-06-10 16:19:51.000000000 +0400
+@@ -340,7 +340,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 -rupN -X ../client-cleanup/dontdiff linux-2.6.18/drivers/serial/cpm_uart/Makefile linux-2.6.18.kgdb/drivers/serial/cpm_uart/Makefile
+--- linux-2.6.18/drivers/serial/cpm_uart/Makefile 2006-09-20 07:42:06.000000000 +0400
++++ linux-2.6.18.kgdb/drivers/serial/cpm_uart/Makefile 2008-06-10 16:19:22.000000000 +0400
+@@ -7,5 +7,6 @@ obj-$(CONFIG_SERIAL_CPM) += cpm_uart.o
+ # Select the correct platform objects.
+ cpm_uart-objs-$(CONFIG_CPM2) += cpm_uart_cpm2.o
+ cpm_uart-objs-$(CONFIG_8xx) += cpm_uart_cpm1.o
++cpm_uart-objs-$(CONFIG_KGDB_CPM_UART) += cpm_uart_kgdb.o
+
+ cpm_uart-objs := cpm_uart_core.o $(cpm_uart-objs-y)
+diff -rupN -X ../client-cleanup/dontdiff linux-2.6.18/drivers/serial/cpm_uart/cpm_uart.h linux-2.6.18.kgdb/drivers/serial/cpm_uart/cpm_uart.h
+--- linux-2.6.18/drivers/serial/cpm_uart/cpm_uart.h 2006-09-20 07:42:06.000000000 +0400
++++ linux-2.6.18.kgdb/drivers/serial/cpm_uart/cpm_uart.h 2008-06-10 16:19:22.000000000 +0400
+@@ -51,6 +51,39 @@
+
+ #define SCC_WAIT_CLOSING 100
+
++#ifdef CONFIG_KGDB_CPM_UART
++
++/* Speed of the debug UART. */
++#if defined(CONFIG_KGDB_9600BAUD)
++#define KGDB_BAUD B9600
++#elif defined(CONFIG_KGDB_19200BAUD)
++#define KGDB_BAUD B19200
++#elif defined(CONFIG_KGDB_38400BAUD)
++#define KGDB_BAUD B38400
++#elif defined(CONFIG_KGDB_57600BAUD)
++#define KGDB_BAUD B57600
++#else
++#define KGDB_BAUD B115200 /* Start with this if not given */
++#endif
++
++#ifdef CONFIG_KGDB_CPM_UART_SCC1
++#define KGDB_PINFO_INDEX UART_SCC1
++#elif CONFIG_KGDB_CPM_UART_SCC2
++#define KGDB_PINFO_INDEX UART_SCC2
++#elif CONFIG_KGDB_CPM_UART_SCC3
++#define KGDB_PINFO_INDEX UART_SCC3
++#elif CONFIG_KGDB_CPM_UART_SCC4
++#define KGDB_PINFO_INDEX UART_SCC4
++#elif CONFIG_KGDB_CPM_UART_SMC1
++#define KGDB_PINFO_INDEX UART_SMC1
++#elif CONFIG_KGDB_CPM_UART_SMC2
++#define KGDB_PINFO_INDEX UART_SMC2
++#else
++#error The S(M)CC for kgdb console is undefined
++#endif
++
++#endif /* CONFIG_KGDB_CPM_UART */
++
+ struct uart_cpm_port {
+ struct uart_port port;
+ u16 rx_nrfifos;
+@@ -87,6 +120,9 @@ extern int cpm_uart_port_map[UART_NR];
+ extern int cpm_uart_nr;
+ extern struct uart_cpm_port cpm_uart_ports[UART_NR];
+
++void cpm_uart_early_write(int index, const char *s, u_int count);
++int cpm_uart_early_setup(int index,int early);
++
+ /* these are located in their respective files */
+ void cpm_line_cr_cmd(int line, int cmd);
+ int cpm_uart_init_portdesc(void);
+@@ -133,5 +169,4 @@ static inline void *cpm2cpu_addr(unsigne
+ return 0;
+ }
+
+-
+ #endif /* CPM_UART_H */
+diff -rupN -X ../client-cleanup/dontdiff linux-2.6.18/drivers/serial/cpm_uart/cpm_uart_core.c linux-2.6.18.kgdb/drivers/serial/cpm_uart/cpm_uart_core.c
+--- linux-2.6.18/drivers/serial/cpm_uart/cpm_uart_core.c 2006-09-20 07:42:06.000000000 +0400
++++ linux-2.6.18.kgdb/drivers/serial/cpm_uart/cpm_uart_core.c 2008-06-10 16:19:22.000000000 +0400
+@@ -1070,22 +1070,17 @@ int cpm_uart_drv_get_platform_data(struc
+ return 0;
+ }
+
+-#ifdef CONFIG_SERIAL_CPM_CONSOLE
+-/*
+- * Print a string to the serial port trying not to disturb
+- * any possible real use of the port...
+- *
+- * Note that this is called with interrupts already disabled
+- */
+-static void cpm_uart_console_write(struct console *co, const char *s,
++void cpm_uart_early_write(int index, const char *s,
+ u_int count)
+ {
+- struct uart_cpm_port *pinfo =
+- &cpm_uart_ports[cpm_uart_port_map[co->index]];
++ struct uart_cpm_port *pinfo;
+ unsigned int i;
+ volatile cbd_t *bdp, *bdbase;
+ volatile unsigned char *cp;
+
++ BUG_ON(index>UART_NR);
++ pinfo = &cpm_uart_ports[index];
++
+ /* Get the address of the host memory buffer.
+ */
+ bdp = pinfo->tx_cur;
+@@ -1149,16 +1144,11 @@ static void cpm_uart_console_write(struc
+ pinfo->tx_cur = (volatile cbd_t *) bdp;
+ }
+
+-
+-static int __init cpm_uart_console_setup(struct console *co, char *options)
++int cpm_uart_early_setup(int index, int early)
+ {
++ int ret;
+ struct uart_port *port;
+ struct uart_cpm_port *pinfo;
+- int baud = 38400;
+- int bits = 8;
+- int parity = 'n';
+- int flow = 'n';
+- int ret;
+
+ struct fs_uart_platform_info *pdata;
+ struct platform_device* pdev = early_uart_get_pdev(co->index);
+@@ -1169,8 +1159,9 @@ static int __init cpm_uart_console_setup
+ cpm_uart_init_portdesc();
+ }
+
++ BUG_ON(index>UART_NR);
+ port =
+- (struct uart_port *)&cpm_uart_ports[cpm_uart_port_map[co->index]];
++ (struct uart_port *)&cpm_uart_ports[index];
+ pinfo = (struct uart_cpm_port *)port;
+ if (!pdev) {
+ if (pinfo->set_lineif)
+@@ -1184,19 +1175,6 @@ static int __init cpm_uart_console_setup
+ cpm_uart_drv_get_platform_data(pdev, 1);
+ }
+
+- pinfo->flags |= FLAG_CONSOLE;
+-
+- if (options) {
+- uart_parse_options(options, &baud, &parity, &bits, &flow);
+- } else {
+- bd_t *bd = (bd_t *) __res;
+-
+- if (bd->bi_baudrate)
+- baud = bd->bi_baudrate;
+- else
+- baud = 9600;
+- }
+-
+ if (IS_SMC(pinfo)) {
+ pinfo->smcp->smc_smcm &= ~(SMCM_RX | SMCM_TX);
+ pinfo->smcp->smc_smcmr &= ~(SMCMR_REN | SMCMR_TEN);
+@@ -1204,8 +1182,7 @@ static int __init cpm_uart_console_setup
+ pinfo->sccp->scc_sccm &= ~(UART_SCCM_TX | UART_SCCM_RX);
+ pinfo->sccp->scc_gsmrl &= ~(SCC_GSMRL_ENR | SCC_GSMRL_ENT);
+ }
+-
+- ret = cpm_uart_allocbuf(pinfo, 1);
++ ret = cpm_uart_allocbuf(pinfo, early);
+
+ if (ret)
+ return ret;
+@@ -1217,6 +1194,56 @@ static int __init cpm_uart_console_setup
+ else
+ cpm_uart_init_scc(pinfo);
+
++ return 0;
++}
++
++#ifdef CONFIG_SERIAL_CPM_CONSOLE
++/*
++ * Print a string to the serial port trying not to disturb
++ * any possible real use of the port...
++ *
++ * Note that this is called with interrupts already disabled
++ */
++
++static void cpm_uart_console_write(struct console *co, const char *s,
++ u_int count)
++{
++ cpm_uart_early_write(cpm_uart_port_map[co->index],s,count);
++}
++
++/*
++ * Setup console. Be careful is called early !
++ */
++static int __init cpm_uart_console_setup(struct console *co, char *options)
++{
++ struct uart_port *port;
++ struct uart_cpm_port *pinfo;
++ int baud = 115200;
++ int bits = 8;
++ int parity = 'n';
++ int flow = 'n';
++ int ret;
++
++ port =
++ (struct uart_port *)&cpm_uart_ports[cpm_uart_port_map[co->index]];
++ pinfo = (struct uart_cpm_port *)port;
++
++ pinfo->flags |= FLAG_CONSOLE;
++
++ if (options) {
++ uart_parse_options(options, &baud, &parity, &bits, &flow);
++ } else {
++ bd_t *bd = (bd_t *) __res;
++
++ if (bd->bi_baudrate)
++ baud = bd->bi_baudrate;
++ else
++ baud = 9600;
++ }
++
++ ret = cpm_uart_early_setup(cpm_uart_port_map[co->index], 1);
++ if(ret)
++ return ret;
+ uart_set_options(port, co, baud, parity, bits, flow);
+
+ return 0;
+@@ -1364,6 +1391,12 @@ static int cpm_uart_init(void) {
+
+ for (i = 0; i < cpm_uart_nr; i++) {
+ int con = cpm_uart_port_map[i];
++
++#ifdef CONFIG_KGDB_CPM_UART
++ /* We are not interested in ports yet utilized by kgdb */
++ if(con == KGDB_PINFO_INDEX)
++ continue;
++#endif
+ cpm_uart_ports[con].port.line = i;
+ cpm_uart_ports[con].port.flags = UPF_BOOT_AUTOCONF;
+ uart_add_one_port(&cpm_reg, &cpm_uart_ports[con].port);
+diff -rupN -X ../client-cleanup/dontdiff linux-2.6.18/drivers/serial/cpm_uart/cpm_uart_cpm1.c linux-2.6.18.kgdb/drivers/serial/cpm_uart/cpm_uart_cpm1.c
+--- linux-2.6.18/drivers/serial/cpm_uart/cpm_uart_cpm1.c 2006-09-20 07:42:06.000000000 +0400
++++ linux-2.6.18.kgdb/drivers/serial/cpm_uart/cpm_uart_cpm1.c 2008-06-10 16:19:22.000000000 +0400
+@@ -52,6 +52,7 @@ void cpm_line_cr_cmd(int line, int cmd)
+ {
+ ushort val;
+ volatile cpm8xx_t *cp = cpmp;
++ unsigned *bcsr_io;
+
+ switch (line) {
+ case UART_SMC1:
+@@ -94,12 +95,35 @@ void scc1_lineif(struct uart_cpm_port *p
+ {
+ /* XXX SCC1: insert port configuration here */
+ pinfo->brg = 1;
++
++#if defined (CONFIG_MPC885ADS) || defined (CONFIG_MPC86XADS)
++ bcsr_io = ioremap(BCSR1, sizeof(unsigned long));
++
++ if (bcsr_io == NULL) {
++ printk(KERN_CRIT "Could not remap BCSR\n");
++ return;
++ }
++ out_be32(bcsr_io, in_be32(bcsr_io) & ~BCSR1_RS232EN_1);
++ iounmap(bcsr_io);
++#endif
+ }
+
+ void scc2_lineif(struct uart_cpm_port *pinfo)
+ {
+ /* XXX SCC2: insert port configuration here */
+ pinfo->brg = 2;
++ unsigned *bcsr_io;
++
++#if defined (CONFIG_MPC885ADS) || defined (CONFIG_MPC86XADS)
++ bcsr_io = ioremap(BCSR1, sizeof(unsigned long));
++
++ if (bcsr_io == NULL) {
++ printk(KERN_CRIT "Could not remap BCSR\n");
++ return;
++ }
++ out_be32(bcsr_io, in_be32(bcsr_io) & ~BCSR1_RS232EN_2);
++ iounmap(bcsr_io);
++#endif
+ }
+
+ void scc3_lineif(struct uart_cpm_port *pinfo)
+@@ -188,6 +212,10 @@ int cpm_uart_init_portdesc(void)
+ {
+ pr_debug("CPM uart[-]:init portdesc\n");
+
++ /* Check if we have called this yet. This may happen if early kgdb
++ breakpoint is on */
++ if(cpm_uart_nr)
++ return 0;
+ cpm_uart_nr = 0;
+ #ifdef CONFIG_SERIAL_CPM_SMC1
+ cpm_uart_ports[UART_SMC1].smcp = &cpmp->cp_smc[0];
+diff -rupN -X ../client-cleanup/dontdiff linux-2.6.18/drivers/serial/cpm_uart/cpm_uart_cpm2.c linux-2.6.18.kgdb/drivers/serial/cpm_uart/cpm_uart_cpm2.c
+--- linux-2.6.18/drivers/serial/cpm_uart/cpm_uart_cpm2.c 2006-09-20 07:42:06.000000000 +0400
++++ linux-2.6.18.kgdb/drivers/serial/cpm_uart/cpm_uart_cpm2.c 2008-06-10 16:19:22.000000000 +0400
+@@ -256,6 +256,10 @@ int cpm_uart_init_portdesc(void)
+ {
+ pr_debug("CPM uart[-]:init portdesc\n");
+
++ /* Check if we have called this yet. This may happen if early kgdb
++ breakpoint is on */
++ if(cpm_uart_nr)
++ return 0;
+ cpm_uart_nr = 0;
+ #ifdef CONFIG_SERIAL_CPM_SMC1
+ cpm_uart_ports[UART_SMC1].smcp = (smc_t *) & cpm2_immr->im_smc[0];
+diff -rupN -X ../client-cleanup/dontdiff linux-2.6.18/drivers/serial/cpm_uart/cpm_uart_kgdb.c linux-2.6.18.kgdb/drivers/serial/cpm_uart/cpm_uart_kgdb.c
+--- linux-2.6.18/drivers/serial/cpm_uart/cpm_uart_kgdb.c 1970-01-01 03:00:00.000000000 +0300
++++ linux-2.6.18.kgdb/drivers/serial/cpm_uart/cpm_uart_kgdb.c 2008-06-10 16:19:22.000000000 +0400
+@@ -0,0 +1,195 @@
++/*
++ * drivers/serial/cpm_uart/cpm_uart_kgdb.c
++ *
++ * CPM UART interface for kgdb.
++ *
++ * Author: Vitaly Bordug <vbordug@ru.mvista.com>
++ *
++ * Used some bits from drivers/serial/kgdb_8250.c as a template
++ *
++ * 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.
++ */
++
++#include <linux/kgdb.h>
++#include <linux/config.h>
++#include <linux/kernel.h>
++#include <linux/init.h>
++#include <linux/interrupt.h>
++#include <linux/tty.h>
++#include <linux/serial.h>
++#include <linux/serial_core.h>
++#include <linux/serial_reg.h>
++
++#include <asm/io.h>
++#include <asm/serial.h> /* For BASE_BAUD and SERIAL_PORT_DFNS */
++
++#include "cpm_uart.h"
++
++#define GDB_BUF_SIZE 512 /* power of 2, please */
++
++
++static char kgdb_buf[GDB_BUF_SIZE], *kgdbp;
++static int kgdb_chars;
++
++/* Forward declarations. */
++
++/*
++ * Receive character from the serial port. This only works well
++ * before the port is initialize for real use.
++ */
++static int kgdb_wait_key(char *obuf)
++{
++ struct uart_cpm_port *pinfo;
++
++ u_char c, *cp;
++ volatile cbd_t *bdp;
++ int i;
++
++ pinfo = &cpm_uart_ports[KGDB_PINFO_INDEX];
++
++ /* Get the address of the host memory buffer.
++ */
++ bdp = pinfo->rx_cur;
++ while (bdp->cbd_sc & BD_SC_EMPTY);
++
++ /* If the buffer address is in the CPM DPRAM, don't
++ * convert it.
++ */
++ cp = cpm2cpu_addr(bdp->cbd_bufaddr);
++
++ if (obuf) {
++ i = c = bdp->cbd_datlen;
++ while (i-- > 0)
++ {
++ *obuf++ = *cp++;
++ }
++ } else {
++ c = *cp;
++ }
++ bdp->cbd_sc |= BD_SC_EMPTY;
++
++ if (bdp->cbd_sc & BD_SC_WRAP) {
++ bdp = pinfo->rx_bd_base;
++ } else {
++ bdp++;
++ }
++ pinfo->rx_cur = (cbd_t *)bdp;
++
++ return((int)c);
++}
++
++
++/*
++ * Wait until the interface can accept a char, then write it.
++ */
++static void
++kgdb_put_debug_char(int chr)
++{
++ static char ch[2];
++ ch[0]=(char)chr;
++ cpm_uart_early_write(KGDB_PINFO_INDEX, ch, 1);
++}
++
++
++/*
++ * Get a char if available, return -1 if nothing available.
++ * Empty the receive buffer first, then look at the interface hardware.
++ */
++static int
++kgdb_get_debug_char(void)
++{
++ if (kgdb_chars<=0) {
++ kgdb_chars = kgdb_wait_key(kgdb_buf);
++ kgdbp = kgdb_buf;
++ }
++ kgdb_chars--;
++
++ return (*kgdbp++);
++}
++
++static void termios_set_options(int index,
++ int baud, int parity, int bits, int flow)
++{
++ struct termios termios;
++ struct uart_port *port;
++ struct uart_cpm_port *pinfo;
++
++ BUG_ON(index>UART_NR);
++
++ port =
++ (struct uart_port *)&cpm_uart_ports[index];
++ pinfo = (struct uart_cpm_port *)port;
++
++ /*
++ * Ensure that the serial console lock is initialised
++ * early.
++ */
++ spin_lock_init(&port->lock);
++
++ memset(&termios, 0, sizeof(struct termios));
++
++ termios.c_cflag = CREAD | HUPCL | CLOCAL;
++
++ termios.c_cflag |= baud;
++
++ if (bits == 7)
++ termios.c_cflag |= CS7;
++ else
++ termios.c_cflag |= CS8;
++
++ switch (parity) {
++ case 'o': case 'O':
++ termios.c_cflag |= PARODD;
++ /*fall through*/
++ case 'e': case 'E':
++ termios.c_cflag |= PARENB;
++ break;
++ }
++
++ if (flow == 'r')
++ termios.c_cflag |= CRTSCTS;
++
++ port->ops->set_termios(port, &termios, NULL);
++}
++
++/*
++ * Returns:
++ * 0 on success, 1 on failure.
++ */
++static int kgdb_init(void)
++{
++ struct uart_port *port;
++ struct uart_cpm_port *pinfo;
++
++ int use_bootmem = 0; /* use dma by default */
++
++ if(!cpm_uart_nr)
++ {
++ use_bootmem = 1;
++ cpm_uart_init_portdesc();
++ }
++ port = (struct uart_port *)&cpm_uart_ports[KGDB_PINFO_INDEX];
++ pinfo = (struct uart_cpm_port *)port;
++
++ if (cpm_uart_early_setup(KGDB_PINFO_INDEX, use_bootmem))
++ return 1;
++
++ termios_set_options(KGDB_PINFO_INDEX, KGDB_BAUD,'n',8,'n');
++ if (IS_SMC(pinfo))
++ pinfo->smcp->smc_smcm |= SMCM_TX;
++ else
++ pinfo->sccp->scc_sccm |= UART_SCCM_TX;
++
++ return 0;
++}
++
++
++struct kgdb_io kgdb_io_ops = {
++ .read_char = kgdb_get_debug_char,
++ .write_char = kgdb_put_debug_char,
++ .init = kgdb_init,
++};
++
+diff -rupN -X ../client-cleanup/dontdiff linux-2.6.18/drivers/serial/mpsc.c linux-2.6.18.kgdb/drivers/serial/mpsc.c
+--- linux-2.6.18/drivers/serial/mpsc.c 2006-09-20 07:42:06.000000000 +0400
++++ linux-2.6.18.kgdb/drivers/serial/mpsc.c 2008-06-10 16:19:22.000000000 +0400
+@@ -242,6 +242,11 @@ struct mpsc_port_info *mpsc_device_remov
+ #define MPSC_RCRR 0x0004
+ #define MPSC_TCRR 0x0008
+
++/* MPSC Interrupt registers (offset from MV64x60_SDMA_INTR_OFFSET) */
++#define MPSC_INTR_CAUSE 0x0004
++#define MPSC_INTR_MASK 0x0084
++#define MPSC_INTR_CAUSE_RCC (1<<6)
++
+ /* Serial DMA Controller Interface Registers */
+ #define SDMA_SDC 0x0000
+ #define SDMA_SDCM 0x0008
+diff -rupN -X ../client-cleanup/dontdiff linux-2.6.18/drivers/serial/mpsc_kgdb.c linux-2.6.18.kgdb/drivers/serial/mpsc_kgdb.c
+--- linux-2.6.18/drivers/serial/mpsc_kgdb.c 1970-01-01 03:00:00.000000000 +0300
++++ linux-2.6.18.kgdb/drivers/serial/mpsc_kgdb.c 2008-06-10 16:19:22.000000000 +0400
+@@ -0,0 +1,299 @@
++/*
++ * drivers/serial/mpsc_kgdb.c
++ *
++ * KGDB driver for the Marvell MultiProtocol Serial Controller (MPCS)
++ *
++ * Based on the polled boot loader driver by Ajit Prem (ajit.prem@motorola.com)
++ *
++ * Author: Randy Vinson <rvinson@mvista.com>
++ *
++ * 2005 (c) 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 as published by the
++ * Free Software Foundation; either version 2 of the License, or (at your
++ * option) any later version.
++ */
++
++#include <linux/config.h>
++#include <linux/kgdb.h>
++#include <linux/mv643xx.h>
++#include <linux/device.h>
++#include <asm/mv64x60.h>
++#include <asm/serial.h>
++#include <asm/io.h>
++#include <asm/delay.h>
++
++#include "mpsc.h"
++
++/* Speed of the UART. */
++static int kgdbmpsc_baud = CONFIG_KGDB_BAUDRATE;
++
++/* Index of the UART, matches ttyMX naming. */
++static int kgdbmpsc_ttyMM = CONFIG_KGDB_PORT_NUM;
++
++#define MPSC_INTR_REG_SELECT(x) ((x) + (8 * kgdbmpsc_ttyMM))
++
++static int kgdbmpsc_init(void);
++
++static struct platform_device mpsc_dev, shared_dev;
++
++static void __iomem *mpsc_base;
++static void __iomem *brg_base;
++static void __iomem *routing_base;
++static void __iomem *sdma_base;
++
++static unsigned int mpsc_irq;
++
++static void kgdb_write_debug_char(int c)
++{
++ u32 data;
++
++ data = readl(mpsc_base + MPSC_MPCR);
++ writeb(c, mpsc_base + MPSC_CHR_1);
++ mb();
++ data = readl(mpsc_base + MPSC_CHR_2);
++ data |= MPSC_CHR_2_TTCS;
++ writel(data, mpsc_base + MPSC_CHR_2);
++ mb();
++
++ while (readl(mpsc_base + MPSC_CHR_2) & MPSC_CHR_2_TTCS) ;
++}
++
++static int kgdb_get_debug_char(void)
++{
++ unsigned char c;
++
++ while (!(readl(sdma_base + MPSC_INTR_REG_SELECT(MPSC_INTR_CAUSE)) &
++ MPSC_INTR_CAUSE_RCC)) ;
++
++ c = readb(mpsc_base + MPSC_CHR_10 + (1 << 1));
++ mb();
++ writeb(c, mpsc_base + MPSC_CHR_10 + (1 << 1));
++ mb();
++ writel(~MPSC_INTR_CAUSE_RCC, sdma_base +
++ MPSC_INTR_REG_SELECT(MPSC_INTR_CAUSE));
++ return (c);
++}
++
++/*
++ * This is the receiver interrupt routine for the GDB stub.
++ * All that we need to do is verify that the interrupt happened on the
++ * line we're in charge of. If this is true, schedule a breakpoint and
++ * return.
++ */
++static irqreturn_t
++kgdbmpsc_interrupt(int irq, void *dev_id, struct pt_regs *regs)
++{
++ if (irq != mpsc_irq)
++ return IRQ_NONE;
++ /*
++ * If there is some other CPU in KGDB then this is a
++ * spurious interrupt. so return without even checking a byte
++ */
++ if (atomic_read(&debugger_active))
++ return IRQ_NONE;
++
++ if (readl(sdma_base + MPSC_INTR_REG_SELECT(MPSC_INTR_CAUSE)) &
++ MPSC_INTR_CAUSE_RCC)
++ breakpoint();
++
++ return IRQ_HANDLED;
++}
++
++static int __init kgdbmpsc_init(void)
++{
++ struct mpsc_pdata *pdata;
++ u32 cdv;
++
++ if (!brg_base || !mpsc_base || !routing_base || !sdma_base)
++ return -1;
++
++ /* Set MPSC Routing to enable both ports */
++ writel(0x0, routing_base + MPSC_MRR);
++
++ /* MPSC 0/1 Rx & Tx get clocks BRG0/1 */
++ writel(0x00000100, routing_base + MPSC_RCRR);
++ writel(0x00000100, routing_base + MPSC_TCRR);
++
++ /* Disable all MPSC interrupts and clear any pending interrupts */
++ writel(0, sdma_base + MPSC_INTR_REG_SELECT(MPSC_INTR_MASK));
++ writel(0, sdma_base + MPSC_INTR_REG_SELECT(MPSC_INTR_CAUSE));
++
++ pdata = (struct mpsc_pdata *)mpsc_dev.dev.platform_data;
++
++ /* cdv = (clock/(2*16*baud rate)) for 16X mode. */
++ cdv = ((pdata->brg_clk_freq / (32 * kgdbmpsc_baud)) - 1);
++ writel((pdata->brg_clk_src << 18) | (1 << 16) | cdv,
++ brg_base + BRG_BCR);
++
++ /* Put MPSC into UART mode, no null modem, 16x clock mode */
++ writel(0x000004c4, mpsc_base + MPSC_MMCRL);
++ writel(0x04400400, mpsc_base + MPSC_MMCRH);
++
++ writel(0, mpsc_base + MPSC_CHR_1);
++ writel(0, mpsc_base + MPSC_CHR_9);
++ writel(0, mpsc_base + MPSC_CHR_10);
++ writel(4, mpsc_base + MPSC_CHR_3);
++ writel(0x20000000, mpsc_base + MPSC_CHR_4);
++ writel(0x9000, mpsc_base + MPSC_CHR_5);
++ writel(0, mpsc_base + MPSC_CHR_6);
++ writel(0, mpsc_base + MPSC_CHR_7);
++ writel(0, mpsc_base + MPSC_CHR_8);
++
++ /* 8 data bits, 1 stop bit */
++ writel((3 << 12), mpsc_base + MPSC_MPCR);
++
++ /* Enter "hunt" mode */
++ writel((1 << 31), mpsc_base + MPSC_CHR_2);
++
++ udelay(100);
++ return 0;
++}
++
++static void __iomem *__init
++kgdbmpsc_map_resource(struct platform_device *pd, int type, int num)
++{
++ void __iomem *base = NULL;
++ struct resource *r;
++
++ if ((r = platform_get_resource(pd, IORESOURCE_MEM, num)))
++ base = ioremap(r->start, r->end - r->start + 1);
++ return base;
++}
++
++static void __iomem *__init
++kgdbmpsc_unmap_resource(struct platform_device *pd, int type, int num,
++ void __iomem * base)
++{
++ if (base)
++ iounmap(base);
++ return NULL;
++}
++
++static void __init
++kgdbmpsc_reserve_resource(struct platform_device *pd, int type, int num)
++{
++ struct resource *r;
++
++ if ((r = platform_get_resource(pd, IORESOURCE_MEM, num)))
++ request_mem_region(r->start, r->end - r->start + 1, "kgdb");
++}
++
++static int __init kgdbmpsc_local_init(void)
++{
++ if (!mpsc_dev.num_resources || !shared_dev.num_resources)
++ return 1; /* failure */
++
++ mpsc_base = kgdbmpsc_map_resource(&mpsc_dev, IORESOURCE_MEM,
++ MPSC_BASE_ORDER);
++ brg_base = kgdbmpsc_map_resource(&mpsc_dev, IORESOURCE_MEM,
++ MPSC_BRG_BASE_ORDER);
++
++ /* get the platform data for the shared registers and get them mapped */
++ routing_base = kgdbmpsc_map_resource(&shared_dev,
++ IORESOURCE_MEM,
++ MPSC_ROUTING_BASE_ORDER);
++ sdma_base =
++ kgdbmpsc_map_resource(&shared_dev, IORESOURCE_MEM,
++ MPSC_SDMA_INTR_BASE_ORDER);
++
++ mpsc_irq = platform_get_irq(&mpsc_dev, 1);
++
++ if (mpsc_base && brg_base && routing_base && sdma_base)
++ return 0; /* success */
++
++ return 1; /* failure */
++}
++
++static void __init kgdbmpsc_local_exit(void)
++{
++ if (sdma_base)
++ sdma_base = kgdbmpsc_unmap_resource(&shared_dev, IORESOURCE_MEM,
++ MPSC_SDMA_INTR_BASE_ORDER,
++ sdma_base);
++ if (routing_base)
++ routing_base = kgdbmpsc_unmap_resource(&shared_dev,
++ IORESOURCE_MEM,
++ MPSC_ROUTING_BASE_ORDER,
++ routing_base);
++ if (brg_base)
++ brg_base = kgdbmpsc_unmap_resource(&mpsc_dev, IORESOURCE_MEM,
++ MPSC_BRG_BASE_ORDER,
++ brg_base);
++ if (mpsc_base)
++ mpsc_base = kgdbmpsc_unmap_resource(&mpsc_dev, IORESOURCE_MEM,
++ MPSC_BASE_ORDER, mpsc_base);
++}
++
++static void __init kgdbmpsc_update_pdata(struct platform_device *pdev)
++{
++
++ snprintf(pdev->dev.bus_id, BUS_ID_SIZE, "%s%u", pdev->name, pdev->id);
++}
++
++static int __init kgdbmpsc_pdev_init(void)
++{
++ struct platform_device *pdev;
++
++ /* get the platform data for the specified port. */
++ pdev = mv64x60_early_get_pdev_data(MPSC_CTLR_NAME, kgdbmpsc_ttyMM, 1);
++ if (pdev) {
++ memcpy(&mpsc_dev, pdev, sizeof(struct platform_device));
++ if (platform_notify) {
++ kgdbmpsc_update_pdata(&mpsc_dev);
++ platform_notify(&mpsc_dev.dev);
++ }
++
++ /* get the platform data for the shared registers. */
++ pdev = mv64x60_early_get_pdev_data(MPSC_SHARED_NAME, 0, 0);
++ if (pdev) {
++ memcpy(&shared_dev, pdev,
++ sizeof(struct platform_device));
++ if (platform_notify) {
++ kgdbmpsc_update_pdata(&shared_dev);
++ platform_notify(&shared_dev.dev);
++ }
++ }
++ }
++ return 0;
++}
++
++postcore_initcall(kgdbmpsc_pdev_init);
++
++static int __init kgdbmpsc_init_io(void)
++{
++
++ kgdbmpsc_pdev_init();
++
++ if (kgdbmpsc_local_init()) {
++ kgdbmpsc_local_exit();
++ return -1;
++ }
++
++ if (kgdbmpsc_init() == -1)
++ return -1;
++ return 0;
++}
++
++static void __init kgdbmpsc_hookup_irq(void)
++{
++ unsigned int msk;
++ if (!request_irq(mpsc_irq, kgdbmpsc_interrupt, 0, "kgdb mpsc", NULL)) {
++ /* Enable interrupt */
++ msk = readl(sdma_base + MPSC_INTR_REG_SELECT(MPSC_INTR_MASK));
++ msk |= MPSC_INTR_CAUSE_RCC;
++ writel(msk, sdma_base + MPSC_INTR_REG_SELECT(MPSC_INTR_MASK));
++
++ kgdbmpsc_reserve_resource(&mpsc_dev, IORESOURCE_MEM,
++ MPSC_BASE_ORDER);
++ kgdbmpsc_reserve_resource(&mpsc_dev, IORESOURCE_MEM,
++ MPSC_BRG_BASE_ORDER);
++ }
++}
++
++struct kgdb_io kgdb_io_ops = {
++ .read_char = kgdb_get_debug_char,
++ .write_char = kgdb_write_debug_char,
++ .init = kgdbmpsc_init_io,
++ .late_init = kgdbmpsc_hookup_irq,
++};
+diff -rupN -X ../client-cleanup/dontdiff linux-2.6.18/drivers/serial/pxa.c linux-2.6.18.kgdb/drivers/serial/pxa.c
+--- linux-2.6.18/drivers/serial/pxa.c 2006-09-20 07:42:06.000000000 +0400
++++ linux-2.6.18.kgdb/drivers/serial/pxa.c 2008-06-10 16:19:51.000000000 +0400
+@@ -42,6 +42,9 @@
+ #include <linux/tty.h>
+ #include <linux/tty_flip.h>
+ #include <linux/serial_core.h>
++#ifdef CONFIG_KGDB_CONSOLE
++#include <linux/kgdb.h>
++#endif
+
+ #include <asm/io.h>
+ #include <asm/hardware.h>
+@@ -692,6 +695,8 @@ serial_pxa_console_init(void)
+ console_initcall(serial_pxa_console_init);
+
+ #define PXA_CONSOLE &serial_pxa_console
++#elif defined(CONFIG_KGDB_CONSOLE)
++#define PXA_CONSOLE &kgdbcons
+ #else
+ #define PXA_CONSOLE NULL
+ #endif
+diff -rupN -X ../client-cleanup/dontdiff linux-2.6.18/drivers/serial/serial_core.c linux-2.6.18.kgdb/drivers/serial/serial_core.c
+--- linux-2.6.18/drivers/serial/serial_core.c 2006-09-20 07:42:06.000000000 +0400
++++ linux-2.6.18.kgdb/drivers/serial/serial_core.c 2008-06-10 16:19:03.000000000 +0400
+@@ -33,6 +33,7 @@
+ #include <linux/serial.h> /* for serial_state and serial_icounter_struct */
+ #include <linux/delay.h>
+ #include <linux/mutex.h>
++#include <linux/kgdb.h>
+
+ #include <asm/irq.h>
+ #include <asm/uaccess.h>
+@@ -65,6 +66,12 @@ static struct lock_class_key port_lock_k
+ #define uart_console(port) (0)
+ #endif
+
++#ifdef CONFIG_KGDB_CONSOLE
++#define uart_kgdb(port) (port->cons && !strcmp(port->cons->name, "kgdb"))
++#else
++#define uart_kgdb(port) (0)
++#endif
++
+ static void uart_change_speed(struct uart_state *state, struct termios *old_termios);
+ static void uart_wait_until_sent(struct tty_struct *tty, int timeout);
+ static void uart_change_pm(struct uart_state *state, int pm_state);
+@@ -1673,6 +1680,9 @@ static int uart_line_info(char *buf, str
+ port->iotype == UPIO_MEM ? port->mapbase :
+ (unsigned long) port->iobase,
+ port->irq);
++ if (port->iotype == UPIO_MEM)
++ ret += sprintf(buf+ret, " membase 0x%08lX",
++ (unsigned long) port->membase);
+
+ if (port->type == PORT_UNKNOWN) {
+ strcat(buf, "\n");
+@@ -2038,7 +2048,8 @@ uart_report_port(struct uart_driver *drv
+ case UPIO_AU:
+ case UPIO_TSI:
+ snprintf(address, sizeof(address),
+- "MMIO 0x%lx", port->mapbase);
++ "MMIO map 0x%lx mem 0x%lx", port->mapbase,
++ (unsigned long) port->membase);
+ break;
+ default:
+ strlcpy(address, "*unknown*", sizeof(address));
+@@ -2090,9 +2101,9 @@ uart_configure_port(struct uart_driver *
+
+ /*
+ * Power down all ports by default, except the
+- * console if we have one.
++ * console (real or kgdb) if we have one.
+ */
+- if (!uart_console(port))
++ if (!uart_console(port) && !uart_kgdb(port))
+ uart_change_pm(state, 3);
+ }
+ }
+@@ -2284,6 +2295,12 @@ int uart_add_one_port(struct uart_driver
+ */
+ port->flags &= ~UPF_DEAD;
+
++#if defined(CONFIG_KGDB_8250)
++ /* Add any 8250-like ports we find later. */
++ if (port->type <= PORT_MAX_8250)
++ kgdb8250_add_port(port->line, port);
++#endif
++
+ out:
+ mutex_unlock(&state->mutex);
+ mutex_unlock(&port_mutex);
+diff -rupN -X ../client-cleanup/dontdiff linux-2.6.18/drivers/serial/serial_txx9.c linux-2.6.18.kgdb/drivers/serial/serial_txx9.c
+--- linux-2.6.18/drivers/serial/serial_txx9.c 2006-09-20 07:42:06.000000000 +0400
++++ linux-2.6.18.kgdb/drivers/serial/serial_txx9.c 2008-06-10 16:19:28.000000000 +0400
+@@ -1164,6 +1164,96 @@ static struct pci_driver serial_txx9_pci
+ MODULE_DEVICE_TABLE(pci, serial_txx9_pci_tbl);
+ #endif /* ENABLE_SERIAL_TXX9_PCI */
+
++/******************************************************************************/
++/* BEG: KDBG Routines */
++/******************************************************************************/
++
++#ifdef CONFIG_KGDB
++int kgdb_init_count = 0;
++
++void txx9_sio_kgdb_hook(unsigned int port, unsigned int baud_rate)
++{
++ static struct resource kgdb_resource;
++ int ret;
++ struct uart_txx9_port *up = &serial_txx9_ports[port];
++
++ /* prevent initialization by driver */
++ kgdb_resource.name = "serial_txx9(debug)";
++ kgdb_resource.start = (unsigned long)up->port.membase;
++ kgdb_resource.end = (unsigned long)(up->port.membase + 36 - 1);
++ kgdb_resource.flags = IORESOURCE_MEM | IORESOURCE_BUSY;
++
++ ret = request_resource(&iomem_resource, &kgdb_resource);
++ if(ret == -EBUSY)
++ printk(" serial_txx9(debug): request_resource failed\n");
++
++ return;
++}
++void
++txx9_sio_kdbg_init( unsigned int port_number )
++{
++ if (port_number == 1) {
++ txx9_sio_kgdb_hook(port_number, 38400);
++ } else {
++ printk("Bad Port Number [%u] != [1]\n",port_number);
++ }
++ return;
++}
++
++u8
++txx9_sio_kdbg_rd( void )
++{
++ unsigned int status,ch;
++ struct uart_txx9_port *up = &serial_txx9_ports[1];
++
++ if (kgdb_init_count == 0) {
++ txx9_sio_kdbg_init(1);
++ kgdb_init_count = 1;
++ }
++
++ while (1) {
++ status = sio_in(up, TXX9_SIDISR);
++ if ( status & 0x1f ) {
++ ch = sio_in(up, TXX9_SIRFIFO );
++ break;
++ }
++ }
++
++ return (ch);
++}
++
++int
++txx9_sio_kdbg_wr( u8 ch )
++{
++ unsigned int status;
++ struct uart_txx9_port *up = &serial_txx9_ports[1];
++
++ if (kgdb_init_count == 0) {
++ txx9_sio_kdbg_init(1);
++ kgdb_init_count = 1;
++ }
++
++ while (1) {
++ status = sio_in(up, TXX9_SICISR);
++ if (status & TXX9_SICISR_TRDY) {
++ if ( ch == '\n' ) {
++ txx9_sio_kdbg_wr( '\r' );
++ }
++ sio_out(up, TXX9_SITFIFO, (u32)ch );
++
++ break;
++ }
++ }
++
++ return (1);
++}
++#endif /* CONFIG_KGDB */
++
++
++/******************************************************************************/
++/* END: KDBG Routines */
++/******************************************************************************/
++
+ static int __init serial_txx9_init(void)
+ {
+ int ret;
+diff -rupN -X ../client-cleanup/dontdiff linux-2.6.18/drivers/serial/sh-sci.c linux-2.6.18.kgdb/drivers/serial/sh-sci.c
+--- linux-2.6.18/drivers/serial/sh-sci.c 2006-09-20 07:42:06.000000000 +0400
++++ linux-2.6.18.kgdb/drivers/serial/sh-sci.c 2008-06-10 16:19:47.000000000 +0400
+@@ -42,6 +42,7 @@
+ #include <linux/console.h>
+ #include <linux/bitops.h>
+ #include <linux/generic_serial.h>
++#include <linux/kgdb.h>
+
+ #ifdef CONFIG_CPU_FREQ
+ #include <linux/notifier.h>
+@@ -67,14 +68,16 @@
+
+ #include "sh-sci.h"
+
+-#ifdef CONFIG_SH_KGDB
+-#include <asm/kgdb.h>
+-
+-static int kgdb_get_char(struct sci_port *port);
+-static void kgdb_put_char(struct sci_port *port, char c);
+-static void kgdb_handle_error(struct sci_port *port);
+-static struct sci_port *kgdb_sci_port;
+-#endif /* CONFIG_SH_KGDB */
++#ifdef CONFIG_KGDB_SH_SCI
++/* Speed of the UART. */
++static int kgdbsci_baud = CONFIG_KGDB_BAUDRATE
++
++/* Index of the UART, matches ttySCX naming. */
++static int kgdbsci_ttySC = CONFIG_KGDB_PORT_NUM;
++
++/* Make life easier on us. */
++#define KGDBPORT sci_ports[kgdbsci_ttySC]
++#endif /* CONFIG_KGDB_SH_SCI */
+
+ #ifdef CONFIG_SERIAL_SH_SCI_CONSOLE
+ static struct sci_port *serial_console_port = 0;
+@@ -87,20 +90,17 @@ static void sci_start_rx(struct uart_por
+ static void sci_stop_rx(struct uart_port *port);
+ static int sci_request_irq(struct sci_port *port);
+ static void sci_free_irq(struct sci_port *port);
++static void sci_set_termios(struct uart_port *port, struct termios *termios,
++ struct termios *old);
++static int kgdbsci_init(void);
+
+ static struct sci_port sci_ports[];
+ static struct uart_driver sci_uart_driver;
+
+ #define SCI_NPORTS sci_uart_driver.nr
+
+-#if defined(CONFIG_SH_STANDARD_BIOS) || defined(CONFIG_SH_KGDB)
+-
+-static void handle_error(struct uart_port *port)
+-{ /* Clear error flags */
+- sci_out(port, SCxSR, SCxSR_ERROR_CLEAR(port));
+-}
+-
+-static int get_char(struct uart_port *port)
++#if defined(CONFIG_SH_STANDARD_BIOS) || defined(CONFIG_KGDB_SH_SCI)
++static int get_char_for_gdb(struct uart_port *port)
+ {
+ unsigned long flags;
+ unsigned short status;
+@@ -110,7 +110,8 @@ static int get_char(struct uart_port *po
+ do {
+ status = sci_in(port, SCxSR);
+ if (status & SCxSR_ERRORS(port)) {
+- handle_error(port);
++ /* Clear error flags. */
++ sci_out(port, SCxSR, SCxSR_ERROR_CLEAR(port));
+ continue;
+ }
+ } while (!(status & SCxSR_RDxF(port)));
+@@ -121,21 +122,7 @@ static int get_char(struct uart_port *po
+
+ return c;
+ }
+-
+-/* Taken from sh-stub.c of GDB 4.18 */
+-static const char hexchars[] = "0123456789abcdef";
+-
+-static __inline__ char highhex(int x)
+-{
+- return hexchars[(x >> 4) & 0xf];
+-}
+-
+-static __inline__ char lowhex(int x)
+-{
+- return hexchars[x & 0xf];
+-}
+-
+-#endif /* CONFIG_SH_STANDARD_BIOS || CONFIG_SH_KGDB */
++#endif /* CONFIG_SH_STANDARD_BIOS || CONFIG_KGDB_SH_SCI */
+
+ /*
+ * Send the packet in buffer. The host gets one chance to read it.
+@@ -167,21 +154,14 @@ static void put_string(struct sci_port *
+ const unsigned char *p = buffer;
+ int i;
+
+-#if defined(CONFIG_SH_STANDARD_BIOS) || defined(CONFIG_SH_KGDB)
+- int checksum;
+- int usegdb=0;
+-
+ #ifdef CONFIG_SH_STANDARD_BIOS
++ int checksum;
++ const char hexchars[] = "0123456789abcdef";
++
+ /* This call only does a trap the first time it is
+ * called, and so is safe to do here unconditionally
+ */
+- usegdb |= sh_bios_in_gdb_mode();
+-#endif
+-#ifdef CONFIG_SH_KGDB
+- usegdb |= (kgdb_in_gdb_mode && (port == kgdb_sci_port));
+-#endif
+-
+- if (usegdb) {
++ if (sh_bios_in_gdb_mode()) {
+ /* $<packet info>#<checksum>. */
+ do {
+ unsigned char c;
+@@ -193,18 +173,18 @@ static void put_string(struct sci_port *
+ int h, l;
+
+ c = *p++;
+- h = highhex(c);
+- l = lowhex(c);
++ h = hexchars[c >> 4];
++ l = hexchars[c % 16];
+ put_char(port, h);
+ put_char(port, l);
+ checksum += h + l;
+ }
+ put_char(port, '#');
+- put_char(port, highhex(checksum));
+- put_char(port, lowhex(checksum));
++ put_char(port, hexchars[checksum >> 4]);
++ put_char(port, hexchars[checksum % 16]);
+ } while (get_char(port) != '+');
+ } else
+-#endif /* CONFIG_SH_STANDARD_BIOS || CONFIG_SH_KGDB */
++#endif /* CONFIG_SH_STANDARD_BIOS */
+ for (i=0; i<count; i++) {
+ if (*p == 10)
+ put_char(port, '\r');
+@@ -214,90 +194,163 @@ static void put_string(struct sci_port *
+ #endif /* CONFIG_SERIAL_SH_SCI_CONSOLE */
+
+
+-#ifdef CONFIG_SH_KGDB
+-
+-/* Is the SCI ready, ie is there a char waiting? */
+-static int kgdb_is_char_ready(struct sci_port *port)
++#ifdef CONFIG_KGDB_SH_SCI
++static int kgdbsci_read_char(void)
+ {
+- unsigned short status = sci_in(port, SCxSR);
+-
+- if (status & (SCxSR_ERRORS(port) | SCxSR_BRK(port)))
+- kgdb_handle_error(port);
+-
+- return (status & SCxSR_RDxF(port));
++ return get_char_for_gdb(&KGDBPORT.port);
+ }
+
+-/* Write a char */
+-static void kgdb_put_char(struct sci_port *port, char c)
++/* Called from kgdbstub.c to put a character, just a wrapper */
++static void kgdbsci_write_char(int c)
+ {
+- unsigned short status;
+-
+- do
+- status = sci_in(port, SCxSR);
+- while (!(status & SCxSR_TDxE(port)));
++ unsigned short status;
+
+- sci_out(port, SCxTDR, c);
+- sci_in(port, SCxSR); /* Dummy read */
+- sci_out(port, SCxSR, SCxSR_TDxE_CLEAR(port));
++ do
++ status = sci_in(&KGDBPORT.port, SCxSR);
++ while (!(status & SCxSR_TDxE(&KGDBPORT.port)));
++
++ sci_out(&KGDBPORT.port, SCxTDR, c);
++ sci_in(&KGDBPORT.port, SCxSR); /* Dummy read */
++ sci_out(&KGDBPORT.port, SCxSR, SCxSR_TDxE_CLEAR(&KGDBPORT.port));
+ }
+
+-/* Get a char if there is one, else ret -1 */
+-static int kgdb_get_char(struct sci_port *port)
++#ifndef CONFIG_SERIAL_SH_SCI_CONSOLE
++/* If we don't have console, we never hookup IRQs. But we need to
++ * hookup one so that we can interrupt the system.
++ */
++static irqreturn_t kgdbsci_rx_interrupt(int irq, void *ptr,
++ struct pt_regs *regs)
+ {
+- int c;
++ struct uart_port *port = ptr;
+
+- if (kgdb_is_char_ready(port) == 0)
+- c = -1;
+- else {
+- c = sci_in(port, SCxRDR);
+- sci_in(port, SCxSR); /* Dummy read */
+- sci_out(port, SCxSR, SCxSR_RDxF_CLEAR(port));
+- }
++ if (!(sci_in(port, SCxSR) & SCxSR_RDxF(port)))
++ return IRQ_NONE;
+
+- return c;
+-}
+-
+-/* Called from kgdbstub.c to get a character, i.e. is blocking */
+-static int kgdb_sci_getchar(void)
+-{
+- volatile int c;
++ if (kgdb_io_ops.init != kgdbsci_init) {
++ /* Throw away the data if another I/O routine is active */
++ get_char_for_gdb(&KGDBPORT.port);
++ } else
++ /* We've got an interrupt, so go ahead and call breakpoint() */
++ breakpoint();
+
+- /* Keep trying to read a character, this could be neater */
+- while ((c = kgdb_get_char(kgdb_sci_port)) < 0);
++ sci_in(port, SCxSR); /* dummy read */
++ sci_out(port, SCxSR, SCxSR_RDxF_CLEAR(port));
+
+- return c;
++ return IRQ_HANDLED;
+ }
+
+-/* Called from kgdbstub.c to put a character, just a wrapper */
+-static void kgdb_sci_putchar(int c)
++static irqreturn_t kgdbsci_mpxed_interrupt(int irq, void *ptr,
++ struct pt_regs *regs)
+ {
++ unsigned short ssr_status, scr_status;
++ struct uart_port *port = ptr;
++
++ ssr_status = sci_in(port,SCxSR);
++ scr_status = sci_in(port,SCSCR);
++
++ /* Rx Interrupt */
++ if ((ssr_status&0x0002) && (scr_status&0x0040))
++ kgdbsci_rx_interrupt(irq, ptr, regs);
+
+- kgdb_put_char(kgdb_sci_port, c);
++ return IRQ_HANDLED;
+ }
+
+-/* Clear any errors on the SCI */
+-static void kgdb_handle_error(struct sci_port *port)
++static void __init kgdbsci_lateinit(void)
+ {
+- sci_out(port, SCxSR, SCxSR_ERROR_CLEAR(port)); /* Clear error flags */
++ if (KGDBPORT.irqs[0] == KGDBPORT.irqs[1]) {
++ if (!KGDBPORT.irqs[0]) {
++ printk(KERN_ERR "kgdbsci: Cannot allocate irq.\n");
++ return;
++ }
++ if (request_irq(KGDBPORT.irqs[0], kgdbsci_mpxed_interrupt,
++ SA_INTERRUPT, "kgdbsci",
++ &KGDBPORT.port)) {
++ printk(KERN_ERR "kgdbsci: Cannot allocate irq.\n");
++ return;
++ }
++ } else {
++ if (KGDBPORT.irqs[1])
++ request_irq(KGDBPORT.irqs[1],
++ kgdbsci_rx_interrupt, SA_INTERRUPT,
++ "kgdbsci", &KGDBPORT.port);
++ }
+ }
++#endif
+
+-/* Breakpoint if there's a break sent on the serial port */
+-static void kgdb_break_interrupt(int irq, void *ptr, struct pt_regs *regs)
++/*
++ * We use the normal init routine to setup the port, so we can't be
++ * in here too early.
++ */
++static int kgdbsci_init(void)
+ {
+- struct sci_port *port = ptr;
+- unsigned short status = sci_in(port, SCxSR);
++ struct termios termios;
+
+- if (status & SCxSR_BRK(port)) {
++ memset(&termios, 0, sizeof(struct termios));
+
+- /* Break into the debugger if a break is detected */
+- BREAKPOINT();
++ termios.c_cflag = CREAD | HUPCL | CLOCAL | CS8;
++ switch (kgdbsci_baud) {
++ case 9600:
++ termios.c_cflag |= B9600;
++ break;
++ case 19200:
++ termios.c_cflag |= B19200;
++ break;
++ case 38400:
++ termios.c_cflag |= B38400;
++ break;
++ case 57600:
++ termios.c_cflag |= B57600;
++ break;
++ case 115200:
++ termios.c_cflag |= B115200;
++ break;
++ }
++ sci_set_termios(&KGDBPORT.port, &termios, NULL);
+
+- /* Clear */
+- sci_out(port, SCxSR, SCxSR_BREAK_CLEAR(port));
+- }
++ return 0;
+ }
+
+-#endif /* CONFIG_SH_KGDB */
++struct kgdb_io kgdb_io_ops = {
++ .read_char = kgdbsci_read_char,
++ .write_char = kgdbsci_write_char,
++ .init = kgdbsci_init,
++#ifndef CONFIG_SERIAL_SH_SCI_CONSOLE
++ .late_init = kgdbsci_lateinit,
++#else /* ! CONFIG_SERIAL_SH_SCI_CONSOLE */
++ .late_init = NULL,
++#endif /* ! CONFIG_SERIAL_SH_SCI_CONSOLE */
++ .pre_exception = NULL,
++ .post_exception = NULL
++};
++
++/*
++ * Syntax for this cmdline option is "kgdbsci=ttyno,baudrate".
++ */
++static int __init
++kgdbsci_opt(char *str)
++{
++ /* We might have anywhere from 1 to 3 ports. */
++ if (*str < '0' || *str > SCI_NPORTS + '0')
++ goto errout;
++ kgdbsci_ttySC = *str - '0';
++ str++;
++ if (*str != ',')
++ goto errout;
++ str++;
++ kgdbsci_baud = simple_strtoul(str, &str, 10);
++ if (kgdbsci_baud != 9600 && kgdbsci_baud != 19200 &&
++ kgdbsci_baud != 38400 && kgdbsci_baud != 57600 &&
++ kgdbsci_baud != 115200)
++ goto errout;
++
++ return 0;
++
++errout:
++ printk(KERN_ERR "Invalid syntax for option kgdbsci=\n");
++ return 1;
++}
++__setup("kgdbsci", kgdbsci_opt);
++#endif /* CONFIG_KGDB_SH_SCI */
+
+ #if defined(__H8300S__)
+ enum { sci_disable, sci_enable };
+@@ -555,6 +608,16 @@ static inline void sci_receive_chars(str
+ continue;
+ }
+
++#ifdef CONFIG_KGDB_SH_SCI
++ /* We assume that a ^C on the port KGDB
++ * is using means that KGDB wants to
++ * interrupt the running system.
++ */
++ if (port->line == KGDBPORT.port.line &&
++ c == 3)
++ breakpoint();
++#endif
++
+ /* Store data and status */
+ if (status&SCxSR_FER(port)) {
+ flag = TTY_FRAME;
+@@ -1618,6 +1681,7 @@ static int __init sci_console_init(void)
+ console_initcall(sci_console_init);
+ #endif /* CONFIG_SERIAL_SH_SCI_CONSOLE */
+
++#if 0
+ #ifdef CONFIG_SH_KGDB
+ /*
+ * FIXME: Most of this can go away.. at the moment, we rely on
+@@ -1663,30 +1727,9 @@ int __init kgdb_console_setup(struct con
+ return uart_set_options(port, co, baud, parity, bits, flow);
+ }
+ #endif /* CONFIG_SH_KGDB */
++#endif /* 0 */
+
+-#ifdef CONFIG_SH_KGDB_CONSOLE
+-static struct console kgdb_console = {
+- .name = "ttySC",
+- .write = kgdb_console_write,
+- .setup = kgdb_console_setup,
+- .flags = CON_PRINTBUFFER | CON_ENABLED,
+- .index = -1,
+- .data = &sci_uart_driver,
+-};
+-
+-/* Register the KGDB console so we get messages (d'oh!) */
+-static int __init kgdb_console_init(void)
+-{
+- register_console(&kgdb_console);
+- return 0;
+-}
+-
+-console_initcall(kgdb_console_init);
+-#endif /* CONFIG_SH_KGDB_CONSOLE */
+-
+-#if defined(CONFIG_SH_KGDB_CONSOLE)
+-#define SCI_CONSOLE &kgdb_console
+-#elif defined(CONFIG_SERIAL_SH_SCI_CONSOLE)
++#ifdef CONFIG_SERIAL_SH_SCI_CONSOLE
+ #define SCI_CONSOLE &serial_console
+ #else
+ #define SCI_CONSOLE 0
+@@ -1757,4 +1800,3 @@ static void __exit sci_exit(void)
+
+ module_init(sci_init);
+ module_exit(sci_exit);
+-
+diff -rupN -X ../client-cleanup/dontdiff linux-2.6.18/include/asm-arm/kgdb.h linux-2.6.18.kgdb/include/asm-arm/kgdb.h
+--- linux-2.6.18/include/asm-arm/kgdb.h 1970-01-01 03:00:00.000000000 +0300
++++ linux-2.6.18.kgdb/include/asm-arm/kgdb.h 2008-06-10 16:19:58.000000000 +0400
+@@ -0,0 +1,92 @@
++/*
++ * include/asm-arm/kgdb.h
++ *
++ * ARM KGDB support
++ *
++ * Author: Deepak Saxena <dsaxena@mvista.com>
++ *
++ * Copyright (C) 2002 MontaVista Software Inc.
++ *
++ */
++
++#ifndef __ASM_KGDB_H__
++#define __ASM_KGDB_H__
++
++#include <linux/config.h>
++#include <asm/ptrace.h>
++#include <asm-generic/kgdb.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;
++#endif /* !__ASSEMBLY__ */
++
++/*
++ * 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 _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)
++
++/* So that we can denote the end of a frame for tracing, in the simple
++ * case. */
++#define CFI_END_FRAME(func) __CFI_END_FRAME(_PC,_SP,func)
++
++#endif /* __ASM_KGDB_H__ */
+diff -rupN -X ../client-cleanup/dontdiff linux-2.6.18/include/asm-arm/system.h linux-2.6.18.kgdb/include/asm-arm/system.h
+--- linux-2.6.18/include/asm-arm/system.h 2006-09-20 07:42:06.000000000 +0400
++++ linux-2.6.18.kgdb/include/asm-arm/system.h 2008-06-10 16:19:51.000000000 +0400
+@@ -444,6 +444,47 @@ static inline unsigned long __xchg(unsig
+ extern void disable_hlt(void);
+ extern void enable_hlt(void);
+
++#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 -rupN -X ../client-cleanup/dontdiff linux-2.6.18/include/asm-generic/kgdb.h linux-2.6.18.kgdb/include/asm-generic/kgdb.h
+--- linux-2.6.18/include/asm-generic/kgdb.h 1970-01-01 03:00:00.000000000 +0300
++++ linux-2.6.18.kgdb/include/asm-generic/kgdb.h 2008-06-10 16:19:58.000000000 +0400
+@@ -0,0 +1,34 @@
++/*
++ * include/asm-generic/kgdb.h
++ *
++ * This provides the assembly level information so that KGDB can provide
++ * a GDB that has been patched with enough information to know to stop
++ * trying to unwind the function.
++ *
++ * Author: Tom Rini <trini@kernel.crashing.org>
++ *
++ * 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.
++ */
++
++#ifndef __ASM_GENERIC_KGDB_H__
++#define __ASM_GENERIC_KGDB_H__
++
++#include <linux/dwarf2-lang.h>
++#ifdef __ASSEMBLY__
++#ifdef CONFIG_KGDB
++/* This MUST be put at the end of a given assembly function */
++#define __CFI_END_FRAME(pc,sp,func) \
++CAT3(.Lend_,func,:) \
++ CFI_preamble(func,pc,0x1,-DATA_ALIGN_FACTOR) \
++ CFA_define_reference(sp, 0) \
++ CFA_undefine_reg(pc) \
++ CFI_postamble() \
++ FDE_preamble(func,func,CAT3(.Lend,_,func)) \
++ FDE_postamble()
++#else
++#define __CFI_END_FRAME(pc,sp,fn)
++#endif /* CONFIG_KGDB */
++#endif /* __ASSEMBLY__ */
++#endif /* __ASM_GENERIC_KGDB_H__ */
+diff -rupN -X ../client-cleanup/dontdiff linux-2.6.18/include/asm-i386/kdebug.h linux-2.6.18.kgdb/include/asm-i386/kdebug.h
+--- linux-2.6.18/include/asm-i386/kdebug.h 2006-09-20 07:42:06.000000000 +0400
++++ linux-2.6.18.kgdb/include/asm-i386/kdebug.h 2008-06-10 16:19:17.000000000 +0400
+@@ -39,6 +39,7 @@ enum die_val {
+ DIE_CALL,
+ DIE_NMI_IPI,
+ DIE_PAGE_FAULT,
++ DIE_PAGE_FAULT_NO_CONTEXT,
+ };
+
+ static inline int notify_die(enum die_val val, const char *str,
+diff -rupN -X ../client-cleanup/dontdiff linux-2.6.18/include/asm-i386/kgdb.h linux-2.6.18.kgdb/include/asm-i386/kgdb.h
+--- linux-2.6.18/include/asm-i386/kgdb.h 1970-01-01 03:00:00.000000000 +0300
++++ linux-2.6.18.kgdb/include/asm-i386/kgdb.h 2008-06-10 16:19:58.000000000 +0400
+@@ -0,0 +1,58 @@
++#ifdef __KERNEL__
++#ifndef _ASM_KGDB_H_
++#define _ASM_KGDB_H_
++
++/*
++ * Copyright (C) 2001-2004 Amit S. Kale
++ */
++
++#include <asm-generic/kgdb.h>
++
++/*
++ * Note that this register image is in a different order than
++ * the register image that Linux produces at interrupt time.
++ *
++ * Linux's register image is defined by struct pt_regs in ptrace.h.
++ * Just why GDB uses a different order is a historical mystery.
++ */
++#define _EAX 0
++#define _ECX 1
++#define _EDX 2
++#define _EBX 3
++#define _ESP 4
++#define _EBP 5
++#define _ESI 6
++#define _EDI 7
++#define _PC 8
++#define _EIP 8
++#define _PS 9
++#define _EFLAGS 9
++#define _CS 10
++#define _SS 11
++#define _DS 12
++#define _ES 13
++#define _FS 14
++#define _GS 15
++
++/* So that we can denote the end of a frame for tracing, in the simple
++ * case. */
++#define CFI_END_FRAME(func) __CFI_END_FRAME(_EIP,_ESP,func)
++
++#ifndef __ASSEMBLY__
++/************************************************************************/
++/* BUFMAX defines the maximum number of characters in inbound/outbound buffers*/
++/* at least NUMREGBYTES*2 are needed for register packets */
++/* Longer buffer is needed to list all threads */
++#define BUFMAX 1024
++
++/* Number of bytes of registers. */
++#define NUMREGBYTES 64
++/* Number of bytes of registers we need to save for a setjmp/longjmp. */
++#define NUMCRITREGBYTES 24
++
++#define BREAKPOINT() asm(" int $3");
++#define BREAK_INSTR_SIZE 1
++#define CACHE_FLUSH_IS_SAFE 1
++#endif /* !__ASSEMBLY__ */
++#endif /* _ASM_KGDB_H_ */
++#endif /* __KERNEL__ */
+diff -rupN -X ../client-cleanup/dontdiff linux-2.6.18/include/asm-ia64/kdebug.h linux-2.6.18.kgdb/include/asm-ia64/kdebug.h
+--- linux-2.6.18/include/asm-ia64/kdebug.h 2006-09-20 07:42:06.000000000 +0400
++++ linux-2.6.18.kgdb/include/asm-ia64/kdebug.h 2008-06-10 16:19:32.000000000 +0400
+@@ -72,6 +72,7 @@ enum die_val {
+ DIE_KDEBUG_LEAVE,
+ DIE_KDUMP_ENTER,
+ DIE_KDUMP_LEAVE,
++ DIE_PAGE_FAULT_NO_CONTEXT,
+ };
+
+ static inline int notify_die(enum die_val val, char *str, struct pt_regs *regs,
+diff -rupN -X ../client-cleanup/dontdiff linux-2.6.18/include/asm-ia64/kgdb.h linux-2.6.18.kgdb/include/asm-ia64/kgdb.h
+--- linux-2.6.18/include/asm-ia64/kgdb.h 1970-01-01 03:00:00.000000000 +0300
++++ linux-2.6.18.kgdb/include/asm-ia64/kgdb.h 2008-06-10 16:19:32.000000000 +0400
+@@ -0,0 +1,36 @@
++#ifdef __KERNEL__
++#ifndef _ASM_KGDB_H_
++#define _ASM_KGDB_H_
++
++/*
++ * Copyright (C) 2001-2004 Amit S. Kale
++ */
++
++#include <linux/threads.h>
++
++/************************************************************************/
++/* BUFMAX defines the maximum number of characters in inbound/outbound buffers*/
++/* at least NUMREGBYTES*2 are needed for register packets */
++/* Longer buffer is needed to list all threads */
++#define BUFMAX 1024
++
++/* Number of bytes of registers. We set this to 0 so that certain GDB
++ * packets will fail, forcing the use of others, which are more friendly
++ * on ia64. */
++#define NUMREGBYTES 0
++
++#define NUMCRITREGBYTES (70*8)
++#define JMP_REGS_ALIGNMENT __attribute__ ((aligned (16)))
++
++#define BREAKNUM 0x00003333300LL
++#define KGDBBREAKNUM 0x6665UL
++#define BREAKPOINT() asm volatile ("break.m 0x6665")
++#define BREAK_INSTR_SIZE 16
++#define CACHE_FLUSH_IS_SAFE 1
++
++struct pt_regs;
++extern volatile int kgdb_hwbreak_sstep[NR_CPUS];
++extern void smp_send_nmi_allbutself(void);
++extern void kgdb_wait_ipi(struct pt_regs *);
++#endif /* _ASM_KGDB_H_ */
++#endif /* __KERNEL__ */
+diff -rupN -X ../client-cleanup/dontdiff linux-2.6.18/include/asm-mips/kdebug.h linux-2.6.18.kgdb/include/asm-mips/kdebug.h
+--- linux-2.6.18/include/asm-mips/kdebug.h 1970-01-01 03:00:00.000000000 +0300
++++ linux-2.6.18.kgdb/include/asm-mips/kdebug.h 2008-06-10 16:19:28.000000000 +0400
+@@ -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 -rupN -X ../client-cleanup/dontdiff linux-2.6.18/include/asm-mips/kgdb.h linux-2.6.18.kgdb/include/asm-mips/kgdb.h
+--- linux-2.6.18/include/asm-mips/kgdb.h 1970-01-01 03:00:00.000000000 +0300
++++ linux-2.6.18.kgdb/include/asm-mips/kgdb.h 2008-06-10 16:19:58.000000000 +0400
+@@ -0,0 +1,34 @@
++#ifdef __KERNEL__
++#ifndef _ASM_KGDB_H_
++#define _ASM_KGDB_H_
++
++#ifndef __ASSEMBLY__
++#if (_MIPS_ISA == _MIPS_ISA_MIPS1) || (_MIPS_ISA == _MIPS_ISA_MIPS2)
++typedef u32 gdb_reg_t;
++#elif (_MIPS_ISA == _MIPS_ISA_MIPS3) || (_MIPS_ISA == _MIPS_ISA_MIPS4)
++typedef u64 gdb_reg_t;
++#else
++#error need to do
++#endif /* _MIPS_ISA */
++
++#include <asm-generic/kgdb.h>
++
++#ifndef __ASSEMBLY__
++#define BUFMAX 2048
++#define NUMREGBYTES (90*sizeof(gdb_reg_t))
++#define NUMCRITREGBYTES (12*sizeof(gdb_reg_t))
++#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 CACHE_FLUSH_IS_SAFE 0
++
++extern int kgdb_early_setup;
++
++#endif /* !__ASSEMBLY__ */
++#endif /* _ASM_KGDB_H_ */
++#endif /* __KERNEL__ */
+diff -rupN -X ../client-cleanup/dontdiff linux-2.6.18/include/asm-powerpc/kgdb.h linux-2.6.18.kgdb/include/asm-powerpc/kgdb.h
+--- linux-2.6.18/include/asm-powerpc/kgdb.h 1970-01-01 03:00:00.000000000 +0300
++++ linux-2.6.18.kgdb/include/asm-powerpc/kgdb.h 2008-06-10 16:19:58.000000000 +0400
+@@ -0,0 +1,74 @@
++/*
++ * include/asm-powerpc/kgdb.h
++ *
++ * The PowerPC (32/64) specific defines / externs for KGDB. Based on
++ * the previous 32bit and 64bit specific files, which had the following
++ * copyrights:
++ *
++ * PPC64 Mods (C) 2005 Frank Rowand (frowand@mvista.com)
++ * PPC Mods (C) 2004 Tom Rini (trini@mvista.com)
++ * PPC Mods (C) 2003 John Whitney (john.whitney@timesys.com)
++ * PPC Mods (C) 1998 Michael Tesch (tesch@cs.wisc.edu)
++ *
++ *
++ * Copyright (C) 1995 David S. Miller (davem@caip.rutgers.edu)
++ * Author: Tom Rini <trini@kernel.crashing.org>
++ *
++ * 2006 (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.
++ */
++#ifdef __KERNEL__
++#ifndef __POWERPC_KGDB_H__
++#define __POWERPC_KGDB_H__
++
++#include <asm-generic/kgdb.h>
++#ifndef __ASSEMBLY__
++
++#define BREAK_INSTR_SIZE 4
++#define BUFMAX ((NUMREGBYTES * 2) + 512)
++#define OUTBUFMAX ((NUMREGBYTES * 2) + 512)
++#define BREAKPOINT() asm(".long 0x7d821008"); /* twge r2, r2 */
++#define CACHE_FLUSH_IS_SAFE 1
++
++/* The number bytes of registers we have to save depends on a few
++ * things. For 64bit we default to not including vector registers and
++ * vector state registers. */
++#ifdef CONFIG_PPC64
++/*
++ * 64 bit (8 byte) registers:
++ * 32 gpr, 32 fpr, nip, msr, link, ctr
++ * 32 bit (4 byte) registers:
++ * ccr, xer, fpscr
++ */
++#define NUMREGBYTES ((68 * 8) + (3 * 4))
++#if 0
++/* The following adds in vector registers and vector state registers. */
++/* 128 bit (16 byte) registers:
++ * 32 vr
++ * 64 bit (8 byte) registers:
++ * 32 gpr, 32 fpr, nip, msr, link, ctr
++ * 32 bit (4 byte) registers:
++ * ccr, xer, fpscr, vscr, vrsave
++ */
++#define NUMREGBYTES ((128 * 16) + (68 * 8) + (5 * 4))
++#endif
++#define NUMCRITREGBYTES 184
++#else /* CONFIG_PPC32 */
++/* On non-E500 family PPC32 we determine the size by picking the last
++ * register we need, but on E500 we skip sections so we list what we
++ * need to store, and add it up. */
++#ifndef CONFIG_E500
++#define MAXREG (PT_FPSCR+1)
++#else
++/* 32 GPRs (8 bytes), nip, msr, ccr, link, ctr, xer, acc (8 bytes), spefscr*/
++#define MAXREG ((32*2)+6+2+1)
++#endif
++#define NUMREGBYTES (MAXREG * sizeof(int))
++/* CR/LR, R1, R2, R13-R31 inclusive. */
++#define NUMCRITREGBYTES (23 * sizeof(int))
++#endif /* 32/64 */
++#endif /* !(__ASSEMBLY__) */
++#endif /* !__POWERPC_KGDB_H__ */
++#endif /* __KERNEL__ */
+diff -rupN -X ../client-cleanup/dontdiff linux-2.6.18/include/asm-ppc/kgdb.h linux-2.6.18.kgdb/include/asm-ppc/kgdb.h
+--- linux-2.6.18/include/asm-ppc/kgdb.h 2006-09-20 07:42:06.000000000 +0400
++++ linux-2.6.18.kgdb/include/asm-ppc/kgdb.h 2008-06-10 16:19:22.000000000 +0400
+@@ -1,57 +1,18 @@
+-/*
+- * kgdb.h: Defines and declarations for serial line source level
+- * remote debugging of the Linux kernel using gdb.
+- *
+- * PPC Mods (C) 1998 Michael Tesch (tesch@cs.wisc.edu)
+- *
+- * Copyright (C) 1995 David S. Miller (davem@caip.rutgers.edu)
+- */
+ #ifdef __KERNEL__
+-#ifndef _PPC_KGDB_H
+-#define _PPC_KGDB_H
+-
++#ifndef __PPC_KGDB_H__
++#define __PPC_KGDB_H__
++#include <asm-powerpc/kgdb.h>
+ #ifndef __ASSEMBLY__
+-
+-/* Things specific to the gen550 backend. */
+-struct uart_port;
+-
+-extern void gen550_progress(char *, unsigned short);
+-extern void gen550_kgdb_map_scc(void);
+-extern void gen550_init(int, struct uart_port *);
+-
+-/* Things specific to the pmac backend. */
+-extern void zs_kgdb_hook(int tty_num);
+-
+-/* To init the kgdb engine. (called by serial hook)*/
+-extern void set_debug_traps(void);
+-
+-/* To enter the debugger explicitly. */
+-extern void breakpoint(void);
+-
+-/* For taking exceptions
+- * these are defined in traps.c
+- */
+-extern int (*debugger)(struct pt_regs *regs);
++ /* For taking exceptions
++ * these are defined in traps.c
++ */
++struct pt_regs;
++extern void (*debugger)(struct pt_regs *regs);
+ extern int (*debugger_bpt)(struct pt_regs *regs);
+ extern int (*debugger_sstep)(struct pt_regs *regs);
+ extern int (*debugger_iabr_match)(struct pt_regs *regs);
+ extern int (*debugger_dabr_match)(struct pt_regs *regs);
+ extern void (*debugger_fault_handler)(struct pt_regs *regs);
+-
+-/* What we bring to the party */
+-int kgdb_bpt(struct pt_regs *regs);
+-int kgdb_sstep(struct pt_regs *regs);
+-void kgdb(struct pt_regs *regs);
+-int kgdb_iabr_match(struct pt_regs *regs);
+-int kgdb_dabr_match(struct pt_regs *regs);
+-
+-/*
+- * external low-level support routines (ie macserial.c)
+- */
+-extern void kgdb_interruptible(int); /* control interrupts from serial */
+-extern void putDebugChar(char); /* write a single character */
+-extern char getDebugChar(void); /* read and return a single char */
+-
+-#endif /* !(__ASSEMBLY__) */
+-#endif /* !(_PPC_KGDB_H) */
++#endif /* !__ASSEMBLY__ */
++#endif /* __PPC_KGDB_H__ */
+ #endif /* __KERNEL__ */
+diff -rupN -X ../client-cleanup/dontdiff linux-2.6.18/include/asm-ppc/machdep.h linux-2.6.18.kgdb/include/asm-ppc/machdep.h
+--- linux-2.6.18/include/asm-ppc/machdep.h 2006-09-20 07:42:06.000000000 +0400
++++ linux-2.6.18.kgdb/include/asm-ppc/machdep.h 2008-06-10 16:19:22.000000000 +0400
+@@ -72,9 +72,7 @@ struct machdep_calls {
+ unsigned long (*find_end_of_memory)(void);
+ void (*setup_io_mappings)(void);
+
+- void (*early_serial_map)(void);
+ void (*progress)(char *, unsigned short);
+- void (*kgdb_map_scc)(void);
+
+ unsigned char (*nvram_read_val)(int addr);
+ void (*nvram_write_val)(int addr, unsigned char val);
+diff -rupN -X ../client-cleanup/dontdiff linux-2.6.18/include/asm-ppc/mv64x60.h linux-2.6.18.kgdb/include/asm-ppc/mv64x60.h
+--- linux-2.6.18/include/asm-ppc/mv64x60.h 2006-09-20 07:42:06.000000000 +0400
++++ linux-2.6.18.kgdb/include/asm-ppc/mv64x60.h 2008-06-10 16:19:22.000000000 +0400
+@@ -348,6 +348,8 @@ u32 mv64x60_calc_mem_size(struct mv64x60
+
+ void mv64x60_progress_init(u32 base);
+ void mv64x60_mpsc_progress(char *s, unsigned short hex);
++struct platform_device * mv64x60_early_get_pdev_data(const char *name,
++ int id, int remove);
+
+ extern struct mv64x60_32bit_window
+ gt64260_32bit_windows[MV64x60_32BIT_WIN_COUNT];
+diff -rupN -X ../client-cleanup/dontdiff linux-2.6.18/include/asm-ppc/mv64x60_defs.h linux-2.6.18.kgdb/include/asm-ppc/mv64x60_defs.h
+--- linux-2.6.18/include/asm-ppc/mv64x60_defs.h 2006-09-20 07:42:06.000000000 +0400
++++ linux-2.6.18.kgdb/include/asm-ppc/mv64x60_defs.h 2008-06-10 16:19:22.000000000 +0400
+@@ -57,7 +57,8 @@
+ #define MV64x60_IRQ_I2C 37
+ #define MV64x60_IRQ_BRG 39
+ #define MV64x60_IRQ_MPSC_0 40
+-#define MV64x60_IRQ_MPSC_1 42
++#define MV64360_IRQ_MPSC_1 41
++#define GT64260_IRQ_MPSC_1 42
+ #define MV64x60_IRQ_COMM 43
+ #define MV64x60_IRQ_P0_GPP_0_7 56
+ #define MV64x60_IRQ_P0_GPP_8_15 57
+diff -rupN -X ../client-cleanup/dontdiff linux-2.6.18/include/asm-sh/kgdb.h linux-2.6.18.kgdb/include/asm-sh/kgdb.h
+--- linux-2.6.18/include/asm-sh/kgdb.h 2006-09-20 07:42:06.000000000 +0400
++++ linux-2.6.18.kgdb/include/asm-sh/kgdb.h 2008-06-10 16:19:58.000000000 +0400
+@@ -2,94 +2,40 @@
+ * May be copied or modified under the terms of the GNU General Public
+ * License. See linux/COPYING for more information.
+ *
+- * Based on original code by Glenn Engel, Jim Kingdon,
+- * David Grothe <dave@gcom.com>, Tigran Aivazian, <tigran@sco.com> and
+- * Amit S. Kale <akale@veritas.com>
+- *
+- * Super-H port based on sh-stub.c (Ben Lee and Steve Chamberlain) by
+- * Henry Bell <henry.bell@st.com>
+- *
+- * Header file for low-level support for remote debug using GDB.
++ * Based on a file that was modified or based on files by: Glenn Engel,
++ * Jim Kingdon, David Grothe <dave@gcom.com>, Tigran Aivazian <tigran@sco.com>,
++ * Amit S. Kale <akale@veritas.com>, sh-stub.c from Ben Lee and
++ * Steve Chamberlain, Henry Bell <henry.bell@st.com>
++ *
++ * Maintainer: Tom Rini <trini@kernel.crashing.org>
+ *
+ */
+
+ #ifndef __KGDB_H
+ #define __KGDB_H
+
+-#include <asm/ptrace.h>
+-
+-struct console;
++#include <asm-generic/kgdb.h>
++/* Based on sh-gdb.c from gdb-6.1, Glenn
++ Engel at HP Ben Lee and Steve Chamberlain */
++#define NUMREGBYTES 112 /* 92 */
++#define NUMCRITREGBYTES (9 << 2)
++#define BUFMAX 400
+
+-/* Same as pt_regs but has vbr in place of syscall_nr */
++#ifndef __ASSEMBLY__
+ struct kgdb_regs {
+ unsigned long regs[16];
+ unsigned long pc;
+ unsigned long pr;
+- unsigned long sr;
+ unsigned long gbr;
++ unsigned long vbr;
+ unsigned long mach;
+ unsigned long macl;
+- unsigned long vbr;
+-};
+-
+-/* State info */
+-extern char kgdb_in_gdb_mode;
+-extern int kgdb_done_init;
+-extern int kgdb_enabled;
+-extern int kgdb_nofault; /* Ignore bus errors (in gdb mem access) */
+-extern int kgdb_halt; /* Execute initial breakpoint at startup */
+-extern char in_nmi; /* Debounce flag to prevent NMI reentry*/
+-
+-/* SCI */
+-extern int kgdb_portnum;
+-extern int kgdb_baud;
+-extern char kgdb_parity;
+-extern char kgdb_bits;
+-extern int kgdb_console_setup(struct console *, char *);
+-
+-/* Init and interface stuff */
+-extern int kgdb_init(void);
+-extern int (*kgdb_serial_setup)(void);
+-extern int (*kgdb_getchar)(void);
+-extern void (*kgdb_putchar)(int);
+-
+-struct kgdb_sermap {
+- char *name;
+- int namelen;
+- int (*setup_fn)(struct console *, char *);
+- struct kgdb_sermap *next;
++ unsigned long sr;
+ };
+-extern void kgdb_register_sermap(struct kgdb_sermap *map);
+-extern struct kgdb_sermap *kgdb_porttype;
+
+-/* Trap functions */
+-typedef void (kgdb_debug_hook_t)(struct pt_regs *regs);
+-typedef void (kgdb_bus_error_hook_t)(void);
+-extern kgdb_debug_hook_t *kgdb_debug_hook;
+-extern kgdb_bus_error_hook_t *kgdb_bus_err_hook;
+-
+-extern void breakpoint(void);
+-
+-/* Console */
+-struct console;
+-void kgdb_console_write(struct console *co, const char *s, unsigned count);
+-void kgdb_console_init(void);
+-
+-/* Prototypes for jmp fns */
+-#define _JBLEN 9
+-typedef int jmp_buf[_JBLEN];
+-extern void longjmp(jmp_buf __jmpb, int __retval);
+-extern int setjmp(jmp_buf __jmpb);
+-
+-/* Variadic macro to print our own message to the console */
+-#define KGDB_PRINTK(...) printk("KGDB: " __VA_ARGS__)
+-
+-/* Forced breakpoint */
+-#define BREAKPOINT() do { \
+- if (kgdb_enabled) { \
+- asm volatile("trapa #0xff"); \
+- } \
+-} while (0)
++#define BREAKPOINT() asm("trapa #0xff");
++#define BREAK_INSTR_SIZE 2
++#define CACHE_FLUSH_IS_SAFE 1
+
+ /* KGDB should be able to flush all kernel text space */
+ #if defined(CONFIG_CPU_SH4)
+@@ -102,30 +48,5 @@ extern int setjmp(jmp_buf __jmpb);
+ #else
+ #define kgdb_flush_icache_range(start, end) do { } while (0)
+ #endif
+-
+-/* Kernel assert macros */
+-#ifdef CONFIG_KGDB_KERNEL_ASSERTS
+-
+-/* Predefined conditions */
+-#define KA_VALID_ERRNO(errno) ((errno) > 0 && (errno) <= EMEDIUMTYPE)
+-#define KA_VALID_PTR_ERR(ptr) KA_VALID_ERRNO(-PTR_ERR(ptr))
+-#define KA_VALID_KPTR(ptr) (!(ptr) || \
+- ((void *)(ptr) >= (void *)PAGE_OFFSET && \
+- (void *)(ptr) < ERR_PTR(-EMEDIUMTYPE)))
+-#define KA_VALID_PTRORERR(errptr) \
+- (KA_VALID_KPTR(errptr) || KA_VALID_PTR_ERR(errptr))
+-#define KA_HELD_GKL() (current->lock_depth >= 0)
+-
+-/* The actual assert */
+-#define KGDB_ASSERT(condition, message) do { \
+- if (!(condition) && (kgdb_enabled)) { \
+- KGDB_PRINTK("Assertion failed at %s:%d: %s\n", \
+- __FILE__, __LINE__, message);\
+- BREAKPOINT(); \
+- } \
+-} while (0)
+-#else
+-#define KGDB_ASSERT(condition, message)
+-#endif
+-
++#endif /* !__ASSEMBLY__ */
+ #endif
+diff -rupN -X ../client-cleanup/dontdiff linux-2.6.18/include/asm-sh/system.h linux-2.6.18.kgdb/include/asm-sh/system.h
+--- linux-2.6.18/include/asm-sh/system.h 2006-09-20 07:42:06.000000000 +0400
++++ linux-2.6.18.kgdb/include/asm-sh/system.h 2008-06-10 16:19:47.000000000 +0400
+@@ -6,6 +6,7 @@
+ * Copyright (C) 2002 Paul Mundt
+ */
+
++#include <asm/types.h>
+
+ /*
+ * switch_to() should switch tasks to task nr n, first
+@@ -260,6 +261,45 @@ static __inline__ unsigned long __xchg(u
+ return x;
+ }
+
++static inline unsigned long __cmpxchg_u32(volatile int * m, unsigned long old,
++ unsigned long new)
++{
++ __u32 retval;
++ unsigned long flags;
++
++ local_irq_save(flags);
++ retval = *m;
++ if (retval == old)
++ *m = new;
++ local_irq_restore(flags); /* implies memory barrier */
++ return retval;
++}
++
++/* This function doesn't exist, so you'll get a linker error
++ * if something tries to do an invalid cmpxchg(). */
++extern void __cmpxchg_called_with_bad_pointer(void);
++
++#define __HAVE_ARCH_CMPXCHG 1
++
++static inline unsigned long __cmpxchg(volatile void * ptr, unsigned long old,
++ unsigned long new, int size)
++{
++ switch (size) {
++ case 4:
++ return __cmpxchg_u32(ptr, old, new);
++ }
++ __cmpxchg_called_with_bad_pointer();
++ return old;
++}
++
++#define cmpxchg(ptr,o,n) \
++ ({ \
++ __typeof__(*(ptr)) _o_ = (o); \
++ __typeof__(*(ptr)) _n_ = (n); \
++ (__typeof__(*(ptr))) __cmpxchg((ptr), (unsigned long)_o_, \
++ (unsigned long)_n_, sizeof(*(ptr))); \
++ })
++
+ /* XXX
+ * disable hlt during certain critical i/o operations
+ */
+diff -rupN -X ../client-cleanup/dontdiff linux-2.6.18/include/asm-x86_64/kdebug.h linux-2.6.18.kgdb/include/asm-x86_64/kdebug.h
+--- linux-2.6.18/include/asm-x86_64/kdebug.h 2006-09-20 07:42:06.000000000 +0400
++++ linux-2.6.18.kgdb/include/asm-x86_64/kdebug.h 2008-06-10 16:19:36.000000000 +0400
+@@ -34,6 +34,7 @@ enum die_val {
+ DIE_CALL,
+ DIE_NMI_IPI,
+ DIE_PAGE_FAULT,
++ DIE_PAGE_FAULT_NO_CONTEXT,
+ };
+
+ static inline int notify_die(enum die_val val, const char *str,
+diff -rupN -X ../client-cleanup/dontdiff linux-2.6.18/include/asm-x86_64/kgdb.h linux-2.6.18.kgdb/include/asm-x86_64/kgdb.h
+--- linux-2.6.18/include/asm-x86_64/kgdb.h 1970-01-01 03:00:00.000000000 +0300
++++ linux-2.6.18.kgdb/include/asm-x86_64/kgdb.h 2008-06-10 16:19:58.000000000 +0400
+@@ -0,0 +1,54 @@
++#ifdef __KERNEL__
++#ifndef _ASM_KGDB_H_
++#define _ASM_KGDB_H_
++
++/*
++ * Copyright (C) 2001-2004 Amit S. Kale
++ */
++
++#include <asm-generic/kgdb.h>
++
++/*
++ * Note that this register image is in a different order than
++ * the register image that Linux produces at interrupt time.
++ *
++ * Linux's register image is defined by struct pt_regs in ptrace.h.
++ * Just why GDB uses a different order is a historical mystery.
++ */
++#define _RAX 0
++#define _RDX 1
++#define _RCX 2
++#define _RBX 3
++#define _RSI 4
++#define _RDI 5
++#define _RBP 6
++#define _RSP 7
++#define _R8 8
++#define _R9 9
++#define _R10 10
++#define _R11 11
++#define _R12 12
++#define _R13 13
++#define _R14 14
++#define _R15 15
++#define _PC 16
++#define _PS 17
++
++/* Number of bytes of registers. */
++#define NUMREGBYTES ((_PS+1)*8)
++#define NUMCRITREGBYTES (8 * 8) /* 8 registers. */
++
++/* Help GDB to know when to stop backtracing. */
++#define CFI_END_FRAME(func) __CFI_END_FRAME(_PC,_RSP,func)
++#ifndef __ASSEMBLY__
++/* BUFMAX defines the maximum number of characters in inbound/outbound
++ * buffers at least NUMREGBYTES*2 are needed for register packets, and
++ * a longer buffer is needed to list all threads. */
++#define BUFMAX 1024
++#define BREAKPOINT() asm(" int $3");
++#define CHECK_EXCEPTION_STACK() ((&__get_cpu_var(init_tss))[0].ist[0])
++#define BREAK_INSTR_SIZE 1
++#define CACHE_FLUSH_IS_SAFE 1
++#endif /* !__ASSEMBLY__ */
++#endif /* _ASM_KGDB_H_ */
++#endif /* __KERNEL__ */
+diff -rupN -X ../client-cleanup/dontdiff linux-2.6.18/include/asm-x86_64/system.h linux-2.6.18.kgdb/include/asm-x86_64/system.h
+--- linux-2.6.18/include/asm-x86_64/system.h 2006-09-20 07:42:06.000000000 +0400
++++ linux-2.6.18.kgdb/include/asm-x86_64/system.h 2008-06-10 16:19:42.000000000 +0400
+@@ -21,7 +21,9 @@
+ ,"rcx","rbx","rdx","r8","r9","r10","r11","r12","r13","r14","r15"
+
+ #define switch_to(prev,next,last) \
+- asm volatile(SAVE_CONTEXT \
++ asm volatile(".globl __switch_to_begin\n\t" \
++ "__switch_to_begin:\n\t" \
++ SAVE_CONTEXT \
+ "movq %%rsp,%P[threadrsp](%[prev])\n\t" /* save RSP */ \
+ "movq %P[threadrsp](%[next]),%%rsp\n\t" /* restore RSP */ \
+ "call __switch_to\n\t" \
+@@ -33,6 +35,8 @@
+ "movq %%rax,%%rdi\n\t" \
+ "jc ret_from_fork\n\t" \
+ RESTORE_CONTEXT \
++ ".globl __switch_to_end\n\t" \
++ "__switch_to_end:\n\t" \
+ : "=a" (last) \
+ : [next] "S" (next), [prev] "D" (prev), \
+ [threadrsp] "i" (offsetof(struct task_struct, thread.rsp)), \
+diff -rupN -X ../client-cleanup/dontdiff linux-2.6.18/include/linux/dwarf2-defs.h linux-2.6.18.kgdb/include/linux/dwarf2-defs.h
+--- linux-2.6.18/include/linux/dwarf2-defs.h 1970-01-01 03:00:00.000000000 +0300
++++ linux-2.6.18.kgdb/include/linux/dwarf2-defs.h 2008-06-10 16:22:59.000000000 +0400
+@@ -0,0 +1,515 @@
++#ifndef _ELF_DWARF_H
++/* Machine generated from dwarf2.h by scripts/dwarfh.awk */
++#define _ELF_DWARF2_H
++#define DW_TAG_padding 0x00
++#define DW_TAG_array_type 0x01
++#define DW_TAG_class_type 0x02
++#define DW_TAG_entry_point 0x03
++#define DW_TAG_enumeration_type 0x04
++#define DW_TAG_formal_parameter 0x05
++#define DW_TAG_imported_declaration 0x08
++#define DW_TAG_label 0x0a
++#define DW_TAG_lexical_block 0x0b
++#define DW_TAG_member 0x0d
++#define DW_TAG_pointer_type 0x0f
++#define DW_TAG_reference_type 0x10
++#define DW_TAG_compile_unit 0x11
++#define DW_TAG_string_type 0x12
++#define DW_TAG_structure_type 0x13
++#define DW_TAG_subroutine_type 0x15
++#define DW_TAG_typedef 0x16
++#define DW_TAG_union_type 0x17
++#define DW_TAG_unspecified_parameters 0x18
++#define DW_TAG_variant 0x19
++#define DW_TAG_common_block 0x1a
++#define DW_TAG_common_inclusion 0x1b
++#define DW_TAG_inheritance 0x1c
++#define DW_TAG_inlined_subroutine 0x1d
++#define DW_TAG_module 0x1e
++#define DW_TAG_ptr_to_member_type 0x1f
++#define DW_TAG_set_type 0x20
++#define DW_TAG_subrange_type 0x21
++#define DW_TAG_with_stmt 0x22
++#define DW_TAG_access_declaration 0x23
++#define DW_TAG_base_type 0x24
++#define DW_TAG_catch_block 0x25
++#define DW_TAG_const_type 0x26
++#define DW_TAG_constant 0x27
++#define DW_TAG_enumerator 0x28
++#define DW_TAG_file_type 0x29
++#define DW_TAG_friend 0x2a
++#define DW_TAG_namelist 0x2b
++#define DW_TAG_namelist_item 0x2c
++#define DW_TAG_packed_type 0x2d
++#define DW_TAG_subprogram 0x2e
++#define DW_TAG_template_type_param 0x2f
++#define DW_TAG_template_value_param 0x30
++#define DW_TAG_thrown_type 0x31
++#define DW_TAG_try_block 0x32
++#define DW_TAG_variant_part 0x33
++#define DW_TAG_variable 0x34
++#define DW_TAG_volatile_type 0x35
++#define DW_TAG_dwarf_procedure 0x36
++#define DW_TAG_restrict_type 0x37
++#define DW_TAG_interface_type 0x38
++#define DW_TAG_namespace 0x39
++#define DW_TAG_imported_module 0x3a
++#define DW_TAG_unspecified_type 0x3b
++#define DW_TAG_partial_unit 0x3c
++#define DW_TAG_imported_unit 0x3d
++#define DW_TAG_MIPS_loop 0x4081
++#define DW_TAG_HP_array_descriptor 0x4090
++#define DW_TAG_format_label 0x4101
++#define DW_TAG_function_template 0x4102
++#define DW_TAG_class_template 0x4103
++#define DW_TAG_GNU_BINCL 0x4104
++#define DW_TAG_GNU_EINCL 0x4105
++#define DW_TAG_upc_shared_type 0x8765
++#define DW_TAG_upc_strict_type 0x8766
++#define DW_TAG_upc_relaxed_type 0x8767
++#define DW_TAG_PGI_kanji_type 0xA000
++#define DW_TAG_PGI_interface_block 0xA020
++#define DW_TAG_lo_user 0x4080
++#define DW_TAG_hi_user 0xffff
++#define DW_children_no 0
++#define DW_children_yes 1
++#define DW_FORM_addr 0x01
++#define DW_FORM_block2 0x03
++#define DW_FORM_block4 0x04
++#define DW_FORM_data2 0x05
++#define DW_FORM_data4 0x06
++#define DW_FORM_data8 0x07
++#define DW_FORM_string 0x08
++#define DW_FORM_block 0x09
++#define DW_FORM_block1 0x0a
++#define DW_FORM_data1 0x0b
++#define DW_FORM_flag 0x0c
++#define DW_FORM_sdata 0x0d
++#define DW_FORM_strp 0x0e
++#define DW_FORM_udata 0x0f
++#define DW_FORM_ref_addr 0x10
++#define DW_FORM_ref1 0x11
++#define DW_FORM_ref2 0x12
++#define DW_FORM_ref4 0x13
++#define DW_FORM_ref8 0x14
++#define DW_FORM_ref_udata 0x15
++#define DW_FORM_indirect 0x16
++#define DW_AT_sibling 0x01
++#define DW_AT_location 0x02
++#define DW_AT_name 0x03
++#define DW_AT_ordering 0x09
++#define DW_AT_subscr_data 0x0a
++#define DW_AT_byte_size 0x0b
++#define DW_AT_bit_offset 0x0c
++#define DW_AT_bit_size 0x0d
++#define DW_AT_element_list 0x0f
++#define DW_AT_stmt_list 0x10
++#define DW_AT_low_pc 0x11
++#define DW_AT_high_pc 0x12
++#define DW_AT_language 0x13
++#define DW_AT_member 0x14
++#define DW_AT_discr 0x15
++#define DW_AT_discr_value 0x16
++#define DW_AT_visibility 0x17
++#define DW_AT_import 0x18
++#define DW_AT_string_length 0x19
++#define DW_AT_common_reference 0x1a
++#define DW_AT_comp_dir 0x1b
++#define DW_AT_const_value 0x1c
++#define DW_AT_containing_type 0x1d
++#define DW_AT_default_value 0x1e
++#define DW_AT_inline 0x20
++#define DW_AT_is_optional 0x21
++#define DW_AT_lower_bound 0x22
++#define DW_AT_producer 0x25
++#define DW_AT_prototyped 0x27
++#define DW_AT_return_addr 0x2a
++#define DW_AT_start_scope 0x2c
++#define DW_AT_stride_size 0x2e
++#define DW_AT_upper_bound 0x2f
++#define DW_AT_abstract_origin 0x31
++#define DW_AT_accessibility 0x32
++#define DW_AT_address_class 0x33
++#define DW_AT_artificial 0x34
++#define DW_AT_base_types 0x35
++#define DW_AT_calling_convention 0x36
++#define DW_AT_count 0x37
++#define DW_AT_data_member_location 0x38
++#define DW_AT_decl_column 0x39
++#define DW_AT_decl_file 0x3a
++#define DW_AT_decl_line 0x3b
++#define DW_AT_declaration 0x3c
++#define DW_AT_discr_list 0x3d
++#define DW_AT_encoding 0x3e
++#define DW_AT_external 0x3f
++#define DW_AT_frame_base 0x40
++#define DW_AT_friend 0x41
++#define DW_AT_identifier_case 0x42
++#define DW_AT_macro_info 0x43
++#define DW_AT_namelist_items 0x44
++#define DW_AT_priority 0x45
++#define DW_AT_segment 0x46
++#define DW_AT_specification 0x47
++#define DW_AT_static_link 0x48
++#define DW_AT_type 0x49
++#define DW_AT_use_location 0x4a
++#define DW_AT_variable_parameter 0x4b
++#define DW_AT_virtuality 0x4c
++#define DW_AT_vtable_elem_location 0x4d
++#define DW_AT_allocated 0x4e
++#define DW_AT_associated 0x4f
++#define DW_AT_data_location 0x50
++#define DW_AT_stride 0x51
++#define DW_AT_entry_pc 0x52
++#define DW_AT_use_UTF8 0x53
++#define DW_AT_extension 0x54
++#define DW_AT_ranges 0x55
++#define DW_AT_trampoline 0x56
++#define DW_AT_call_column 0x57
++#define DW_AT_call_file 0x58
++#define DW_AT_call_line 0x59
++#define DW_AT_MIPS_fde 0x2001
++#define DW_AT_MIPS_loop_begin 0x2002
++#define DW_AT_MIPS_tail_loop_begin 0x2003
++#define DW_AT_MIPS_epilog_begin 0x2004
++#define DW_AT_MIPS_loop_unroll_factor 0x2005
++#define DW_AT_MIPS_software_pipeline_depth 0x2006
++#define DW_AT_MIPS_linkage_name 0x2007
++#define DW_AT_MIPS_stride 0x2008
++#define DW_AT_MIPS_abstract_name 0x2009
++#define DW_AT_MIPS_clone_origin 0x200a
++#define DW_AT_MIPS_has_inlines 0x200b
++#define DW_AT_HP_block_index 0x2000
++#define DW_AT_HP_unmodifiable 0x2001
++#define DW_AT_HP_actuals_stmt_list 0x2010
++#define DW_AT_HP_proc_per_section 0x2011
++#define DW_AT_HP_raw_data_ptr 0x2012
++#define DW_AT_HP_pass_by_reference 0x2013
++#define DW_AT_HP_opt_level 0x2014
++#define DW_AT_HP_prof_version_id 0x2015
++#define DW_AT_HP_opt_flags 0x2016
++#define DW_AT_HP_cold_region_low_pc 0x2017
++#define DW_AT_HP_cold_region_high_pc 0x2018
++#define DW_AT_HP_all_variables_modifiable 0x2019
++#define DW_AT_HP_linkage_name 0x201a
++#define DW_AT_HP_prof_flags 0x201b
++#define DW_AT_sf_names 0x2101
++#define DW_AT_src_info 0x2102
++#define DW_AT_mac_info 0x2103
++#define DW_AT_src_coords 0x2104
++#define DW_AT_body_begin 0x2105
++#define DW_AT_body_end 0x2106
++#define DW_AT_GNU_vector 0x2107
++#define DW_AT_VMS_rtnbeg_pd_address 0x2201
++#define DW_AT_upc_threads_scaled 0x3210
++#define DW_AT_PGI_lbase 0x3a00
++#define DW_AT_PGI_soffset 0x3a01
++#define DW_AT_PGI_lstride 0x3a02
++#define DW_AT_lo_user 0x2000 /* Implementation-defined range start. */
++#define DW_AT_hi_user 0x3ff0 /* Implementation-defined range end. */
++#define DW_OP_addr 0x03
++#define DW_OP_deref 0x06
++#define DW_OP_const1u 0x08
++#define DW_OP_const1s 0x09
++#define DW_OP_const2u 0x0a
++#define DW_OP_const2s 0x0b
++#define DW_OP_const4u 0x0c
++#define DW_OP_const4s 0x0d
++#define DW_OP_const8u 0x0e
++#define DW_OP_const8s 0x0f
++#define DW_OP_constu 0x10
++#define DW_OP_consts 0x11
++#define DW_OP_dup 0x12
++#define DW_OP_drop 0x13
++#define DW_OP_over 0x14
++#define DW_OP_pick 0x15
++#define DW_OP_swap 0x16
++#define DW_OP_rot 0x17
++#define DW_OP_xderef 0x18
++#define DW_OP_abs 0x19
++#define DW_OP_and 0x1a
++#define DW_OP_div 0x1b
++#define DW_OP_minus 0x1c
++#define DW_OP_mod 0x1d
++#define DW_OP_mul 0x1e
++#define DW_OP_neg 0x1f
++#define DW_OP_not 0x20
++#define DW_OP_or 0x21
++#define DW_OP_plus 0x22
++#define DW_OP_plus_uconst 0x23
++#define DW_OP_shl 0x24
++#define DW_OP_shr 0x25
++#define DW_OP_shra 0x26
++#define DW_OP_xor 0x27
++#define DW_OP_bra 0x28
++#define DW_OP_eq 0x29
++#define DW_OP_ge 0x2a
++#define DW_OP_gt 0x2b
++#define DW_OP_le 0x2c
++#define DW_OP_lt 0x2d
++#define DW_OP_ne 0x2e
++#define DW_OP_skip 0x2f
++#define DW_OP_lit0 0x30
++#define DW_OP_lit1 0x31
++#define DW_OP_lit2 0x32
++#define DW_OP_lit3 0x33
++#define DW_OP_lit4 0x34
++#define DW_OP_lit5 0x35
++#define DW_OP_lit6 0x36
++#define DW_OP_lit7 0x37
++#define DW_OP_lit8 0x38
++#define DW_OP_lit9 0x39
++#define DW_OP_lit10 0x3a
++#define DW_OP_lit11 0x3b
++#define DW_OP_lit12 0x3c
++#define DW_OP_lit13 0x3d
++#define DW_OP_lit14 0x3e
++#define DW_OP_lit15 0x3f
++#define DW_OP_lit16 0x40
++#define DW_OP_lit17 0x41
++#define DW_OP_lit18 0x42
++#define DW_OP_lit19 0x43
++#define DW_OP_lit20 0x44
++#define DW_OP_lit21 0x45
++#define DW_OP_lit22 0x46
++#define DW_OP_lit23 0x47
++#define DW_OP_lit24 0x48
++#define DW_OP_lit25 0x49
++#define DW_OP_lit26 0x4a
++#define DW_OP_lit27 0x4b
++#define DW_OP_lit28 0x4c
++#define DW_OP_lit29 0x4d
++#define DW_OP_lit30 0x4e
++#define DW_OP_lit31 0x4f
++#define DW_OP_reg0 0x50
++#define DW_OP_reg1 0x51
++#define DW_OP_reg2 0x52
++#define DW_OP_reg3 0x53
++#define DW_OP_reg4 0x54
++#define DW_OP_reg5 0x55
++#define DW_OP_reg6 0x56
++#define DW_OP_reg7 0x57
++#define DW_OP_reg8 0x58
++#define DW_OP_reg9 0x59
++#define DW_OP_reg10 0x5a
++#define DW_OP_reg11 0x5b
++#define DW_OP_reg12 0x5c
++#define DW_OP_reg13 0x5d
++#define DW_OP_reg14 0x5e
++#define DW_OP_reg15 0x5f
++#define DW_OP_reg16 0x60
++#define DW_OP_reg17 0x61
++#define DW_OP_reg18 0x62
++#define DW_OP_reg19 0x63
++#define DW_OP_reg20 0x64
++#define DW_OP_reg21 0x65
++#define DW_OP_reg22 0x66
++#define DW_OP_reg23 0x67
++#define DW_OP_reg24 0x68
++#define DW_OP_reg25 0x69
++#define DW_OP_reg26 0x6a
++#define DW_OP_reg27 0x6b
++#define DW_OP_reg28 0x6c
++#define DW_OP_reg29 0x6d
++#define DW_OP_reg30 0x6e
++#define DW_OP_reg31 0x6f
++#define DW_OP_breg0 0x70
++#define DW_OP_breg1 0x71
++#define DW_OP_breg2 0x72
++#define DW_OP_breg3 0x73
++#define DW_OP_breg4 0x74
++#define DW_OP_breg5 0x75
++#define DW_OP_breg6 0x76
++#define DW_OP_breg7 0x77
++#define DW_OP_breg8 0x78
++#define DW_OP_breg9 0x79
++#define DW_OP_breg10 0x7a
++#define DW_OP_breg11 0x7b
++#define DW_OP_breg12 0x7c
++#define DW_OP_breg13 0x7d
++#define DW_OP_breg14 0x7e
++#define DW_OP_breg15 0x7f
++#define DW_OP_breg16 0x80
++#define DW_OP_breg17 0x81
++#define DW_OP_breg18 0x82
++#define DW_OP_breg19 0x83
++#define DW_OP_breg20 0x84
++#define DW_OP_breg21 0x85
++#define DW_OP_breg22 0x86
++#define DW_OP_breg23 0x87
++#define DW_OP_breg24 0x88
++#define DW_OP_breg25 0x89
++#define DW_OP_breg26 0x8a
++#define DW_OP_breg27 0x8b
++#define DW_OP_breg28 0x8c
++#define DW_OP_breg29 0x8d
++#define DW_OP_breg30 0x8e
++#define DW_OP_breg31 0x8f
++#define DW_OP_regx 0x90
++#define DW_OP_fbreg 0x91
++#define DW_OP_bregx 0x92
++#define DW_OP_piece 0x93
++#define DW_OP_deref_size 0x94
++#define DW_OP_xderef_size 0x95
++#define DW_OP_nop 0x96
++#define DW_OP_push_object_address 0x97
++#define DW_OP_call2 0x98
++#define DW_OP_call4 0x99
++#define DW_OP_call_ref 0x9a
++#define DW_OP_GNU_push_tls_address 0xe0
++#define DW_OP_HP_unknown 0xe0
++#define DW_OP_HP_is_value 0xe1
++#define DW_OP_HP_fltconst4 0xe2
++#define DW_OP_HP_fltconst8 0xe3
++#define DW_OP_HP_mod_range 0xe4
++#define DW_OP_HP_unmod_range 0xe5
++#define DW_OP_HP_tls 0xe6
++#define DW_OP_lo_user 0xe0 /* Implementation-defined range start. */
++#define DW_OP_hi_user 0xff /* Implementation-defined range end. */
++#define DW_ATE_void 0x0
++#define DW_ATE_address 0x1
++#define DW_ATE_boolean 0x2
++#define DW_ATE_complex_float 0x3
++#define DW_ATE_float 0x4
++#define DW_ATE_signed 0x5
++#define DW_ATE_signed_char 0x6
++#define DW_ATE_unsigned 0x7
++#define DW_ATE_unsigned_char 0x8
++#define DW_ATE_imaginary_float 0x9
++#define DW_ATE_HP_float80 0x80
++#define DW_ATE_HP_complex_float80 0x81
++#define DW_ATE_HP_float128 0x82
++#define DW_ATE_HP_complex_float128 0x83
++#define DW_ATE_HP_floathpintel 0x84
++#define DW_ATE_HP_imaginary_float80 0x85
++#define DW_ATE_HP_imaginary_float128 0x86
++#define DW_ATE_lo_user 0x80
++#define DW_ATE_hi_user 0xff
++#define DW_ORD_row_major 0
++#define DW_ORD_col_major 1
++#define DW_ACCESS_public 1
++#define DW_ACCESS_protected 2
++#define DW_ACCESS_private 3
++#define DW_VIS_local 1
++#define DW_VIS_exported 2
++#define DW_VIS_qualified 3
++#define DW_VIRTUALITY_none 0
++#define DW_VIRTUALITY_virtual 1
++#define DW_VIRTUALITY_pure_virtual 2
++#define DW_ID_case_sensitive 0
++#define DW_ID_up_case 1
++#define DW_ID_down_case 2
++#define DW_ID_case_insensitive 3
++#define DW_CC_normal 0x1
++#define DW_CC_program 0x2
++#define DW_CC_nocall 0x3
++#define DW_CC_lo_user 0x40
++#define DW_CC_hi_user 0xff
++#define DW_INL_not_inlined 0
++#define DW_INL_inlined 1
++#define DW_INL_declared_not_inlined 2
++#define DW_INL_declared_inlined 3
++#define DW_DSC_label 0
++#define DW_DSC_range 1
++#define DW_LNS_extended_op 0
++#define DW_LNS_copy 1
++#define DW_LNS_advance_pc 2
++#define DW_LNS_advance_line 3
++#define DW_LNS_set_file 4
++#define DW_LNS_set_column 5
++#define DW_LNS_negate_stmt 6
++#define DW_LNS_set_basic_block 7
++#define DW_LNS_const_add_pc 8
++#define DW_LNS_fixed_advance_pc 9
++#define DW_LNS_set_prologue_end 10
++#define DW_LNS_set_epilogue_begin 11
++#define DW_LNS_set_isa 12
++#define DW_LNE_end_sequence 1
++#define DW_LNE_set_address 2
++#define DW_LNE_define_file 3
++#define DW_LNE_HP_negate_is_UV_update 0x11
++#define DW_LNE_HP_push_context 0x12
++#define DW_LNE_HP_pop_context 0x13
++#define DW_LNE_HP_set_file_line_column 0x14
++#define DW_LNE_HP_set_routine_name 0x15
++#define DW_LNE_HP_set_sequence 0x16
++#define DW_LNE_HP_negate_post_semantics 0x17
++#define DW_LNE_HP_negate_function_exit 0x18
++#define DW_LNE_HP_negate_front_end_logical 0x19
++#define DW_LNE_HP_define_proc 0x20
++#define DW_CFA_advance_loc 0x40
++#define DW_CFA_offset 0x80
++#define DW_CFA_restore 0xc0
++#define DW_CFA_nop 0x00
++#define DW_CFA_set_loc 0x01
++#define DW_CFA_advance_loc1 0x02
++#define DW_CFA_advance_loc2 0x03
++#define DW_CFA_advance_loc4 0x04
++#define DW_CFA_offset_extended 0x05
++#define DW_CFA_restore_extended 0x06
++#define DW_CFA_undefined 0x07
++#define DW_CFA_same_value 0x08
++#define DW_CFA_register 0x09
++#define DW_CFA_remember_state 0x0a
++#define DW_CFA_restore_state 0x0b
++#define DW_CFA_def_cfa 0x0c
++#define DW_CFA_def_cfa_register 0x0d
++#define DW_CFA_def_cfa_offset 0x0e
++#define DW_CFA_def_cfa_expression 0x0f
++#define DW_CFA_expression 0x10
++#define DW_CFA_offset_extended_sf 0x11
++#define DW_CFA_def_cfa_sf 0x12
++#define DW_CFA_def_cfa_offset_sf 0x13
++#define DW_CFA_MIPS_advance_loc8 0x1d
++#define DW_CFA_GNU_window_save 0x2d
++#define DW_CFA_GNU_args_size 0x2e
++#define DW_CFA_GNU_negative_offset_extended 0x2f
++#define DW_CIE_ID 0xffffffff
++#define DW_CIE_VERSION 1
++#define DW_CFA_extended 0
++#define DW_CFA_lo_user 0x1c
++#define DW_CFA_hi_user 0x3f
++#define DW_CHILDREN_no 0x00
++#define DW_CHILDREN_yes 0x01
++#define DW_ADDR_none 0
++#define DW_LANG_C89 0x0001
++#define DW_LANG_C 0x0002
++#define DW_LANG_Ada83 0x0003
++#define DW_LANG_C_plus_plus 0x0004
++#define DW_LANG_Cobol74 0x0005
++#define DW_LANG_Cobol85 0x0006
++#define DW_LANG_Fortran77 0x0007
++#define DW_LANG_Fortran90 0x0008
++#define DW_LANG_Pascal83 0x0009
++#define DW_LANG_Modula2 0x000a
++#define DW_LANG_Java 0x000b
++#define DW_LANG_C99 0x000c
++#define DW_LANG_Ada95 0x000d
++#define DW_LANG_Fortran95 0x000e
++#define DW_LANG_Mips_Assembler 0x8001
++#define DW_LANG_Upc 0x8765
++#define DW_LANG_lo_user 0x8000 /* Implementation-defined range start. */
++#define DW_LANG_hi_user 0xffff /* Implementation-defined range start. */
++#define DW_MACINFO_define 1
++#define DW_MACINFO_undef 2
++#define DW_MACINFO_start_file 3
++#define DW_MACINFO_end_file 4
++#define DW_MACINFO_vendor_ext 255
++#define DW_EH_PE_absptr 0x00
++#define DW_EH_PE_omit 0xff
++#define DW_EH_PE_uleb128 0x01
++#define DW_EH_PE_udata2 0x02
++#define DW_EH_PE_udata4 0x03
++#define DW_EH_PE_udata8 0x04
++#define DW_EH_PE_sleb128 0x09
++#define DW_EH_PE_sdata2 0x0A
++#define DW_EH_PE_sdata4 0x0B
++#define DW_EH_PE_sdata8 0x0C
++#define DW_EH_PE_signed 0x08
++#define DW_EH_PE_pcrel 0x10
++#define DW_EH_PE_textrel 0x20
++#define DW_EH_PE_datarel 0x30
++#define DW_EH_PE_funcrel 0x40
++#define DW_EH_PE_aligned 0x50
++#define DW_EH_PE_indirect 0x80
++#endif
+diff -rupN -X ../client-cleanup/dontdiff linux-2.6.18/include/linux/dwarf2-lang.h linux-2.6.18.kgdb/include/linux/dwarf2-lang.h
+--- linux-2.6.18/include/linux/dwarf2-lang.h 1970-01-01 03:00:00.000000000 +0300
++++ linux-2.6.18.kgdb/include/linux/dwarf2-lang.h 2008-06-10 16:19:58.000000000 +0400
+@@ -0,0 +1,300 @@
++#ifndef DWARF2_LANG
++#define DWARF2_LANG
++
++/*
++ * This 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, or (at your option) any later
++ * version.
++ */
++/*
++ * This file defines macros that allow generation of DWARF debug records
++ * for asm files. This file is platform independent. Register numbers
++ * (which are about the only thing that is platform dependent) are to be
++ * supplied by a platform defined file.
++ */
++/*
++ * We need this to work for both asm and C. In asm we are using the
++ * old comment trick to concatenate while C uses the new ANSI thing.
++ * Here we have concat macro... The multi level thing is to allow and
++ * macros used in the names to be resolved prior to the cat (at which
++ * time they are no longer the same string).
++ */
++#define CAT3(a,b,c) _CAT3(a,b,c)
++#define _CAT3(a,b,c) __CAT3(a,b,c)
++#ifndef __STDC__
++#define __CAT3(a,b,c) a/**/b/**/c
++#else
++#define __CAT3(a,b,c) a##b##c
++#endif
++#ifdef __ASSEMBLY__
++#define IFC(a)
++#define IFN_C(a) a
++#define NL ;
++#define QUOTE_THIS(a) a
++#define DWARF_preamble .section .debug_frame,"",%progbits;
++#else
++#define IFC(a) a
++#define IFN_C(a)
++#define NL \n\t
++#define QUOTE_THIS(a) _QUOTE_THIS(a)
++#define _QUOTE_THIS(a) #a
++/* Don't let CPP see the " and , \042=" \054=, */
++#define DWARF_preamble .section .debug_frame \054\042\042\054%progbits
++#endif
++
++#ifdef CONFIG_64BIT
++#define DATA_ALIGN_FACTOR 8
++#define ADDR_LOC .quad
++#else
++#define DATA_ALIGN_FACTOR 4
++#define ADDR_LOC .long
++#endif
++
++#include <linux/dwarf2-defs.h>
++/*
++ * This macro starts a debug frame section. The debug_frame describes
++ * where to find the registers that the enclosing function saved on
++ * entry.
++ *
++ * ORD is use by the label generator and should be the same as what is
++ * passed to CFI_postamble.
++ *
++ * pc, pc register gdb ordinal.
++ *
++ * code_align this is the factor used to define locations or regions
++ * where the given definitions apply. If you use labels to define these
++ * this should be 1.
++ *
++ * data_align this is the factor used to define register offsets. If
++ * you use struct offset, this should be the size of the register in
++ * bytes or the negative of that. This is how it is used: you will
++ * define a register as the reference register, say the stack pointer,
++ * then you will say where a register is located relative to this
++ * reference registers value, say 40 for register 3 (the gdb register
++ * number). The <40> will be multiplied by <data_align> to define the
++ * byte offset of the given register (3, in this example). So if your
++ * <40> is the byte offset and the reference register points at the
++ * begining, you would want 1 for the data_offset. If <40> was the 40th
++ * 4-byte element in that structure you would want 4. And if your
++ * reference register points at the end of the structure you would want
++ * a negative data_align value(and you would have to do other math as
++ * well).
++ */
++
++#define CFI_preamble(ORD, pc, code_align, data_align) \
++ DWARF_preamble NL \
++ .align DATA_ALIGN_FACTOR NL \
++ .globl CAT3(frame,_,ORD) NL \
++CAT3(frame,_,ORD): NL \
++ .long 7f-6f NL \
++6: \
++ .long DW_CIE_ID NL \
++ .byte DW_CIE_VERSION NL \
++ .byte 0 NL \
++ .uleb128 code_align NL \
++ .sleb128 data_align NL \
++ .byte pc NL
++
++/*
++ * After the above macro and prior to the CFI_postamble, you need to
++ * define the initial state. This starts with defining the reference
++ * register and, usually the pc. Here are some helper macros:
++ */
++
++#define CFA_define_reference(reg, offset) \
++ .byte DW_CFA_def_cfa NL \
++ .uleb128 reg NL \
++ .uleb128 (offset) NL
++
++#define CFA_define_offset(reg, offset) \
++ .byte (DW_CFA_offset + reg) NL \
++ .uleb128 (offset) NL
++
++#define CFA_restore(reg) \
++ .byte (DW_CFA_restore + reg) NL
++
++#define CFI_postamble() \
++ .align DATA_ALIGN_FACTOR NL \
++7: NL \
++.previous NL
++
++/*
++ * So now your code pushs stuff on the stack, you need a new location
++ * and the rules for what to do. This starts a running description of
++ * the call frame. You need to describe what changes with respect to
++ * the call registers as the location of the pc moves through the code.
++ * The following builds an FDE (fram descriptor entry?). Like the
++ * above, it has a preamble and a postamble. It also is tied to the CFI
++ * above.
++ * The preamble macro is tied to the CFI thru the first parameter. The
++ * second is the code start address and then the code end address+1.
++ */
++#define FDE_preamble(ORD, initial_address, end_address) \
++ DWARF_preamble NL \
++ .align DATA_ALIGN_FACTOR NL \
++ .long 9f-8f NL \
++8: \
++ .long CAT3(frame,_,ORD) NL \
++ ADDR_LOC initial_address NL \
++ ADDR_LOC (end_address - initial_address) NL
++
++#define FDE_postamble() \
++ .align DATA_ALIGN_FACTOR NL \
++9: NL \
++.previous NL
++
++/*
++ * That done, you can now add registers, subtract registers, move the
++ * reference and even change the reference. You can also define a new
++ * area of code the info applies to. For discontinuous bits you should
++ * start a new FDE. You may have as many as you like.
++ */
++
++/*
++ * To advance the stack address by <bytes> (0x3f max)
++ */
++
++#define CFA_advance_loc(bytes) \
++ .byte DW_CFA_advance_loc+bytes NL
++
++/*
++ * This one is good for 0xff or 255
++ */
++#define CFA_advance_loc1(bytes) \
++ .byte DW_CFA_advance_loc1 NL \
++ .byte bytes NL
++
++#define CFA_undefine_reg(reg) \
++ .byte DW_CFA_undefined NL \
++ .uleb128 reg NL
++/*
++ * With the above you can define all the register locations. But
++ * suppose the reference register moves... Takes the new offset NOT an
++ * increment. This is how esp is tracked if it is not saved.
++ */
++
++#define CFA_define_cfa_offset(offset) \
++ .byte DW_CFA_def_cfa_offset NL \
++ .uleb128 (offset) NL
++/*
++ * Or suppose you want to use a different reference register...
++ */
++#define CFA_define_cfa_register(reg) \
++ .byte DW_CFA_def_cfa_register NL \
++ .uleb128 reg NL
++
++/*
++ * If you want to mess with the stack pointer, here is the expression.
++ * The stack starts empty.
++ */
++#define CFA_def_cfa_expression \
++ .byte DW_CFA_def_cfa_expression NL \
++ .uleb128 20f-10f NL \
++10: NL
++/*
++ * This expression is to be used for other regs. The stack starts with the
++ * stack address.
++ */
++
++#define CFA_expression(reg) \
++ .byte DW_CFA_expression NL \
++ .uleb128 reg NL \
++ .uleb128 20f-10f NL \
++10: NL
++/*
++ * Here we do the expression stuff. You should code the above followed
++ * by expression OPs followed by CFA_expression_end.
++ */
++
++
++#define CFA_expression_end \
++20: NL
++
++#define CFA_exp_OP_const4s(a) \
++ .byte DW_OP_const4s NL \
++ .long a NL
++
++#define CFA_exp_OP_swap .byte DW_OP_swap NL
++#define CFA_exp_OP_dup .byte DW_OP_dup NL
++#define CFA_exp_OP_drop .byte DW_OP_drop NL
++/*
++ * All these work on the top two elements on the stack, replacing them
++ * with the result. Top comes first where it matters. True is 1, false 0.
++ */
++#define CFA_exp_OP_deref .byte DW_OP_deref NL
++#define CFA_exp_OP_and .byte DW_OP_and NL
++#define CFA_exp_OP_div .byte DW_OP_div NL
++#define CFA_exp_OP_minus .byte DW_OP_minus NL
++#define CFA_exp_OP_mod .byte DW_OP_mod NL
++#define CFA_exp_OP_neg .byte DW_OP_neg NL
++#define CFA_exp_OP_plus .byte DW_OP_plus NL
++#define CFA_exp_OP_not .byte DW_OP_not NL
++#define CFA_exp_OP_or .byte DW_OP_or NL
++#define CFA_exp_OP_xor .byte DW_OP_xor NL
++#define CFA_exp_OP_le .byte DW_OP_le NL
++#define CFA_exp_OP_ge .byte DW_OP_ge NL
++#define CFA_exp_OP_eq .byte DW_OP_eq NL
++#define CFA_exp_OP_lt .byte DW_OP_lt NL
++#define CFA_exp_OP_gt .byte DW_OP_gt NL
++#define CFA_exp_OP_ne .byte DW_OP_ne NL
++/*
++ * These take a parameter as noted
++ */
++/*
++ * Unconditional skip to loc. loc is a label (loc:)
++ */
++#define CFA_exp_OP_skip(loc) \
++ .byte DW_OP_skip NL \
++ .hword loc-.-2 NL
++/*
++ * Conditional skip to loc (TOS != 0, TOS--) (loc is a label)
++ */
++#define CFA_exp_OP_bra(loc) \
++ .byte DW_OP_bra NL \
++ .hword loc-.-2 NL
++
++/*
++ * TOS += no (an unsigned number)
++ */
++#define CFA_exp_OP_plus_uconst(no) \
++ .byte DW_OP_plus_uconst NL \
++ .uleb128 no NL
++
++/*
++ * ++TOS = no (a unsigned number)
++ */
++#define CFA_exp_OP_constu(no) \
++ .byte DW_OP_constu NL \
++ .uleb128 no NL
++/*
++ * ++TOS = no (a signed number)
++ */
++#define CFA_exp_OP_consts(no) \
++ .byte DW_OP_consts NL \
++ .sleb128 no NL
++/*
++ * ++TOS = no (an unsigned byte)
++ */
++#define CFA_exp_OP_const1u(no) \
++ .byte DW_OP_const1u NL \
++ .byte no NL
++
++
++/*
++ * ++TOS = no (a address)
++ */
++#define CFA_exp_OP_addr(no) \
++ .byte DW_OP_addr NL \
++ .long no NL
++
++/*
++ * Push current frames value for "reg" + offset
++ * We take advantage of the opcode assignments to make this a litteral reg
++ * rather than use the DW_OP_bregx opcode.
++ */
++
++#define CFA_exp_OP_breg(reg,offset) \
++ .byte DW_OP_breg0+reg NL \
++ .sleb128 offset NL
++#endif
+diff -rupN -X ../client-cleanup/dontdiff linux-2.6.18/include/linux/dwarf2.h linux-2.6.18.kgdb/include/linux/dwarf2.h
+--- linux-2.6.18/include/linux/dwarf2.h 1970-01-01 03:00:00.000000000 +0300
++++ linux-2.6.18.kgdb/include/linux/dwarf2.h 2008-06-10 16:19:58.000000000 +0400
+@@ -0,0 +1,775 @@
++/* Declarations and definitions of codes relating to the DWARF2 symbolic
++ debugging information format.
++ Copyright (C) 1992, 1993, 1995, 1996, 1997, 1999, 2000, 2001, 2002,
++ 2003 Free Software Foundation, Inc.
++
++ Written by Gary Funck (gary@intrepid.com) The Ada Joint Program
++ Office (AJPO), Florida State Unviversity and Silicon Graphics Inc.
++ provided support for this effort -- June 21, 1995.
++
++ Derived from the DWARF 1 implementation written by Ron Guilmette
++ (rfg@netcom.com), November 1990.
++
++ This file is part of GCC.
++
++ GCC 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, or (at your option) any later
++ version.
++
++ GCC is distributed in the hope that it will be useful, but WITHOUT
++ ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
++ or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public
++ License for more details.
++
++ You should have received a copy of the GNU General Public License
++ along with GCC; see the file COPYING. If not, write to the Free
++ Software Foundation, 59 Temple Place - Suite 330, Boston, MA
++ 02111-1307, USA. */
++
++/* This file is derived from the DWARF specification (a public document)
++ Revision 2.0.0 (July 27, 1993) developed by the UNIX International
++ Programming Languages Special Interest Group (UI/PLSIG) and distributed
++ by UNIX International. Copies of this specification are available from
++ UNIX International, 20 Waterview Boulevard, Parsippany, NJ, 07054.
++
++ This file also now contains definitions from the DWARF 3 specification. */
++
++/* This file is shared between GCC and GDB, and should not contain
++ prototypes. */
++
++#ifndef _ELF_DWARF2_H
++#define _ELF_DWARF2_H
++
++/* Structure found in the .debug_line section. */
++typedef struct
++{
++ unsigned char li_length [4];
++ unsigned char li_version [2];
++ unsigned char li_prologue_length [4];
++ unsigned char li_min_insn_length [1];
++ unsigned char li_default_is_stmt [1];
++ unsigned char li_line_base [1];
++ unsigned char li_line_range [1];
++ unsigned char li_opcode_base [1];
++}
++DWARF2_External_LineInfo;
++
++typedef struct
++{
++ unsigned long li_length;
++ unsigned short li_version;
++ unsigned int li_prologue_length;
++ unsigned char li_min_insn_length;
++ unsigned char li_default_is_stmt;
++ int li_line_base;
++ unsigned char li_line_range;
++ unsigned char li_opcode_base;
++}
++DWARF2_Internal_LineInfo;
++
++/* Structure found in .debug_pubnames section. */
++typedef struct
++{
++ unsigned char pn_length [4];
++ unsigned char pn_version [2];
++ unsigned char pn_offset [4];
++ unsigned char pn_size [4];
++}
++DWARF2_External_PubNames;
++
++typedef struct
++{
++ unsigned long pn_length;
++ unsigned short pn_version;
++ unsigned long pn_offset;
++ unsigned long pn_size;
++}
++DWARF2_Internal_PubNames;
++
++/* Structure found in .debug_info section. */
++typedef struct
++{
++ unsigned char cu_length [4];
++ unsigned char cu_version [2];
++ unsigned char cu_abbrev_offset [4];
++ unsigned char cu_pointer_size [1];
++}
++DWARF2_External_CompUnit;
++
++typedef struct
++{
++ unsigned long cu_length;
++ unsigned short cu_version;
++ unsigned long cu_abbrev_offset;
++ unsigned char cu_pointer_size;
++}
++DWARF2_Internal_CompUnit;
++
++typedef struct
++{
++ unsigned char ar_length [4];
++ unsigned char ar_version [2];
++ unsigned char ar_info_offset [4];
++ unsigned char ar_pointer_size [1];
++ unsigned char ar_segment_size [1];
++}
++DWARF2_External_ARange;
++
++typedef struct
++{
++ unsigned long ar_length;
++ unsigned short ar_version;
++ unsigned long ar_info_offset;
++ unsigned char ar_pointer_size;
++ unsigned char ar_segment_size;
++}
++DWARF2_Internal_ARange;
++
++
++/* Tag names and codes. */
++enum dwarf_tag
++ {
++ DW_TAG_padding = 0x00,
++ DW_TAG_array_type = 0x01,
++ DW_TAG_class_type = 0x02,
++ DW_TAG_entry_point = 0x03,
++ DW_TAG_enumeration_type = 0x04,
++ DW_TAG_formal_parameter = 0x05,
++ DW_TAG_imported_declaration = 0x08,
++ DW_TAG_label = 0x0a,
++ DW_TAG_lexical_block = 0x0b,
++ DW_TAG_member = 0x0d,
++ DW_TAG_pointer_type = 0x0f,
++ DW_TAG_reference_type = 0x10,
++ DW_TAG_compile_unit = 0x11,
++ DW_TAG_string_type = 0x12,
++ DW_TAG_structure_type = 0x13,
++ DW_TAG_subroutine_type = 0x15,
++ DW_TAG_typedef = 0x16,
++ DW_TAG_union_type = 0x17,
++ DW_TAG_unspecified_parameters = 0x18,
++ DW_TAG_variant = 0x19,
++ DW_TAG_common_block = 0x1a,
++ DW_TAG_common_inclusion = 0x1b,
++ DW_TAG_inheritance = 0x1c,
++ DW_TAG_inlined_subroutine = 0x1d,
++ DW_TAG_module = 0x1e,
++ DW_TAG_ptr_to_member_type = 0x1f,
++ DW_TAG_set_type = 0x20,
++ DW_TAG_subrange_type = 0x21,
++ DW_TAG_with_stmt = 0x22,
++ DW_TAG_access_declaration = 0x23,
++ DW_TAG_base_type = 0x24,
++ DW_TAG_catch_block = 0x25,
++ DW_TAG_const_type = 0x26,
++ DW_TAG_constant = 0x27,
++ DW_TAG_enumerator = 0x28,
++ DW_TAG_file_type = 0x29,
++ DW_TAG_friend = 0x2a,
++ DW_TAG_namelist = 0x2b,
++ DW_TAG_namelist_item = 0x2c,
++ DW_TAG_packed_type = 0x2d,
++ DW_TAG_subprogram = 0x2e,
++ DW_TAG_template_type_param = 0x2f,
++ DW_TAG_template_value_param = 0x30,
++ DW_TAG_thrown_type = 0x31,
++ DW_TAG_try_block = 0x32,
++ DW_TAG_variant_part = 0x33,
++ DW_TAG_variable = 0x34,
++ DW_TAG_volatile_type = 0x35,
++ /* DWARF 3. */
++ DW_TAG_dwarf_procedure = 0x36,
++ DW_TAG_restrict_type = 0x37,
++ DW_TAG_interface_type = 0x38,
++ DW_TAG_namespace = 0x39,
++ DW_TAG_imported_module = 0x3a,
++ DW_TAG_unspecified_type = 0x3b,
++ DW_TAG_partial_unit = 0x3c,
++ DW_TAG_imported_unit = 0x3d,
++ /* SGI/MIPS Extensions. */
++ DW_TAG_MIPS_loop = 0x4081,
++ /* HP extensions. See: ftp://ftp.hp.com/pub/lang/tools/WDB/wdb-4.0.tar.gz . */
++ DW_TAG_HP_array_descriptor = 0x4090,
++ /* GNU extensions. */
++ DW_TAG_format_label = 0x4101, /* For FORTRAN 77 and Fortran 90. */
++ DW_TAG_function_template = 0x4102, /* For C++. */
++ DW_TAG_class_template = 0x4103, /* For C++. */
++ DW_TAG_GNU_BINCL = 0x4104,
++ DW_TAG_GNU_EINCL = 0x4105,
++ /* Extensions for UPC. See: http://upc.gwu.edu/~upc. */
++ DW_TAG_upc_shared_type = 0x8765,
++ DW_TAG_upc_strict_type = 0x8766,
++ DW_TAG_upc_relaxed_type = 0x8767,
++ /* PGI (STMicroelectronics) extensions. No documentation available. */
++ DW_TAG_PGI_kanji_type = 0xA000,
++ DW_TAG_PGI_interface_block = 0xA020
++ };
++
++#define DW_TAG_lo_user 0x4080
++#define DW_TAG_hi_user 0xffff
++
++/* Flag that tells whether entry has a child or not. */
++#define DW_children_no 0
++#define DW_children_yes 1
++
++/* Form names and codes. */
++enum dwarf_form
++ {
++ DW_FORM_addr = 0x01,
++ DW_FORM_block2 = 0x03,
++ DW_FORM_block4 = 0x04,
++ DW_FORM_data2 = 0x05,
++ DW_FORM_data4 = 0x06,
++ DW_FORM_data8 = 0x07,
++ DW_FORM_string = 0x08,
++ DW_FORM_block = 0x09,
++ DW_FORM_block1 = 0x0a,
++ DW_FORM_data1 = 0x0b,
++ DW_FORM_flag = 0x0c,
++ DW_FORM_sdata = 0x0d,
++ DW_FORM_strp = 0x0e,
++ DW_FORM_udata = 0x0f,
++ DW_FORM_ref_addr = 0x10,
++ DW_FORM_ref1 = 0x11,
++ DW_FORM_ref2 = 0x12,
++ DW_FORM_ref4 = 0x13,
++ DW_FORM_ref8 = 0x14,
++ DW_FORM_ref_udata = 0x15,
++ DW_FORM_indirect = 0x16
++ };
++
++/* Attribute names and codes. */
++enum dwarf_attribute
++ {
++ DW_AT_sibling = 0x01,
++ DW_AT_location = 0x02,
++ DW_AT_name = 0x03,
++ DW_AT_ordering = 0x09,
++ DW_AT_subscr_data = 0x0a,
++ DW_AT_byte_size = 0x0b,
++ DW_AT_bit_offset = 0x0c,
++ DW_AT_bit_size = 0x0d,
++ DW_AT_element_list = 0x0f,
++ DW_AT_stmt_list = 0x10,
++ DW_AT_low_pc = 0x11,
++ DW_AT_high_pc = 0x12,
++ DW_AT_language = 0x13,
++ DW_AT_member = 0x14,
++ DW_AT_discr = 0x15,
++ DW_AT_discr_value = 0x16,
++ DW_AT_visibility = 0x17,
++ DW_AT_import = 0x18,
++ DW_AT_string_length = 0x19,
++ DW_AT_common_reference = 0x1a,
++ DW_AT_comp_dir = 0x1b,
++ DW_AT_const_value = 0x1c,
++ DW_AT_containing_type = 0x1d,
++ DW_AT_default_value = 0x1e,
++ DW_AT_inline = 0x20,
++ DW_AT_is_optional = 0x21,
++ DW_AT_lower_bound = 0x22,
++ DW_AT_producer = 0x25,
++ DW_AT_prototyped = 0x27,
++ DW_AT_return_addr = 0x2a,
++ DW_AT_start_scope = 0x2c,
++ DW_AT_stride_size = 0x2e,
++ DW_AT_upper_bound = 0x2f,
++ DW_AT_abstract_origin = 0x31,
++ DW_AT_accessibility = 0x32,
++ DW_AT_address_class = 0x33,
++ DW_AT_artificial = 0x34,
++ DW_AT_base_types = 0x35,
++ DW_AT_calling_convention = 0x36,
++ DW_AT_count = 0x37,
++ DW_AT_data_member_location = 0x38,
++ DW_AT_decl_column = 0x39,
++ DW_AT_decl_file = 0x3a,
++ DW_AT_decl_line = 0x3b,
++ DW_AT_declaration = 0x3c,
++ DW_AT_discr_list = 0x3d,
++ DW_AT_encoding = 0x3e,
++ DW_AT_external = 0x3f,
++ DW_AT_frame_base = 0x40,
++ DW_AT_friend = 0x41,
++ DW_AT_identifier_case = 0x42,
++ DW_AT_macro_info = 0x43,
++ DW_AT_namelist_items = 0x44,
++ DW_AT_priority = 0x45,
++ DW_AT_segment = 0x46,
++ DW_AT_specification = 0x47,
++ DW_AT_static_link = 0x48,
++ DW_AT_type = 0x49,
++ DW_AT_use_location = 0x4a,
++ DW_AT_variable_parameter = 0x4b,
++ DW_AT_virtuality = 0x4c,
++ DW_AT_vtable_elem_location = 0x4d,
++ /* DWARF 3 values. */
++ DW_AT_allocated = 0x4e,
++ DW_AT_associated = 0x4f,
++ DW_AT_data_location = 0x50,
++ DW_AT_stride = 0x51,
++ DW_AT_entry_pc = 0x52,
++ DW_AT_use_UTF8 = 0x53,
++ DW_AT_extension = 0x54,
++ DW_AT_ranges = 0x55,
++ DW_AT_trampoline = 0x56,
++ DW_AT_call_column = 0x57,
++ DW_AT_call_file = 0x58,
++ DW_AT_call_line = 0x59,
++ /* SGI/MIPS extensions. */
++ DW_AT_MIPS_fde = 0x2001,
++ DW_AT_MIPS_loop_begin = 0x2002,
++ DW_AT_MIPS_tail_loop_begin = 0x2003,
++ DW_AT_MIPS_epilog_begin = 0x2004,
++ DW_AT_MIPS_loop_unroll_factor = 0x2005,
++ DW_AT_MIPS_software_pipeline_depth = 0x2006,
++ DW_AT_MIPS_linkage_name = 0x2007,
++ DW_AT_MIPS_stride = 0x2008,
++ DW_AT_MIPS_abstract_name = 0x2009,
++ DW_AT_MIPS_clone_origin = 0x200a,
++ DW_AT_MIPS_has_inlines = 0x200b,
++ /* HP extensions. */
++ DW_AT_HP_block_index = 0x2000,
++ DW_AT_HP_unmodifiable = 0x2001, /* Same as DW_AT_MIPS_fde. */
++ DW_AT_HP_actuals_stmt_list = 0x2010,
++ DW_AT_HP_proc_per_section = 0x2011,
++ DW_AT_HP_raw_data_ptr = 0x2012,
++ DW_AT_HP_pass_by_reference = 0x2013,
++ DW_AT_HP_opt_level = 0x2014,
++ DW_AT_HP_prof_version_id = 0x2015,
++ DW_AT_HP_opt_flags = 0x2016,
++ DW_AT_HP_cold_region_low_pc = 0x2017,
++ DW_AT_HP_cold_region_high_pc = 0x2018,
++ DW_AT_HP_all_variables_modifiable = 0x2019,
++ DW_AT_HP_linkage_name = 0x201a,
++ DW_AT_HP_prof_flags = 0x201b, /* In comp unit of procs_info for -g. */
++ /* GNU extensions. */
++ DW_AT_sf_names = 0x2101,
++ DW_AT_src_info = 0x2102,
++ DW_AT_mac_info = 0x2103,
++ DW_AT_src_coords = 0x2104,
++ DW_AT_body_begin = 0x2105,
++ DW_AT_body_end = 0x2106,
++ DW_AT_GNU_vector = 0x2107,
++ /* VMS extensions. */
++ DW_AT_VMS_rtnbeg_pd_address = 0x2201,
++ /* UPC extension. */
++ DW_AT_upc_threads_scaled = 0x3210,
++ /* PGI (STMicroelectronics) extensions. */
++ DW_AT_PGI_lbase = 0x3a00,
++ DW_AT_PGI_soffset = 0x3a01,
++ DW_AT_PGI_lstride = 0x3a02
++ };
++
++#define DW_AT_lo_user 0x2000 /* Implementation-defined range start. */
++#define DW_AT_hi_user 0x3ff0 /* Implementation-defined range end. */
++
++/* Location atom names and codes. */
++enum dwarf_location_atom
++ {
++ DW_OP_addr = 0x03,
++ DW_OP_deref = 0x06,
++ DW_OP_const1u = 0x08,
++ DW_OP_const1s = 0x09,
++ DW_OP_const2u = 0x0a,
++ DW_OP_const2s = 0x0b,
++ DW_OP_const4u = 0x0c,
++ DW_OP_const4s = 0x0d,
++ DW_OP_const8u = 0x0e,
++ DW_OP_const8s = 0x0f,
++ DW_OP_constu = 0x10,
++ DW_OP_consts = 0x11,
++ DW_OP_dup = 0x12,
++ DW_OP_drop = 0x13,
++ DW_OP_over = 0x14,
++ DW_OP_pick = 0x15,
++ DW_OP_swap = 0x16,
++ DW_OP_rot = 0x17,
++ DW_OP_xderef = 0x18,
++ DW_OP_abs = 0x19,
++ DW_OP_and = 0x1a,
++ DW_OP_div = 0x1b,
++ DW_OP_minus = 0x1c,
++ DW_OP_mod = 0x1d,
++ DW_OP_mul = 0x1e,
++ DW_OP_neg = 0x1f,
++ DW_OP_not = 0x20,
++ DW_OP_or = 0x21,
++ DW_OP_plus = 0x22,
++ DW_OP_plus_uconst = 0x23,
++ DW_OP_shl = 0x24,
++ DW_OP_shr = 0x25,
++ DW_OP_shra = 0x26,
++ DW_OP_xor = 0x27,
++ DW_OP_bra = 0x28,
++ DW_OP_eq = 0x29,
++ DW_OP_ge = 0x2a,
++ DW_OP_gt = 0x2b,
++ DW_OP_le = 0x2c,
++ DW_OP_lt = 0x2d,
++ DW_OP_ne = 0x2e,
++ DW_OP_skip = 0x2f,
++ DW_OP_lit0 = 0x30,
++ DW_OP_lit1 = 0x31,
++ DW_OP_lit2 = 0x32,
++ DW_OP_lit3 = 0x33,
++ DW_OP_lit4 = 0x34,
++ DW_OP_lit5 = 0x35,
++ DW_OP_lit6 = 0x36,
++ DW_OP_lit7 = 0x37,
++ DW_OP_lit8 = 0x38,
++ DW_OP_lit9 = 0x39,
++ DW_OP_lit10 = 0x3a,
++ DW_OP_lit11 = 0x3b,
++ DW_OP_lit12 = 0x3c,
++ DW_OP_lit13 = 0x3d,
++ DW_OP_lit14 = 0x3e,
++ DW_OP_lit15 = 0x3f,
++ DW_OP_lit16 = 0x40,
++ DW_OP_lit17 = 0x41,
++ DW_OP_lit18 = 0x42,
++ DW_OP_lit19 = 0x43,
++ DW_OP_lit20 = 0x44,
++ DW_OP_lit21 = 0x45,
++ DW_OP_lit22 = 0x46,
++ DW_OP_lit23 = 0x47,
++ DW_OP_lit24 = 0x48,
++ DW_OP_lit25 = 0x49,
++ DW_OP_lit26 = 0x4a,
++ DW_OP_lit27 = 0x4b,
++ DW_OP_lit28 = 0x4c,
++ DW_OP_lit29 = 0x4d,
++ DW_OP_lit30 = 0x4e,
++ DW_OP_lit31 = 0x4f,
++ DW_OP_reg0 = 0x50,
++ DW_OP_reg1 = 0x51,
++ DW_OP_reg2 = 0x52,
++ DW_OP_reg3 = 0x53,
++ DW_OP_reg4 = 0x54,
++ DW_OP_reg5 = 0x55,
++ DW_OP_reg6 = 0x56,
++ DW_OP_reg7 = 0x57,
++ DW_OP_reg8 = 0x58,
++ DW_OP_reg9 = 0x59,
++ DW_OP_reg10 = 0x5a,
++ DW_OP_reg11 = 0x5b,
++ DW_OP_reg12 = 0x5c,
++ DW_OP_reg13 = 0x5d,
++ DW_OP_reg14 = 0x5e,
++ DW_OP_reg15 = 0x5f,
++ DW_OP_reg16 = 0x60,
++ DW_OP_reg17 = 0x61,
++ DW_OP_reg18 = 0x62,
++ DW_OP_reg19 = 0x63,
++ DW_OP_reg20 = 0x64,
++ DW_OP_reg21 = 0x65,
++ DW_OP_reg22 = 0x66,
++ DW_OP_reg23 = 0x67,
++ DW_OP_reg24 = 0x68,
++ DW_OP_reg25 = 0x69,
++ DW_OP_reg26 = 0x6a,
++ DW_OP_reg27 = 0x6b,
++ DW_OP_reg28 = 0x6c,
++ DW_OP_reg29 = 0x6d,
++ DW_OP_reg30 = 0x6e,
++ DW_OP_reg31 = 0x6f,
++ DW_OP_breg0 = 0x70,
++ DW_OP_breg1 = 0x71,
++ DW_OP_breg2 = 0x72,
++ DW_OP_breg3 = 0x73,
++ DW_OP_breg4 = 0x74,
++ DW_OP_breg5 = 0x75,
++ DW_OP_breg6 = 0x76,
++ DW_OP_breg7 = 0x77,
++ DW_OP_breg8 = 0x78,
++ DW_OP_breg9 = 0x79,
++ DW_OP_breg10 = 0x7a,
++ DW_OP_breg11 = 0x7b,
++ DW_OP_breg12 = 0x7c,
++ DW_OP_breg13 = 0x7d,
++ DW_OP_breg14 = 0x7e,
++ DW_OP_breg15 = 0x7f,
++ DW_OP_breg16 = 0x80,
++ DW_OP_breg17 = 0x81,
++ DW_OP_breg18 = 0x82,
++ DW_OP_breg19 = 0x83,
++ DW_OP_breg20 = 0x84,
++ DW_OP_breg21 = 0x85,
++ DW_OP_breg22 = 0x86,
++ DW_OP_breg23 = 0x87,
++ DW_OP_breg24 = 0x88,
++ DW_OP_breg25 = 0x89,
++ DW_OP_breg26 = 0x8a,
++ DW_OP_breg27 = 0x8b,
++ DW_OP_breg28 = 0x8c,
++ DW_OP_breg29 = 0x8d,
++ DW_OP_breg30 = 0x8e,
++ DW_OP_breg31 = 0x8f,
++ DW_OP_regx = 0x90,
++ DW_OP_fbreg = 0x91,
++ DW_OP_bregx = 0x92,
++ DW_OP_piece = 0x93,
++ DW_OP_deref_size = 0x94,
++ DW_OP_xderef_size = 0x95,
++ DW_OP_nop = 0x96,
++ /* DWARF 3 extensions. */
++ DW_OP_push_object_address = 0x97,
++ DW_OP_call2 = 0x98,
++ DW_OP_call4 = 0x99,
++ DW_OP_call_ref = 0x9a,
++ /* GNU extensions. */
++ DW_OP_GNU_push_tls_address = 0xe0,
++ /* HP extensions. */
++ DW_OP_HP_unknown = 0xe0, /* Ouch, the same as GNU_push_tls_address. */
++ DW_OP_HP_is_value = 0xe1,
++ DW_OP_HP_fltconst4 = 0xe2,
++ DW_OP_HP_fltconst8 = 0xe3,
++ DW_OP_HP_mod_range = 0xe4,
++ DW_OP_HP_unmod_range = 0xe5,
++ DW_OP_HP_tls = 0xe6
++ };
++
++#define DW_OP_lo_user 0xe0 /* Implementation-defined range start. */
++#define DW_OP_hi_user 0xff /* Implementation-defined range end. */
++
++/* Type encodings. */
++enum dwarf_type
++ {
++ DW_ATE_void = 0x0,
++ DW_ATE_address = 0x1,
++ DW_ATE_boolean = 0x2,
++ DW_ATE_complex_float = 0x3,
++ DW_ATE_float = 0x4,
++ DW_ATE_signed = 0x5,
++ DW_ATE_signed_char = 0x6,
++ DW_ATE_unsigned = 0x7,
++ DW_ATE_unsigned_char = 0x8,
++ /* DWARF 3. */
++ DW_ATE_imaginary_float = 0x9,
++ /* HP extensions. */
++ DW_ATE_HP_float80 = 0x80, /* Floating-point (80 bit). */
++ DW_ATE_HP_complex_float80 = 0x81, /* Complex floating-point (80 bit). */
++ DW_ATE_HP_float128 = 0x82, /* Floating-point (128 bit). */
++ DW_ATE_HP_complex_float128 = 0x83, /* Complex floating-point (128 bit). */
++ DW_ATE_HP_floathpintel = 0x84, /* Floating-point (82 bit IA64). */
++ DW_ATE_HP_imaginary_float80 = 0x85,
++ DW_ATE_HP_imaginary_float128 = 0x86
++ };
++
++#define DW_ATE_lo_user 0x80
++#define DW_ATE_hi_user 0xff
++
++/* Array ordering names and codes. */
++enum dwarf_array_dim_ordering
++ {
++ DW_ORD_row_major = 0,
++ DW_ORD_col_major = 1
++ };
++
++/* Access attribute. */
++enum dwarf_access_attribute
++ {
++ DW_ACCESS_public = 1,
++ DW_ACCESS_protected = 2,
++ DW_ACCESS_private = 3
++ };
++
++/* Visibility. */
++enum dwarf_visibility_attribute
++ {
++ DW_VIS_local = 1,
++ DW_VIS_exported = 2,
++ DW_VIS_qualified = 3
++ };
++
++/* Virtuality. */
++enum dwarf_virtuality_attribute
++ {
++ DW_VIRTUALITY_none = 0,
++ DW_VIRTUALITY_virtual = 1,
++ DW_VIRTUALITY_pure_virtual = 2
++ };
++
++/* Case sensitivity. */
++enum dwarf_id_case
++ {
++ DW_ID_case_sensitive = 0,
++ DW_ID_up_case = 1,
++ DW_ID_down_case = 2,
++ DW_ID_case_insensitive = 3
++ };
++
++/* Calling convention. */
++enum dwarf_calling_convention
++ {
++ DW_CC_normal = 0x1,
++ DW_CC_program = 0x2,
++ DW_CC_nocall = 0x3
++ };
++
++#define DW_CC_lo_user 0x40
++#define DW_CC_hi_user 0xff
++
++/* Inline attribute. */
++enum dwarf_inline_attribute
++ {
++ DW_INL_not_inlined = 0,
++ DW_INL_inlined = 1,
++ DW_INL_declared_not_inlined = 2,
++ DW_INL_declared_inlined = 3
++ };
++
++/* Discriminant lists. */
++enum dwarf_discrim_list
++ {
++ DW_DSC_label = 0,
++ DW_DSC_range = 1
++ };
++
++/* Line number opcodes. */
++enum dwarf_line_number_ops
++ {
++ DW_LNS_extended_op = 0,
++ DW_LNS_copy = 1,
++ DW_LNS_advance_pc = 2,
++ DW_LNS_advance_line = 3,
++ DW_LNS_set_file = 4,
++ DW_LNS_set_column = 5,
++ DW_LNS_negate_stmt = 6,
++ DW_LNS_set_basic_block = 7,
++ DW_LNS_const_add_pc = 8,
++ DW_LNS_fixed_advance_pc = 9,
++ /* DWARF 3. */
++ DW_LNS_set_prologue_end = 10,
++ DW_LNS_set_epilogue_begin = 11,
++ DW_LNS_set_isa = 12
++ };
++
++/* Line number extended opcodes. */
++enum dwarf_line_number_x_ops
++ {
++ DW_LNE_end_sequence = 1,
++ DW_LNE_set_address = 2,
++ DW_LNE_define_file = 3,
++ /* HP extensions. */
++ DW_LNE_HP_negate_is_UV_update = 0x11,
++ DW_LNE_HP_push_context = 0x12,
++ DW_LNE_HP_pop_context = 0x13,
++ DW_LNE_HP_set_file_line_column = 0x14,
++ DW_LNE_HP_set_routine_name = 0x15,
++ DW_LNE_HP_set_sequence = 0x16,
++ DW_LNE_HP_negate_post_semantics = 0x17,
++ DW_LNE_HP_negate_function_exit = 0x18,
++ DW_LNE_HP_negate_front_end_logical = 0x19,
++ DW_LNE_HP_define_proc = 0x20
++ };
++
++/* Call frame information. */
++enum dwarf_call_frame_info
++ {
++ DW_CFA_advance_loc = 0x40,
++ DW_CFA_offset = 0x80,
++ DW_CFA_restore = 0xc0,
++ DW_CFA_nop = 0x00,
++ DW_CFA_set_loc = 0x01,
++ DW_CFA_advance_loc1 = 0x02,
++ DW_CFA_advance_loc2 = 0x03,
++ DW_CFA_advance_loc4 = 0x04,
++ DW_CFA_offset_extended = 0x05,
++ DW_CFA_restore_extended = 0x06,
++ DW_CFA_undefined = 0x07,
++ DW_CFA_same_value = 0x08,
++ DW_CFA_register = 0x09,
++ DW_CFA_remember_state = 0x0a,
++ DW_CFA_restore_state = 0x0b,
++ DW_CFA_def_cfa = 0x0c,
++ DW_CFA_def_cfa_register = 0x0d,
++ DW_CFA_def_cfa_offset = 0x0e,
++ /* DWARF 3. */
++ DW_CFA_def_cfa_expression = 0x0f,
++ DW_CFA_expression = 0x10,
++ DW_CFA_offset_extended_sf = 0x11,
++ DW_CFA_def_cfa_sf = 0x12,
++ DW_CFA_def_cfa_offset_sf = 0x13,
++ /* SGI/MIPS specific. */
++ DW_CFA_MIPS_advance_loc8 = 0x1d,
++ /* GNU extensions. */
++ DW_CFA_GNU_window_save = 0x2d,
++ DW_CFA_GNU_args_size = 0x2e,
++ DW_CFA_GNU_negative_offset_extended = 0x2f
++ };
++
++#define DW_CIE_ID 0xffffffff
++#define DW_CIE_VERSION 1
++
++#define DW_CFA_extended 0
++#define DW_CFA_lo_user 0x1c
++#define DW_CFA_hi_user 0x3f
++
++#define DW_CHILDREN_no 0x00
++#define DW_CHILDREN_yes 0x01
++
++#define DW_ADDR_none 0
++
++/* Source language names and codes. */
++enum dwarf_source_language
++ {
++ DW_LANG_C89 = 0x0001,
++ DW_LANG_C = 0x0002,
++ DW_LANG_Ada83 = 0x0003,
++ DW_LANG_C_plus_plus = 0x0004,
++ DW_LANG_Cobol74 = 0x0005,
++ DW_LANG_Cobol85 = 0x0006,
++ DW_LANG_Fortran77 = 0x0007,
++ DW_LANG_Fortran90 = 0x0008,
++ DW_LANG_Pascal83 = 0x0009,
++ DW_LANG_Modula2 = 0x000a,
++ DW_LANG_Java = 0x000b,
++ /* DWARF 3. */
++ DW_LANG_C99 = 0x000c,
++ DW_LANG_Ada95 = 0x000d,
++ DW_LANG_Fortran95 = 0x000e,
++ /* MIPS. */
++ DW_LANG_Mips_Assembler = 0x8001,
++ /* UPC. */
++ DW_LANG_Upc = 0x8765
++ };
++
++#define DW_LANG_lo_user 0x8000 /* Implementation-defined range start. */
++#define DW_LANG_hi_user 0xffff /* Implementation-defined range start. */
++
++/* Names and codes for macro information. */
++enum dwarf_macinfo_record_type
++ {
++ DW_MACINFO_define = 1,
++ DW_MACINFO_undef = 2,
++ DW_MACINFO_start_file = 3,
++ DW_MACINFO_end_file = 4,
++ DW_MACINFO_vendor_ext = 255
++ };
++\f
++/* @@@ For use with GNU frame unwind information. */
++
++#define DW_EH_PE_absptr 0x00
++#define DW_EH_PE_omit 0xff
++
++#define DW_EH_PE_uleb128 0x01
++#define DW_EH_PE_udata2 0x02
++#define DW_EH_PE_udata4 0x03
++#define DW_EH_PE_udata8 0x04
++#define DW_EH_PE_sleb128 0x09
++#define DW_EH_PE_sdata2 0x0A
++#define DW_EH_PE_sdata4 0x0B
++#define DW_EH_PE_sdata8 0x0C
++#define DW_EH_PE_signed 0x08
++
++#define DW_EH_PE_pcrel 0x10
++#define DW_EH_PE_textrel 0x20
++#define DW_EH_PE_datarel 0x30
++#define DW_EH_PE_funcrel 0x40
++#define DW_EH_PE_aligned 0x50
++
++#define DW_EH_PE_indirect 0x80
++
++#endif /* _ELF_DWARF2_H */
+diff -rupN -X ../client-cleanup/dontdiff linux-2.6.18/include/linux/kgdb.h linux-2.6.18.kgdb/include/linux/kgdb.h
+--- linux-2.6.18/include/linux/kgdb.h 1970-01-01 03:00:00.000000000 +0300
++++ linux-2.6.18.kgdb/include/linux/kgdb.h 2008-06-10 16:20:11.000000000 +0400
+@@ -0,0 +1,279 @@
++/*
++ * include/linux/kgdb.h
++ *
++ * This provides the hooks and functions that KGDB needs to share between
++ * the core, I/O and arch-specific portions.
++ *
++ * Author: Amit Kale <amitkale@linsyssoft.com> and
++ * Tom Rini <trini@kernel.crashing.org>
++ *
++ * 2001-2004 (c) Amit S. Kale and 2003-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.
++ */
++#ifdef __KERNEL__
++#ifndef _KGDB_H_
++#define _KGDB_H_
++
++#include <asm/atomic.h>
++
++#ifdef CONFIG_KGDB
++#include <asm/kgdb.h>
++#include <linux/serial_8250.h>
++#include <linux/linkage.h>
++#include <linux/init.h>
++
++#ifndef CHECK_EXCEPTION_STACK
++#define CHECK_EXCEPTION_STACK() 1
++#endif
++
++struct tasklet_struct;
++struct pt_regs;
++struct task_struct;
++struct uart_port;
++
++#ifdef CONFIG_KGDB_CONSOLE
++extern struct console kgdbcons;
++#endif
++
++/* To enter the debugger explicitly. */
++extern void breakpoint(void);
++extern int kgdb_connected;
++extern int kgdb_may_fault;
++extern struct tasklet_struct kgdb_tasklet_breakpoint;
++
++extern atomic_t kgdb_setting_breakpoint;
++extern atomic_t cpu_doing_single_step;
++extern atomic_t kgdb_sync_softlockup[NR_CPUS];
++
++extern struct task_struct *kgdb_usethread, *kgdb_contthread;
++
++enum kgdb_bptype {
++ bp_breakpoint = '0',
++ bp_hardware_breakpoint,
++ bp_write_watchpoint,
++ bp_read_watchpoint,
++ bp_access_watchpoint
++};
++
++enum kgdb_bpstate {
++ bp_none = 0,
++ bp_removed,
++ bp_set,
++ bp_active
++};
++
++struct kgdb_bkpt {
++ unsigned long bpt_addr;
++ unsigned char saved_instr[BREAK_INSTR_SIZE];
++ enum kgdb_bptype type;
++ enum kgdb_bpstate state;
++};
++
++/* The maximum number of KGDB I/O modules that can be loaded */
++#define MAX_KGDB_IO_HANDLERS 3
++
++#ifndef MAX_BREAKPOINTS
++#define MAX_BREAKPOINTS 1000
++#endif
++
++#define KGDB_HW_BREAKPOINT 1
++
++/* Required functions. */
++/**
++ * regs_to_gdb_regs - Convert ptrace regs to GDB regs
++ * @gdb_regs: A pointer to hold the registers in the order GDB wants.
++ * @regs: The &struct pt_regs of the current process.
++ *
++ * Convert the pt_regs in @regs into the format for registers that
++ * GDB expects, stored in @gdb_regs.
++ */
++extern void regs_to_gdb_regs(unsigned long *gdb_regs, struct pt_regs *regs);
++
++/**
++ * sleeping_regs_to_gdb_regs - Convert ptrace regs to GDB regs
++ * @gdb_regs: A pointer to hold the registers in the order GDB wants.
++ * @p: The &struct task_struct of the desired process.
++ *
++ * Convert the register values of the sleeping process in @p to
++ * the format that GDB expects.
++ * This function is called when kgdb does not have access to the
++ * &struct pt_regs and therefore it should fill the gdb registers
++ * @gdb_regs with what has been saved in &struct thread_struct
++ * thread field during switch_to.
++ */
++extern void sleeping_thread_to_gdb_regs(unsigned long *gdb_regs,
++ struct task_struct *p);
++
++/**
++ * gdb_regs_to_regs - Convert GDB regs to ptrace regs.
++ * @gdb_regs: A pointer to hold the registers we've recieved from GDB.
++ * @regs: A pointer to a &struct pt_regs to hold these values in.
++ *
++ * Convert the GDB regs in @gdb_regs into the pt_regs, and store them
++ * in @regs.
++ */
++extern void gdb_regs_to_regs(unsigned long *gdb_regs, struct pt_regs *regs);
++
++/**
++ * kgdb_arch_handle_exception - Handle architecture specific GDB packets.
++ * @vector: The error vector of the exception that happened.
++ * @signo: The signal number of the exception that happened.
++ * @err_code: The error code of the exception that happened.
++ * @remcom_in_buffer: The buffer of the packet we have read.
++ * @remcom_out_buffer: The buffer, of %BUFMAX to write a packet into.
++ * @regs: The &struct pt_regs of the current process.
++ *
++ * This function MUST handle the 'c' and 's' command packets,
++ * as well packets to set / remove a hardware breakpoint, if used.
++ * If there are additional packets which the hardware needs to handle,
++ * they are handled here. The code should return -1 if it wants to
++ * process more packets, and a %0 or %1 if it wants to exit from the
++ * kgdb hook.
++ */
++extern int kgdb_arch_handle_exception(int vector, int signo, int err_code,
++ char *remcom_in_buffer,
++ char *remcom_out_buffer,
++ struct pt_regs *regs);
++
++#ifndef JMP_REGS_ALIGNMENT
++#define JMP_REGS_ALIGNMENT
++#endif
++
++extern unsigned long kgdb_fault_jmp_regs[];
++
++/**
++ * kgdb_fault_setjmp - Store state in case we fault.
++ * @curr_context: An array to store state into.
++ *
++ * Certain functions may try and access memory, and in doing so may
++ * cause a fault. When this happens, we trap it, restore state to
++ * this call, and let ourself know that something bad has happened.
++ */
++extern asmlinkage int kgdb_fault_setjmp(unsigned long *curr_context);
++
++/**
++ * kgdb_fault_longjmp - Restore state when we have faulted.
++ * @curr_context: The previously stored state.
++ *
++ * When something bad does happen, this function is called to
++ * restore the known good state, and set the return value to 1, so
++ * we know something bad happened.
++ */
++extern asmlinkage void kgdb_fault_longjmp(unsigned long *curr_context);
++
++/* Optional functions. */
++extern int kgdb_arch_init(void);
++extern void kgdb_disable_hw_debug(struct pt_regs *regs);
++extern void kgdb_post_master_code(struct pt_regs *regs, int e_vector,
++ int err_code);
++extern void kgdb_roundup_cpus(unsigned long flags);
++extern int kgdb_set_hw_break(unsigned long addr);
++extern int kgdb_remove_hw_break(unsigned long addr);
++extern void kgdb_remove_all_hw_break(void);
++extern void kgdb_correct_hw_break(void);
++extern void kgdb_shadowinfo(struct pt_regs *regs, char *buffer,
++ unsigned threadid);
++extern struct task_struct *kgdb_get_shadow_thread(struct pt_regs *regs,
++ int threadid);
++extern struct pt_regs *kgdb_shadow_regs(struct pt_regs *regs, int threadid);
++extern int kgdb_validate_break_address(unsigned long addr);
++extern int kgdb_arch_set_breakpoint(unsigned long addr, char *saved_instr);
++extern int kgdb_arch_remove_breakpoint(unsigned long addr, char *bundle);
++
++/**
++ * struct kgdb_arch - Desribe architecture specific values.
++ * @gdb_bpt_instr: The instruction to trigger a breakpoint.
++ * @flags: Flags for the breakpoint, currently just %KGDB_HW_BREAKPOINT.
++ * @shadowth: A value of %1 indicates we shadow information on processes.
++ * @set_breakpoint: Allow an architecture to specify how to set a software
++ * breakpoint.
++ * @remove_breakpoint: Allow an architecture to specify how to remove a
++ * software breakpoint.
++ * @set_hw_breakpoint: Allow an architecture to specify how to set a hardware
++ * breakpoint.
++ * @remove_hw_breakpoint: Allow an architecture to specify how to remove a
++ * hardware breakpoint.
++ *
++ * The @shadowth flag is an option to shadow information not retrievable by
++ * gdb otherwise. This is deprecated in favor of a binutils which supports
++ * CFI macros.
++ */
++struct kgdb_arch {
++ unsigned char gdb_bpt_instr[BREAK_INSTR_SIZE];
++ unsigned long flags;
++ unsigned shadowth;
++ int (*set_breakpoint) (unsigned long, char *);
++ int (*remove_breakpoint)(unsigned long, char *);
++ int (*set_hw_breakpoint)(unsigned long, int, enum kgdb_bptype);
++ int (*remove_hw_breakpoint)(unsigned long, int, enum kgdb_bptype);
++};
++
++/* Thread reference */
++typedef unsigned char threadref[8];
++
++/**
++ * struct kgdb_io - Desribe the interface for an I/O driver to talk with KGDB.
++ * @read_char: Pointer to a function that will return one char.
++ * @write_char: Pointer to a function that will write one char.
++ * @flush: Pointer to a function that will flush any pending writes.
++ * @init: Pointer to a function that will initialize the device.
++ * @late_init: Pointer to a function that will do any setup that has
++ * other dependencies.
++ * @pre_exception: Pointer to a function that will do any prep work for
++ * the I/O driver.
++ * @post_exception: Pointer to a function that will do any cleanup work
++ * for the I/O driver.
++ *
++ * The @init and @late_init function pointers allow for an I/O driver
++ * such as a serial driver to fully initialize the port with @init and
++ * be called very early, yet safely call request_irq() later in the boot
++ * sequence.
++ *
++ * @init is allowed to return a non-0 return value to indicate failure.
++ * If this is called early on, then KGDB will try again when it would call
++ * @late_init. If it has failed later in boot as well, the user will be
++ * notified.
++ */
++struct kgdb_io {
++ int (*read_char) (void);
++ void (*write_char) (u8);
++ void (*flush) (void);
++ int (*init) (void);
++ void (*late_init) (void);
++ void (*pre_exception) (void);
++ void (*post_exception) (void);
++};
++
++extern struct kgdb_io kgdb_io_ops;
++extern struct kgdb_arch arch_kgdb_ops;
++extern int kgdb_initialized;
++
++extern int kgdb_register_io_module(struct kgdb_io *local_kgdb_io_ops);
++extern void kgdb_unregister_io_module(struct kgdb_io *local_kgdb_io_ops);
++
++extern void __init kgdb8250_add_port(int i, struct uart_port *serial_req);
++extern void __init kgdb8250_add_platform_port(int i, struct plat_serial8250_port *serial_req);
++
++extern int kgdb_hex2long(char **ptr, long *long_val);
++extern char *kgdb_mem2hex(char *mem, char *buf, int count);
++extern char *kgdb_hex2mem(char *buf, char *mem, int count);
++extern int kgdb_get_mem(char *addr, unsigned char *buf, int count);
++extern int kgdb_set_mem(char *addr, unsigned char *buf, int count);
++
++int kgdb_isremovedbreak(unsigned long addr);
++int kgdb_skipexception(int exception, struct pt_regs *regs);
++
++extern int kgdb_handle_exception(int ex_vector, int signo, int err_code,
++ struct pt_regs *regs);
++extern void kgdb_nmihook(int cpu, void *regs);
++extern int debugger_step;
++extern atomic_t debugger_active;
++extern struct kgdb_arch *kgdb_ops;
++#else
++/* Stubs for when KGDB is not set. */
++static const atomic_t debugger_active = ATOMIC_INIT(0);
++#endif /* CONFIG_KGDB */
++#endif /* _KGDB_H_ */
++#endif /* __KERNEL__ */
+diff -rupN -X ../client-cleanup/dontdiff linux-2.6.18/include/linux/module.h linux-2.6.18.kgdb/include/linux/module.h
+--- linux-2.6.18/include/linux/module.h 2006-09-20 07:42:06.000000000 +0400
++++ linux-2.6.18.kgdb/include/linux/module.h 2008-06-10 16:20:07.000000000 +0400
+@@ -224,8 +224,17 @@ enum module_state
+ MODULE_STATE_LIVE,
+ MODULE_STATE_COMING,
+ MODULE_STATE_GOING,
++ MODULE_STATE_GONE,
+ };
+
++#ifdef CONFIG_KGDB
++#define MAX_SECTNAME 31
++struct mod_section {
++ void *address;
++ char name[MAX_SECTNAME + 1];
++};
++#endif
++
+ /* Similar stuff for section attributes. */
+ #define MODULE_SECT_NAME_LEN 32
+ struct module_sect_attr
+@@ -253,6 +262,13 @@ struct module
+ /* Unique handle for this module */
+ char name[MODULE_NAME_LEN];
+
++#ifdef CONFIG_KGDB
++ /* keep kgdb info at the begining so that gdb doesn't have a chance to
++ * miss out any fields */
++ unsigned long num_sections;
++ struct mod_section *mod_sections;
++#endif
++
+ /* Sysfs stuff. */
+ struct module_kobject mkobj;
+ struct module_param_attrs *param_attrs;
+diff -rupN -X ../client-cleanup/dontdiff linux-2.6.18/include/linux/netpoll.h linux-2.6.18.kgdb/include/linux/netpoll.h
+--- linux-2.6.18/include/linux/netpoll.h 2006-09-20 07:42:06.000000000 +0400
++++ linux-2.6.18.kgdb/include/linux/netpoll.h 2008-06-10 16:19:07.000000000 +0400
+@@ -17,7 +17,7 @@ struct netpoll;
+ struct netpoll {
+ struct net_device *dev;
+ char dev_name[16], *name;
+- void (*rx_hook)(struct netpoll *, int, char *, int);
++ void (*rx_hook)(struct netpoll *, int, char *, int, struct sk_buff *);
+ void (*drop)(struct sk_buff *skb);
+ u32 local_ip, remote_ip;
+ u16 local_port, remote_port;
+diff -rupN -X ../client-cleanup/dontdiff linux-2.6.18/include/linux/serial_8250.h linux-2.6.18.kgdb/include/linux/serial_8250.h
+--- linux-2.6.18/include/linux/serial_8250.h 2006-09-20 07:42:06.000000000 +0400
++++ linux-2.6.18.kgdb/include/linux/serial_8250.h 2008-06-10 16:19:03.000000000 +0400
+@@ -56,6 +56,7 @@ struct uart_port;
+
+ int serial8250_register_port(struct uart_port *);
+ void serial8250_unregister_port(int line);
++void serial8250_unregister_by_port(struct uart_port *port);
+ void serial8250_suspend_port(int line);
+ void serial8250_resume_port(int line);
+
+diff -rupN -X ../client-cleanup/dontdiff linux-2.6.18/kernel/Makefile linux-2.6.18.kgdb/kernel/Makefile
+--- linux-2.6.18/kernel/Makefile 2006-09-20 07:42:06.000000000 +0400
++++ linux-2.6.18.kgdb/kernel/Makefile 2008-06-10 16:18:58.000000000 +0400
+@@ -42,6 +42,7 @@ obj-$(CONFIG_STOP_MACHINE) += stop_machi
+ obj-$(CONFIG_AUDIT) += audit.o auditfilter.o
+ obj-$(CONFIG_AUDITSYSCALL) += auditsc.o
+ obj-$(CONFIG_KPROBES) += kprobes.o
++obj-$(CONFIG_KGDB) += kgdb.o kgdbarchlib.o
+ obj-$(CONFIG_SYSFS) += ksysfs.o
+ obj-$(CONFIG_DETECT_SOFTLOCKUP) += softlockup.o
+ obj-$(CONFIG_GENERIC_HARDIRQS) += irq/
+diff -rupN -X ../client-cleanup/dontdiff linux-2.6.18/kernel/kgdb.c linux-2.6.18.kgdb/kernel/kgdb.c
+--- linux-2.6.18/kernel/kgdb.c 1970-01-01 03:00:00.000000000 +0300
++++ linux-2.6.18.kgdb/kernel/kgdb.c 2008-06-10 16:20:11.000000000 +0400
+@@ -0,0 +1,1778 @@
++/*
++ * kernel/kgdb.c
++ *
++ * Maintainer: Tom Rini <trini@kernel.crashing.org>
++ *
++ * Copyright (C) 2000-2001 VERITAS Software Corporation.
++ * Copyright (C) 2002-2004 Timesys Corporation
++ * Copyright (C) 2003-2004 Amit S. Kale <amitkale@linsyssoft.com>
++ * Copyright (C) 2004 Pavel Machek <pavel@suse.cz>
++ * Copyright (C) 2004-2005 Tom Rini <trini@kernel.crashing.org>
++ * Copyright (C) 2004-2006 LinSysSoft Technologies Pvt. Ltd.
++ * Copyright (C) 2005 Wind River Systems, Inc.
++ *
++ * Contributors at various stages not listed above:
++ * Jason Wessel ( jason.wessel@windriver.com )
++ * George Anzinger <george@mvista.com>
++ * Anurekh Saxena (anurekh.saxena@timesys.com)
++ * Lake Stevens Instrument Division (Glenn Engel)
++ * Jim Kingdon, Cygnus Support.
++ *
++ * Original KGDB stub: David Grothe <dave@gcom.com>,
++ * Tigran Aivazian <tigran@sco.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/interrupt.h>
++#include <linux/sched.h>
++#include <linux/smp.h>
++#include <linux/spinlock.h>
++#include <linux/delay.h>
++#include <linux/mm.h>
++#include <linux/threads.h>
++#include <linux/reboot.h>
++#include <asm/system.h>
++#include <asm/ptrace.h>
++#include <asm/uaccess.h>
++#include <linux/kgdb.h>
++#include <asm/atomic.h>
++#include <linux/notifier.h>
++#include <linux/module.h>
++#include <asm/cacheflush.h>
++#include <linux/init.h>
++#include <linux/sysrq.h>
++#include <linux/console.h>
++#include <linux/sched.h>
++#include <asm/byteorder.h>
++
++extern int pid_max;
++/* How many times to count all of the waiting CPUs */
++#define ROUNDUP_WAIT 640000 /* Arbitrary, increase if needed. */
++#define BUF_THREAD_ID_SIZE 16
++
++/*
++ * kgdb_initialized with a value of 1 indicates that kgdb is setup and is
++ * all ready to serve breakpoints and other kernel exceptions. A value of
++ * -1 indicates that we have tried to initialize early, and need to try
++ * again later.
++ */
++int kgdb_initialized;
++/* Is a host GDB connected to us? */
++int kgdb_connected;
++/* Could we be about to try and access a bad memory location? If so we
++ * also need to flag this has happend. */
++int kgdb_may_fault;
++/* All the KGDB handlers are installed */
++int kgdb_from_module_registered = 0;
++
++/* We provide a kgdb_io_ops structure that may be overriden. */
++struct kgdb_io __attribute__ ((weak)) kgdb_io_ops;
++
++static struct kgdb_io kgdb_io_ops_prev[MAX_KGDB_IO_HANDLERS];
++static int kgdb_io_handler_cnt = 0;
++
++/* Export the following symbols for use with kernel modules */
++EXPORT_SYMBOL(kgdb_io_ops);
++EXPORT_SYMBOL(kgdb_tasklet_breakpoint);
++EXPORT_SYMBOL(kgdb_connected);
++EXPORT_SYMBOL(kgdb_register_io_module);
++EXPORT_SYMBOL(kgdb_unregister_io_module);
++EXPORT_SYMBOL(debugger_active);
++
++/*
++ * Holds information about breakpoints in a kernel. These breakpoints are
++ * added and removed by gdb.
++ */
++struct kgdb_bkpt kgdb_break[MAX_BREAKPOINTS];
++
++static const char hexchars[] = "0123456789abcdef";
++
++static spinlock_t slavecpulocks[NR_CPUS];
++static atomic_t procindebug[NR_CPUS];
++atomic_t kgdb_setting_breakpoint;
++EXPORT_SYMBOL(kgdb_setting_breakpoint);
++struct task_struct *kgdb_usethread, *kgdb_contthread;
++
++int debugger_step;
++atomic_t debugger_active;
++
++/* Our I/O buffers. */
++static char remcom_in_buffer[BUFMAX];
++static char remcom_out_buffer[BUFMAX];
++/* Storage for the registers, in GDB format. */
++static unsigned long gdb_regs[(NUMREGBYTES + sizeof(unsigned long) - 1) /
++ sizeof(unsigned long)];
++/* Storage of registers for handling a fault. */
++unsigned long kgdb_fault_jmp_regs[NUMCRITREGBYTES / sizeof(unsigned long)]
++ JMP_REGS_ALIGNMENT;
++static int kgdb_notify_reboot(struct notifier_block *this,
++ unsigned long code ,void *x);
++struct debuggerinfo_struct {
++ void *debuggerinfo;
++ struct task_struct *task;
++} kgdb_info[NR_CPUS];
++
++/* to keep track of the CPU which is doing the single stepping*/
++atomic_t cpu_doing_single_step = ATOMIC_INIT(-1);
++
++atomic_t kgdb_sync_softlockup[NR_CPUS] = {ATOMIC_INIT(0)};
++
++/* reboot notifier block */
++static struct notifier_block kgdb_reboot_notifier = {
++ .notifier_call = kgdb_notify_reboot,
++ .next = NULL,
++ .priority = INT_MAX,
++};
++
++static int hex(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 get_packet(char *buffer)
++{
++ unsigned char checksum;
++ unsigned char xmitcsum;
++ int count;
++ char ch;
++ if (!kgdb_io_ops.read_char)
++ return;
++ do {
++ /* Spin and wait around for the start character, ignore all
++ * other characters */
++ while ((ch = (kgdb_io_ops.read_char())) != '$') ;
++ kgdb_connected = 1;
++ checksum = 0;
++ xmitcsum = -1;
++
++ count = 0;
++
++ /* now, read until a # or end of buffer is found */
++ while (count < (BUFMAX - 1)) {
++ ch = kgdb_io_ops.read_char();
++ if (ch == '#')
++ break;
++ checksum = checksum + ch;
++ buffer[count] = ch;
++ count = count + 1;
++ }
++ buffer[count] = 0;
++
++ if (ch == '#') {
++ xmitcsum = hex(kgdb_io_ops.read_char()) << 4;
++ xmitcsum += hex(kgdb_io_ops.read_char());
++
++ if (checksum != xmitcsum)
++ /* failed checksum */
++ kgdb_io_ops.write_char('-');
++ else
++ /* successful transfer */
++ kgdb_io_ops.write_char('+');
++ if (kgdb_io_ops.flush)
++ kgdb_io_ops.flush();
++ }
++ } while (checksum != xmitcsum);
++}
++
++/*
++ * Send the packet in buffer.
++ * Check for gdb connection if asked for.
++ */
++static void put_packet(char *buffer)
++{
++ unsigned char checksum;
++ int count;
++ char ch;
++
++ if (!kgdb_io_ops.write_char)
++ return;
++ /* $<packet info>#<checksum>. */
++ while (1) {
++ kgdb_io_ops.write_char('$');
++ checksum = 0;
++ count = 0;
++
++ while ((ch = buffer[count])) {
++ kgdb_io_ops.write_char(ch);
++ checksum += ch;
++ count++;
++ }
++
++ kgdb_io_ops.write_char('#');
++ kgdb_io_ops.write_char(hexchars[checksum >> 4]);
++ kgdb_io_ops.write_char(hexchars[checksum % 16]);
++ if (kgdb_io_ops.flush)
++ kgdb_io_ops.flush();
++
++ /* Now see what we get in reply. */
++ ch = kgdb_io_ops.read_char();
++
++ if (ch == 3)
++ ch = kgdb_io_ops.read_char();
++
++ /* If we get an ACK, we are done. */
++ if (ch == '+')
++ return;
++
++ /* If we get the start of another packet, this means
++ * that GDB is attempting to reconnect. We will NAK
++ * the packet being sent, and stop trying to send this
++ * packet. */
++ if (ch == '$') {
++ kgdb_io_ops.write_char('-');
++ if (kgdb_io_ops.flush)
++ kgdb_io_ops.flush();
++ return;
++ }
++ }
++}
++
++/*
++ * convert the memory pointed to by mem into hex, placing result in buf
++ * return a pointer to the last char put in buf (null). May return an error.
++ */
++char *kgdb_mem2hex(char *mem, char *buf, int count)
++{
++ kgdb_may_fault = 1;
++ if ((kgdb_fault_setjmp(kgdb_fault_jmp_regs)) != 0) {
++ kgdb_may_fault = 0;
++ return ERR_PTR(-EINVAL);
++ }
++ /* Accessing some registers in a single load instruction is
++ * required to avoid bad side effects for some I/O registers.
++ */
++ if ((count == 2) && (((long)mem & 1) == 0)) {
++ unsigned short tmp_s = *(unsigned short *)mem;
++ mem += 2;
++#ifdef __BIG_ENDIAN
++ *buf++ = hexchars[(tmp_s >> 12) & 0xf];
++ *buf++ = hexchars[(tmp_s >> 8) & 0xf];
++ *buf++ = hexchars[(tmp_s >> 4) & 0xf];
++ *buf++ = hexchars[tmp_s & 0xf];
++#else
++ *buf++ = hexchars[(tmp_s >> 4) & 0xf];
++ *buf++ = hexchars[tmp_s & 0xf];
++ *buf++ = hexchars[(tmp_s >> 12) & 0xf];
++ *buf++ = hexchars[(tmp_s >> 8) & 0xf];
++#endif
++ } else if ((count == 4) && (((long)mem & 3) == 0)) {
++ unsigned long tmp_l = *(unsigned int *)mem;
++ mem += 4;
++#ifdef __BIG_ENDIAN
++ *buf++ = hexchars[(tmp_l >> 28) & 0xf];
++ *buf++ = hexchars[(tmp_l >> 24) & 0xf];
++ *buf++ = hexchars[(tmp_l >> 20) & 0xf];
++ *buf++ = hexchars[(tmp_l >> 16) & 0xf];
++ *buf++ = hexchars[(tmp_l >> 12) & 0xf];
++ *buf++ = hexchars[(tmp_l >> 8) & 0xf];
++ *buf++ = hexchars[(tmp_l >> 4) & 0xf];
++ *buf++ = hexchars[tmp_l & 0xf];
++#else
++ *buf++ = hexchars[(tmp_l >> 4) & 0xf];
++ *buf++ = hexchars[tmp_l & 0xf];
++ *buf++ = hexchars[(tmp_l >> 12) & 0xf];
++ *buf++ = hexchars[(tmp_l >> 8) & 0xf];
++ *buf++ = hexchars[(tmp_l >> 20) & 0xf];
++ *buf++ = hexchars[(tmp_l >> 16) & 0xf];
++ *buf++ = hexchars[(tmp_l >> 28) & 0xf];
++ *buf++ = hexchars[(tmp_l >> 24) & 0xf];
++#endif
++#ifdef CONFIG_64BIT
++ } else if ((count == 8) && (((long)mem & 7) == 0)) {
++ unsigned long long tmp_ll = *(unsigned long long *)mem;
++ mem += 8;
++#ifdef __BIG_ENDIAN
++ *buf++ = hexchars[(tmp_ll >> 60) & 0xf];
++ *buf++ = hexchars[(tmp_ll >> 56) & 0xf];
++ *buf++ = hexchars[(tmp_ll >> 52) & 0xf];
++ *buf++ = hexchars[(tmp_ll >> 48) & 0xf];
++ *buf++ = hexchars[(tmp_ll >> 44) & 0xf];
++ *buf++ = hexchars[(tmp_ll >> 40) & 0xf];
++ *buf++ = hexchars[(tmp_ll >> 36) & 0xf];
++ *buf++ = hexchars[(tmp_ll >> 32) & 0xf];
++ *buf++ = hexchars[(tmp_ll >> 28) & 0xf];
++ *buf++ = hexchars[(tmp_ll >> 24) & 0xf];
++ *buf++ = hexchars[(tmp_ll >> 20) & 0xf];
++ *buf++ = hexchars[(tmp_ll >> 16) & 0xf];
++ *buf++ = hexchars[(tmp_ll >> 12) & 0xf];
++ *buf++ = hexchars[(tmp_ll >> 8) & 0xf];
++ *buf++ = hexchars[(tmp_ll >> 4) & 0xf];
++ *buf++ = hexchars[tmp_ll & 0xf];
++#else
++ *buf++ = hexchars[(tmp_ll >> 4) & 0xf];
++ *buf++ = hexchars[tmp_ll & 0xf];
++ *buf++ = hexchars[(tmp_ll >> 12) & 0xf];
++ *buf++ = hexchars[(tmp_ll >> 8) & 0xf];
++ *buf++ = hexchars[(tmp_ll >> 20) & 0xf];
++ *buf++ = hexchars[(tmp_ll >> 16) & 0xf];
++ *buf++ = hexchars[(tmp_ll >> 28) & 0xf];
++ *buf++ = hexchars[(tmp_ll >> 24) & 0xf];
++ *buf++ = hexchars[(tmp_ll >> 36) & 0xf];
++ *buf++ = hexchars[(tmp_ll >> 32) & 0xf];
++ *buf++ = hexchars[(tmp_ll >> 44) & 0xf];
++ *buf++ = hexchars[(tmp_ll >> 40) & 0xf];
++ *buf++ = hexchars[(tmp_ll >> 52) & 0xf];
++ *buf++ = hexchars[(tmp_ll >> 48) & 0xf];
++ *buf++ = hexchars[(tmp_ll >> 60) & 0xf];
++ *buf++ = hexchars[(tmp_ll >> 56) & 0xf];
++#endif
++#endif
++ } else {
++ while (count-- > 0) {
++ unsigned char ch = *mem++;
++ *buf++ = hexchars[ch >> 4];
++ *buf++ = hexchars[ch & 0xf];
++ }
++ }
++ kgdb_may_fault = 0;
++ *buf = 0;
++ return (buf);
++}
++
++/*
++ * Copy the binary array pointed to by buf into mem. Fix $, #, and
++ * 0x7d escaped with 0x7d. Return a pointer to the character after
++ * the last byte written.
++ */
++static char *kgdb_ebin2mem(char *buf, char *mem, int count)
++{
++ kgdb_may_fault = 1;
++ if ((kgdb_fault_setjmp(kgdb_fault_jmp_regs)) != 0) {
++ kgdb_may_fault = 0;
++ return ERR_PTR(-EINVAL);
++ }
++ for (; count > 0; count--, buf++) {
++ if (*buf == 0x7d)
++ *mem++ = *(++buf) ^ 0x20;
++ else
++ *mem++ = *buf;
++ }
++ kgdb_may_fault = 0;
++ return mem;
++}
++
++/*
++ * 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 return an error.
++ */
++char *kgdb_hex2mem(char *buf, char *mem, int count)
++{
++ kgdb_may_fault = 1;
++ if ((kgdb_fault_setjmp(kgdb_fault_jmp_regs)) != 0) {
++ kgdb_may_fault = 0;
++ return ERR_PTR(-EINVAL);
++ }
++ if ((count == 2) && (((long)mem & 1) == 0)) {
++ unsigned short tmp_s = 0;
++#ifdef __BIG_ENDIAN
++ tmp_s |= hex(*buf++) << 12;
++ tmp_s |= hex(*buf++) << 8;
++ tmp_s |= hex(*buf++) << 4;
++ tmp_s |= hex(*buf++);
++#else
++ tmp_s |= hex(*buf++) << 4;
++ tmp_s |= hex(*buf++);
++ tmp_s |= hex(*buf++) << 12;
++ tmp_s |= hex(*buf++) << 8;
++#endif
++ *(unsigned short *)mem = tmp_s;
++ mem += 2;
++ } else if ((count == 4) && (((long)mem & 3) == 0)) {
++ unsigned long tmp_l = 0;
++#ifdef __BIG_ENDIAN
++ tmp_l |= hex(*buf++) << 28;
++ tmp_l |= hex(*buf++) << 24;
++ tmp_l |= hex(*buf++) << 20;
++ tmp_l |= hex(*buf++) << 16;
++ tmp_l |= hex(*buf++) << 12;
++ tmp_l |= hex(*buf++) << 8;
++ tmp_l |= hex(*buf++) << 4;
++ tmp_l |= hex(*buf++);
++#else
++ tmp_l |= hex(*buf++) << 4;
++ tmp_l |= hex(*buf++);
++ tmp_l |= hex(*buf++) << 12;
++ tmp_l |= hex(*buf++) << 8;
++ tmp_l |= hex(*buf++) << 20;
++ tmp_l |= hex(*buf++) << 16;
++ tmp_l |= hex(*buf++) << 28;
++ tmp_l |= hex(*buf++) << 24;
++#endif
++ *(unsigned long *)mem = tmp_l;
++ mem += 4;
++ } else {
++ int i;
++ for (i = 0; i < count; i++) {
++ unsigned char ch = hex(*buf++) << 4;
++ ch |= hex(*buf++);
++ *mem++ = ch;
++ }
++ }
++ kgdb_may_fault = 0;
++ return (mem);
++}
++
++/*
++ * While we find nice hex chars, build a long_val.
++ * Return number of chars processed.
++ */
++int kgdb_hex2long(char **ptr, long *long_val)
++{
++ int hex_val, num = 0;
++
++ *long_val = 0;
++
++ while (**ptr) {
++ hex_val = hex(**ptr);
++ if (hex_val >= 0) {
++ *long_val = (*long_val << 4) | hex_val;
++ num++;
++ } else
++ break;
++
++ (*ptr)++;
++ }
++
++ return (num);
++}
++
++/* Write memory due to an 'M' or 'X' packet. */
++static char *write_mem_msg(int binary)
++{
++ char *ptr = &remcom_in_buffer[1];
++ unsigned long addr, length;
++
++ if (kgdb_hex2long(&ptr, &addr) > 0 && *(ptr++) == ',' &&
++ kgdb_hex2long(&ptr, &length) > 0 && *(ptr++) == ':') {
++ if (binary)
++ ptr = kgdb_ebin2mem(ptr, (char *)addr, length);
++ else
++ ptr = kgdb_hex2mem(ptr, (char *)addr, length);
++ if (CACHE_FLUSH_IS_SAFE)
++ flush_icache_range(addr, addr + length + 1);
++ if (IS_ERR(ptr))
++ return ptr;
++ return NULL;
++ }
++
++ return ERR_PTR(-EINVAL);
++}
++
++static inline char *pack_hex_byte(char *pkt, int byte)
++{
++ *pkt++ = hexchars[(byte >> 4) & 0xf];
++ *pkt++ = hexchars[(byte & 0xf)];
++ return pkt;
++}
++
++static inline void error_packet(char *pkt, int error)
++{
++ error = -error;
++ pkt[0] = 'E';
++ pkt[1] = hexchars[(error / 10)];
++ pkt[2] = hexchars[(error % 10)];
++ pkt[3] = '\0';
++}
++
++static char *pack_threadid(char *pkt, threadref * id)
++{
++ char *limit;
++ unsigned char *altid;
++
++ altid = (unsigned char *)id;
++ limit = pkt + BUF_THREAD_ID_SIZE;
++ while (pkt < limit)
++ pkt = pack_hex_byte(pkt, *altid++);
++
++ return pkt;
++}
++
++void int_to_threadref(threadref * id, int value)
++{
++ unsigned char *scan;
++ int i = 4;
++
++ scan = (unsigned char *)id;
++ while (i--)
++ *scan++ = 0;
++ *scan++ = (value >> 24) & 0xff;
++ *scan++ = (value >> 16) & 0xff;
++ *scan++ = (value >> 8) & 0xff;
++ *scan++ = (value & 0xff);
++}
++
++static struct task_struct *getthread(struct pt_regs *regs, int tid)
++{
++ if (last_pid == 0)
++ return current;
++
++ if (num_online_cpus() &&
++ (tid >= pid_max + num_online_cpus() + kgdb_ops->shadowth))
++ return NULL;
++
++ if (kgdb_ops->shadowth && (tid >= pid_max + num_online_cpus()))
++ return kgdb_get_shadow_thread(regs, tid - pid_max -
++ num_online_cpus());
++
++ if (tid >= pid_max)
++ return idle_task(tid - pid_max);
++
++ if (!tid)
++ return NULL;
++
++ return find_task_by_pid(tid);
++}
++
++#ifdef CONFIG_SMP
++static void kgdb_wait(struct pt_regs *regs)
++{
++ unsigned long flags;
++ int processor;
++
++ local_irq_save(flags);
++ processor = smp_processor_id();
++ kgdb_info[processor].debuggerinfo = regs;
++ kgdb_info[processor].task = current;
++ atomic_set(&procindebug[processor], 1);
++ atomic_set(&kgdb_sync_softlockup[smp_processor_id()], 1);
++
++ /* Wait till master processor goes completely into the debugger.
++ * FIXME: this looks racy */
++ while (!atomic_read(&procindebug[atomic_read(&debugger_active) - 1])) {
++ int i = 10; /* an arbitrary number */
++
++ while (--i)
++ cpu_relax();
++ }
++
++ /* Wait till master processor is done with debugging */
++ spin_lock_nested(&slavecpulocks[processor], processor);
++
++ /* This has been taken from x86 kgdb implementation and
++ * will be needed by architectures that have SMP support
++ */
++ kgdb_correct_hw_break();
++
++ kgdb_info[processor].debuggerinfo = NULL;
++ kgdb_info[processor].task = NULL;
++
++ /* Signal the master processor that we are done */
++ atomic_set(&procindebug[processor], 0);
++ spin_unlock(&slavecpulocks[processor]);
++ local_irq_restore(flags);
++}
++#endif
++
++int kgdb_get_mem(char *addr, unsigned char *buf, int count)
++{
++ kgdb_may_fault = 1;
++ if ((kgdb_fault_setjmp(kgdb_fault_jmp_regs)) != 0) {
++ kgdb_may_fault = 0;
++ return -EINVAL;
++ }
++ while (count) {
++ if ((unsigned long)addr < TASK_SIZE)
++ return -EINVAL;
++ *buf++ = *addr++;
++ count--;
++ }
++ kgdb_may_fault = 0;
++ return 0;
++}
++
++int kgdb_set_mem(char *addr, unsigned char *buf, int count)
++{
++ kgdb_may_fault = 1;
++ if ((kgdb_fault_setjmp(kgdb_fault_jmp_regs)) != 0) {
++ kgdb_may_fault = 0;
++ return -EINVAL;
++ }
++ while (count) {
++ if ((unsigned long)addr < TASK_SIZE)
++ return -EINVAL;
++ *addr++ = *buf++;
++ count--;
++ }
++ kgdb_may_fault = 0;
++ return 0;
++}
++int kgdb_activate_sw_breakpoints(void)
++{
++ int i;
++ int error = 0;
++ unsigned long addr;
++ for (i = 0; i < MAX_BREAKPOINTS; i++) {
++ if (kgdb_break[i].state != bp_set)
++ continue;
++ addr = kgdb_break[i].bpt_addr;
++ if ((error = kgdb_arch_set_breakpoint(addr,
++ kgdb_break[i].saved_instr)))
++ return error;
++
++ if (CACHE_FLUSH_IS_SAFE) {
++ if (current->mm && addr < TASK_SIZE)
++ flush_cache_range(current->mm->mmap_cache,
++ addr, addr + BREAK_INSTR_SIZE);
++ else
++ flush_icache_range(addr, addr +
++ BREAK_INSTR_SIZE);
++ }
++
++ kgdb_break[i].state = bp_active;
++ }
++ return 0;
++}
++
++static int kgdb_set_sw_break(unsigned long addr)
++{
++ int i, breakno = -1;
++ int error = 0;
++ if ((error = kgdb_validate_break_address(addr)) < 0)
++ return error;
++ for (i = 0; i < MAX_BREAKPOINTS; i++) {
++ if ((kgdb_break[i].state == bp_set) &&
++ (kgdb_break[i].bpt_addr == addr))
++ return -EEXIST;
++ }
++ for (i = 0; i < MAX_BREAKPOINTS; i++) {
++ if (kgdb_break[i].state == bp_removed &&
++ kgdb_break[i].bpt_addr == addr) {
++ breakno = i;
++ break;
++ }
++ }
++
++ if (breakno == -1) {
++ for (i = 0; i < MAX_BREAKPOINTS; i++) {
++ if (kgdb_break[i].state == bp_none) {
++ breakno = i;
++ break;
++ }
++ }
++ }
++ if (breakno == -1)
++ return -E2BIG;
++
++ kgdb_break[breakno].state = bp_set;
++ kgdb_break[breakno].type = bp_breakpoint;
++ kgdb_break[breakno].bpt_addr = addr;
++
++ return 0;
++}
++
++int kgdb_deactivate_sw_breakpoints(void)
++{
++ int i;
++ int error = 0;
++ unsigned long addr;
++ for (i = 0; i < MAX_BREAKPOINTS; i++) {
++ if (kgdb_break[i].state != bp_active)
++ continue;
++ addr = kgdb_break[i].bpt_addr;
++ if ((error = kgdb_arch_remove_breakpoint(addr,
++ kgdb_break[i].saved_instr)))
++ return error;
++
++ if (CACHE_FLUSH_IS_SAFE && current->mm &&
++ addr < TASK_SIZE)
++ flush_cache_range(current->mm->mmap_cache,
++ addr, addr + BREAK_INSTR_SIZE);
++ else if (CACHE_FLUSH_IS_SAFE)
++ flush_icache_range(addr,
++ addr + BREAK_INSTR_SIZE);
++ kgdb_break[i].state = bp_set;
++ }
++ return 0;
++}
++
++static int kgdb_remove_sw_break(unsigned long addr)
++{
++ int i;
++
++ for (i = 0; i < MAX_BREAKPOINTS; i++) {
++ if ((kgdb_break[i].state == bp_set) &&
++ (kgdb_break[i].bpt_addr == addr)) {
++ kgdb_break[i].state = bp_removed;
++ return 0;
++ }
++ }
++ return -ENOENT;
++}
++
++int kgdb_isremovedbreak(unsigned long addr)
++{
++ int i;
++ for (i = 0; i < MAX_BREAKPOINTS; i++) {
++ if ((kgdb_break[i].state == bp_removed) &&
++ (kgdb_break[i].bpt_addr == addr)) {
++ return 1;
++ }
++ }
++ return 0;
++}
++
++int remove_all_break(void)
++{
++ int i;
++ int error;
++ unsigned long addr;
++
++ /* Clear memory breakpoints. */
++ for (i = 0; i < MAX_BREAKPOINTS; i++) {
++ if (kgdb_break[i].state != bp_set)
++ continue;
++ addr = kgdb_break[i].bpt_addr;
++ if ((error = kgdb_arch_remove_breakpoint(addr,
++ kgdb_break[i].saved_instr)))
++ return error;
++ kgdb_break[i].state = bp_removed;
++ }
++
++ /* Clear hardware breakpoints. */
++ kgdb_remove_all_hw_break();
++
++ return 0;
++}
++
++static inline int shadow_pid(int realpid)
++{
++ if (realpid) {
++ return realpid;
++ }
++ return pid_max + smp_processor_id();
++}
++
++static char gdbmsgbuf[BUFMAX + 1];
++static void kgdb_msg_write(const char *s, int len)
++{
++ int i;
++ int wcount;
++ char *bufptr;
++
++ /* 'O'utput */
++ gdbmsgbuf[0] = 'O';
++
++ /* Fill and send buffers... */
++ while (len > 0) {
++ bufptr = gdbmsgbuf + 1;
++
++ /* Calculate how many this time */
++ if ((len << 1) > (BUFMAX - 2))
++ wcount = (BUFMAX - 2) >> 1;
++ else
++ wcount = len;
++
++ /* Pack in hex chars */
++ for (i = 0; i < wcount; i++)
++ bufptr = pack_hex_byte(bufptr, s[i]);
++ *bufptr = '\0';
++
++ /* Move up */
++ s += wcount;
++ len -= wcount;
++
++ /* Write packet */
++ put_packet(gdbmsgbuf);
++ }
++}
++
++/*
++ * This function does all command procesing for interfacing to gdb.
++ *
++ * Locking hierarchy:
++ * interface locks, if any (begin_session)
++ * kgdb lock (debugger_active)
++ *
++ * Note that since we can be in here prior to our cpumask being filled
++ * out, we err on the side of caution and loop over NR_CPUS instead
++ * of a for_each_online_cpu.
++ *
++ */
++int kgdb_handle_exception(int ex_vector, int signo, int err_code,
++ struct pt_regs *linux_regs)
++{
++ unsigned long length, addr;
++ char *ptr;
++ unsigned long flags;
++ unsigned i;
++ long threadid;
++ threadref thref;
++ struct task_struct *thread = NULL;
++ unsigned procid;
++ int numshadowth = num_online_cpus() + kgdb_ops->shadowth;
++ long kgdb_usethreadid = 0;
++ int error = 0, all_cpus_synced = 0;
++ struct pt_regs *shadowregs;
++ int processor = smp_processor_id();
++ void *local_debuggerinfo;
++
++ /* Panic on recursive debugger calls. */
++ if (atomic_read(&debugger_active) == smp_processor_id() + 1)
++ return 0;
++
++ acquirelock:
++
++ /* Call the I/O drivers pre_exception routine if the I/O
++ * driver defined one
++ */
++ if (kgdb_io_ops.pre_exception)
++ kgdb_io_ops.pre_exception();
++
++ /*
++ * Interrupts will be restored by the 'trap return' code, except when
++ * single stepping.
++ */
++ local_irq_save(flags);
++
++ /* Hold debugger_active */
++ procid = smp_processor_id();
++
++ while (cmpxchg(&atomic_read(&debugger_active), 0, (procid + 1)) != 0) {
++ int i = 25; /* an arbitrary number */
++
++ while (--i)
++ cpu_relax();
++
++ if (atomic_read(&cpu_doing_single_step) != -1 &&
++ atomic_read(&cpu_doing_single_step) != procid)
++ udelay(1);
++ }
++
++ atomic_set(&kgdb_sync_softlockup[smp_processor_id()], 1);
++
++ /*
++ * Don't enter if the last instance of the exception handler wanted to
++ * come into the debugger again.
++ */
++ if (atomic_read(&cpu_doing_single_step) != -1 &&
++ atomic_read(&cpu_doing_single_step) != procid) {
++ atomic_set(&debugger_active, 0);
++ local_irq_restore(flags);
++ goto acquirelock;
++ }
++
++ /*
++ * Don't enter if we have hit a removed breakpoint.
++ */
++ if (kgdb_skipexception(ex_vector, linux_regs))
++ goto kgdb_restore;
++
++ kgdb_info[processor].debuggerinfo = linux_regs;
++ kgdb_info[processor].task = current;
++
++ kgdb_disable_hw_debug(linux_regs);
++
++ if (!debugger_step || !kgdb_contthread)
++ for (i = 0; i < NR_CPUS; i++)
++ spin_lock_nested(&slavecpulocks[i], i);
++
++ /* Make sure we get the other CPUs */
++ if (!debugger_step || !kgdb_contthread)
++ kgdb_roundup_cpus(flags);
++
++ /* spin_lock code is good enough as a barrier so we don't
++ * need one here */
++ atomic_set(&procindebug[processor], 1);
++
++ /* Wait a reasonable time for the other CPUs to be notified and
++ * be waiting for us. Very early on this could be imperfect
++ * as num_online_cpus() could be 0.*/
++ for (i = 0; i < ROUNDUP_WAIT; i++) {
++ int cpu, num = 0;
++ for (cpu = 0; cpu < NR_CPUS; cpu++) {
++ if (atomic_read(&procindebug[cpu]))
++ num++;
++ }
++ if (num >= num_online_cpus()) {
++ all_cpus_synced = 1;
++ break;
++ }
++ }
++
++ /* Clear the out buffer. */
++ memset(remcom_out_buffer, 0, sizeof(remcom_out_buffer));
++
++ /* Master processor is completely in the debugger */
++ kgdb_post_master_code(linux_regs, ex_vector, err_code);
++ kgdb_deactivate_sw_breakpoints();
++ debugger_step = 0;
++ kgdb_contthread = NULL;
++
++ if (kgdb_connected) {
++ /* If we're still unable to roundup all of the CPUs,
++ * send an 'O' packet informing the user again. */
++ if (!all_cpus_synced)
++ kgdb_msg_write("Not all CPUs have been synced for "
++ "KGDB\n", 39);
++ /* Reply to host that an exception has occurred */
++ ptr = remcom_out_buffer;
++ *ptr++ = 'T';
++ *ptr++ = hexchars[(signo >> 4) % 16];
++ *ptr++ = hexchars[signo % 16];
++ ptr += strlen(strcpy(ptr, "thread:"));
++ int_to_threadref(&thref, shadow_pid(current->pid));
++ ptr = pack_threadid(ptr, &thref);
++ *ptr++ = ';';
++
++ put_packet(remcom_out_buffer);
++ }
++
++ kgdb_usethread = kgdb_info[processor].task;
++ kgdb_usethreadid = shadow_pid(kgdb_info[processor].task->pid);
++
++ while (kgdb_io_ops.read_char) {
++ char *bpt_type;
++ error = 0;
++
++ /* Clear the out buffer. */
++ memset(remcom_out_buffer, 0, sizeof(remcom_out_buffer));
++
++ get_packet(remcom_in_buffer);
++
++ switch (remcom_in_buffer[0]) {
++ case '?':
++ /* We know that this packet is only sent
++ * during initial connect. So to be safe,
++ * we clear out our breakpoints now incase
++ * GDB is reconnecting. */
++ remove_all_break();
++ /* Also, if we haven't been able to roundup all
++ * CPUs, send an 'O' packet informing the user
++ * as much. Only need to do this once. */
++ if (!all_cpus_synced)
++ kgdb_msg_write("Not all CPUs have been "
++ "synced for KGDB\n", 39);
++ remcom_out_buffer[0] = 'S';
++ remcom_out_buffer[1] = hexchars[signo >> 4];
++ remcom_out_buffer[2] = hexchars[signo % 16];
++ break;
++
++ case 'g': /* return the value of the CPU registers */
++ thread = kgdb_usethread;
++
++ if (!thread) {
++ thread = kgdb_info[processor].task;
++ local_debuggerinfo =
++ kgdb_info[processor].debuggerinfo;
++ } else {
++ local_debuggerinfo = NULL;
++ for (i = 0; i < NR_CPUS; i++) {
++ /* Try to find the task on some other
++ * or possibly this node if we do not
++ * find the matching task then we try
++ * to approximate the results.
++ */
++ if (thread == kgdb_info[i].task)
++ local_debuggerinfo =
++ kgdb_info[i].debuggerinfo;
++ }
++ }
++
++ /* All threads that don't have debuggerinfo should be
++ * in __schedule() sleeping, since all other CPUs
++ * are in kgdb_wait, and thus have debuggerinfo. */
++ if (kgdb_ops->shadowth &&
++ kgdb_usethreadid >= pid_max + num_online_cpus()) {
++ shadowregs = kgdb_shadow_regs(linux_regs,
++ kgdb_usethreadid -
++ pid_max -
++ num_online_cpus
++ ());
++ if (!shadowregs) {
++ error_packet(remcom_out_buffer,
++ -EINVAL);
++ break;
++ }
++ regs_to_gdb_regs(gdb_regs, shadowregs);
++ } else if (local_debuggerinfo)
++ regs_to_gdb_regs(gdb_regs, local_debuggerinfo);
++ else {
++ /* Pull stuff saved during
++ * switch_to; nothing else is
++ * accessible (or even particularly relevant).
++ * This should be enough for a stack trace. */
++ sleeping_thread_to_gdb_regs(gdb_regs, thread);
++ }
++ kgdb_mem2hex((char *)gdb_regs, remcom_out_buffer,
++ NUMREGBYTES);
++ break;
++
++ /* set the value of the CPU registers - return OK */
++ case 'G':
++ kgdb_hex2mem(&remcom_in_buffer[1], (char *)gdb_regs,
++ NUMREGBYTES);
++
++ if (kgdb_usethread && kgdb_usethread != current)
++ error_packet(remcom_out_buffer, -EINVAL);
++ else {
++ gdb_regs_to_regs(gdb_regs, linux_regs);
++ strcpy(remcom_out_buffer, "OK");
++ }
++ break;
++
++ /* mAA..AA,LLLL Read LLLL bytes at address AA..AA */
++ case 'm':
++ ptr = &remcom_in_buffer[1];
++ if (kgdb_hex2long(&ptr, &addr) > 0 && *ptr++ == ',' &&
++ kgdb_hex2long(&ptr, &length) > 0) {
++ if (IS_ERR(ptr = kgdb_mem2hex((char *)addr,
++ remcom_out_buffer,
++ length)))
++ error_packet(remcom_out_buffer,
++ PTR_ERR(ptr));
++ } else
++ error_packet(remcom_out_buffer, -EINVAL);
++ break;
++
++ /* MAA..AA,LLLL: Write LLLL bytes at address AA..AA */
++ case 'M':
++ if (IS_ERR(ptr = write_mem_msg(0)))
++ error_packet(remcom_out_buffer, PTR_ERR(ptr));
++ else
++ strcpy(remcom_out_buffer, "OK");
++ break;
++ /* XAA..AA,LLLL: Write LLLL bytes at address AA..AA */
++ case 'X':
++ if (IS_ERR(ptr = write_mem_msg(1)))
++ error_packet(remcom_out_buffer, PTR_ERR(ptr));
++ else
++ strcpy(remcom_out_buffer, "OK");
++ break;
++
++ /* kill or detach. KGDB should treat this like a
++ * continue.
++ */
++ case 'D':
++ if ((error = remove_all_break()) < 0) {
++ error_packet(remcom_out_buffer, error);
++ } else {
++ strcpy(remcom_out_buffer, "OK");
++ kgdb_connected = 0;
++ }
++ put_packet(remcom_out_buffer);
++ goto default_handle;
++
++ case 'k':
++ /* Don't care about error from remove_all_break */
++ remove_all_break();
++ kgdb_connected = 0;
++ goto default_handle;
++
++ /* Reboot */
++ case 'R':
++ /* For now, only honor R0 */
++ if (strcmp(remcom_in_buffer, "R0") == 0) {
++ printk(KERN_CRIT "Executing reboot\n");
++ strcpy(remcom_out_buffer, "OK");
++ put_packet(remcom_out_buffer);
++ emergency_sync();
++ /* Execution should not return from
++ * machine_restart()
++ */
++ machine_restart(NULL);
++ kgdb_connected = 0;
++ goto default_handle;
++ }
++
++ /* query */
++ case 'q':
++ switch (remcom_in_buffer[1]) {
++ case 's':
++ case 'f':
++ if (memcmp(remcom_in_buffer + 2, "ThreadInfo",
++ 10)) {
++ error_packet(remcom_out_buffer,
++ -EINVAL);
++ break;
++ }
++
++ /*
++ * If we have not yet completed in
++ * pidhash_init() there isn't much we
++ * can give back.
++ */
++ if (last_pid == 0) {
++ if (remcom_in_buffer[1] == 'f')
++ strcpy(remcom_out_buffer,
++ "m0000000000000001");
++ break;
++ }
++
++ if (remcom_in_buffer[1] == 'f') {
++ threadid = 1;
++ }
++ remcom_out_buffer[0] = 'm';
++ ptr = remcom_out_buffer + 1;
++ for (i = 0; i < 17 && threadid < pid_max +
++ numshadowth; threadid++) {
++ thread = getthread(linux_regs,
++ threadid);
++ if (thread) {
++ int_to_threadref(&thref,
++ threadid);
++ pack_threadid(ptr, &thref);
++ ptr += 16;
++ *(ptr++) = ',';
++ i++;
++ }
++ }
++ *(--ptr) = '\0';
++ break;
++
++ case 'C':
++ /* Current thread id */
++ strcpy(remcom_out_buffer, "QC");
++
++ threadid = shadow_pid(current->pid);
++
++ int_to_threadref(&thref, threadid);
++ pack_threadid(remcom_out_buffer + 2, &thref);
++ break;
++ case 'T':
++ if (memcmp(remcom_in_buffer + 1,
++ "ThreadExtraInfo,", 16)) {
++ error_packet(remcom_out_buffer,
++ -EINVAL);
++ break;
++ }
++ threadid = 0;
++ ptr = remcom_in_buffer + 17;
++ kgdb_hex2long(&ptr, &threadid);
++ if (!getthread(linux_regs, threadid)) {
++ error_packet(remcom_out_buffer,
++ -EINVAL);
++ break;
++ }
++ if (threadid < pid_max) {
++ kgdb_mem2hex(getthread(linux_regs,
++ threadid)->comm,
++ remcom_out_buffer, 16);
++ } else if (threadid >= pid_max +
++ num_online_cpus()) {
++ kgdb_shadowinfo(linux_regs,
++ remcom_out_buffer,
++ threadid - pid_max -
++ num_online_cpus());
++ } else {
++ static char tmpstr[23 +
++ BUF_THREAD_ID_SIZE];
++ sprintf(tmpstr, "Shadow task %d"
++ " for pid 0",
++ (int)(threadid - pid_max));
++ kgdb_mem2hex(tmpstr, remcom_out_buffer,
++ strlen(tmpstr));
++ }
++ break;
++ }
++ break;
++
++ /* task related */
++ case 'H':
++ switch (remcom_in_buffer[1]) {
++ case 'g':
++ ptr = &remcom_in_buffer[2];
++ kgdb_hex2long(&ptr, &threadid);
++ thread = getthread(linux_regs, threadid);
++ if (!thread && threadid > 0) {
++ error_packet(remcom_out_buffer,
++ -EINVAL);
++ break;
++ }
++ kgdb_usethread = thread;
++ kgdb_usethreadid = threadid;
++ strcpy(remcom_out_buffer, "OK");
++ break;
++
++ case 'c':
++ ptr = &remcom_in_buffer[2];
++ kgdb_hex2long(&ptr, &threadid);
++ if (!threadid) {
++ kgdb_contthread = NULL;
++ } else {
++ thread = getthread(linux_regs,
++ threadid);
++ if (!thread && threadid > 0) {
++ error_packet(remcom_out_buffer,
++ -EINVAL);
++ break;
++ }
++ kgdb_contthread = thread;
++ }
++ strcpy(remcom_out_buffer, "OK");
++ break;
++ }
++ break;
++
++ /* Query thread status */
++ case 'T':
++ ptr = &remcom_in_buffer[1];
++ kgdb_hex2long(&ptr, &threadid);
++ thread = getthread(linux_regs, threadid);
++ if (thread)
++ strcpy(remcom_out_buffer, "OK");
++ else
++ error_packet(remcom_out_buffer, -EINVAL);
++ break;
++ /* Since GDB-5.3, it's been drafted that '0' is a software
++ * breakpoint, '1' is a hardware breakpoint, so let's do
++ * that.
++ */
++ case 'z':
++ case 'Z':
++ bpt_type = &remcom_in_buffer[1];
++ ptr = &remcom_in_buffer[2];
++
++ if (kgdb_ops->set_hw_breakpoint && *bpt_type >= '1') {
++ /* Unsupported */
++ if (*bpt_type > '4')
++ break;
++ } else if (*bpt_type != '0' && *bpt_type != '1')
++ /* Unsupported. */
++ break;
++ /* Test if this is a hardware breakpoint, and
++ * if we support it. */
++ if (*bpt_type == '1' &&
++ !kgdb_ops->flags & KGDB_HW_BREAKPOINT)
++ /* Unsupported. */
++ break;
++
++ if (*(ptr++) != ',') {
++ error_packet(remcom_out_buffer, -EINVAL);
++ break;
++ } else if (kgdb_hex2long(&ptr, &addr)) {
++ if (*(ptr++) != ',' ||
++ !kgdb_hex2long(&ptr, &length)) {
++ error_packet(remcom_out_buffer,
++ -EINVAL);
++ break;
++ }
++ } else {
++ error_packet(remcom_out_buffer, -EINVAL);
++ break;
++ }
++
++ if (remcom_in_buffer[0] == 'Z' && *bpt_type == '0')
++ error = kgdb_set_sw_break(addr);
++ else if (remcom_in_buffer[0] == 'Z' && *bpt_type == '1')
++ error = kgdb_set_hw_break(addr);
++ else if (remcom_in_buffer[0] == 'z' && *bpt_type == '0')
++ error = kgdb_remove_sw_break(addr);
++ else if (remcom_in_buffer[0] == 'z' && *bpt_type == '1')
++ error = kgdb_remove_hw_break(addr);
++ else if (remcom_in_buffer[0] == 'Z')
++ error = kgdb_ops->set_hw_breakpoint(addr,
++ (int)length,
++ *bpt_type);
++ else if (remcom_in_buffer[0] == 'z')
++ error = kgdb_ops->remove_hw_breakpoint(addr,
++ (int)
++ length,
++ *bpt_type);
++
++ if (error == 0)
++ strcpy(remcom_out_buffer, "OK");
++ else
++ error_packet(remcom_out_buffer, error);
++
++ break;
++ case 'c':
++ case 's':
++ if (kgdb_contthread && kgdb_contthread != current) {
++ /* Can't switch threads in kgdb */
++ error_packet(remcom_out_buffer, -EINVAL);
++ break;
++ }
++ kgdb_activate_sw_breakpoints();
++ /* Followthrough to default processing */
++ default:
++ default_handle:
++ error = kgdb_arch_handle_exception(ex_vector, signo,
++ err_code,
++ remcom_in_buffer,
++ remcom_out_buffer,
++ linux_regs);
++
++ if (error >= 0 || remcom_in_buffer[0] == 'D' ||
++ remcom_in_buffer[0] == 'k')
++ goto kgdb_exit;
++
++ } /* switch */
++
++ /* reply to the request */
++ put_packet(remcom_out_buffer);
++ }
++
++ kgdb_exit:
++ /* Call the I/O driver's post_exception routine if the I/O
++ * driver defined one.
++ */
++ if (kgdb_io_ops.post_exception)
++ kgdb_io_ops.post_exception();
++
++ kgdb_info[processor].debuggerinfo = NULL;
++ kgdb_info[processor].task = NULL;
++ atomic_set(&procindebug[processor], 0);
++
++ if (!debugger_step || !kgdb_contthread) {
++ for (i = 0; i < NR_CPUS; i++)
++ spin_unlock(&slavecpulocks[i]);
++ /* Wait till all the processors have quit
++ * from the debugger. */
++ for (i = 0; i < NR_CPUS; i++) {
++ while (atomic_read(&procindebug[i])) {
++ int j = 10; /* an arbitrary number */
++
++ while (--j)
++ cpu_relax();
++ }
++ }
++ }
++
++#ifdef CONFIG_SMP
++ /* This delay has a real purpose. The problem is that if you
++ * are single-stepping, you are sending an NMI to all the
++ * other processors to stop them. Interrupts come in, but
++ * don't get handled. Then you let them go just long enough
++ * to get into their interrupt routines and use up some stack.
++ * You stop them again, and then do the same thing. After a
++ * while you blow the stack on the other processors. This
++ * delay gives some time for interrupts to be cleared out on
++ * the other processors.
++ */
++ if (debugger_step)
++ mdelay(2);
++#endif
++kgdb_restore:
++ /* Free debugger_active */
++ atomic_set(&debugger_active, 0);
++ local_irq_restore(flags);
++
++ return error;
++}
++
++/*
++ * GDB places a breakpoint at this function to know dynamically
++ * loaded objects. It's not defined static so that only one instance with this
++ * name exists in the kernel.
++ */
++
++int module_event(struct notifier_block *self, unsigned long val, void *data)
++{
++ return 0;
++}
++
++static struct notifier_block kgdb_module_load_nb = {
++ .notifier_call = module_event,
++};
++
++void kgdb_nmihook(int cpu, void *regs)
++{
++#ifdef CONFIG_SMP
++ if (!atomic_read(&procindebug[cpu]) && atomic_read(&debugger_active) != (cpu + 1))
++ kgdb_wait((struct pt_regs *)regs);
++#endif
++}
++
++/*
++ * This is called when a panic happens. All we need to do is
++ * breakpoint().
++ */
++static int kgdb_panic_notify(struct notifier_block *self, unsigned long cmd,
++ void *ptr)
++{
++ breakpoint();
++
++ return 0;
++}
++
++static struct notifier_block kgdb_panic_notifier = {
++ .notifier_call = kgdb_panic_notify,
++};
++
++/*
++ * Initialization that needs to be done in either of our entry points.
++ */
++static void __init kgdb_internal_init(void)
++{
++ int i;
++
++ /* Initialize our spinlocks. */
++ for (i = 0; i < NR_CPUS; i++)
++ spin_lock_init(&slavecpulocks[i]);
++
++ for (i = 0; i < MAX_BREAKPOINTS; i++)
++ kgdb_break[i].state = bp_none;
++
++ /* Initialize the I/O handles */
++ memset(&kgdb_io_ops_prev, 0, sizeof(kgdb_io_ops_prev));
++
++ /* We can't do much if this fails */
++ register_module_notifier(&kgdb_module_load_nb);
++
++ kgdb_initialized = 1;
++}
++
++static void kgdb_register_for_panic(void)
++{
++ /* Register for panics(). */
++ /* The registration is done in the kgdb_register_for_panic
++ * routine because KGDB should not try to handle a panic when
++ * there are no kgdb_io_ops setup. It is assumed that the
++ * kgdb_io_ops are setup at the time this method is called.
++ */
++ if (!kgdb_from_module_registered) {
++ atomic_notifier_chain_register(&panic_notifier_list,
++ &kgdb_panic_notifier);
++ kgdb_from_module_registered = 1;
++ }
++}
++
++static void kgdb_unregister_for_panic(void)
++{
++ /* When this routine is called KGDB should unregister from the
++ * panic handler and clean up, making sure it is not handling any
++ * break exceptions at the time.
++ */
++ if (kgdb_from_module_registered) {
++ kgdb_from_module_registered = 0;
++ atomic_notifier_chain_unregister(&panic_notifier_list,
++ &kgdb_panic_notifier);
++ }
++}
++
++int kgdb_register_io_module(struct kgdb_io *local_kgdb_io_ops)
++{
++
++ if (kgdb_connected) {
++ printk(KERN_ERR "kgdb: Cannot load I/O module while KGDB "
++ "connected.\n");
++ return -EINVAL;
++ }
++
++ /* Save the old values so they can be restored */
++ if (kgdb_io_handler_cnt >= MAX_KGDB_IO_HANDLERS) {
++ printk(KERN_ERR "kgdb: No more I/O handles available.\n");
++ return -EINVAL;
++ }
++
++ /* Check to see if there is an existing driver and if so save its
++ * values. Also check to make sure the same driver was not trying
++ * to re-register.
++ */
++ if (kgdb_io_ops.read_char != NULL &&
++ kgdb_io_ops.read_char != local_kgdb_io_ops->read_char) {
++ memcpy(&kgdb_io_ops_prev[kgdb_io_handler_cnt],
++ &kgdb_io_ops, sizeof(struct kgdb_io));
++ kgdb_io_handler_cnt++;
++ }
++
++ /* Initialize the io values for this module */
++ memcpy(&kgdb_io_ops, local_kgdb_io_ops, sizeof(struct kgdb_io));
++
++ /* Make the call to register kgdb if is not initialized */
++ kgdb_register_for_panic();
++
++ return 0;
++}
++
++void kgdb_unregister_io_module(struct kgdb_io *local_kgdb_io_ops)
++{
++ int i;
++
++ /* Unregister KGDB if there were no other prior io hooks, else
++ * restore the io hooks.
++ */
++ if (kgdb_io_handler_cnt > 0 && kgdb_io_ops_prev[0].read_char != NULL) {
++ /* First check if the hook that is in use is the one being
++ * removed */
++ if (kgdb_io_ops.read_char == local_kgdb_io_ops->read_char) {
++ /* Set 'i' to the value of where the list should be
++ * shifed */
++ i = kgdb_io_handler_cnt - 1;
++ memcpy(&kgdb_io_ops, &kgdb_io_ops_prev[i],
++ sizeof(struct kgdb_io));
++ } else {
++ /* Simple case to remove an entry for an I/O handler
++ * that is not in use */
++ for (i = 0; i < kgdb_io_handler_cnt; i++) {
++ if (kgdb_io_ops_prev[i].read_char ==
++ local_kgdb_io_ops->read_char)
++ break;
++ }
++ }
++
++ /* Shift all the entries in the handler array so it is
++ * ordered from oldest to newest.
++ */
++ kgdb_io_handler_cnt--;
++ for (; i < kgdb_io_handler_cnt; i++) {
++ memcpy(&kgdb_io_ops_prev[i], &kgdb_io_ops_prev[i + 1],
++ sizeof(struct kgdb_io));
++ }
++ /* Handle the case if we are on the last element and set it
++ * to NULL; */
++ memset(&kgdb_io_ops_prev[kgdb_io_handler_cnt], 0,
++ sizeof(struct kgdb_io));
++
++ if (kgdb_connected)
++ printk(KERN_ERR "kgdb: WARNING: I/O method changed "
++ "while kgdb was connected state.\n");
++ } else {
++ /* KGDB is no longer able to communicate out, so
++ * unregister our hooks and reset state. */
++ kgdb_unregister_for_panic();
++ if (kgdb_connected) {
++ printk(KERN_CRIT "kgdb: I/O module was unloaded while "
++ "a debugging session was running. "
++ "KGDB will be reset.\n");
++ if (remove_all_break() < 0)
++ printk(KERN_CRIT "kgdb: Reset failed.\n");
++ kgdb_connected = 0;
++ }
++ memset(&kgdb_io_ops, 0, sizeof(struct kgdb_io));
++ }
++}
++
++/*
++ * There are times we need to call a tasklet to cause a breakpoint
++ * as calling breakpoint() at that point might be fatal. We have to
++ * check that the exception stack is setup, as tasklets may be scheduled
++ * prior to this. When that happens, it is up to the architecture to
++ * schedule this when it is safe to run.
++ */
++static void kgdb_tasklet_bpt(unsigned long ing)
++{
++ if(CHECK_EXCEPTION_STACK())
++ breakpoint();
++}
++
++DECLARE_TASKLET(kgdb_tasklet_breakpoint, kgdb_tasklet_bpt, 0);
++
++/*
++ * This function can be called very early, either via early_param() or
++ * an explicit breakpoint() early on.
++ */
++static void __init kgdb_early_entry(void)
++{
++ /*
++ * Don't try and do anything until the architecture is able to
++ * setup the exception stack. In this case, it is up to the
++ * architecture to hook in and look at us when they are ready.
++ */
++ if(!CHECK_EXCEPTION_STACK()) {
++ kgdb_initialized = -1;
++ tasklet_schedule(&kgdb_tasklet_breakpoint);
++ return;
++ }
++
++ /* Let the architecture do any setup that it needs to. */
++ kgdb_arch_init();
++
++ /* Now try the I/O. */
++ /* For early entry kgdb_io_ops.init must be defined */
++ if (!kgdb_io_ops.init || kgdb_io_ops.init()) {
++ /* Try again later. */
++ kgdb_initialized = -1;
++ return;
++ }
++
++ /* Finish up. */
++ kgdb_internal_init();
++
++ /* KGDB can assume that if kgdb_io_ops.init was defined that the
++ * panic registion should be performed at this time. This means
++ * kgdb_io_ops.init did not come from a kernel module and was
++ * initialized statically by a built in.
++ */
++ if (kgdb_io_ops.init)
++ kgdb_register_for_panic();
++}
++
++/*
++ * This function will always be invoked to make sure that KGDB will grab
++ * what it needs to so that if something happens while the system is
++ * running, KGDB will get involved. If kgdb_early_entry() has already
++ * been invoked, there is little we need to do.
++ */
++static int __init kgdb_late_entry(void)
++{
++ int need_break = 0;
++
++ /* If kgdb_initialized is -1 then we were passed kgdbwait. */
++ if (kgdb_initialized == -1)
++ need_break = 1;
++
++ /*
++ * If we haven't tried to initialize KGDB yet, we need to call
++ * kgdb_arch_init before moving onto the I/O.
++ */
++ if (!kgdb_initialized)
++ kgdb_arch_init();
++
++ if (kgdb_initialized != 1) {
++ if (kgdb_io_ops.init && kgdb_io_ops.init()) {
++ /* When KGDB allows I/O via modules and the core
++ * I/O init fails KGDB must default to defering the
++ * I/O setup, and appropriately print an error about
++ * it.
++ */
++ printk(KERN_ERR "kgdb: Could not setup core I/O "
++ "for KGDB.\n");
++ printk(KERN_INFO "kgdb: Defering I/O setup to kernel "
++ "module.\n");
++ memset(&kgdb_io_ops, 0, sizeof(struct kgdb_io));
++ }
++
++ kgdb_internal_init();
++
++ /* KGDB can assume that if kgdb_io_ops.init was defined that
++ * panic registion should be performed at this time. This means
++ * kgdb_io_ops.init did not come from a kernel module and was
++ * initialized statically by a built in.
++ */
++ if (kgdb_io_ops.init)
++ kgdb_register_for_panic();
++ }
++
++ /* Registering to reboot notifier list*/
++ register_reboot_notifier(&kgdb_reboot_notifier);
++
++ /* Now do any late init of the I/O. */
++ if (kgdb_io_ops.late_init)
++ kgdb_io_ops.late_init();
++
++ if (need_break) {
++ printk(KERN_CRIT "kgdb: Waiting for connection from remote"
++ " gdb...\n");
++ breakpoint();
++ }
++
++ return 0;
++}
++
++late_initcall(kgdb_late_entry);
++
++/*
++ * 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 (kgdb_initialized != 1) {
++ kgdb_early_entry();
++ if (kgdb_initialized == 1)
++ printk(KERN_CRIT "Waiting for connection from remote "
++ "gdb...\n");
++ else {
++ printk(KERN_CRIT "KGDB cannot initialize I/O yet.\n");
++ return;
++ }
++ }
++
++ atomic_set(&kgdb_setting_breakpoint, 1);
++ wmb();
++ BREAKPOINT();
++ wmb();
++ atomic_set(&kgdb_setting_breakpoint, 0);
++}
++
++EXPORT_SYMBOL(breakpoint);
++
++#ifdef CONFIG_MAGIC_SYSRQ
++static void sysrq_handle_gdb(int key, struct pt_regs *pt_regs,
++ struct tty_struct *tty)
++{
++ printk("Entering GDB stub\n");
++ breakpoint();
++}
++static struct sysrq_key_op sysrq_gdb_op = {
++ .handler = sysrq_handle_gdb,
++ .help_msg = "Gdb",
++ .action_msg = "GDB",
++};
++
++static int gdb_register_sysrq(void)
++{
++ printk("Registering GDB sysrq handler\n");
++ register_sysrq_key('g', &sysrq_gdb_op);
++ return 0;
++}
++
++module_init(gdb_register_sysrq);
++#endif
++
++static int kgdb_notify_reboot(struct notifier_block *this,
++ unsigned long code, void *x)
++{
++
++ unsigned long flags;
++
++ /* If we're debugging, or KGDB has not connected, don't try
++ * and print. */
++ if (!kgdb_connected || atomic_read(&debugger_active) != 0)
++ return 0;
++ if ((code == SYS_RESTART) || (code == SYS_HALT) || (code == SYS_POWER_OFF)){
++ local_irq_save(flags);
++ put_packet("X00");
++ local_irq_restore(flags);
++ }
++ return NOTIFY_DONE;
++}
++
++#ifdef CONFIG_KGDB_CONSOLE
++void kgdb_console_write(struct console *co, const char *s, unsigned count)
++{
++ unsigned long flags;
++
++ /* If we're debugging, or KGDB has not connected, don't try
++ * and print. */
++ if (!kgdb_connected || atomic_read(&debugger_active) != 0)
++ return;
++
++ local_irq_save(flags);
++ kgdb_msg_write(s, count);
++ local_irq_restore(flags);
++}
++
++struct console kgdbcons = {
++ .name = "kgdb",
++ .write = kgdb_console_write,
++ .flags = CON_PRINTBUFFER | CON_ENABLED,
++};
++static int __init kgdb_console_init(void)
++{
++ register_console(&kgdbcons);
++ return 0;
++}
++
++console_initcall(kgdb_console_init);
++#endif
++
++static int __init opt_kgdb_enter(char *str)
++{
++ /* We've already done this by an explicit breakpoint() call. */
++ if (kgdb_initialized)
++ return 0;
++
++ /* Call breakpoint() which will take care of init. */
++ breakpoint();
++
++ return 0;
++}
++
++early_param("kgdbwait", opt_kgdb_enter);
+diff -rupN -X ../client-cleanup/dontdiff linux-2.6.18/kernel/kgdbarchlib.c linux-2.6.18.kgdb/kernel/kgdbarchlib.c
+--- linux-2.6.18/kernel/kgdbarchlib.c 1970-01-01 03:00:00.000000000 +0300
++++ linux-2.6.18.kgdb/kernel/kgdbarchlib.c 2008-06-10 16:18:58.000000000 +0400
+@@ -0,0 +1,198 @@
++#include <linux/kgdb.h>
++
++struct kgdb_arch *kgdb_ops = &arch_kgdb_ops;
++
++/**
++ * kgdb_arch_init - Perform any architecture specific initalization.
++ *
++ * RETURN:
++ * The return value is ignored.
++ *
++ * This function will handle the initalization of any architecture
++ * specific hooks.
++ */
++int __attribute__ ((weak))
++ kgdb_arch_init(void)
++{
++ return 0;
++}
++
++/**
++ * kgdb_disable_hw_debug - Disable hardware debugging while we in kgdb.
++ * @regs: Current &struct pt_regs.
++ *
++ * This function will be called if the particular architecture must
++ * disable hardware debugging while it is processing gdb packets or
++ * handling exception.
++ */
++void __attribute__ ((weak))
++ kgdb_disable_hw_debug(struct pt_regs *regs)
++{
++}
++
++/*
++ * Skip an int3 exception when it occurs after a breakpoint has been
++ * removed. Backtrack eip by 1 since the int3 would have caused it to
++ * increment by 1.
++ */
++int __attribute__ ((weak))
++ kgdb_skipexception(int exception, struct pt_regs *regs)
++{
++ return 0;
++}
++
++/**
++ * kgdb_set_hw_break - Set a hardware breakpoint at @addr.
++ * @addr: The address to set a hardware breakpoint at.
++ */
++int __attribute__ ((weak))
++ kgdb_set_hw_break(unsigned long addr)
++{
++ return 0;
++}
++
++/**
++ * kgdb_remove_hw_break - Remove a hardware breakpoint at @addr.
++ * @addr: The address to remove a hardware breakpoint from.
++ */
++int __attribute__ ((weak))
++ kgdb_remove_hw_break(unsigned long addr)
++{
++ return 0;
++}
++
++/**
++ * kgdb_remove_all_hw_break - Clear all hardware breakpoints.
++ */
++void __attribute__ ((weak))
++ kgdb_remove_all_hw_break(void)
++{
++}
++
++/**
++ * kgdb_correct_hw_break - Correct hardware breakpoints.
++ *
++ * A hook to allow for changes to the hardware breakpoint, called
++ * after a single step (s) or continue (c) packet, and once we're about
++ * to let the kernel continue running.
++ *
++ * This is used to set the hardware breakpoint registers for all the
++ * slave cpus on an SMP configuration. This must be called after any
++ * changes are made to the hardware breakpoints (such as by a single
++ * step (s) or continue (c) packet. This is only required on
++ * architectures that support SMP and every processor has its own set
++ * of breakpoint registers.
++ */
++void __attribute__ ((weak))
++ kgdb_correct_hw_break(void)
++{
++}
++
++/**
++ * kgdb_post_master_code - Save error vector/code numbers.
++ * @regs: Original pt_regs.
++ * @e_vector: Original error vector.
++ * @err_code: Original error code.
++ *
++ * This is needed on architectures which support SMP and KGDB.
++ * This function is called after all the slave cpus have been put
++ * to a know spin state and the master CPU has control over KGDB.
++ */
++
++void __attribute__ ((weak))
++ kgdb_post_master_code(struct pt_regs *regs, int e_vector, int err_code)
++{
++}
++
++/**
++ * kgdb_roundup_cpus - Get other CPUs into a holding pattern
++ * @flags: Current IRQ state
++ *
++ * On SMP systems, we need to get the attention of the other CPUs
++ * and get them be in a known state. This should do what is needed
++ * to get the other CPUs to call kgdb_wait(). Note that on some arches,
++ * the NMI approach is not used for rounding up all the CPUs. For example,
++ * in case of MIPS, smp_call_function() is used to roundup CPUs. In
++ * this case, we have to make sure that interrupts are enabled before
++ * calling smp_call_function(). The argument to this function is
++ * the flags that will be used when restoring the interrupts. There is
++ * local_irq_save() call before kgdb_roundup_cpus().
++ */
++void __attribute__ ((weak))
++ kgdb_roundup_cpus(unsigned long flags)
++{
++}
++
++/**
++ * kgdb_shadowinfo - Get shadowed information on @threadid.
++ * @regs: The &struct pt_regs of the current process.
++ * @buffer: A buffer of %BUFMAX size.
++ * @threadid: The thread id of the shadowed process to get information on.
++ */
++void __attribute__ ((weak))
++ kgdb_shadowinfo(struct pt_regs *regs, char *buffer, unsigned threadid)
++{
++}
++
++/**
++ * kgdb_get_shadow_thread - Get the shadowed &task_struct of @threadid.
++ * @regs: The &struct pt_regs of the current thread.
++ * @threadid: The thread id of the shadowed process to get information on.
++ *
++ * RETURN:
++ * This returns a pointer to the &struct task_struct of the shadowed
++ * thread, @threadid.
++ */
++struct task_struct __attribute__ ((weak))
++ * kgdb_get_shadow_thread(struct pt_regs *regs, int threadid)
++{
++ return NULL;
++}
++
++/**
++ * kgdb_shadow_regs - Return the shadowed registers of @threadid.
++ * @regs: The &struct pt_regs of the current thread.
++ * @threadid: The thread id we want the &struct pt_regs for.
++ *
++ * RETURN:
++ * The a pointer to the &struct pt_regs of the shadowed thread @threadid.
++ */
++struct pt_regs __attribute__ ((weak))
++ * kgdb_shadow_regs(struct pt_regs *regs, int threadid)
++{
++ return NULL;
++}
++
++int __attribute__ ((weak))
++ kgdb_validate_break_address(unsigned long addr)
++{
++ int error = 0;
++ char tmp_variable[BREAK_INSTR_SIZE];
++ error = kgdb_get_mem((char *)addr, tmp_variable, BREAK_INSTR_SIZE);
++ return error;
++}
++
++int __attribute__ ((weak))
++ kgdb_arch_set_breakpoint(unsigned long addr, char *saved_instr)
++{
++ int error = 0;
++ if ((error = kgdb_get_mem((char *)addr,
++ saved_instr, BREAK_INSTR_SIZE)) < 0)
++ return error;
++
++ if ((error = kgdb_set_mem((char *)addr, kgdb_ops->gdb_bpt_instr,
++ BREAK_INSTR_SIZE)) < 0)
++ return error;
++ return 0;
++}
++
++int __attribute__ ((weak))
++ kgdb_arch_remove_breakpoint(unsigned long addr, char *bundle)
++{
++
++ int error = 0;
++ if ((error =kgdb_set_mem((char *)addr, (char *)bundle,
++ BREAK_INSTR_SIZE)) < 0)
++ return error;
++ return 0;
++}
+diff -rupN -X ../client-cleanup/dontdiff linux-2.6.18/kernel/module.c linux-2.6.18.kgdb/kernel/module.c
+--- linux-2.6.18/kernel/module.c 2006-09-20 07:42:06.000000000 +0400
++++ linux-2.6.18.kgdb/kernel/module.c 2008-06-10 16:20:07.000000000 +0400
+@@ -64,6 +64,7 @@ static DEFINE_SPINLOCK(modlist_lock);
+ /* List of modules, protected by module_mutex AND modlist_lock */
+ static DEFINE_MUTEX(module_mutex);
+ static LIST_HEAD(modules);
++static DECLARE_MUTEX(notify_mutex);
+
+ static BLOCKING_NOTIFIER_HEAD(module_notify_list);
+
+@@ -700,6 +701,12 @@ sys_delete_module(const char __user *nam
+ if (ret != 0)
+ goto out;
+
++ down(¬ify_mutex);
++ blocking_notifier_call_chain(&module_notify_list, MODULE_STATE_GOING,
++ mod);
++ up(¬ify_mutex);
++
++
+ /* Never wait if forced. */
+ if (!forced && module_refcount(mod) != 0)
+ wait_for_zero_refcount(mod);
+@@ -712,6 +719,11 @@ sys_delete_module(const char __user *nam
+ }
+ free_module(mod);
+
++ down(¬ify_mutex);
++ blocking_notifier_call_chain(&module_notify_list, MODULE_STATE_GONE,
++ NULL);
++ up(¬ify_mutex);
++
+ out:
+ mutex_unlock(&module_mutex);
+ return ret;
+@@ -1112,6 +1124,11 @@ static void free_module(struct module *m
+ /* Arch-specific cleanup. */
+ module_arch_cleanup(mod);
+
++#ifdef CONFIG_KGDB
++ /* kgdb info */
++ vfree(mod->mod_sections);
++#endif
++
+ /* Module unload stuff */
+ module_unload_free(mod);
+
+@@ -1371,6 +1388,31 @@ static void setup_modinfo(struct module
+ }
+ }
+
++#ifdef CONFIG_KGDB
++int add_modsects (struct module *mod, Elf_Ehdr *hdr, Elf_Shdr *sechdrs, const
++ char *secstrings)
++{
++ int i;
++
++ mod->num_sections = hdr->e_shnum - 1;
++ mod->mod_sections = vmalloc((hdr->e_shnum - 1)*
++ sizeof (struct mod_section));
++
++ if (mod->mod_sections == NULL) {
++ return -ENOMEM;
++ }
++
++ for (i = 1; i < hdr->e_shnum; i++) {
++ mod->mod_sections[i - 1].address = (void *)sechdrs[i].sh_addr;
++ strncpy(mod->mod_sections[i - 1].name, secstrings +
++ sechdrs[i].sh_name, MAX_SECTNAME);
++ mod->mod_sections[i - 1].name[MAX_SECTNAME] = '\0';
++ }
++
++ return 0;
++}
++#endif
++
+ #ifdef CONFIG_KALLSYMS
+ int is_exported(const char *name, const struct module *mod)
+ {
+@@ -1782,6 +1824,12 @@ static struct module *load_module(void _
+
+ add_kallsyms(mod, sechdrs, symindex, strindex, secstrings);
+
++#ifdef CONFIG_KGDB
++ if ((err = add_modsects(mod, hdr, sechdrs, secstrings)) < 0) {
++ goto nomodsectinfo;
++ }
++#endif
++
+ err = module_finalize(hdr, sechdrs, mod);
+ if (err < 0)
+ goto cleanup;
+@@ -1842,6 +1890,11 @@ static struct module *load_module(void _
+ arch_cleanup:
+ module_arch_cleanup(mod);
+ cleanup:
++
++#ifdef CONFIG_KGDB
++nomodsectinfo:
++ vfree(mod->mod_sections);
++#endif
+ module_unload_free(mod);
+ module_free(mod, mod->module_init);
+ free_core:
+@@ -1913,6 +1966,10 @@ sys_init_module(void __user *umod,
+ /* Init routine failed: abort. Try to protect us from
+ buggy refcounters. */
+ mod->state = MODULE_STATE_GOING;
++ down(¬ify_mutex);
++ blocking_notifier_call_chain(&module_notify_list, MODULE_STATE_GOING,
++ mod);
++ up(¬ify_mutex);
+ synchronize_sched();
+ if (mod->unsafe)
+ printk(KERN_ERR "%s: module is now stuck!\n",
+diff -rupN -X ../client-cleanup/dontdiff linux-2.6.18/kernel/sched.c linux-2.6.18.kgdb/kernel/sched.c
+--- linux-2.6.18/kernel/sched.c 2006-09-20 07:42:06.000000000 +0400
++++ linux-2.6.18.kgdb/kernel/sched.c 2008-06-10 16:18:58.000000000 +0400
+@@ -52,6 +52,7 @@
+ #include <linux/acct.h>
+ #include <linux/kprobes.h>
+ #include <linux/delayacct.h>
++#include <linux/kgdb.h>
+ #include <asm/tlb.h>
+
+ #include <asm/unistd.h>
+@@ -6790,6 +6791,9 @@ void __might_sleep(char *file, int line)
+ #ifdef in_atomic
+ static unsigned long prev_jiffy; /* ratelimiting */
+
++ if (atomic_read(&debugger_active))
++ return;
++
+ if ((in_atomic() || irqs_disabled()) &&
+ system_state == SYSTEM_RUNNING && !oops_in_progress) {
+ if (time_before(jiffies, prev_jiffy + HZ) && prev_jiffy)
+diff -rupN -X ../client-cleanup/dontdiff linux-2.6.18/kernel/softlockup.c linux-2.6.18.kgdb/kernel/softlockup.c
+--- linux-2.6.18/kernel/softlockup.c 2006-09-20 07:42:06.000000000 +0400
++++ linux-2.6.18.kgdb/kernel/softlockup.c 2008-06-10 16:20:11.000000000 +0400
+@@ -13,6 +13,7 @@
+ #include <linux/kthread.h>
+ #include <linux/notifier.h>
+ #include <linux/module.h>
++#include <linux/kgdb.h>
+
+ static DEFINE_SPINLOCK(print_lock);
+
+@@ -37,6 +38,9 @@ static struct notifier_block panic_block
+ void touch_softlockup_watchdog(void)
+ {
+ __raw_get_cpu_var(touch_timestamp) = jiffies;
++#ifdef CONFIG_KGDB
++ atomic_set(&kgdb_sync_softlockup[raw_smp_processor_id()], 0);
++#endif
+ }
+ EXPORT_SYMBOL(touch_softlockup_watchdog);
+
+diff -rupN -X ../client-cleanup/dontdiff linux-2.6.18/kernel/timer.c linux-2.6.18.kgdb/kernel/timer.c
+--- linux-2.6.18/kernel/timer.c 2006-09-20 07:42:06.000000000 +0400
++++ linux-2.6.18.kgdb/kernel/timer.c 2008-06-10 16:20:11.000000000 +0400
+@@ -34,6 +34,7 @@
+ #include <linux/cpu.h>
+ #include <linux/syscalls.h>
+ #include <linux/delay.h>
++#include <linux/kgdb.h>
+
+ #include <asm/uaccess.h>
+ #include <asm/unistd.h>
+@@ -1257,7 +1258,11 @@ static void run_timer_softirq(struct sof
+ */
+ void run_local_timers(void)
+ {
++ int this_cpu = smp_processor_id();
+ raise_softirq(TIMER_SOFTIRQ);
++#ifdef CONFIG_KGDB
++ if(!atomic_read(&kgdb_sync_softlockup[this_cpu]))
++#endif
+ softlockup_tick();
+ }
+
+diff -rupN -X ../client-cleanup/dontdiff linux-2.6.18/lib/Kconfig.debug linux-2.6.18.kgdb/lib/Kconfig.debug
+--- linux-2.6.18/lib/Kconfig.debug 2006-09-20 07:42:06.000000000 +0400
++++ linux-2.6.18.kgdb/lib/Kconfig.debug 2008-06-10 16:19:51.000000000 +0400
+@@ -315,7 +315,7 @@ config DEBUG_VM
+
+ config FRAME_POINTER
+ bool "Compile the kernel with frame pointers"
+- depends on DEBUG_KERNEL && (X86 || CRIS || M68K || M68KNOMMU || FRV || UML || S390)
++ depends on DEBUG_KERNEL && (X86 || CRIS || M68K || M68KNOMMU || FRV || UML || S390 || SUPERH)
+ default y if DEBUG_INFO && UML
+ help
+ If you say Y here the resulting kernel image will be slightly larger
+@@ -368,3 +368,158 @@ config RCU_TORTURE_TEST
+ at boot time (you probably don't).
+ Say M if you want the RCU torture tests to build as a module.
+ Say N if you are unsure.
++
++config WANT_EXTRA_DEBUG_INFORMATION
++ bool
++ select DEBUG_INFO
++ select FRAME_POINTER if X86 || SUPERH
++ default n
++
++config KGDB
++ bool "KGDB: kernel debugging with remote gdb"
++ select WANT_EXTRA_DEBUG_INFORMATION
++ depends on DEBUG_KERNEL && (ARM || X86 || MIPS || (SUPERH && !SUPERH64) || IA64 || X86_64 || PPC)
++ help
++ If you say Y here, it will be possible to remotely debug the
++ kernel using gdb. It is strongly suggested that you enable
++ DEBUG_INFO, and if available on your platform, FRAME_POINTER.
++ Documentation of kernel debugger available at
++ http://kgdb.sourceforge.net as well as in DocBook form
++ in Documentation/DocBook/. If unsure, say N.
++
++config KGDB_CONSOLE
++ bool "KGDB: Console messages through gdb"
++ depends on KGDB
++ help
++ If you say Y here, console messages will appear through gdb.
++ Other consoles such as tty or ttyS will continue to work as usual.
++ Note, that if you use this in conjunction with KGDB_ETH, if the
++ ethernet driver runs into an error condition during use with KGDB
++ it is possible to hit an infinite recusrion, causing the kernel
++ to crash, and typically reboot. For this reason, it is preferable
++ to use NETCONSOLE in conjunction with KGDB_ETH instead of
++ KGDB_CONSOLE.
++
++choice
++ prompt "Method for KGDB communication"
++ depends on KGDB
++ default KGDB_8250_NOMODULE
++ default KGDB_MPSC if SERIAL_MPSC
++ default KGDB_CPM_UART if (8xx || 8260)
++ default KGDB_SIBYTE if SIBYTE_SB1xxx_SOC
++ 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
++ (should your hardware have an 8250, or ns1655x style uart).
++ Another option is to use the NETPOLL framework and UDP, should
++ your ethernet card support this. Other options may exist.
++ You can elect to have one core I/O driver that is built into the
++ kernel for debugging as the kernel is booting, or using only
++ kernel modules.
++
++config KGDB_ONLY_MODULES
++ bool "KGDB: Use only kernel modules for I/O"
++ depends on MODULES
++ help
++ Use only kernel modules to configure KGDB I/O after the
++ kernel is booted.
++
++config KGDB_8250_NOMODULE
++ bool "KGDB: On generic serial port (8250)"
++ select KGDB_8250
++ help
++ Uses generic serial port (8250) to communicate with the host
++ GDB. This is independent of the normal (SERIAL_8250) driver
++ for this chipset.
++
++config KGDBOE_NOMODULE
++ bool "KGDB: On ethernet - in kernel"
++ select KGDBOE
++ select NETPOLL
++ select NETPOLL_TRAP
++ select NETPOLL_RX
++ help
++ Uses the NETPOLL API to communicate with the host GDB via UDP.
++ In order for this to work, the ethernet interface specified must
++ support the NETPOLL API, and this must be initialized at boot.
++ See the documentation for syntax.
++
++config KGDB_MPSC
++ bool "KGDB on MV64x60 MPSC"
++ depends on SERIAL_MPSC
++ help
++ Uses a Marvell GT64260B or MV64x60 Multi-Purpose Serial
++ Controller (MPSC) channel. Note that the GT64260A is not
++ supported.
++
++config KGDB_CPM_UART
++ bool "KGDB: On CPM UART"
++ depends on PPC && (CPM2 || 8xx)
++ help
++ Uses CPM UART to communicate with the host GDB.
++
++config KGDB_SIBYTE
++ bool "KGDB: On the Broadcom SWARM serial port"
++ depends on MIPS && SIBYTE_SB1xxx_SOC
++endchoice
++
++config KGDBOE
++ tristate "KGDB: On ethernet" if !KGDBOE_NOMODULE
++ depends on m && KGDB
++ select NETPOLL
++ select NETPOLL_TRAP
++ select NETPOLL_RX
++ help
++ Uses the NETPOLL API to communicate with the host GDB via UDP.
++ In order for this to work, the ethernet interface specified must
++ support the NETPOLL API, and this must be initialized at boot.
++ See the documentation for syntax.
++
++config KGDB_8250
++ tristate "KGDB: On generic serial port (8250)" if !KGDB_8250_NOMODULE
++ depends on m && KGDB_ONLY_MODULES
++ help
++ Uses generic serial port (8250) to communicate with the host
++ GDB. This is independent of the normal (SERIAL_8250) driver
++ for this chipset.
++
++config KGDB_SIMPLE_SERIAL
++ bool "Simple selection of KGDB serial port"
++ depends on KGDB_8250_NOMODULE
++ default y
++ help
++ If you say Y here, you will only have to pick the baud rate
++ and port number that you wish to use for KGDB. Note that this
++ only works on architectures that register known serial ports
++ early on. If you say N, you will have to provide, either here
++ or on the command line, the type (I/O or MMIO), IRQ and
++ address to use. If in doubt, say Y.
++
++config KGDB_BAUDRATE
++ int "Debug serial port baud rate"
++ depends on (KGDB_8250 && KGDB_SIMPLE_SERIAL)
++ default "115200"
++ help
++ gdb and the kernel stub need to agree on the baud rate to be
++ used. Standard rates from 9600 to 115200 are allowed, and this
++ may be overridden via the commandline.
++
++config KGDB_PORT_NUM
++ int "Serial port number for KGDB"
++ range 0 1 if KGDB_MPSC
++ range 0 3
++ depends on (KGDB_8250 && KGDB_SIMPLE_SERIAL) || KGDB_MPSC
++ default "1"
++ help
++ Pick the port number (0 based) for KGDB to use.
++
++config KGDB_8250_CONF_STRING
++ string "Configuration string for KGDB"
++ depends on KGDB_8250_NOMODULE && !KGDB_SIMPLE_SERIAL
++ default "io,2f8,115200,3" if X86
++ help
++ The format of this string should be <io or
++ mmio>,<address>,<baud rate>,<irq>. For example, to use the
++ serial port on an i386 box located at 0x2f8 and 115200 baud
++ on IRQ 3 at use:
++ io,2f8,115200,3
+diff -rupN -X ../client-cleanup/dontdiff linux-2.6.18/net/core/netpoll.c linux-2.6.18.kgdb/net/core/netpoll.c
+--- linux-2.6.18/net/core/netpoll.c 2006-09-20 07:42:06.000000000 +0400
++++ linux-2.6.18.kgdb/net/core/netpoll.c 2008-06-10 16:19:07.000000000 +0400
+@@ -519,7 +519,8 @@ int __netpoll_rx(struct sk_buff *skb)
+
+ np->rx_hook(np, ntohs(uh->source),
+ (char *)(uh+1),
+- ulen - sizeof(struct udphdr));
++ ulen - sizeof(struct udphdr),
++ skb);
+
+ kfree_skb(skb);
+ return 1;
+diff -rupN -X ../client-cleanup/dontdiff linux-2.6.18/scripts/dwarfh.awk linux-2.6.18.kgdb/scripts/dwarfh.awk
+--- linux-2.6.18/scripts/dwarfh.awk 1970-01-01 03:00:00.000000000 +0300
++++ linux-2.6.18.kgdb/scripts/dwarfh.awk 2008-06-10 16:19:58.000000000 +0400
+@@ -0,0 +1,19 @@
++BEGIN {
++ print "#ifndef _ELF_DWARF_H"
++ print "/* Machine generated from dwarf2.h by scripts/dwarfh.awk */"
++}
++$2 == "=" {
++ gsub(/,/, "", $3)
++ print "#define " $1 "\t " $3
++}
++$1 == "#define" {
++ print $0
++ while( index($0,"\\") == length($0)){
++ getline
++ print $0
++ }
++}
++/.*/ {}
++END {
++ print "#endif"
++}