[PATCH,RFC 2.6.14 01/15] KGDB: core infrastructure

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

 



This is the core of the KGDB stub.  It provides all of the common code,
documentation and basic Kconfig changes, as well as the common hooks.

 Documentation/DocBook/Makefile  |    2 
 Documentation/DocBook/kgdb.tmpl |  224 ++++
 MAINTAINERS                     |    9 
 include/linux/kgdb.h            |  261 +++++
 kernel/Makefile                 |    1 
 kernel/kgdb.c                   | 1819 ++++++++++++++++++++++++++++++++++++++++
 kernel/pid.c                    |   11 
 kernel/sched.c                  |    4 
 lib/Kconfig.debug               |   53 +
 9 files changed, 2382 insertions(+), 2 deletions(-)

Index: linux-2.6.14/Documentation/DocBook/kgdb.tmpl
===================================================================
--- /dev/null
+++ linux-2.6.14/Documentation/DocBook/kgdb.tmpl
@@ -0,0 +1,224 @@
+<?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>[email protected]</email>
+     </address>
+    </affiliation>
+   </author>
+  </authorgroup>
+
+  <authorgroup>
+   <author>
+    <firstname>Amit S.</firstname>
+    <surname>Kale</surname>
+    <affiliation>
+     <address>
+      <email>[email protected]</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_KGDB_ETH</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
+    <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 serial port at boot:
+    <constant>kgdb8250=io,3f8,115200,3</constant>.
+    On IA64 this could also be:
+    <constant>kgdb8250=mmio,0xc0000000ff5e0000,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_KGDB_ETH</symbol> driver, pass in
+    <constant>kgdboe=[src-port]@&lt;src-ip&gt;/[dev],[tgt-port]@&lt;tgt-ip&gt;/[tgt-macaddr]</constant>
+    where:
+    <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>
+  </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="CommonBackEndReq">
+    <title>The common backend (required)</title>
+      <para>
+      There are a few flags which must be set on every architecture in
+      their &lt;asm/kgdb.h&gt; 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>
Index: linux-2.6.14/Documentation/DocBook/Makefile
===================================================================
--- linux-2.6.14.orig/Documentation/DocBook/Makefile
+++ linux-2.6.14/Documentation/DocBook/Makefile
@@ -10,7 +10,7 @@ DOCBOOKS := wanbook.xml z8530book.xml mc
 	    kernel-hacking.xml kernel-locking.xml deviceiobook.xml \
 	    procfs-guide.xml writing_usb_driver.xml \
 	    sis900.xml kernel-api.xml journal-api.xml lsm.xml usb.xml \
-	    gadget.xml libata.xml mtdnand.xml librs.xml
+	    gadget.xml libata.xml mtdnand.xml librs.xml kgdb.xml
 
 ###
 # The build process is as follows (targets):
Index: linux-2.6.14/include/linux/kgdb.h
===================================================================
--- /dev/null
+++ linux-2.6.14/include/linux/kgdb.h
@@ -0,0 +1,261 @@
+/*
+ * 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 <[email protected]> and
+ *         Tom Rini <[email protected]>
+ *
+ * 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>
+
+struct tasklet_struct;
+struct pt_regs;
+struct task_struct;
+struct uart_port;
+
+
+/* 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 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_disabled,
+	bp_enabled
+};
+
+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		16
+#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);
+
+/**
+ * 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);
+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;
+#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__ */
Index: linux-2.6.14/kernel/kgdb.c
===================================================================
--- /dev/null
+++ linux-2.6.14/kernel/kgdb.c
@@ -0,0 +1,1819 @@
+/*
+ * kernel/kgdb.c
+ *
+ * Maintainer: Tom Rini <[email protected]>
+ *
+ * Copyright (C) 2000-2001 VERITAS Software Corporation.
+ * Copyright (C) 2002-2004 Timesys Corporation
+ * Copyright (C) 2003-2004 Amit S. Kale <[email protected]>
+ * Copyright (C) 2004 Pavel Machek <[email protected]>
+ * Copyright (C) 2004-2005 Tom Rini <[email protected]>
+ * Copyright (C) 2004 LinSysSoft Technologies Pvt. Ltd.
+ * Copyright (C) 2005 Wind River System, Inc.
+ *
+ * Contributors at various stages not listed above:
+ *  Jason Wessel ( [email protected] )
+ *  George Anzinger <[email protected]>
+ *  Anurekh Saxena ([email protected])
+ *  Lake Stevens Instrument Division (Glenn Engel)
+ *  Jim Kingdon, Cygnus Support.
+ *
+ * Original KGDB stub: David Grothe <[email protected]>,
+ * Tigran Aivazian <[email protected]>
+ *
+ * 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 <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 <asm/byteorder.h>
+
+extern int pid_max;
+extern int pidhash_init_done;
+
+/* 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];
+
+struct kgdb_arch *kgdb_ops = &arch_kgdb_ops;
+
+static const char hexchars[] = "0123456789abcdef";
+
+static spinlock_t slavecpulocks[NR_CPUS];
+static volatile int 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;
+
+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);
+
+/**
+ *	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)
+{
+}
+
+/**
+ *	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;
+}
+
+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 (!pidhash_init_done)
+		return current;
+
+	if (tid >= pid_max + num_online_cpus() + kgdb_ops->shadowth)
+		return NULL;
+
+	if (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;
+	procindebug[processor] = 1;
+
+	/* Wait till master processor goes completely into the debugger.
+	 * FIXME: this looks racy */
+	while (!procindebug[atomic_read(&debugger_active) - 1]) {
+		int i = 10;	/* an arbitrary number */
+
+		while (--i)
+			cpu_relax();
+		barrier();
+	}
+
+	/* Wait till master processor is done with debugging */
+	spin_lock(&slavecpulocks[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 */
+	procindebug[processor] = 0;
+	spin_unlock(&slavecpulocks[processor]);
+	local_irq_restore(flags);
+}
+#endif
+
+int kgdb_get_mem(char *addr, unsigned char *buf, int count)
+{
+	while (count) {
+		if ((unsigned long)addr < TASK_SIZE)
+			return -EINVAL;
+		*buf++ = *addr++;
+		count--;
+	}
+	return 0;
+}
+
+int kgdb_set_mem(char *addr, unsigned char *buf, int count)
+{
+	while (count) {
+		if ((unsigned long)addr < TASK_SIZE)
+			return -EINVAL;
+		*addr++ = *buf++;
+		count--;
+	}
+	return 0;
+}
+
+static int kgdb_set_sw_break(unsigned long addr)
+{
+	int i, breakno = -1;
+	int error;
+
+	for (i = 0; i < MAX_BREAKPOINTS; i++) {
+		if ((kgdb_break[i].state == bp_enabled) &&
+		    (kgdb_break[i].bpt_addr == addr))
+			return -EEXIST;
+
+		if (kgdb_break[i].state == bp_disabled) {
+			if ((breakno == -1) || (kgdb_break[i].bpt_addr == addr))
+				breakno = i;
+		}
+	}
+	if (breakno == -1)
+		return -E2BIG;
+
+	if (kgdb_ops->set_breakpoint) {
+		if ((error = kgdb_ops->set_breakpoint(addr,
+					kgdb_break[breakno].saved_instr)) < 0)
+			return error;
+	} else {
+		if ((error = kgdb_get_mem((char *)addr,
+					  kgdb_break[breakno].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;
+	}
+	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[breakno].state = bp_enabled;
+	kgdb_break[breakno].type = bp_breakpoint;
+	kgdb_break[breakno].bpt_addr = addr;
+
+	return 0;
+}
+
+static int kgdb_remove_sw_break(unsigned long addr)
+{
+	int i;
+	int error;
+
+	for (i = 0; i < MAX_BREAKPOINTS; i++) {
+		if ((kgdb_break[i].state == bp_enabled) &&
+		    (kgdb_break[i].bpt_addr == addr)) {
+			if (kgdb_ops->remove_breakpoint) {
+				if ((error = kgdb_ops->remove_breakpoint(addr,
+						kgdb_break[i].saved_instr)) < 0)
+					return error;
+			} else if ((error =
+				    kgdb_set_mem((char *)addr,
+						 kgdb_break[i].saved_instr,
+						 BREAK_INSTR_SIZE)) < 0)
+				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_disabled;
+			return 0;
+		}
+	}
+	return -ENOENT;
+}
+
+int remove_all_break(void)
+{
+	int i;
+	int error;
+
+	/* Clear memory breakpoints. */
+	for (i = 0; i < MAX_BREAKPOINTS; i++) {
+		if (kgdb_break[i].state == bp_enabled) {
+			unsigned long addr = kgdb_break[i].bpt_addr;
+			if ((error =
+			     kgdb_set_mem((char *)addr,
+					  kgdb_break[i].saved_instr,
+					  BREAK_INSTR_SIZE)) < 0)
+				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_disabled;
+	}
+
+	/* 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);
+	}
+
+	/*
+	 * 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;
+	}
+
+	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(&slavecpulocks[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 */
+	procindebug[smp_processor_id()] = 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 (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);
+
+	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_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;
+
+			/* 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 (!pidhash_init_done) {
+					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;
+			}
+
+			/* 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;
+	procindebug[smp_processor_id()] = 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 (procindebug[i]) {
+				int j = 10;	/* an arbitrary number */
+
+				while (--j)
+					cpu_relax();
+				barrier();
+			}
+		}
+	}
+
+#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
+
+	/* 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 (!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_disabled;
+
+	/* 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) {
+		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;
+		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.
+	 */
+	if (kgdb_io_ops.read_char != NULL) {
+		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)
+{
+	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)
+{
+	/* 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();
+	}
+
+	/* 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
+
+#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);
+}
+
+static 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);
Index: linux-2.6.14/kernel/Makefile
===================================================================
--- linux-2.6.14.orig/kernel/Makefile
+++ linux-2.6.14/kernel/Makefile
@@ -27,6 +27,7 @@ obj-$(CONFIG_STOP_MACHINE) += stop_machi
 obj-$(CONFIG_AUDIT) += audit.o
 obj-$(CONFIG_AUDITSYSCALL) += auditsc.o
 obj-$(CONFIG_KPROBES) += kprobes.o
+obj-$(CONFIG_KGDB) += kgdb.o
 obj-$(CONFIG_SYSFS) += ksysfs.o
 obj-$(CONFIG_DETECT_SOFTLOCKUP) += softlockup.o
 obj-$(CONFIG_GENERIC_HARDIRQS) += irq/
Index: linux-2.6.14/kernel/pid.c
===================================================================
--- linux-2.6.14.orig/kernel/pid.c
+++ linux-2.6.14/kernel/pid.c
@@ -250,8 +250,13 @@ void switch_exec_pids(task_t *leader, ta
 /*
  * The pid hash table is scaled according to the amount of memory in the
  * machine.  From a minimum of 16 slots up to 4096 slots at one gigabyte or
- * more.
+ * more.  KGDB needs to know if this function has been called already,
+ * since we might have entered KGDB very early.
  */
+#ifdef CONFIG_KGDB
+int pidhash_init_done;
+#endif
+
 void __init pidhash_init(void)
 {
 	int i, j, pidhash_size;
@@ -273,6 +278,10 @@ void __init pidhash_init(void)
 		for (j = 0; j < pidhash_size; j++)
 			INIT_HLIST_HEAD(&pid_hash[i][j]);
 	}
+
+#ifdef CONFIG_KGDB
+	pidhash_init_done = 1;
+#endif
 }
 
 void __init pidmap_init(void)
Index: linux-2.6.14/kernel/sched.c
===================================================================
--- linux-2.6.14.orig/kernel/sched.c
+++ linux-2.6.14/kernel/sched.c
@@ -47,6 +47,7 @@
 #include <linux/syscalls.h>
 #include <linux/times.h>
 #include <linux/acct.h>
+#include <linux/kgdb.h>
 #include <asm/tlb.h>
 
 #include <asm/unistd.h>
@@ -5557,6 +5558,9 @@ void __might_sleep(char *file, int line)
 #if defined(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)
Index: linux-2.6.14/lib/Kconfig.debug
===================================================================
--- linux-2.6.14.orig/lib/Kconfig.debug
+++ linux-2.6.14/lib/Kconfig.debug
@@ -178,3 +178,56 @@ config FRAME_POINTER
 	  on some architectures or you use external debuggers.
 	  If you don't debug the kernel, you can say N.
 
+config WANT_EXTRA_DEBUG_INFORMATION
+	bool
+	select DEBUG_INFO
+	select FRAME_POINTER if X86
+	default n
+
+config KGDB
+	bool "KGDB: kernel debugging with remote gdb"
+	select WANT_EXTRA_DEBUG_INFORMATION
+	depends on DEBUG_KERNEL
+	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_ONLY_MODULES
+	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.
+
+endchoice
Index: linux-2.6.14/MAINTAINERS
===================================================================
--- linux-2.6.14.orig/MAINTAINERS
+++ linux-2.6.14/MAINTAINERS
@@ -1415,6 +1415,15 @@ L:	[email protected]
 L:	[email protected]
 S:	Maintained
 
+KGDB
+P:	Tom Rini
+P:	Amit S. Kale
+M:	[email protected]
+M:	[email protected]
+W:	http://sourceforge.net/projects/kgdb
+L:	[email protected]
+S:	Maintained
+
 KPROBES
 P:	Prasanna S Panchamukhi
 M:	[email protected]

-- 
Tom
-
To unsubscribe from this list: send the line "unsubscribe linux-kernel" in
the body of a message to [email protected]
More majordomo info at  http://vger.kernel.org/majordomo-info.html
Please read the FAQ at  http://www.tux.org/lkml/

[Index of Archives]     [Kernel Newbies]     [Netfilter]     [Bugtraq]     [Photo]     [Stuff]     [Gimp]     [Yosemite News]     [MIPS Linux]     [ARM Linux]     [Linux Security]     [Linux RAID]     [Video 4 Linux]     [Linux for the blind]     [Linux Resources]
  Powered by Linux