Skip to contentSkip to conversation

KGDB: Core files

PATCH In review Tom Rini 6 participants 30 messages Jul 29, 2005 – Aug 8, 2005

Subsystems (19)
lore
Share & tools
lore

Tom Rini

author
#0 lore raw

PATCH 1/15 KGDB: Core files

CC: Amit Kale <[email protected]>
Here is a different version of KGDB than found currently in Andrew Morton's tree that Amit Kale and I (and many others) have been working on for some time now (and submitted a while back). I appologize for not resubmitting this sooner, but solving some of the issues George Anzinger and others dug up turned out to take more time than I would have liked.

Having said that, this version of KGDB is designed so that as much code as possible is done in a core file shared by all architectures, and with I/O (ie 8250 serial, custom uart, ethernet) being common when possible and modular. The rough splitup of this is that 95% of the interaction with KGDB is done in files common to all implementations with a small set of architecture specific things (setjmp/longjmp, actually formatting registers for GDB, single stepping).

Much of how to use this version (it is slightly different from George Anzinger's version) is written up in DocBook and viewable that way. I've tried to do this in as clean a way as possible (notifier when possible for example) so that it's as minimally instrusive as possible. But, in order to allow for KGDB to be used very early on (some folks argue this is critical, some argue it's not) there's a few hooks so we can know if pidhash_init has been run, or to try and have KGDB break in as soon as possible, if it can't right then (such as on x86_64 where stacks aren't ready for us to use just yet).

Comments? Thanks!

---

 linux-2.6.13-rc3-trini/Documentation/DocBook/Makefile  |    2 
 linux-2.6.13-rc3-trini/Documentation/DocBook/kgdb.tmpl |  231 ++
 linux-2.6.13-rc3-trini/MAINTAINERS                     |    9 
 linux-2.6.13-rc3-trini/include/linux/kgdb.h            |  260 ++
 linux-2.6.13-rc3-trini/kernel/Makefile                 |    1 
 linux-2.6.13-rc3-trini/kernel/kgdb.c                   | 1835 +++++++++++++++++
 linux-2.6.13-rc3-trini/kernel/pid.c                    |   11 
 linux-2.6.13-rc3-trini/kernel/sched.c                  |    4 
 linux-2.6.13-rc3-trini/lib/Kconfig.debug               |   47 
 9 files changed, 2398 insertions(+), 2 deletions(-)
Documentation/DocBook/kgdb.tmpl new file +231 -0
diff -puN /dev/null Documentation/DocBook/kgdb.tmpl
@@ -0,0 +1,231 @@
+<?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=portnumber,speed</constant> or on IA64
+    <constant>kgdb8250=portnumber,speed,irq,iomembase</constant> before
+    <constant>kgdbwait</constant>.  The values for portnumber are 0-3 and
+    correspond to ttyS0 to ttyS3 respectively.  The supported speeds 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=0,115200</constant>.
+    On IA64 this could also be:
+    <constant>kgdb8250=1,115200,74,0xc0000000ff5e0000</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>
+	<listitem>
+	  <para>
+	  CHECK_EXCEPTION_STACK(): It is possible for the kernel to be
+	  trying to use KGDB before our exception stacks are setup.  In
+	  this case, we must not let the KGDB happen yet.  If we do not
+	  have to worry about this, it should be set to one.  If we do
+	  have to worry about this, it should be set to a suitable
+	  check.
+	  </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/kgdb_8250.c
+   </chapter>
+</book>
Documentation/DocBook/Makefile renamed from Documentation/DocBook/Makefile~core-lite +1 -1
diff -puN Documentation/DocBook/Makefile~core-lite 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):
include/linux/kgdb.h new file +260 -0

260 lines not on this page · raw message

kernel/kgdb.c new file +1835 -0

1,835 lines not on this page · raw message

kernel/Makefile renamed from kernel/Makefile~core-lite +1 -0
diff -puN kernel/Makefile~core-lite kernel/Makefile
@@ -26,6 +26,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_GENERIC_HARDIRQS) += irq/
 obj-$(CONFIG_CRASH_DUMP) += crash_dump.o
kernel/pid.c renamed from kernel/pid.c~core-lite +10 -1
diff -puN kernel/pid.c~core-lite 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)
kernel/sched.c renamed from kernel/sched.c~core-lite +4 -0
diff -puN kernel/sched.c~core-lite 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>
@@ -5215,6 +5216,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)
lib/Kconfig.debug renamed from lib/Kconfig.debug~core-lite +47 -0

62 lines not on this page · raw message

MAINTAINERS renamed from MAINTAINERS~core-lite +9 -0
diff -puN MAINTAINERS~core-lite MAINTAINERS
@@ -1343,6 +1343,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
+
 LANMEDIA WAN CARD DRIVER
 P:	Andrew Stanley-Jones
 M:	[email protected]

_

author
#1 lore raw

PATCH 2/15 KGDB: i386 core functionality.

This adds the basic support for i386. The only real changes outside of new KGDB files and Makefile/related is that for support early on we must set some traps sooner rather than later, but it is safe to always do this. Also, to break in as early as possible, i386 now calls parse_early_param() to explicitly look at anything marked early_param(). We also add a few more notify_die() calls in areas where KGDB needs to take a peek sometimes. Finally, we add some labels to switch_to macros so that when backtracing we can see where we really are.

---

 linux-2.6.13-rc3-trini/arch/i386/kernel/Makefile   |    1 
 linux-2.6.13-rc3-trini/arch/i386/kernel/kgdb-jmp.S |   74 +++++
 linux-2.6.13-rc3-trini/arch/i386/kernel/kgdb.c     |  301 +++++++++++++++++++++
 linux-2.6.13-rc3-trini/arch/i386/kernel/setup.c    |    3 
 linux-2.6.13-rc3-trini/arch/i386/kernel/traps.c    |   15 -
 linux-2.6.13-rc3-trini/arch/i386/mm/fault.c        |    4 
 linux-2.6.13-rc3-trini/include/asm-i386/kgdb.h     |   50 +++
 linux-2.6.13-rc3-trini/include/asm-i386/system.h   |   10 
 linux-2.6.13-rc3-trini/lib/Kconfig.debug           |    2 
 9 files changed, 452 insertions(+), 8 deletions(-)
arch/i386/kernel/kgdb.c new file +301 -0
diff -puN /dev/null arch/i386/kernel/kgdb.c
@@ -0,0 +1,301 @@
+/*
+ *
+ * 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<[email protected]>
+ *  Updated by:	     Tom Rini <[email protected]>
+ *  Modified for 386 by Jim Kingdon, Cygnus Support.
+ *  Origianl kgdb, compatibility with 2.1.xx kernel by
+ *  David Grothe <[email protected]>
+ *  Additional support from Tigran Aivazian <[email protected]>
+ */
+
+#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)(&regs->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] = *(unsigned long *)(p->thread.esp + 4);
+	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));
+}
+
+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;
+			if (kgdb_contthread)
+				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 && strcmp(args->str, "no context") == 0 &&
+	    atomic_read(&debugger_active) && kgdb_may_fault) {
+		kgdb_fault_longjmp(kgdb_fault_jmp_regs);
+		return NOTIFY_STOP;
+	} else if (cmd == DIE_PAGE_FAULT &&
+		   strcmp(args->str, "page fault") == 0)
+		/* A normal page fault, ignore. */
+		return NOTIFY_DONE;
+	else if (cmd == DIE_NMI && atomic_read(&debugger_active)) {
+		/* CPU roundup */
+		kgdb_nmihook(smp_processor_id(), regs);
+		return NOTIFY_STOP;
+	} else if (cmd == DIE_NMI_IPI || 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)
+{
+	notifier_chain_register(&i386die_chain, &kgdb_notifier);
+	return 0;
+}
+
+struct kgdb_arch arch_kgdb_ops = {
+	.gdb_bpt_instr = {0xcc},
+};
arch/i386/kernel/kgdb-jmp.S new file +74 -0

74 lines not on this page · raw message

arch/i386/kernel/Makefile renamed from arch/i386/kernel/Makefile~i386-lite +1 -0
diff -puN arch/i386/kernel/Makefile~i386-lite arch/i386/kernel/Makefile
@@ -34,6 +34,7 @@ obj-$(CONFIG_ACPI_SRAT) 	+= srat.o
 obj-$(CONFIG_HPET_TIMER) 	+= time_hpet.o
 obj-$(CONFIG_EFI) 		+= efi.o efi_stub.o
 obj-$(CONFIG_EARLY_PRINTK)	+= early_printk.o
+obj-$(CONFIG_KGDB)		+= kgdb.o kgdb-jmp.o
 
 EXTRA_AFLAGS   := -traditional
 
arch/i386/kernel/setup.c renamed from arch/i386/kernel/setup.c~i386-lite +3 -0
diff -puN arch/i386/kernel/setup.c~i386-lite arch/i386/kernel/setup.c
@@ -147,6 +147,7 @@ EXPORT_SYMBOL(ist_info);
 struct e820map e820;
 
 extern void early_cpu_init(void);
+extern void early_trap_init(void);
 extern void dmi_scan_machine(void);
 extern void generic_apic_probe(char *);
 extern int root_mountflags;
@@ -1485,6 +1486,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
@@ -1541,6 +1543,7 @@ void __init setup_arch(char **cmdline_p)
 	data_resource.end = virt_to_phys(_edata)-1;
 
 	parse_cmdline_early(cmdline_p);
+	parse_early_param();
 
 	max_low_pfn = setup_memory();
 
arch/i386/kernel/traps.c renamed from arch/i386/kernel/traps.c~i386-lite +10 -5
diff -puN arch/i386/kernel/traps.c~i386-lite arch/i386/kernel/traps.c
@@ -337,7 +337,7 @@ void die(const char * str, struct pt_reg
 #endif
 		if (nl)
 			printk("\n");
-	notify_die(DIE_OOPS, (char *)str, regs, err, 255, SIGSEGV);
+		notify_die(DIE_OOPS, (char *)str, regs, err, 255, SIGSEGV);
 		show_registers(regs);
   	} else
 		printk(KERN_ERR "Recursive die() failure, output suppressed\n");
@@ -568,6 +568,7 @@ static DEFINE_SPINLOCK(nmi_print_lock);
 
 void die_nmi (struct pt_regs *regs, const char *msg)
 {
+	notify_die(DIE_NMIWATCHDOG, "nmi watchdog", regs, 0, 2, SIGPWR);
 	spin_lock(&nmi_print_lock);
 	/*
 	* We are in trouble anyway, lets at least try
@@ -757,6 +758,7 @@ fastcall void do_debug(struct pt_regs * 
 	 */
 clear_dr7:
 	set_debugreg(0, 7);
+	notify_die(DIE_DEBUG, "debug2", regs, condition, error_code, SIGTRAP);
 	return;
 
 debug_vm86:
@@ -1058,6 +1060,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)
 {
@@ -1074,10 +1082,8 @@ void __init trap_init(void)
 #endif
 
 	set_trap_gate(0,&divide_error);
-	set_intr_gate(1,&debug);
 	set_intr_gate(2,&nmi);
-	set_system_intr_gate(3, &int3); /* int3-5 can be called from all */
-	set_system_gate(4,&overflow);
+	set_system_gate(4,&overflow); /* int4/5 can be called from all */
 	set_system_gate(5,&bounds);
 	set_trap_gate(6,&invalid_op);
 	set_trap_gate(7,&device_not_available);
@@ -1087,7 +1093,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);
arch/i386/mm/fault.c renamed from arch/i386/mm/fault.c~i386-lite +4 -0
diff -puN arch/i386/mm/fault.c~i386-lite arch/i386/mm/fault.c
@@ -424,6 +424,10 @@ no_context:
  	if (is_prefetch(regs, address, error_code))
  		return;
 
+	if (notify_die(DIE_PAGE_FAULT, "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.
include/asm-i386/kgdb.h new file +50 -0

50 lines not on this page · raw message

include/asm-i386/system.h renamed from include/asm-i386/system.h~i386-lite +8 -2
diff -puN include/asm-i386/system.h~i386-lite include/asm-i386/system.h
@@ -12,9 +12,13 @@
 struct task_struct;	/* one of the stranger aspects of C forward declarations.. */
 extern struct task_struct * FASTCALL(__switch_to(struct task_struct *prev, struct task_struct *next));
 
+/* sleeping_thread_to_gdb_regs depends on this code. Correct it if you change
+ * any of the following */
 #define switch_to(prev,next,last) do {					\
 	unsigned long esi,edi;						\
-	asm volatile("pushfl\n\t"					\
+	asm volatile(".globl __switch_to_begin\n"			\
+		     "__switch_to_begin:"				\
+		     "pushfl\n\t"					\
 		     "pushl %%ebp\n\t"					\
 		     "movl %%esp,%0\n\t"	/* save ESP */		\
 		     "movl %5,%%esp\n\t"	/* restore ESP */	\
@@ -23,7 +27,9 @@ extern struct task_struct * FASTCALL(__s
 		     "jmp __switch_to\n"				\
 		     "1:\t"						\
 		     "popl %%ebp\n\t"					\
-		     "popfl"						\
+		     "popfl\n"						\
+		     ".globl __switch_to_end\n"				\
+		     "__switch_to_end:\n"				\
 		     :"=m" (prev->thread.esp),"=m" (prev->thread.eip),	\
 		      "=a" (last),"=S" (esi),"=D" (edi)			\
 		     :"m" (next->thread.esp),"m" (next->thread.eip),	\
lib/Kconfig.debug renamed from lib/Kconfig.debug~i386-lite +1 -1
diff -puN lib/Kconfig.debug~i386-lite lib/Kconfig.debug
@@ -163,7 +163,7 @@ config FRAME_POINTER
 
 config KGDB
 	bool "KGDB: kernel debugging with remote gdb"
-	depends on DEBUG_KERNEL
+	depends on DEBUG_KERNEL && (X86)
 	help
 	  If you say Y here, it will be possible to remotely debug the
 	  kernel using gdb. It is strongly suggested that you enable

_

author
#2 lore raw

PATCH 3/15 Basic PowerPC32 support

CC: Paul Mackerras <[email protected]>
This adds basic KGDB support to ppc32 (classic, e500 and 4xx), and support for kgdb8250 to a number of boards. This was done mostly myself with some help from Scott Hall for e500 and Frank Rowand pointed out some parts as he did the ppc64 code, as well as Takeharu KATO <[email protected]> for some of the 4xx code and testing.

---

 linux-2.6.13-rc3-trini/arch/ppc/Kconfig.debug                |   36 
 linux-2.6.13-rc3-trini/arch/ppc/kernel/Makefile              |    2 
 linux-2.6.13-rc3-trini/arch/ppc/kernel/kgdb.c                |  329 ++++
 linux-2.6.13-rc3-trini/arch/ppc/kernel/setup.c               |   16 
 linux-2.6.13-rc3-trini/arch/ppc/mm/fault.c                   |    9 
 linux-2.6.13-rc3-trini/arch/ppc/platforms/4xx/bubinga.c      |   23 
 linux-2.6.13-rc3-trini/arch/ppc/platforms/4xx/ebony.c        |   27 
 linux-2.6.13-rc3-trini/arch/ppc/platforms/4xx/ocotea.c       |   22 
 linux-2.6.13-rc3-trini/arch/ppc/platforms/4xx/xilinx_ml300.c |   18 
 linux-2.6.13-rc3-trini/arch/ppc/platforms/85xx/sbc8560.c     |   36 
 linux-2.6.13-rc3-trini/arch/ppc/platforms/chestnut.c         |    5 
 linux-2.6.13-rc3-trini/arch/ppc/platforms/cpci690.c          |   10 
 linux-2.6.13-rc3-trini/arch/ppc/platforms/mcpn765.c          |    5 
 linux-2.6.13-rc3-trini/arch/ppc/platforms/pcore.c            |    3 
 linux-2.6.13-rc3-trini/arch/ppc/platforms/pplus.c            |    3 
 linux-2.6.13-rc3-trini/arch/ppc/platforms/sandpoint.c        |    3 
 linux-2.6.13-rc3-trini/arch/ppc/platforms/spruce.c           |   21 
 linux-2.6.13-rc3-trini/arch/ppc/syslib/Makefile              |    1 
 linux-2.6.13-rc3-trini/arch/ppc/syslib/gen550.h              |    1 
 linux-2.6.13-rc3-trini/arch/ppc/syslib/ibm44x_common.c       |    3 
 linux-2.6.13-rc3-trini/arch/ppc/syslib/mv64x60.c             |   56 
 linux-2.6.13-rc3-trini/arch/ppc/syslib/mv64x60_dbg.c         |   52 
 linux-2.6.13-rc3-trini/arch/ppc/syslib/ppc85xx_setup.c       |   13 
 linux-2.6.13-rc3-trini/drivers/serial/Makefile               |    1 
 linux-2.6.13-rc3-trini/drivers/serial/kgdb_mpsc.c            |  313 +++
 linux-2.6.13-rc3-trini/drivers/serial/mpsc.h                 |    4 
 linux-2.6.13-rc3-trini/include/asm-ppc/kgdb.h                |   48 
 linux-2.6.13-rc3-trini/include/asm-ppc/machdep.h             |    2 
 linux-2.6.13-rc3-trini/include/asm-ppc/mv64x60.h             |    2 
 linux-2.6.13-rc3-trini/include/asm-ppc/mv64x60_defs.h        |    3 
 linux-2.6.13-rc3-trini/lib/Kconfig.debug                     |   10 
 linux-2.6.13-rc3/arch/ppc/kernel/ppc-stub.c                  |  867 -----------
 linux-2.6.13-rc3/arch/ppc/syslib/gen550_kgdb.c               |   86 -
 33 files changed, 837 insertions(+), 1193 deletions(-)
arch/ppc/Kconfig.debug renamed from arch/ppc/Kconfig.debug~ppc-lite +0 -36
diff -puN arch/ppc/Kconfig.debug~ppc-lite arch/ppc/Kconfig.debug
@@ -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
arch/ppc/kernel/kgdb.c new file +329 -0

329 lines not on this page · raw message

arch/ppc/kernel/Makefile renamed from arch/ppc/kernel/Makefile~ppc-lite +1 -1
diff -puN arch/ppc/kernel/Makefile~ppc-lite arch/ppc/kernel/Makefile
@@ -22,7 +22,7 @@ obj-$(CONFIG_POWER4)		+= cpu_setup_power
 obj-$(CONFIG_MODULES)		+= module.o ppc_ksyms.o
 obj-$(CONFIG_NOT_COHERENT_CACHE)	+= dma-mapping.o
 obj-$(CONFIG_PCI)		+= pci.o
-obj-$(CONFIG_KGDB)		+= ppc-stub.o
+obj-$(CONFIG_KGDB)		+= kgdb.o
 obj-$(CONFIG_SMP)		+= smp.o smp-tbsync.o
 obj-$(CONFIG_TAU)		+= temp.o
 obj-$(CONFIG_ALTIVEC)		+= vecemu.o vector.o
arch/ppc/kernel/ppc-stub.c deleted +0 -867

867 lines not on this page · raw message

arch/ppc/kernel/setup.c renamed from arch/ppc/kernel/setup.c~ppc-lite +0 -16
diff -puN arch/ppc/kernel/setup.c~ppc-lite arch/ppc/kernel/setup.c
@@ -45,10 +45,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 bootx_init(unsigned long r4, unsigned long phys);
@@ -709,18 +705,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)
arch/ppc/mm/fault.c renamed from arch/ppc/mm/fault.c~ppc-lite +9 -0
diff -puN arch/ppc/mm/fault.c~ppc-lite arch/ppc/mm/fault.c
@@ -28,6 +28,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>
@@ -332,6 +333,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)
arch/ppc/platforms/4xx/bubinga.c renamed from arch/ppc/platforms/4xx/bubinga.c~ppc-lite +14 -9
diff -puN arch/ppc/platforms/4xx/bubinga.c~ppc-lite arch/ppc/platforms/4xx/bubinga.c
@@ -4,7 +4,7 @@
  * Author: SAW (IBM), derived from walnut.c.
  *         Maintained by MontaVista Software <[email protected]>
  *
- * 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.
@@ -101,17 +101,26 @@ bubinga_early_serial_map(void)
 	port.flags = ASYNC_BOOT_AUTOCONF | ASYNC_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
@@ -256,8 +265,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
 }
-
arch/ppc/platforms/4xx/ebony.c renamed from arch/ppc/platforms/4xx/ebony.c~ppc-lite +15 -12
diff -puN arch/ppc/platforms/4xx/ebony.c~ppc-lite arch/ppc/platforms/4xx/ebony.c
@@ -36,6 +36,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>
@@ -241,28 +242,34 @@ ebony_early_serial_map(void)
 	port.flags = ASYNC_BOOT_AUTOCONF | ASYNC_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");
-	}
-
-#if defined(CONFIG_SERIAL_TEXT_DEBUG) || defined(CONFIG_KGDB)
+#endif
+#ifdef CONFIG_SERIAL_TEXT_DEBUG
 	/* Configure debug serial access */
 	gen550_init(0, &port);
 #endif
+#ifdef CONFIG_KGDB_8250
+	kgdb8250_add_port(0, &port);
+#endif
 
 	port.membase = ioremap64(PPC440GP_UART1_ADDR, 8);
 	port.irq = 1;
 	port.uartclk = clocks.uart1;
 	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");
-	}
-
-#if defined(CONFIG_SERIAL_TEXT_DEBUG) || defined(CONFIG_KGDB)
+#endif
+#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
@@ -348,8 +355,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
 }
-
arch/ppc/platforms/4xx/ocotea.c renamed from arch/ppc/platforms/4xx/ocotea.c~ppc-lite +14 -8
diff -puN arch/ppc/platforms/4xx/ocotea.c~ppc-lite arch/ppc/platforms/4xx/ocotea.c
@@ -259,28 +259,34 @@ ocotea_early_serial_map(void)
 	port.flags = ASYNC_BOOT_AUTOCONF | ASYNC_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");
-	}
-
-#if defined(CONFIG_SERIAL_TEXT_DEBUG) || defined(CONFIG_KGDB)
+#endif
+#ifdef CONFIG_SERIAL_TEXT_DEBUG
 	/* Configure debug serial access */
 	gen550_init(0, &port);
 #endif
+#ifdef CONFIG_KGDB_8250
+	kgdb8250_add_port(0, &port);
+#endif
 
 	port.membase = ioremap64(PPC440GX_UART1_ADDR, 8);
 	port.irq = UART1_INT;
 	port.uartclk = clocks.uart1;
 	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");
-	}
-
-#if defined(CONFIG_SERIAL_TEXT_DEBUG) || defined(CONFIG_KGDB)
+#endif
+#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
arch/ppc/platforms/4xx/xilinx_ml300.c renamed from arch/ppc/platforms/4xx/xilinx_ml300.c~ppc-lite +6 -12
diff -puN arch/ppc/platforms/4xx/xilinx_ml300.c~ppc-lite arch/ppc/platforms/4xx/xilinx_ml300.c
@@ -42,9 +42,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
@@ -83,7 +80,6 @@ ml300_map_io(void)
 static void __init
 ml300_early_serial_map(void)
 {
-#ifdef CONFIG_SERIAL_8250
 	struct serial_state old_ports[] = { SERIAL_PORT_DFNS };
 	struct uart_port port;
 	int i;
@@ -99,11 +95,14 @@ ml300_early_serial_map(void)
 		port.flags = ASYNC_BOOT_AUTOCONF | ASYNC_SKIP_TEST;
 		port.line = i;
 
-		if (early_serial_setup(&port) != 0) {
+#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
 	}
-#endif /* CONFIG_SERIAL_8250 */
 }
 
 void __init
@@ -138,9 +137,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
 }
-
arch/ppc/platforms/85xx/sbc8560.c renamed from arch/ppc/platforms/85xx/sbc8560.c~ppc-lite +20 -16
diff -puN arch/ppc/platforms/85xx/sbc8560.c~ppc-lite arch/ppc/platforms/85xx/sbc8560.c
@@ -54,7 +54,6 @@
 #include <syslib/ppc85xx_common.h>
 #include <syslib/ppc85xx_setup.h>
 
-#ifdef CONFIG_SERIAL_8250
 static void __init
 sbc8560_early_serial_map(void)
 {
@@ -70,27 +69,34 @@ 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
- 
-        if (early_serial_setup(&uart_req) != 0)
-                printk("Early serial init of port 0 failed\n");
- 
+#ifdef CONFIG_SERIAL_TEXT_DEBUG
+	gen550_init(0, &uart_req);
+#endif
+#ifdef CONFIG_KGDB_8250
+	kgdb8250_add_port(0, &uart_req);
+#endif
+
         /* Assume early_serial_setup() doesn't modify uart_req */
 	uart_req.line = 1;
         uart_req.mapbase = UARTB_ADDR;
         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 1 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(1, &uart_req);
 #endif
+#ifdef CONFIG_KGDB_8250
+	kgdb8250_add_port(1, &uart_req);
+#endif
+}
 
 /* ************************************************************************
  *
@@ -118,9 +124,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 */ 
arch/ppc/platforms/chestnut.c renamed from arch/ppc/platforms/chestnut.c~ppc-lite +1 -4
diff -puN arch/ppc/platforms/chestnut.c~ppc-lite arch/ppc/platforms/chestnut.c
@@ -496,7 +496,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
@@ -571,9 +571,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);
arch/ppc/platforms/cpci690.c renamed from arch/ppc/platforms/cpci690.c~ppc-lite +4 -6
diff -puN arch/ppc/platforms/cpci690.c~ppc-lite arch/ppc/platforms/cpci690.c
@@ -429,7 +429,7 @@ cpci690_set_bat(u32 addr, u32 size)
 	mb();
 }
 
-#if defined(CONFIG_SERIAL_TEXT_DEBUG) || defined(CONFIG_KGDB)
+#if defined(CONFIG_SERIAL_TEXT_DEBUG) || defined(CONFIG_KGDB_MPSC)
 static void __init
 cpci690_map_io(void)
 {
@@ -475,15 +475,13 @@ platform_init(unsigned long r3, unsigned
 	cpci690_set_bat(CPCI690_BR_BASE, 32 * MB);
 	cpci690_br_base = CPCI690_BR_BASE;
 
-#ifdef	CONFIG_SERIAL_TEXT_DEBUG
+#if defined(CONFIG_SERIAL_TEXT_DEBUG) || defined(CONFIG_KGDB_MPSC)
 	ppc_md.setup_io_mappings = cpci690_map_io;
+#ifdef CONFIG_SERIAL_TEXT_DEBUG
 	ppc_md.progress = mv64x60_mpsc_progress;
 	mv64x60_progress_init(CONFIG_MV64X60_NEW_BASE);
 #endif	/* CONFIG_SERIAL_TEXT_DEBUG */
-#ifdef	CONFIG_KGDB
-	ppc_md.setup_io_mappings = cpci690_map_io;
-	ppc_md.early_serial_map = cpci690_early_serial_map;
-#endif	/* CONFIG_KGDB */
+#endif	/* defined(CONFIG_SERIAL_TEXT_DEBUG) || defined(CONFIG_KGDB_MPSC) */
 
 #if defined(CONFIG_SERIAL_MPSC)
 	platform_notify = cpci690_platform_notify;
arch/ppc/platforms/mcpn765.c renamed from arch/ppc/platforms/mcpn765.c~ppc-lite +0 -5
diff -puN arch/ppc/platforms/mcpn765.c~ppc-lite arch/ppc/platforms/mcpn765.c
@@ -519,9 +519,4 @@ platform_init(unsigned long r3, unsigned
 #ifdef CONFIG_SERIAL_TEXT_DEBUG
 	ppc_md.progress = gen550_progress;
 #endif
-#ifdef CONFIG_KGDB
-	ppc_md.kgdb_map_scc = gen550_kgdb_map_scc;
-#endif
-
-	return;
 }
arch/ppc/platforms/pcore.c renamed from arch/ppc/platforms/pcore.c~ppc-lite +0 -3
diff -puN arch/ppc/platforms/pcore.c~ppc-lite arch/ppc/platforms/pcore.c
@@ -346,7 +346,4 @@ platform_init(unsigned long r3, unsigned
 #ifdef CONFIG_SERIAL_TEXT_DEBUG
 	ppc_md.progress = gen550_progress;
 #endif
-#ifdef CONFIG_KGDB
-	ppc_md.kgdb_map_scc = gen550_kgdb_map_scc;
-#endif
 }
arch/ppc/platforms/pplus.c renamed from arch/ppc/platforms/pplus.c~ppc-lite +0 -3
diff -puN arch/ppc/platforms/pplus.c~ppc-lite arch/ppc/platforms/pplus.c
@@ -908,9 +908,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
 	ppc_md.smp_ops = &pplus_smp_ops;
 #endif				/* CONFIG_SMP */
arch/ppc/platforms/sandpoint.c renamed from arch/ppc/platforms/sandpoint.c~ppc-lite +0 -3
diff -puN arch/ppc/platforms/sandpoint.c~ppc-lite arch/ppc/platforms/sandpoint.c
@@ -748,9 +748,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
arch/ppc/platforms/spruce.c renamed from arch/ppc/platforms/spruce.c~ppc-lite +12 -9
diff -puN arch/ppc/platforms/spruce.c~ppc-lite arch/ppc/platforms/spruce.c
@@ -181,26 +181,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();
@@ -319,7 +325,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
 }
arch/ppc/syslib/gen550.h renamed from arch/ppc/syslib/gen550.h~ppc-lite +0 -1
diff -puN arch/ppc/syslib/gen550.h~ppc-lite arch/ppc/syslib/gen550.h
@@ -13,4 +13,3 @@
 
 extern void gen550_progress(char *, unsigned short);
 extern void gen550_init(int, struct uart_port *);
-extern void gen550_kgdb_map_scc(void);
arch/ppc/syslib/gen550_kgdb.c deleted +0 -86

86 lines not on this page · raw message

arch/ppc/syslib/ibm44x_common.c renamed from arch/ppc/syslib/ibm44x_common.c~ppc-lite +0 -3
diff -puN arch/ppc/syslib/ibm44x_common.c~ppc-lite arch/ppc/syslib/ibm44x_common.c
@@ -161,9 +161,6 @@ void __init ibm44x_platform_init(void)
 #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
arch/ppc/syslib/Makefile renamed from arch/ppc/syslib/Makefile~ppc-lite +0 -1
diff -puN arch/ppc/syslib/Makefile~ppc-lite arch/ppc/syslib/Makefile
@@ -85,7 +85,6 @@ obj-$(CONFIG_PCI_8260)		+= m82xx_pci.o i
 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)
arch/ppc/syslib/mv64x60.c renamed from arch/ppc/syslib/mv64x60.c~ppc-lite +54 -2

84 lines not on this page · raw message

arch/ppc/syslib/mv64x60_dbg.c renamed from arch/ppc/syslib/mv64x60_dbg.c~ppc-lite +1 -51

61 lines not on this page · raw message

arch/ppc/syslib/ppc85xx_setup.c renamed from arch/ppc/syslib/ppc85xx_setup.c~ppc-lite +8 -5
diff -puN arch/ppc/syslib/ppc85xx_setup.c~ppc-lite arch/ppc/syslib/ppc85xx_setup.c
@@ -71,7 +71,6 @@ mpc85xx_calibrate_decr(void)
 	mtspr(SPRN_TCR, TCR_DIE);
 }
 
-#ifdef CONFIG_SERIAL_8250
 void __init
 mpc85xx_early_serial_map(void)
 {
@@ -87,7 +86,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 = SERIAL_IO_MEM;
 	serial_req.mapbase = pdata[0].mapbase;
@@ -95,18 +94,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
@@ -365,5 +370,3 @@ mpc85xx_setup_hose(void)
 	return;
 }
 #endif /* CONFIG_PCI */
-
-
drivers/serial/kgdb_mpsc.c new file +313 -0

313 lines not on this page · raw message

drivers/serial/Makefile renamed from drivers/serial/Makefile~ppc-lite +1 -0
diff -puN drivers/serial/Makefile~ppc-lite drivers/serial/Makefile
@@ -51,6 +51,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) += kgdb_mpsc.o
 obj-$(CONFIG_SERIAL_MPSC) += mpsc.o
 obj-$(CONFIG_ETRAX_SERIAL) += crisv10.o
 obj-$(CONFIG_SERIAL_JSM) += jsm/
drivers/serial/mpsc.h renamed from drivers/serial/mpsc.h~ppc-lite +4 -0
diff -puN drivers/serial/mpsc.h~ppc-lite drivers/serial/mpsc.h
@@ -207,6 +207,10 @@ 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)
 /*
  *****************************************************************************
  *
include/asm-ppc/kgdb.h renamed from include/asm-ppc/kgdb.h~ppc-lite +18 -30

70 lines not on this page · raw message

include/asm-ppc/machdep.h renamed from include/asm-ppc/machdep.h~ppc-lite +0 -2
diff -puN include/asm-ppc/machdep.h~ppc-lite include/asm-ppc/machdep.h
@@ -59,9 +59,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);
include/asm-ppc/mv64x60_defs.h renamed from include/asm-ppc/mv64x60_defs.h~ppc-lite +2 -1
diff -puN include/asm-ppc/mv64x60_defs.h~ppc-lite include/asm-ppc/mv64x60_defs.h
@@ -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
include/asm-ppc/mv64x60.h renamed from include/asm-ppc/mv64x60.h~ppc-lite +2 -0
diff -puN include/asm-ppc/mv64x60.h~ppc-lite include/asm-ppc/mv64x60.h
@@ -332,6 +332,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];
lib/Kconfig.debug renamed from lib/Kconfig.debug~ppc-lite +9 -1
diff -puN lib/Kconfig.debug~ppc-lite lib/Kconfig.debug
@@ -163,7 +163,7 @@ config FRAME_POINTER
 
 config KGDB
 	bool "KGDB: kernel debugging with remote gdb"
-	depends on DEBUG_KERNEL && (X86)
+	depends on DEBUG_KERNEL && (X86 || ((!SMP || BROKEN) && (PPC32)))
 	help
 	  If you say Y here, it will be possible to remotely debug the
 	  kernel using gdb. It is strongly suggested that you enable
@@ -189,6 +189,7 @@ choice
 	prompt "Method for KGDB communication"
 	depends on KGDB
 	default KGDB_ONLY_MODULES
+	default KGDB_MPSC if SERIAL_MPSC
 	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
@@ -205,4 +206,11 @@ config KGDB_ONLY_MODULES
 	  Use only kernel modules to configure KGDB I/O after the
 	  kernel is booted.
 
+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.
 endchoice

_

author
#3 lore raw

PATCH 4/15 I/O driver for 8250-compatible UARTs

CC: Russell King <[email protected]>
This is the I/O driver for any 8250-compatible UARTs. This also adds some small hooks into the normal serial core so that we can take away the uart and make sure only KGDB is trying to use it. We also make sure that if KGDB_8250 is enabled, SERIAL_8250_NR_UARTS is set to the default of 4. This is so that if we can always depend on that constant in the 8250 driver for giving our table a size. To make it easier (or in some cases, possible) to free up ports on a shared irq system, we add a line member to plat_serial8250_port.

---

 linux-2.6.13-rc3-trini/drivers/serial/8250.c        |   86 ++
 linux-2.6.13-rc3-trini/drivers/serial/Kconfig       |    4 
 linux-2.6.13-rc3-trini/drivers/serial/Makefile      |    1 
 linux-2.6.13-rc3-trini/drivers/serial/kgdb_8250.c   |  610 ++++++++++++++++++++
 linux-2.6.13-rc3-trini/drivers/serial/serial_core.c |    6 
 linux-2.6.13-rc3-trini/include/linux/kgdb.h         |    1 
 linux-2.6.13-rc3-trini/include/linux/serial_8250.h  |    1 
 linux-2.6.13-rc3-trini/lib/Kconfig.debug            |   89 ++
 8 files changed, 795 insertions(+), 3 deletions(-)
drivers/serial/8250.c renamed from drivers/serial/8250.c~8250 +86 -0
diff -puN drivers/serial/8250.c~8250 drivers/serial/8250.c
@@ -1432,6 +1432,8 @@ static void serial8250_break_ctl(struct 
 	spin_unlock_irqrestore(&up->port.lock, flags);
 }
 
+static int released_irq = -1;
+
 static int serial8250_startup(struct uart_port *port)
 {
 	struct uart_8250_port *up = (struct uart_8250_port *)port;
@@ -1439,6 +1441,9 @@ static int serial8250_startup(struct uar
 	unsigned char lsr, iir;
 	int retval;
 
+ 	if (up->port.irq == released_irq)
+		return -EBUSY;
+
 	up->capabilities = uart_config[up->port.type].flags;
 	up->mcr = 0;
 
@@ -2087,6 +2092,9 @@ serial8250_register_ports(struct uart_dr
 	for (i = 0; i < UART_NR; i++) {
 		struct uart_8250_port *up = &serial8250_ports[i];
 
+		if (up->port.irq == released_irq)
+			continue;
+
 		up->port.dev = dev;
 		uart_add_one_port(drv, &up->port);
 	}
@@ -2463,6 +2471,9 @@ int serial8250_register_port(struct uart
 	if (port->uartclk == 0)
 		return -EINVAL;
 
+	if (port->irq == released_irq)
+		return -EBUSY;
+
 	down(&serial_sem);
 
 	uart = serial8250_find_match_or_unused(port);
@@ -2516,6 +2527,38 @@ void serial8250_unregister_port(int line
 }
 EXPORT_SYMBOL(serial8250_unregister_port);
 
+/**
+ *	serial8250_release_irq - remove a 16x50 serial port at runtime based
+ *	on IRQ
+ *	@irq: IRQ number
+ *
+ *	Remove one serial port.  This may not be called from interrupt
+ *	context.  This is called when the caller know the IRQ of the
+ *	port they want, but not where it is in our table.  This allows
+ *	for one port, based on IRQ, to be permanently released from us.
+ */
+
+int serial8250_release_irq(int irq)
+{
+        struct uart_8250_port *up;
+	int ttyS;
+
+	if (released_irq == irq)
+		return 0;
+
+	if (released_irq != -1)
+		return -EBUSY;
+
+	released_irq = irq;
+	for (ttyS = 0; ttyS < UART_NR; ttyS++){
+		up =  &serial8250_ports[ttyS];
+		if (up->port.irq == irq && (irq_lists + irq)->head)
+			serial8250_unregister_port(up->port.line);
+        }
+	return 0;
+}
+EXPORT_SYMBOL(serial8250_release_irq);
+
 static int __init serial8250_init(void)
 {
 	int ret, i;
@@ -2665,3 +2708,46 @@ void unregister_serial(int line)
 	serial8250_unregister_port(line);
 }
 EXPORT_SYMBOL(unregister_serial);
+
+/**
+ *	debug_request_serial_line - disable a 16x50 serial port at runtime
+ *	@line: serial line number
+ *
+ *	Disable one serial port.  This may not be called from
+ *	interrupt context. This function is for the explicit purpose
+ *	of giving the serial line over to the debugger.
+ */
+static struct uart_port debug_port;
+void debug_request_serial_line(int line)
+{
+	struct uart_8250_port *uart = &serial8250_ports[line];
+	/* For now, irq sharing doesn't seem to be supported so the
+	 * irq that the debug port is on is marked as released
+	 */
+	released_irq = uart->port.irq;
+	debug_port.flags = uart->port.flags;
+	debug_port.type = uart->port.type;
+	debug_port.dev = uart->port.dev;
+	serial8250_unregister_port(line);
+}
+EXPORT_SYMBOL(debug_request_serial_line);
+
+/**
+ *	debug_release_serial_line - re-enable a 16x50 serial port at runtime
+ *	@line: serial line number
+ *
+ *	Re-enable one serial port.  This may not be called from
+ *	interrupt context. This function is for the explicit purpose
+ *	of the debugger giving the serial line back to the standard
+ *	serial driver.
+ */
+void debug_release_serial_line(int line)
+{
+	struct uart_port *port = &serial8250_ports[line].port;
+	released_irq = -1;
+	port->flags = debug_port.flags;
+	port->type = debug_port.type;
+	port->dev = debug_port.dev;
+	serial8250_register_port(port);
+}
+EXPORT_SYMBOL(debug_release_serial_line);
drivers/serial/Kconfig renamed from drivers/serial/Kconfig~8250 +2 -2
diff -puN drivers/serial/Kconfig~8250 drivers/serial/Kconfig
@@ -86,8 +86,8 @@ config SERIAL_8250_ACPI
 	  namespace, say Y here.  If unsure, say N.
 
 config SERIAL_8250_NR_UARTS
-	int "Maximum number of 8250/16550 serial ports"
-	depends on SERIAL_8250
+	int "Maximum number of 8250/16550 serial ports" if SERIAL_8250
+	depends on SERIAL_8250 || KGDB_8250
 	default "4"
 	help
 	  Set this to the number of serial ports you want the driver
drivers/serial/kgdb_8250.c new file +610 -0

610 lines not on this page · raw message

drivers/serial/Makefile renamed from drivers/serial/Makefile~8250 +1 -0
diff -puN drivers/serial/Makefile~8250 drivers/serial/Makefile
@@ -58,3 +58,4 @@ obj-$(CONFIG_SERIAL_JSM) += jsm/
 obj-$(CONFIG_SERIAL_TXX9) += serial_txx9.o
 obj-$(CONFIG_SERIAL_VR41XX) += vr41xx_siu.o
 obj-$(CONFIG_SERIAL_SGI_IOC4) += ioc4_serial.o
+obj-$(CONFIG_KGDB_8250) += kgdb_8250.o
drivers/serial/serial_core.c renamed from drivers/serial/serial_core.c~8250 +5 -1
diff -puN drivers/serial/serial_core.c~8250 drivers/serial/serial_core.c
@@ -866,7 +866,11 @@ uart_tiocmset(struct tty_struct *tty, st
 static void uart_break_ctl(struct tty_struct *tty, int break_state)
 {
 	struct uart_state *state = tty->driver_data;
-	struct uart_port *port = state->port;
+	struct uart_port *port;
+
+	if (!state)
+		return;
+	port = state->port;
 
 	BUG_ON(!kernel_locked());
 
include/linux/kgdb.h renamed from include/linux/kgdb.h~8250 +1 -0
diff -puN include/linux/kgdb.h~8250 include/linux/kgdb.h
@@ -241,6 +241,7 @@ extern void kgdb_unregister_io_module(st
 
 extern void kgdb8250_add_port(int i, struct uart_port *serial_req);
 extern void kgdb8250_add_platform_port(int i, struct plat_serial8250_port *serial_req);
+extern int kgdb8250_get_ttyS(void);
 
 extern int kgdb_hex2long(char **ptr, long *long_val);
 extern char *kgdb_mem2hex(char *mem, char *buf, int count);
include/linux/serial_8250.h renamed from include/linux/serial_8250.h~8250 +1 -0
diff -puN include/linux/serial_8250.h~8250 include/linux/serial_8250.h
@@ -24,6 +24,7 @@ struct plat_serial8250_port {
 	unsigned char	iotype;		/* UPIO_* */
 	unsigned char	hub6;
 	unsigned int	flags;		/* UPF_* flags */
+	unsigned int	line;		/* logical line number */
 };
 
 #endif
lib/Kconfig.debug renamed from lib/Kconfig.debug~8250 +89 -0

99 lines not on this page · raw message

_

author
#4 lore raw

PATCH 5/15 Basic MIPS support

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

---

 linux-2.6.13-rc3-trini/arch/mips/Kconfig.debug                   |   19 
 linux-2.6.13-rc3-trini/arch/mips/kernel/Makefile                 |    3 
 linux-2.6.13-rc3-trini/arch/mips/kernel/irq.c                    |   32 
 linux-2.6.13-rc3-trini/arch/mips/kernel/kgdb-jmp.c               |   62 
 linux-2.6.13-rc3-trini/arch/mips/kernel/kgdb-setjmp.S            |   23 
 linux-2.6.13-rc3-trini/arch/mips/kernel/kgdb.c                   |  292 ++
 linux-2.6.13-rc3-trini/arch/mips/kernel/kgdb_handler.S           |   58 
 linux-2.6.13-rc3-trini/arch/mips/kernel/traps.c                  |   26 
 linux-2.6.13-rc3-trini/arch/mips/mips-boards/generic/Makefile    |    1 
 linux-2.6.13-rc3-trini/arch/mips/mips-boards/generic/init.c      |   62 
 linux-2.6.13-rc3-trini/arch/mips/mips-boards/malta/malta_setup.c |    8 
 linux-2.6.13-rc3-trini/arch/mips/mm/extable.c                    |    7 
 linux-2.6.13-rc3-trini/arch/mips/sibyte/cfe/setup.c              |   14 
 linux-2.6.13-rc3-trini/arch/mips/sibyte/sb1250/Makefile          |    1 
 linux-2.6.13-rc3-trini/arch/mips/sibyte/sb1250/irq.c             |   57 
 linux-2.6.13-rc3-trini/arch/mips/sibyte/sb1250/irq_handler.S     |    2 
 linux-2.6.13-rc3-trini/arch/mips/sibyte/sb1250/kgdb_sibyte.c     |  164 +
 linux-2.6.13-rc3-trini/arch/mips/sibyte/swarm/Makefile           |    2 
 linux-2.6.13-rc3-trini/include/asm-mips/kdebug.h                 |   47 
 linux-2.6.13-rc3-trini/include/asm-mips/kgdb.h                   |   22 
 linux-2.6.13-rc3-trini/lib/Kconfig.debug                         |    7 
 linux-2.6.13-rc3/arch/mips/kernel/gdb-low.S                      |  370 ---
 linux-2.6.13-rc3/arch/mips/kernel/gdb-stub.c                     | 1091 ----------
 linux-2.6.13-rc3/arch/mips/sibyte/swarm/dbg_io.c                 |   76 
 24 files changed, 729 insertions(+), 1717 deletions(-)
arch/mips/Kconfig.debug renamed from arch/mips/Kconfig.debug~mips-lite +0 -19
diff -puN arch/mips/Kconfig.debug~mips-lite arch/mips/Kconfig.debug
@@ -27,25 +27,6 @@ config DEBUG_STACK_USAGE
 
 	  This option will slow down process creation somewhat.
 
-config KGDB
-	bool "Remote GDB kernel debugging"
-	depends on DEBUG_KERNEL
-	select DEBUG_INFO
-	help
-	  If you say Y here, it will be possible to remotely debug the MIPS
-	  kernel using gdb. This enlarges your kernel image disk size by
-	  several megabytes and requires a machine with more than 16 MB,
-	  better 32 MB RAM to avoid excessive linking time. This is only
-	  useful for kernel hackers. If unsure, say N.
-
-config GDB_CONSOLE
-	bool "Console output to GDB"
-	depends on KGDB
-	help
-	  If you are using GDB for remote debugging over a serial port and
-	  would like kernel messages to be formatted into GDB $O packets so
-	  that GDB prints them as program output, say 'Y'.
-
 config SB1XXX_CORELIS
 	bool "Corelis Debugger"
 	depends on SIBYTE_SB1xxx_SOC
arch/mips/kernel/gdb-low.S deleted +0 -370

370 lines not on this page · raw message

arch/mips/kernel/gdb-stub.c deleted +0 -1091

1,091 lines not on this page · raw message

arch/mips/kernel/irq.c renamed from arch/mips/kernel/irq.c~mips-lite +13 -19
diff -puN arch/mips/kernel/irq.c~mips-lite arch/mips/kernel/irq.c
@@ -26,6 +26,10 @@
 #include <asm/atomic.h>
 #include <asm/system.h>
 #include <asm/uaccess.h>
+#include <asm/kgdb.h>
+
+/* Keep track of if we've done certain initialization already or not. */
+int kgdb_early_setup;
 
 /*
  * 'what should we do if we get a hw irq event on an illegal vector'.
@@ -103,23 +107,13 @@ skip:
 	return 0;
 }
 
-#ifdef CONFIG_KGDB
-extern void breakpoint(void);
-extern void set_debug_traps(void);
-
-static int kgdb_flag = 1;
-static int __init nokgdb(char *str)
-{
-	kgdb_flag = 0;
-	return 1;
-}
-__setup("nokgdb", nokgdb);
-#endif
-
 void __init init_IRQ(void)
 {
 	int i;
 
+	if (kgdb_early_setup)
+		return;
+
 	for (i = 0; i < NR_IRQS; i++) {
 		irq_desc[i].status  = IRQ_DISABLED;
 		irq_desc[i].action  = NULL;
@@ -129,12 +123,12 @@ void __init init_IRQ(void)
 	}
 
 	arch_init_irq();
-
 #ifdef CONFIG_KGDB
-	if (kgdb_flag) {
-		printk("Wait for gdb client connection ...\n");
-		set_debug_traps();
-		breakpoint();
-	}
+	/*
+	 * We have been called before kgdb_arch_init(). Hence,
+	 * we dont want the traps to be reinitialized
+	 */
+	if (kgdb_early_setup == 0)
+		kgdb_early_setup = 1;
 #endif
 }
arch/mips/kernel/kgdb.c new file +292 -0

292 lines not on this page · raw message

arch/mips/kernel/kgdb_handler.S new file +58 -0

58 lines not on this page · raw message

arch/mips/kernel/kgdb-jmp.c new file +62 -0

62 lines not on this page · raw message

arch/mips/kernel/kgdb-setjmp.S new file +23 -0
diff -puN /dev/null arch/mips/kernel/kgdb-setjmp.S
@@ -0,0 +1,23 @@
+/*
+ * arch/mips/kernel/kgdb-jmp.c
+ *
+ * Save and restore system registers so that within a limited frame we
+ * may have a fault and "jump back" to a known safe location.
+ *
+ * Copyright (C) 2005 by MontaVista Software.
+ *
+ * This file is licensed under the terms of the GNU General Public License
+ * version 2. This program as licensed "as is" without any warranty of
+ * any kind, whether express or implied.
+ */
+
+#include <asm/asm.h>
+#include <asm/mipsregs.h>
+#include <asm/regdef.h>
+#include <asm/stackframe.h>
+
+ENTRY (kgdb_fault_setjmp)
+	move    a1, sp
+	move	a2, fp
+	j	kgdb_fault_setjmp_aux
+	.end	kgdb_fault_setjmp
arch/mips/kernel/Makefile renamed from arch/mips/kernel/Makefile~mips-lite +2 -1
diff -puN arch/mips/kernel/Makefile~mips-lite arch/mips/kernel/Makefile
@@ -52,7 +52,8 @@ obj-$(CONFIG_MIPS32_COMPAT)	+= ioctl32.o
 obj-$(CONFIG_MIPS32_N32)	+= binfmt_elfn32.o scall64-n32.o signal_n32.o
 obj-$(CONFIG_MIPS32_O32)	+= binfmt_elfo32.o scall64-o32.o ptrace32.o
 
-obj-$(CONFIG_KGDB)		+= gdb-low.o gdb-stub.o
+obj-$(CONFIG_KGDB)		+= kgdb_handler.o kgdb.o kgdb-jmp.o	\
+					kgdb-setjmp.o
 obj-$(CONFIG_PROC_FS)		+= proc.o
 
 obj-$(CONFIG_MIPS64)		+= cpu-bugs64.o
arch/mips/kernel/traps.c renamed from arch/mips/kernel/traps.c~mips-lite +25 -1
diff -puN arch/mips/kernel/traps.c~mips-lite arch/mips/kernel/traps.c
@@ -10,6 +10,8 @@
  * Kevin D. Kissell, [email protected] and Carsten Langgaard, [email protected]
  * Copyright (C) 2000, 01 MIPS Technologies, Inc.
  * Copyright (C) 2002, 2003, 2004  Maciej W. Rozycki
+ *
+ * KGDB specific changes - Manish Lachwani ([email protected])
  */
 #include <linux/config.h>
 #include <linux/init.h>
@@ -20,6 +22,7 @@
 #include <linux/smp_lock.h>
 #include <linux/spinlock.h>
 #include <linux/kallsyms.h>
+#include <linux/kgdb.h>
 
 #include <asm/bootinfo.h>
 #include <asm/branch.h>
@@ -37,6 +40,7 @@
 #include <asm/mmu_context.h>
 #include <asm/watch.h>
 #include <asm/types.h>
+#include <asm/kdebug.h>
 
 extern asmlinkage void handle_tlbm(void);
 extern asmlinkage void handle_tlbl(void);
@@ -69,6 +73,21 @@ int (*board_be_handler)(struct pt_regs *
  */
 #define MODULE_RANGE (8*1024*1024)
 
+struct notifier_block *mips_die_chain;
+static spinlock_t die_notifier_lock = SPIN_LOCK_UNLOCKED;
+
+int register_die_notifier(struct notifier_block *nb)
+{
+	int err = 0;
+	unsigned long flags;
+
+	spin_lock_irqsave(&die_notifier_lock, flags);
+	err = notifier_chain_register(&mips_die_chain, nb);
+	spin_unlock_irqrestore(&die_notifier_lock, flags);
+
+	return err;
+}
+
 /*
  * This routine abuses get_user()/put_user() to reference pointers
  * with at least a bit of error checking ...
@@ -271,8 +290,10 @@ NORET_TYPE void __die(const char * str, 
 void __die_if_kernel(const char * str, struct pt_regs * regs,
 		     const char * file, const char * func, unsigned long line)
 {
-	if (!user_mode(regs))
+	if (!user_mode(regs)) {
+		notify_die(DIE_TRAP, (char *)str, regs, 0);
 		__die(str, regs, file, func, line);
+	}
 }
 
 extern const struct exception_table_entry __start___dbe_table[];
@@ -958,6 +979,9 @@ void __init trap_init(void)
 	extern char except_vec4;
 	unsigned long i;
 
+	if (kgdb_early_setup)
+		return;	/* Already done */
+
 	per_cpu_trap_init();
 
 	/*
arch/mips/mips-boards/generic/init.c renamed from arch/mips/mips-boards/generic/init.c~mips-lite +0 -62

74 lines not on this page · raw message

arch/mips/mips-boards/generic/Makefile renamed from arch/mips/mips-boards/generic/Makefile~mips-lite +0 -1
diff -puN arch/mips/mips-boards/generic/Makefile~mips-lite arch/mips/mips-boards/generic/Makefile
@@ -21,6 +21,5 @@
 obj-y				:= mipsIRQ.o reset.o display.o init.o memory.o \
 				   printf.o cmdline.o time.o
 obj-$(CONFIG_PCI)		+= pci.o
-obj-$(CONFIG_KGDB)		+= gdb_hook.o
 
 EXTRA_AFLAGS := $(CFLAGS)
arch/mips/mips-boards/malta/malta_setup.c renamed from arch/mips/mips-boards/malta/malta_setup.c~mips-lite +0 -8
diff -puN arch/mips/mips-boards/malta/malta_setup.c~mips-lite arch/mips/mips-boards/malta/malta_setup.c
@@ -48,10 +48,6 @@ extern void mips_time_init(void);
 extern void mips_timer_setup(struct irqaction *irq);
 extern unsigned long mips_rtc_get_time(void);
 
-#ifdef CONFIG_KGDB
-extern void kgdb_config(void);
-#endif
-
 struct resource standard_io_resources[] = {
 	{ "dma1", 0x00, 0x1f, IORESOURCE_BUSY },
 	{ "timer", 0x40, 0x5f, IORESOURCE_BUSY },
@@ -124,10 +120,6 @@ static int __init malta_setup(void)
 	 */
 	enable_dma(4);
 
-#ifdef CONFIG_KGDB
-	kgdb_config ();
-#endif
-
 	if ((mips_revision_corid == MIPS_REVISION_CORID_BONITO64) ||
 	    (mips_revision_corid == MIPS_REVISION_CORID_CORE_20K) ||
 	    (mips_revision_corid == MIPS_REVISION_CORID_CORE_EMUL_BON)) {
arch/mips/mm/extable.c renamed from arch/mips/mm/extable.c~mips-lite +7 -0
diff -puN arch/mips/mm/extable.c~mips-lite arch/mips/mm/extable.c
@@ -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;
 }
arch/mips/sibyte/cfe/setup.c renamed from arch/mips/sibyte/cfe/setup.c~mips-lite +0 -14
diff -puN arch/mips/sibyte/cfe/setup.c~mips-lite arch/mips/sibyte/cfe/setup.c
@@ -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;
arch/mips/sibyte/sb1250/irq.c renamed from arch/mips/sibyte/sb1250/irq.c~mips-lite +6 -51

79 lines not on this page · raw message

arch/mips/sibyte/sb1250/irq_handler.S renamed from arch/mips/sibyte/sb1250/irq_handler.S~mips-lite +1 -1
diff -puN arch/mips/sibyte/sb1250/irq_handler.S~mips-lite arch/mips/sibyte/sb1250/irq_handler.S
@@ -102,7 +102,7 @@
 2:
 #endif
 
-#ifdef CONFIG_KGDB
+#ifdef CONFIG_KGDB_SIBYTE
 	/* KGDB (uart 1) interrupt is routed to IP[6] */
 	andi	t1, s0, CAUSEF_IP6
 	beqz	t1, 1f
arch/mips/sibyte/sb1250/kgdb_sibyte.c new file +164 -0

164 lines not on this page · raw message

arch/mips/sibyte/sb1250/Makefile renamed from arch/mips/sibyte/sb1250/Makefile~mips-lite +1 -0
diff -puN arch/mips/sibyte/sb1250/Makefile~mips-lite arch/mips/sibyte/sb1250/Makefile
@@ -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)
arch/mips/sibyte/swarm/dbg_io.c deleted +0 -76

76 lines not on this page · raw message

arch/mips/sibyte/swarm/Makefile renamed from arch/mips/sibyte/swarm/Makefile~mips-lite +0 -2
diff -puN arch/mips/sibyte/swarm/Makefile~mips-lite arch/mips/sibyte/swarm/Makefile
@@ -1,3 +1 @@
 lib-y				= setup.o rtc_xicor1241.o rtc_m41t81.o
-
-lib-$(CONFIG_KGDB)		+= dbg_io.o
include/asm-mips/kdebug.h new file +47 -0

47 lines not on this page · raw message

include/asm-mips/kgdb.h new file +22 -0
diff -puN /dev/null include/asm-mips/kgdb.h
@@ -0,0 +1,22 @@
+#ifdef __KERNEL__
+#ifndef _ASM_KGDB_H_
+#define _ASM_KGDB_H_
+
+#define BUFMAX			2048
+#define NUMREGBYTES		(90*sizeof(long))
+#define NUMCRITREGBYTES		(12*sizeof(long))
+#define BREAK_INSTR_SIZE	4
+#define BREAKPOINT()		__asm__ __volatile__(		\
+					".globl breakinst\n\t"	\
+					".set\tnoreorder\n\t"	\
+					"nop\n"			\
+					"breakinst:\tbreak\n\t"	\
+					"nop\n\t"		\
+					".set\treorder")
+#define CHECK_EXCEPTION_STACK()	1
+#define CACHE_FLUSH_IS_SAFE	0
+
+extern int kgdb_early_setup;
+
+#endif				/* _ASM_KGDB_H_ */
+#endif				/* __KERNEL__ */
lib/Kconfig.debug renamed from lib/Kconfig.debug~mips-lite +6 -1
diff -puN lib/Kconfig.debug~mips-lite lib/Kconfig.debug
@@ -163,7 +163,7 @@ config FRAME_POINTER
 
 config KGDB
 	bool "KGDB: kernel debugging with remote gdb"
-	depends on DEBUG_KERNEL && (X86 || ((!SMP || BROKEN) && (PPC32)))
+	depends on DEBUG_KERNEL && (X86 || MIPS32 || ((!SMP || BROKEN) && PPC32))
 	help
 	  If you say Y here, it will be possible to remotely debug the
 	  kernel using gdb. It is strongly suggested that you enable
@@ -189,6 +189,7 @@ choice
 	prompt "Method for KGDB communication"
 	depends on KGDB
 	default KGDB_ONLY_MODULES
+	default KGDB_SIBYTE if SIBYTE_SB1xxx_SOC
 	default KGDB_MPSC if SERIAL_MPSC
 	help
 	  There are a number of different ways in which you can communicate
@@ -222,6 +223,10 @@ config KGDB_MPSC
 	  Controller (MPSC) channel. Note that the GT64260A is not
 	  supported.
 
+config KGDB_SIBYTE
+	bool "KGDB: On the Broadcom SWARM serial port"
+	depends on MIPS && SIBYTE_SB1xxx_SOC
+
 endchoice
 
 config KGDB_8250

_

author
#5 lore raw

PATCH 6/15 Basic IA64 support

CC: Robert Picco <[email protected]>, Tony Luck <[email protected]> This is support of the IA64 arch for KGDB. This is primarily the work of Robert Picco. There are also some IA64 changes in the serial patch so that IA64 can pass in IRQ and iomembase, and all of this is documented in the DocBook files.

---

 linux-2.6.13-rc3-trini/arch/ia64/kernel/Makefile   |    1 
 linux-2.6.13-rc3-trini/arch/ia64/kernel/entry.S    |    4 
 linux-2.6.13-rc3-trini/arch/ia64/kernel/ivt.S      |   15 
 linux-2.6.13-rc3-trini/arch/ia64/kernel/kgdb-jmp.S |  238 ++++
 linux-2.6.13-rc3-trini/arch/ia64/kernel/kgdb.c     | 1038 +++++++++++++++++++++
 linux-2.6.13-rc3-trini/arch/ia64/kernel/mca.c      |   10 
 linux-2.6.13-rc3-trini/arch/ia64/kernel/process.c  |    6 
 linux-2.6.13-rc3-trini/arch/ia64/kernel/smp.c      |   17 
 linux-2.6.13-rc3-trini/arch/ia64/kernel/traps.c    |   36 
 linux-2.6.13-rc3-trini/arch/ia64/kernel/unwind.c   |   87 +
 linux-2.6.13-rc3-trini/arch/ia64/mm/extable.c      |    6 
 linux-2.6.13-rc3-trini/arch/ia64/mm/fault.c        |    5 
 linux-2.6.13-rc3-trini/include/asm-ia64/kgdb.h     |   37 
 linux-2.6.13-rc3-trini/lib/Kconfig.debug           |    2 
 14 files changed, 1497 insertions(+), 5 deletions(-)
arch/ia64/kernel/entry.S renamed from arch/ia64/kernel/entry.S~ia64-lite +2 -2
diff -puN arch/ia64/kernel/entry.S~ia64-lite arch/ia64/kernel/entry.S
@@ -929,9 +929,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
 
 	/*
arch/ia64/kernel/ivt.S renamed from arch/ia64/kernel/ivt.S~ia64-lite +15 -0
diff -puN arch/ia64/kernel/ivt.S~ia64-lite arch/ia64/kernel/ivt.S
@@ -69,6 +69,13 @@
 # define DBG_FAULT(i)
 #endif
 
+#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
+
 #define MINSTATE_VIRT	/* needed by minstate.h */
 #include "minstate.h"
 
@@ -479,6 +486,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
@@ -820,6 +828,7 @@ ENTRY(interrupt)
 	srlz.i			// ensure everybody knows psr.ic is back on
 	;;
 	SAVE_REST
+	KGDB_ENABLE_PSR_DB
 	;;
 	alloc r14=ar.pfs,0,0,2,0 // must be first in an insn group
 	mov out0=cr.ivr		// pass cr.ivr as first arg
@@ -1066,6 +1075,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
@@ -1099,6 +1109,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
@@ -1141,6 +1152,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
arch/ia64/kernel/kgdb.c new file +1038 -0

1,038 lines not on this page · raw message

arch/ia64/kernel/kgdb-jmp.S new file +238 -0

238 lines not on this page · raw message

arch/ia64/kernel/Makefile renamed from arch/ia64/kernel/Makefile~ia64-lite +1 -0
diff -puN arch/ia64/kernel/Makefile~ia64-lite arch/ia64/kernel/Makefile
@@ -24,6 +24,7 @@ obj-$(CONFIG_IA64_MCA_RECOVERY)	+= mca_r
 obj-$(CONFIG_KPROBES)		+= kprobes.o jprobes.o
 obj-$(CONFIG_IA64_UNCACHED_ALLOCATOR)	+= uncached.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
arch/ia64/kernel/mca.c renamed from arch/ia64/kernel/mca.c~ia64-lite +10 -0
diff -puN arch/ia64/kernel/mca.c~ia64-lite arch/ia64/kernel/mca.c
@@ -472,9 +472,18 @@ static void
 init_handler_platform (pal_min_state_area_t *ms,
 		       struct pt_regs *pt, struct switch_stack *sw)
 {
+#ifndef	CONFIG_KGDB
 	struct unw_frame_info info;
+#endif
 
 	/* if a kernel debugger is available call it here else just dump the registers */
+#ifdef	CONFIG_KGDB
+	fetch_min_state(ms, pt, sw);
+	/*
+	 * switch_stack is at ((char *) pt) - sizeof (struct switch_stack)
+	 */
+	kgdb_handle_exception(-1, SIGTRAP, 0, pt);
+#else
 
 	/*
 	 * Wait for a bit.  On some machines (e.g., HP's zx2000 and zx6000, INIT can be
@@ -510,6 +519,7 @@ init_handler_platform (pal_min_state_are
 	if (!tasklist_lock.write_lock)
 		read_unlock(&tasklist_lock);
 #endif
+#endif
 
 	printk("\nINIT dump complete.  Please reboot now.\n");
 	while (1);			/* hang city if no debugger */
arch/ia64/kernel/process.c renamed from arch/ia64/kernel/process.c~ia64-lite +6 -0
diff -puN arch/ia64/kernel/process.c~ia64-lite arch/ia64/kernel/process.c
@@ -451,6 +451,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
@@ -679,6 +682,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;
arch/ia64/kernel/smp.c renamed from arch/ia64/kernel/smp.c~ia64-lite +17 -0
diff -puN arch/ia64/kernel/smp.c~ia64-lite arch/ia64/kernel/smp.c
@@ -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.
arch/ia64/kernel/traps.c renamed from arch/ia64/kernel/traps.c~ia64-lite +34 -2
diff -puN arch/ia64/kernel/traps.c~ia64-lite arch/ia64/kernel/traps.c
@@ -15,6 +15,7 @@
 #include <linux/vt_kern.h>		/* For unblank_screen() */
 #include <linux/module.h>       /* for EXPORT_SYMBOL */
 #include <linux/hardirq.h>
+#include <linux/kgdb.h>
 
 #include <asm/fpswa.h>
 #include <asm/ia32.h>
@@ -108,6 +109,10 @@ die (const char *str, struct pt_regs *re
   	} else
 		printk(KERN_ERR "Recursive die() failure, output suppressed\n");
 
+#ifdef CONFIG_KGDB
+	kgdb_handle_exception(1, SIGTRAP, err, regs);
+#endif
+
 	bust_spinlocks(0);
 	die.lock_owner = -1;
 	spin_unlock_irq(&die.lock);
@@ -157,7 +162,9 @@ ia64_bad_break (unsigned long break_num,
 			       	== NOTIFY_STOP) {
 			return;
 		}
+#ifndef	CONFIG_KGDB
 		die_if_kernel("bugcheck!", regs, break_num);
+#endif
 		sig = SIGILL; code = ILL_ILLOPC;
 		break;
 
@@ -219,8 +226,10 @@ ia64_bad_break (unsigned long break_num,
 		break;
 
 	      default:
+#ifndef	CONFIG_KGDB
 		if (break_num < 0x40000 || break_num > 0x100000)
 			die_if_kernel("Bad break", regs, break_num);
+#endif
 
 		if (break_num < 0x80000) {
 			sig = SIGILL; code = __ILL_BREAK;
@@ -228,6 +237,15 @@ ia64_bad_break (unsigned long break_num,
 			sig = SIGTRAP; code = TRAP_BRKPT;
 		}
 	}
+#ifdef	CONFIG_KGDB
+	/*
+	 * We don't want to trap simulator system calls.
+	 */
+	if (break_num != 0x80001) {
+		kgdb_handle_exception(11, sig, break_num, regs);
+		return;
+	}
+#endif
 	siginfo.si_signo = sig;
 	siginfo.si_errno = 0;
 	siginfo.si_code = code;
@@ -543,10 +561,21 @@ ia64_fault (unsigned long vector, unsign
 		}
 		sprintf(buf, "Unsupported data reference");
 		break;
-
 	      case 29: /* Debug */
-	      case 35: /* Taken Branch Trap */
 	      case 36: /* Single Step Trap */
+#ifdef CONFIG_KGDB
+		if (vector == 36 && !user_mode(&regs) &&
+			kgdb_hwbreak_sstep[smp_processor_id()]) {
+			kgdb_hwbreak_sstep[smp_processor_id()] = 0;
+			regs.cr_ipsr &= ~IA64_PSR_SS;
+			return;
+		} else if (!user_mode(&regs)) {
+			kgdb_handle_exception(vector, SIGTRAP, isr, &regs);
+			return;
+		}
+#endif
+		/* Fall */
+	      case 35: /* Taken Branch Trap */
 		if (fsys_mode(current, &regs)) {
 			extern char __kernel_syscall_via_break[];
 			/*
@@ -664,6 +693,9 @@ ia64_fault (unsigned long vector, unsign
 		sprintf(buf, "Fault %lu", vector);
 		break;
 	}
+#ifdef CONFIG_KGDB
+	kgdb_handle_exception(vector, SIGTRAP, isr, &regs);
+#endif
 	die_if_kernel(buf, &regs, error);
 	force_sig(SIGILL, current);
 }
arch/ia64/kernel/unwind.c renamed from arch/ia64/kernel/unwind.c~ia64-lite +87 -0

123 lines not on this page · raw message

arch/ia64/mm/extable.c renamed from arch/ia64/mm/extable.c~ia64-lite +6 -0
diff -puN arch/ia64/mm/extable.c~ia64-lite arch/ia64/mm/extable.c
@@ -7,6 +7,7 @@
 
 #include <linux/config.h>
 #include <linux/sort.h>
+#include <linux/kgdb.h>
 
 #include <asm/uaccess.h>
 #include <asm/module.h>
@@ -74,6 +75,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;
 }
 
arch/ia64/mm/fault.c renamed from arch/ia64/mm/fault.c~ia64-lite +5 -0
diff -puN arch/ia64/mm/fault.c~ia64-lite arch/ia64/mm/fault.c
@@ -9,6 +9,7 @@
 #include <linux/mm.h>
 #include <linux/smp_lock.h>
 #include <linux/interrupt.h>
+#include <linux/kgdb.h>
 
 #include <asm/pgtable.h>
 #include <asm/processor.h>
@@ -248,6 +249,10 @@ ia64_do_page_fault (unsigned long addres
 	 */
 	bust_spinlocks(1);
 
+#ifdef CONFIG_KGDB
+	kgdb_handle_exception(14, SIGSEGV, isr, regs);
+#endif
+
 	if (address < PAGE_SIZE)
 		printk(KERN_ALERT "Unable to handle kernel NULL pointer dereference (address %016lx)\n", address);
 	else
include/asm-ia64/kgdb.h new file +37 -0
diff -puN /dev/null include/asm-ia64/kgdb.h
@@ -0,0 +1,37 @@
+#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 CHECK_EXCEPTION_STACK()	1
+#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__ */
lib/Kconfig.debug renamed from lib/Kconfig.debug~ia64-lite +1 -1
diff -puN lib/Kconfig.debug~ia64-lite lib/Kconfig.debug
@@ -163,7 +163,7 @@ config FRAME_POINTER
 
 config KGDB
 	bool "KGDB: kernel debugging with remote gdb"
-	depends on DEBUG_KERNEL && (X86 || MIPS32 || ((!SMP || BROKEN) && PPC32))
+	depends on DEBUG_KERNEL && (X86 || MIPS32 || IA64 || ((!SMP || BROKEN) && PPC32))
 	help
 	  If you say Y here, it will be possible to remotely debug the
 	  kernel using gdb. It is strongly suggested that you enable

_

author
#6 lore raw

PATCH 7/15 Basic x86_64 support

CC: Andi Kleen <[email protected]>, Amit S Kale <[email protected]> This adds support for the x86_64 architecture. In addition to what was noted in the core-lite patch about stuff outside of new files, we add -g0 to compiling of syscalls.o as otherwise we run into problems when debugging modules, and like i386 annotate switch_to().

---

 linux-2.6.13-rc3-trini/arch/x86_64/Kconfig.debug     |    3 
 linux-2.6.13-rc3-trini/arch/x86_64/kernel/Makefile   |    2 
 linux-2.6.13-rc3-trini/arch/x86_64/kernel/kgdb-jmp.S |   65 ++
 linux-2.6.13-rc3-trini/arch/x86_64/kernel/kgdb.c     |  462 +++++++++++++++++++
 linux-2.6.13-rc3-trini/arch/x86_64/kernel/traps.c    |    9 
 linux-2.6.13-rc3-trini/include/asm-x86_64/hw_irq.h   |    1 
 linux-2.6.13-rc3-trini/include/asm-x86_64/ipi.h      |   12 
 linux-2.6.13-rc3-trini/include/asm-x86_64/kgdb.h     |   50 ++
 linux-2.6.13-rc3-trini/include/asm-x86_64/system.h   |    6 
 linux-2.6.13-rc3-trini/lib/Kconfig.debug             |    2 
 10 files changed, 607 insertions(+), 5 deletions(-)
arch/x86_64/Kconfig.debug renamed from arch/x86_64/Kconfig.debug~x86_64-lite +0 -3
diff -puN arch/x86_64/Kconfig.debug~x86_64-lite arch/x86_64/Kconfig.debug
@@ -51,7 +51,4 @@ config IOMMU_LEAK
          Add a simple leak tracer to the IOMMU code. This is useful when you
 	 are debugging a buggy device driver that leaks IOMMU mappings.
 
-#config X86_REMOTE_DEBUG
-#       bool "kgdb debugging stub"
-
 endmenu
arch/x86_64/kernel/kgdb.c new file +462 -0

462 lines not on this page · raw message

arch/x86_64/kernel/kgdb-jmp.S new file +65 -0

65 lines not on this page · raw message

arch/x86_64/kernel/Makefile renamed from arch/x86_64/kernel/Makefile~x86_64-lite +2 -0
diff -puN arch/x86_64/kernel/Makefile~x86_64-lite arch/x86_64/kernel/Makefile
@@ -4,6 +4,7 @@
 
 extra-y 	:= head.o head64.o init_task.o vmlinux.lds
 EXTRA_AFLAGS	:= -traditional
+CFLAGS_vsyscall.o := -g0
 obj-y	:= process.o semaphore.o signal.o entry.o traps.o irq.o \
 		ptrace.o time.o ioport.o ldt.o setup.o i8259.o sys_x86_64.o \
 		x8664_ksyms.o i387.o syscall.o vsyscall.o \
@@ -29,6 +30,7 @@ obj-$(CONFIG_GART_IOMMU)	+= pci-gart.o a
 obj-$(CONFIG_DUMMY_IOMMU)	+= pci-nommu.o pci-dma.o
 obj-$(CONFIG_SWIOTLB)		+= swiotlb.o
 obj-$(CONFIG_KPROBES)		+= kprobes.o
+obj-$(CONFIG_KGDB)		+= kgdb.o kgdb-jmp.o
 obj-$(CONFIG_X86_PM_TIMER)	+= pmtimer.o
 
 obj-$(CONFIG_MODULES)		+= module.o
arch/x86_64/kernel/traps.c renamed from arch/x86_64/kernel/traps.c~x86_64-lite +9 -0
diff -puN arch/x86_64/kernel/traps.c~x86_64-lite arch/x86_64/kernel/traps.c
@@ -29,6 +29,7 @@
 #include <linux/module.h>
 #include <linux/moduleparam.h>
 #include <linux/nmi.h>
+#include <linux/kgdb.h>
 
 #include <asm/system.h>
 #include <asm/uaccess.h>
@@ -940,6 +941,14 @@ void __init trap_init(void)
 	 * Should be a barrier for any external CPU state.
 	 */
 	cpu_init();
+
+#ifdef CONFIG_KGDB
+	/*
+	 * Has KGDB been told to break as soon as possible?
+	 */
+	if (kgdb_initialized == -1)
+		tasklet_schedule(&kgdb_tasklet_breakpoint);
+#endif
 }
 
 

diff -puN arch/x86_64/mm/extable.c~x86_64-lite arch/x86_64/mm/extable.c

include/asm-x86_64/hw_irq.h renamed from include/asm-x86_64/hw_irq.h~x86_64-lite +1 -0
diff -puN include/asm-x86_64/hw_irq.h~x86_64-lite include/asm-x86_64/hw_irq.h
@@ -55,6 +55,7 @@ struct hw_interrupt_type;
 #define TASK_MIGRATION_VECTOR	0xfb
 #define CALL_FUNCTION_VECTOR	0xfa
 #define KDB_VECTOR	0xf9
+#define KGDB_VECTOR	0xf8
 
 #define THERMAL_APIC_VECTOR	0xf0
 
include/asm-x86_64/ipi.h renamed from include/asm-x86_64/ipi.h~x86_64-lite +12 -0
diff -puN include/asm-x86_64/ipi.h~x86_64-lite include/asm-x86_64/ipi.h
@@ -62,6 +62,12 @@ static inline void __send_IPI_shortcut(u
 	 * No need to touch the target chip field
 	 */
 	cfg = __prepare_ICR(shortcut, vector, dest);
+        if (vector == KGDB_VECTOR) {
+                 /*
+                  * KGDB IPI is to be delivered as a NMI
+                  */
+                 cfg = (cfg&~APIC_VECTOR_MASK)|APIC_DM_NMI;
+         }
 
 	/*
 	 * Send the IPI. The write to APIC_ICR fires this off.
@@ -100,6 +106,12 @@ static inline void send_IPI_mask_sequenc
 			 * program the ICR
 			 */
 			cfg = __prepare_ICR(0, vector, APIC_DEST_PHYSICAL);
+		        if (vector == KGDB_VECTOR) {
+	                	 /*
+        		          * KGDB IPI is to be delivered as a NMI
+		                  */
+                		 cfg = (cfg&~APIC_VECTOR_MASK)|APIC_DM_NMI;
+		         }
 
 			/*
 			 * Send the IPI. The write to APIC_ICR fires this off.
include/asm-x86_64/kgdb.h new file +50 -0

50 lines not on this page · raw message

include/asm-x86_64/system.h renamed from include/asm-x86_64/system.h~x86_64-lite +5 -1
diff -puN include/asm-x86_64/system.h~x86_64-lite include/asm-x86_64/system.h
@@ -27,7 +27,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"					  \
@@ -39,6 +41,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)), \
lib/Kconfig.debug renamed from lib/Kconfig.debug~x86_64-lite +1 -1
diff -puN lib/Kconfig.debug~x86_64-lite lib/Kconfig.debug
@@ -163,7 +163,7 @@ config FRAME_POINTER
 
 config KGDB
 	bool "KGDB: kernel debugging with remote gdb"
-	depends on DEBUG_KERNEL && (X86 || MIPS32 || IA64 || ((!SMP || BROKEN) && PPC32))
+	depends on DEBUG_KERNEL && (X86 || MIPS32 || IA64 || X86_64 || ((!SMP || BROKEN) && PPC32))
 	help
 	  If you say Y here, it will be possible to remotely debug the
 	  kernel using gdb. It is strongly suggested that you enable

_

author
#7 lore raw

PATCH 8/15 Basic SuperH support

CC: Paul Mundt <[email protected]>, Kazumoto Kojima <[email protected]> This adds basic support for KGDB on SuperH as well as adding some architecture specific notes to the DocBook file and converting the 7751 to use this. I have tested all combinations of 8250 and SCI(F) ports being used as KGDB and console that I could (one of each usable to me).

---

 linux-2.6.13-rc3-trini/Documentation/DocBook/kgdb.tmpl |   16 
 linux-2.6.13-rc3-trini/arch/sh/Kconfig.debug           |   92 -
 linux-2.6.13-rc3-trini/arch/sh/Makefile                |    1 
 linux-2.6.13-rc3-trini/arch/sh/boards/se/7751/setup.c  |  139 -
 linux-2.6.13-rc3-trini/arch/sh/kernel/Makefile         |    2 
 linux-2.6.13-rc3-trini/arch/sh/kernel/cpu/sh3/ex.S     |    2 
 linux-2.6.13-rc3-trini/arch/sh/kernel/cpu/sh4/ex.S     |    2 
 linux-2.6.13-rc3-trini/arch/sh/kernel/entry.S          |   30 
 linux-2.6.13-rc3-trini/arch/sh/kernel/kgdb-jmp.S       |   32 
 linux-2.6.13-rc3-trini/arch/sh/kernel/kgdb.c           |  363 ++++
 linux-2.6.13-rc3-trini/arch/sh/kernel/setup.c          |   94 -
 linux-2.6.13-rc3-trini/arch/sh/kernel/time.c           |   11 
 linux-2.6.13-rc3-trini/arch/sh/kernel/traps.c          |   20 
 linux-2.6.13-rc3-trini/arch/sh/mm/extable.c            |    7 
 linux-2.6.13-rc3-trini/arch/sh/mm/fault-nommu.c        |   14 
 linux-2.6.13-rc3-trini/arch/sh/mm/fault.c              |   12 
 linux-2.6.13-rc3-trini/drivers/serial/sh-sci.c         |  314 ++-
 linux-2.6.13-rc3-trini/include/asm-sh/kgdb.h           |  118 -
 linux-2.6.13-rc3-trini/include/asm-sh/system.h         |   40 
 linux-2.6.13-rc3-trini/lib/Kconfig.debug               |   14 
 linux-2.6.13-rc3/arch/sh/kernel/kgdb_jmp.S             |   33 
 linux-2.6.13-rc3/arch/sh/kernel/kgdb_stub.c            | 1491 -----------------
 22 files changed, 702 insertions(+), 2145 deletions(-)
arch/sh/boards/se/7751/setup.c renamed from arch/sh/boards/se/7751/setup.c~sh-lite +0 -139
diff -puN arch/sh/boards/se/7751/setup.c~sh-lite arch/sh/boards/se/7751/setup.c
@@ -18,10 +18,6 @@
 #include <asm/io.h>
 #include <asm/se7751/se7751.h>
 
-#ifdef CONFIG_SH_KGDB
-#include <asm/kgdb.h>
-#endif
-
 /*
  * Configure the Super I/O chip
  */
@@ -83,12 +79,6 @@ const char *get_system_type(void)
 	return "7751 SolutionEngine";
 }
 
-#ifdef CONFIG_SH_KGDB
-static int kgdb_uart_setup(void);
-static struct kgdb_sermap kgdb_uart_sermap = 
-{ "ttyS", 0, kgdb_uart_setup, NULL };
-#endif
- 
 /*
  * Initialize the board
  */
@@ -96,133 +86,4 @@ void __init platform_setup(void)
 {
 	/* Call init_smsc() replacement to set up SuperIO. */
 	/* XXX: RTC setting comes here */
-#ifdef CONFIG_SH_KGDB
-	kgdb_register_sermap(&kgdb_uart_sermap);
-#endif
-}
-
-/*********************************************************************
- * Currently a hack (e.g. does not interact well w/serial.c, lots of *
- * hardcoded stuff) but may be useful if SCI/F needs debugging.      *
- * Mostly copied from x86 code (see files asm-i386/kgdb_local.h and  *
- * arch/i386/lib/kgdb_serial.c).                                     *
- *********************************************************************/
-
-#ifdef CONFIG_SH_KGDB
-#include <linux/types.h>
-#include <linux/serial.h>
-#include <linux/serialP.h>
-#include <linux/serial_reg.h>
-
-#define COM1_PORT 0x3f8  /* Base I/O address */
-#define COM1_IRQ  4      /* IRQ not used yet */
-#define COM2_PORT 0x2f8  /* Base I/O address */
-#define COM2_IRQ  3      /* IRQ not used yet */
-
-#define SB_CLOCK 1843200 /* Serial baud clock */
-#define SB_BASE (SB_CLOCK/16)
-#define SB_MCR UART_MCR_OUT2 | UART_MCR_DTR | UART_MCR_RTS
-
-struct uart_port {
-	int base;
-};
-#define UART_NPORTS 2
-struct uart_port uart_ports[] = {
-	{ COM1_PORT },
-	{ COM2_PORT },
-};
-struct uart_port *kgdb_uart_port;
-
-#define UART_IN(reg)	inb_p(kgdb_uart_port->base + reg)
-#define UART_OUT(reg,v)	outb_p((v), kgdb_uart_port->base + reg)
-
-/* Basic read/write functions for the UART */
-#define UART_LSR_RXCERR    (UART_LSR_BI | UART_LSR_FE | UART_LSR_PE)
-static int kgdb_uart_getchar(void)
-{
-	int lsr;
-	int c = -1;
-
-	while (c == -1) {
-		lsr = UART_IN(UART_LSR);
-		if (lsr & UART_LSR_DR) 
-			c = UART_IN(UART_RX);
-		if ((lsr & UART_LSR_RXCERR))
-			c = -1;
-	}
-	return c;
-}
-
-static void kgdb_uart_putchar(int c)
-{
-	while ((UART_IN(UART_LSR) & UART_LSR_THRE) == 0)
-		;
-	UART_OUT(UART_TX, c);
-}
-
-/*
- * Initialize UART to configured/requested values.
- * (But we don't interrupts yet, or interact w/serial.c)
- */
-static int kgdb_uart_setup(void)
-{
-	int port;
-	int lcr = 0;
-	int bdiv = 0;
-
-	if (kgdb_portnum >= UART_NPORTS) {
-		KGDB_PRINTK("uart port %d invalid.\n", kgdb_portnum);
-		return -1;
-	}
-
-	kgdb_uart_port = &uart_ports[kgdb_portnum];
-
-	/* Init sequence from gdb_hook_interrupt */
-	UART_IN(UART_RX);
-	UART_OUT(UART_IER, 0);
-
-	UART_IN(UART_RX);	/* Serial driver comments say */
-	UART_IN(UART_IIR);	/* this clears interrupt regs */
-	UART_IN(UART_MSR);
-
-	/* Figure basic LCR values */
-	switch (kgdb_bits) {
-	case '7':
-		lcr |= UART_LCR_WLEN7;
-		break;
-	default: case '8': 
-		lcr |= UART_LCR_WLEN8;
-		break;
-	}
-	switch (kgdb_parity) {
-	case 'O':
-		lcr |= UART_LCR_PARITY;
-		break;
-	case 'E':
-		lcr |= (UART_LCR_PARITY | UART_LCR_EPAR);
-		break;
-	default: break;
-	}
-
-	/* Figure the baud rate divisor */
-	bdiv = (SB_BASE/kgdb_baud);
-	
-	/* Set the baud rate and LCR values */
-	UART_OUT(UART_LCR, (lcr | UART_LCR_DLAB));
-	UART_OUT(UART_DLL, (bdiv & 0xff));
-	UART_OUT(UART_DLM, ((bdiv >> 8) & 0xff));
-	UART_OUT(UART_LCR, lcr);
-
-	/* Set the MCR */
-	UART_OUT(UART_MCR, SB_MCR);
-
-	/* Turn off FIFOs for now */
-	UART_OUT(UART_FCR, 0);
-
-	/* Setup complete: initialize function pointers */
-	kgdb_getchar = kgdb_uart_getchar;
-	kgdb_putchar = kgdb_uart_putchar;
-
-	return 0;
 }
-#endif /* CONFIG_SH_KGDB */
arch/sh/Kconfig.debug renamed from arch/sh/Kconfig.debug~sh-lite +0 -92

96 lines not on this page · raw message

arch/sh/kernel/cpu/sh3/ex.S renamed from arch/sh/kernel/cpu/sh3/ex.S~sh-lite +1 -1
diff -puN arch/sh/kernel/cpu/sh3/ex.S~sh-lite arch/sh/kernel/cpu/sh3/ex.S
@@ -43,7 +43,7 @@ ENTRY(exception_handling_table)
 	.long	exception_error	! reserved_instruction (filled by trap_init) /* 180 */
 	.long	exception_error	! illegal_slot_instruction (filled by trap_init) /*1A0*/
 ENTRY(nmi_slot)
-#if defined (CONFIG_KGDB_NMI)
+#if defined (CONFIG_KGDB)
 	.long	debug_enter	/* 1C0 */	! Allow trap to debugger
 #else
 	.long	exception_none	/* 1C0 */	! Not implemented yet
arch/sh/kernel/cpu/sh4/ex.S renamed from arch/sh/kernel/cpu/sh4/ex.S~sh-lite +1 -1
diff -puN arch/sh/kernel/cpu/sh4/ex.S~sh-lite arch/sh/kernel/cpu/sh4/ex.S
@@ -47,7 +47,7 @@ ENTRY(exception_handling_table)
 	.long	exception_error	! reserved_instruction (filled by trap_init) /* 180 */
 	.long	exception_error	! illegal_slot_instruction (filled by trap_init) /*1A0*/
 ENTRY(nmi_slot)
-#if defined (CONFIG_KGDB_NMI)
+#if defined (CONFIG_KGDB)
 	.long	debug_enter	/* 1C0 */	! Allow trap to debugger
 #else
 	.long	exception_none	/* 1C0 */	! Not implemented yet
arch/sh/kernel/entry.S renamed from arch/sh/kernel/entry.S~sh-lite +16 -14
diff -puN arch/sh/kernel/entry.S~sh-lite arch/sh/kernel/entry.S
@@ -92,7 +92,7 @@ INTEVT  = 0xff000028
 MMU_TEA = 0xff00000c		! TLB Exception Address Register
 #endif
 
-#if defined(CONFIG_KGDB_NMI)
+#if defined(CONFIG_KGDB)
 NMI_VEC = 0x1c0			! Must catch early for debounce
 #endif
 
@@ -244,31 +244,33 @@ call_dae:
 2:	.long   do_address_error
 #endif /* CONFIG_MMU */
 
-#if defined(CONFIG_SH_STANDARD_BIOS) || defined(CONFIG_SH_KGDB)
+#if defined(CONFIG_SH_STANDARD_BIOS) || defined(CONFIG_KGDB)
 ! Handle kernel debug if either kgdb (SW) or gdb-stub (FW) is present.
 ! If both are configured, handle the debug traps (breakpoints) in SW,
 ! but still allow BIOS traps to FW.
 
 	.align	2
 debug_kernel:
-#if defined(CONFIG_SH_STANDARD_BIOS) && defined(CONFIG_SH_KGDB)
+#if defined(CONFIG_SH_STANDARD_BIOS) && defined(CONFIG_KGDB)
 	/* Force BIOS call to FW (debug_trap put TRA in r8) */
 	mov	r8,r0
 	shlr2	r0
 	cmp/eq	#0x3f,r0
 	bt	debug_kernel_fw
-#endif /* CONFIG_SH_STANDARD_BIOS && CONFIG_SH_KGDB */
+#endif /* CONFIG_SH_STANDARD_BIOS && CONFIG_KGDB */
 
-debug_enter:		
-#if defined(CONFIG_SH_KGDB)
+	.align 2
+	.globl debug_enter
+debug_enter:
+#if defined(CONFIG_KGDB)
 	/* Jump to kgdb, pass stacked regs as arg */
 debug_kernel_sw:
 	mov.l	3f, r0
 	jmp	@r0
 	 mov	r15, r4
 	.align	2
-3:	.long	kgdb_handle_exception
-#endif /* CONFIG_SH_KGDB */
+3:	.long	kgdb_exception_handler
+#endif /* CONFIG_KGDB */
 
 #if defined(CONFIG_SH_STANDARD_BIOS)
 	/* Unwind the stack and jmp to the debug entry */
@@ -310,12 +312,12 @@ debug_kernel_fw:
 2:	.long	gdb_vbr_vector
 #endif /* CONFIG_SH_STANDARD_BIOS */
 
-#endif /* CONFIG_SH_STANDARD_BIOS || CONFIG_SH_KGDB */
+#endif /* CONFIG_SH_STANDARD_BIOS || CONFIG_KGDB */
 
 
 	.align	2
-debug_trap:	
-#if defined(CONFIG_SH_STANDARD_BIOS) || defined(CONFIG_SH_KGDB)
+debug_trap:
+#if defined(CONFIG_SH_STANDARD_BIOS) || defined(CONFIG_KGDB)
 	mov	#OFF_SR, r0
 	mov.l	@(r0,r15), r0		! get status register
 	shll	r0
@@ -659,7 +661,7 @@ skip_restore:
 6:	or	k0, k2			! Set the IMASK-bits
 	ldc	k2, ssr
 	!
-#if defined(CONFIG_KGDB_NMI)
+#if defined(CONFIG_KGDB)
 	! Clear in_nmi
 	mov.l	4f, k0
 	mov	#0, k1
@@ -711,7 +713,7 @@ tlb_miss:
 interrupt:
 	mov.l	2f, k2
 	mov.l	3f, k3
-#if defined(CONFIG_KGDB_NMI)
+#if defined(CONFIG_KGDB)
 	! Debounce (filter nested NMI)
 	mov.l	@k2, k0
 	mov.l	5f, k1
@@ -726,7 +728,7 @@ interrupt:
 5:	.long	NMI_VEC
 6:	.long	in_nmi
 0:
-#endif /* defined(CONFIG_KGDB_NMI) */
+#endif /* defined(CONFIG_KGDB) */
 	bra	handle_exception
 	 mov.l	@k2, k2
 
arch/sh/kernel/kgdb.c new file +363 -0

363 lines not on this page · raw message

arch/sh/kernel/kgdb_jmp.S deleted +0 -33
diff -L arch/sh/kernel/kgdb_jmp.S -puN arch/sh/kernel/kgdb_jmp.S~sh-lite /dev/null
@@ -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
-
arch/sh/kernel/kgdb-jmp.S new file +32 -0
diff -puN /dev/null arch/sh/kernel/kgdb-jmp.S
@@ -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
arch/sh/kernel/kgdb_stub.c deleted +0 -1491

1,491 lines not on this page · raw message

arch/sh/kernel/Makefile renamed from arch/sh/kernel/Makefile~sh-lite +1 -1
diff -puN arch/sh/kernel/Makefile~sh-lite arch/sh/kernel/Makefile
@@ -13,7 +13,7 @@ obj-y				+= cpu/
 obj-$(CONFIG_SMP)		+= smp.o
 obj-$(CONFIG_CF_ENABLER)	+= cf-enabler.o
 obj-$(CONFIG_SH_STANDARD_BIOS)	+= sh_bios.o
-obj-$(CONFIG_SH_KGDB)		+= kgdb_stub.o kgdb_jmp.o
+obj-$(CONFIG_KGDB)		+= kgdb.o kgdb-jmp.o
 obj-$(CONFIG_SH_CPU_FREQ)	+= cpufreq.o
 obj-$(CONFIG_MODULES)		+= module.o
 obj-$(CONFIG_EARLY_PRINTK)	+= early_printk.o
arch/sh/kernel/setup.c renamed from arch/sh/kernel/setup.c~sh-lite +0 -94

103 lines not on this page · raw message

arch/sh/kernel/time.c renamed from arch/sh/kernel/time.c~sh-lite +0 -11
diff -puN arch/sh/kernel/time.c~sh-lite arch/sh/kernel/time.c
@@ -34,9 +34,6 @@
 #include <asm/rtc.h>
 #include <asm/freq.h>
 #include <asm/cpu/timer.h>
-#ifdef CONFIG_SH_KGDB
-#include <asm/kgdb.h>
-#endif
 
 #include <linux/timex.h>
 #include <linux/irq.h>
@@ -646,12 +643,4 @@ void __init time_init(void)
 	ctrl_outl(interval, TMU0_TCOR);
 	ctrl_outl(interval, TMU0_TCNT);
 	ctrl_outb(TMU_TSTR_INIT, TMU_TSTR);
-
-#if defined(CONFIG_SH_KGDB)
-	/*
-	 * Set up kgdb as requested. We do it here because the serial
-	 * init uses the timer vars we just set up for figuring baud.
-	 */
-	kgdb_init();
-#endif
 }
arch/sh/kernel/traps.c renamed from arch/sh/kernel/traps.c~sh-lite +7 -13
diff -puN arch/sh/kernel/traps.c~sh-lite arch/sh/kernel/traps.c
@@ -27,6 +27,7 @@
 #include <linux/spinlock.h>
 #include <linux/module.h>
 #include <linux/kallsyms.h>
+#include <linux/kgdb.h>
 
 #include <asm/system.h>
 #include <asm/uaccess.h>
@@ -35,17 +36,8 @@
 #include <asm/processor.h>
 #include <asm/sections.h>
 
-#ifdef CONFIG_SH_KGDB
-#include <asm/kgdb.h>
-#define CHK_REMOTE_DEBUG(regs)                                               \
-{                                                                            \
-  if ((kgdb_debug_hook != (kgdb_debug_hook_t *) NULL) && (!user_mode(regs))) \
-  {                                                                          \
-    (*kgdb_debug_hook)(regs);                                                \
-  }                                                                          \
-}
-#else
-#define CHK_REMOTE_DEBUG(regs)
+#ifndef CONFIG_KGDB
+#define kgdb_handle_exception(t, s, e, r)
 #endif
 
 #define DO_ERROR(trapnr, signr, str, name, tsk)				\
@@ -66,7 +58,7 @@ asmlinkage void do_##name(unsigned long 
 	local_irq_enable();						\
 	tsk->thread.error_code = error_code;				\
 	tsk->thread.trap_no = trapnr;					\
-        CHK_REMOTE_DEBUG(&regs);					\
+	kgdb_handle_exception(trapnr, signr, error_code, &regs);	\
 	force_sig(signr, tsk);						\
 	die_if_no_fixup(str,&regs,error_code);				\
 }
@@ -93,10 +85,12 @@ void die(const char * str, struct pt_reg
 {
 	static int die_counter;
 
+#ifdef CONFIG_KGDB
+	kgdb_handle_exception(1, SIGTRAP, err, regs);
+#endif
 	console_verbose();
 	spin_lock_irq(&die_lock);
 	printk("%s: %04lx [#%d]\n", str, err & 0xffff, ++die_counter);
-	CHK_REMOTE_DEBUG(regs);
 	show_regs(regs);
 	spin_unlock_irq(&die_lock);
 	do_exit(SIGSEGV);
arch/sh/Makefile renamed from arch/sh/Makefile~sh-lite +0 -1
diff -puN arch/sh/Makefile~sh-lite arch/sh/Makefile
@@ -23,7 +23,6 @@ cflags-$(CONFIG_CPU_SH4)		+= -m4 \
 	$(call cc-option,-mno-implicit-fp,-m4-nofpu)
 
 cflags-$(CONFIG_SH_DSP)			+= -Wa,-dsp
-cflags-$(CONFIG_SH_KGDB)		+= -g
 
 cflags-$(CONFIG_MORE_COMPILE_OPTIONS)	+= \
 	$(shell echo $(CONFIG_COMPILE_OPTIONS) | sed -e 's/"//g')
arch/sh/mm/extable.c renamed from arch/sh/mm/extable.c~sh-lite +7 -0
diff -puN arch/sh/mm/extable.c~sh-lite arch/sh/mm/extable.c
@@ -6,6 +6,7 @@
 
 #include <linux/config.h>
 #include <linux/module.h>
+#include <linux/kgdb.h>
 #include <asm/uaccess.h>
 
 int fixup_exception(struct pt_regs *regs)
@@ -17,6 +18,12 @@ int fixup_exception(struct pt_regs *regs
 		regs->pc = fixup->fixup;
 		return 1;
 	}
+#ifdef CONFIG_KGDB
+	if (atomic_read(&debugger_active) && kgdb_may_fault)
+		/* Restore our previous state. */
+		kgdb_fault_longjmp(kgdb_fault_jmp_regs);
+		/* Never reached. */
+#endif
 
 	return 0;
 }
arch/sh/mm/fault.c renamed from arch/sh/mm/fault.c~sh-lite +1 -11
diff -puN arch/sh/mm/fault.c~sh-lite arch/sh/mm/fault.c
@@ -28,7 +28,6 @@
 #include <asm/pgalloc.h>
 #include <asm/mmu_context.h>
 #include <asm/cacheflush.h>
-#include <asm/kgdb.h>
 
 extern void die(const char *,struct pt_regs *,long);
 
@@ -45,11 +44,6 @@ asmlinkage void do_page_fault(struct pt_
 	struct vm_area_struct * vma;
 	unsigned long page;
 
-#ifdef CONFIG_SH_KGDB
-	if (kgdb_nofault && kgdb_bus_err_hook)
-		kgdb_bus_err_hook();
-#endif
-
 	tsk = current;
 	mm = tsk->mm;
 
@@ -153,6 +147,7 @@ no_context:
 	}
 	die("Oops", regs, writeaccess);
 	do_exit(SIGKILL);
+	dump_stack();
 
 /*
  * We ran out of memory, or some other thing happened to us that made
@@ -199,11 +194,6 @@ asmlinkage int __do_page_fault(struct pt
 	pte_t *pte;
 	pte_t entry;
 
-#ifdef CONFIG_SH_KGDB
-	if (kgdb_nofault && kgdb_bus_err_hook)
-		kgdb_bus_err_hook();
-#endif
-
 #ifdef CONFIG_SH_STORE_QUEUES
 	addrmax = P4SEG_STORE_QUE + 0x04000000;
 #endif
arch/sh/mm/fault-nommu.c renamed from arch/sh/mm/fault-nommu.c~sh-lite +0 -14
diff -puN arch/sh/mm/fault-nommu.c~sh-lite arch/sh/mm/fault-nommu.c
@@ -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;
 
Documentation/DocBook/kgdb.tmpl renamed from Documentation/DocBook/kgdb.tmpl~sh-lite +16 -0
diff -puN Documentation/DocBook/kgdb.tmpl~sh-lite Documentation/DocBook/kgdb.tmpl
@@ -127,6 +127,10 @@
     <constant>kgdbwait</constant> after this arguement.
     </para>
     <para>
+    To specify the values of the SH SCI(F) serial port at boot:
+    <constant>kgdbsci=0,115200</constant>.
+    </para>
+    <para>
     To configure the <symbol>CONFIG_KGDB_ETH</symbol> driver, pass in
     <constant>kgdboe=[src-port]@&lt;src-ip&gt;/[dev],[tgt-port]@&lt;tgt-ip&gt;/[tgt-macaddr]</constant>
     where:
@@ -168,6 +172,18 @@
     application program.
     </para>
   </chapter>
+  <chapter id="ArchitectureNotes">
+    <title>Architecture specific notes</title>
+      <para>
+      SuperH: The NMI switch found on some boards can be used to trigger an
+      initial breakpoint.  Subsequent triggers do nothing.  If console
+      is enabled on the SCI(F) serial port, and that is the port being used
+      for KGDB, then you must trigger a breakpoint via sysrq, NMI, or
+      some other method prior to connecting, or echo a control-c to the
+      serial port.  Also, to use the SCI(F) port for KGDB, the
+      <symbol>CONFIG_SERIAL_SH_SCI</symbol> driver must be enabled.
+      </para>
+  </chapter>
   <chapter id="CommonBackEndReq">
     <title>The common backend (required)</title>
       <para>
drivers/serial/sh-sci.c renamed from drivers/serial/sh-sci.c~sh-lite +187 -127

426 lines not on this page · raw message

include/asm-sh/kgdb.h renamed from include/asm-sh/kgdb.h~sh-lite +20 -98

118 lines not on this page · raw message

include/asm-sh/system.h renamed from include/asm-sh/system.h~sh-lite +40 -0
diff -puN include/asm-sh/system.h~sh-lite include/asm-sh/system.h

Lines of this file are not shown. View the raw message.

lib/Kconfig.debug renamed from lib/Kconfig.debug~sh-lite +10 -4
diff -puN lib/Kconfig.debug~sh-lite lib/Kconfig.debug

Lines of this file are not shown. View the raw message.

The rest of this diff is not shown. View the raw message.

_

Part of the diff is not shown here. View the raw message.

author
#8 lore raw

PATCH 9/15 KGDB: Basic ARM support.

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

---

 linux-2.6.13-rc3-trini/arch/arm/kernel/Makefile              |    1 
 linux-2.6.13-rc3-trini/arch/arm/kernel/kgdb-jmp.S            |   30 +
 linux-2.6.13-rc3-trini/arch/arm/kernel/kgdb.c                |  208 +++++++++++
 linux-2.6.13-rc3-trini/arch/arm/kernel/setup.c               |    5 
 linux-2.6.13-rc3-trini/arch/arm/kernel/traps.c               |   11 
 linux-2.6.13-rc3-trini/arch/arm/mach-ixp2000/core.c          |    5 
 linux-2.6.13-rc3-trini/arch/arm/mach-ixp2000/ixdp2x01.c      |    6 
 linux-2.6.13-rc3-trini/arch/arm/mach-ixp4xx/coyote-setup.c   |    5 
 linux-2.6.13-rc3-trini/arch/arm/mach-ixp4xx/ixdp425-setup.c  |   10 
 linux-2.6.13-rc3-trini/arch/arm/mach-omap1/board-osk.c       |    6 
 linux-2.6.13-rc3-trini/arch/arm/mach-omap1/serial.c          |    4 
 linux-2.6.13-rc3-trini/arch/arm/mach-pxa/Makefile            |    1 
 linux-2.6.13-rc3-trini/arch/arm/mach-pxa/kgdb-serial.c       |   98 +++++
 linux-2.6.13-rc3-trini/arch/arm/mach-versatile/kgdb_serial.c |  121 ++++++
 linux-2.6.13-rc3-trini/arch/arm/mm/extable.c                 |    7 
 linux-2.6.13-rc3-trini/drivers/serial/amba-pl011.c           |    2 
 linux-2.6.13-rc3-trini/drivers/serial/kgdb_8250.c            |   16 
 linux-2.6.13-rc3-trini/include/asm-arm/kgdb.h                |   90 ++++
 linux-2.6.13-rc3-trini/include/asm-arm/system.h              |   41 ++
 linux-2.6.13-rc3-trini/lib/Kconfig.debug                     |   35 +
 20 files changed, 695 insertions(+), 7 deletions(-)
arch/arm/kernel/kgdb.c new file +208 -0
diff -puN /dev/null arch/arm/kernel/kgdb.c
@@ -0,0 +1,208 @@
+/*
+ * arch/arm/kernel/kgdb.c
+ *
+ * ARM KGDB support
+ *
+ * Copyright (c) 2002-2004 MontaVista Software, Inc
+ *
+ * Authors:  George Davis <[email protected]>
+ *           Deepak Saxena <[email protected]>
+ */
+#include <linux/config.h>
+#include <linux/types.h>
+#include <linux/kernel.h>
+#include <linux/signal.h>
+#include <linux/sched.h>
+#include <linux/mm.h>
+#include <linux/spinlock.h>
+#include <linux/personality.h>
+#include <linux/ptrace.h>
+#include <linux/elf.h>
+#include <linux/interrupt.h>
+#include <linux/init.h>
+#include <linux/kgdb.h>
+
+#include <asm/atomic.h>
+#include <asm/io.h>
+#include <asm/pgtable.h>
+#include <asm/system.h>
+#include <asm/uaccess.h>
+#include <asm/unistd.h>
+#include <asm/ptrace.h>
+#include <asm/traps.h>
+
+/* Make a local copy of the registers passed into the handler (bletch) */
+void regs_to_gdb_regs(unsigned long *gdb_regs, struct pt_regs *kernel_regs)
+{
+	int regno;
+
+	/* Initialize all to zero (??) */
+	for (regno = 0; regno < GDB_MAX_REGS; regno++)
+		gdb_regs[regno] = 0;
+
+	gdb_regs[_R0] = kernel_regs->ARM_r0;
+	gdb_regs[_R1] = kernel_regs->ARM_r1;
+	gdb_regs[_R2] = kernel_regs->ARM_r2;
+	gdb_regs[_R3] = kernel_regs->ARM_r3;
+	gdb_regs[_R4] = kernel_regs->ARM_r4;
+	gdb_regs[_R5] = kernel_regs->ARM_r5;
+	gdb_regs[_R6] = kernel_regs->ARM_r6;
+	gdb_regs[_R7] = kernel_regs->ARM_r7;
+	gdb_regs[_R8] = kernel_regs->ARM_r8;
+	gdb_regs[_R9] = kernel_regs->ARM_r9;
+	gdb_regs[_R10] = kernel_regs->ARM_r10;
+	gdb_regs[_FP] = kernel_regs->ARM_fp;
+	gdb_regs[_IP] = kernel_regs->ARM_ip;
+	gdb_regs[_SP] = kernel_regs->ARM_sp;
+	gdb_regs[_LR] = kernel_regs->ARM_lr;
+	gdb_regs[_PC] = kernel_regs->ARM_pc;
+	gdb_regs[_CPSR] = kernel_regs->ARM_cpsr;
+}
+
+/* Copy local gdb registers back to kgdb regs, for later copy to kernel */
+void gdb_regs_to_regs(unsigned long *gdb_regs, struct pt_regs *kernel_regs)
+{
+	kernel_regs->ARM_r0 = gdb_regs[_R0];
+	kernel_regs->ARM_r1 = gdb_regs[_R1];
+	kernel_regs->ARM_r2 = gdb_regs[_R2];
+	kernel_regs->ARM_r3 = gdb_regs[_R3];
+	kernel_regs->ARM_r4 = gdb_regs[_R4];
+	kernel_regs->ARM_r5 = gdb_regs[_R5];
+	kernel_regs->ARM_r6 = gdb_regs[_R6];
+	kernel_regs->ARM_r7 = gdb_regs[_R7];
+	kernel_regs->ARM_r8 = gdb_regs[_R8];
+	kernel_regs->ARM_r9 = gdb_regs[_R9];
+	kernel_regs->ARM_r10 = gdb_regs[_R10];
+	kernel_regs->ARM_fp = gdb_regs[_FP];
+	kernel_regs->ARM_ip = gdb_regs[_IP];
+	kernel_regs->ARM_sp = gdb_regs[_SP];
+	kernel_regs->ARM_lr = gdb_regs[_LR];
+	kernel_regs->ARM_pc = gdb_regs[_PC];
+	kernel_regs->ARM_cpsr = gdb_regs[GDB_MAX_REGS - 1];
+}
+
+static inline struct pt_regs *kgdb_get_user_regs(struct task_struct *task)
+{
+	return (struct pt_regs *)
+	    ((unsigned long)task->thread_info + THREAD_SIZE -
+	     8 - sizeof(struct pt_regs));
+}
+
+void sleeping_thread_to_gdb_regs(unsigned long *gdb_regs,
+				 struct task_struct *task)
+{
+	int regno;
+	struct pt_regs *thread_regs;
+
+	/* Just making sure... */
+	if (task == NULL)
+		return;
+
+	/* Initialize to zero */
+	for (regno = 0; regno < GDB_MAX_REGS; regno++)
+		gdb_regs[regno] = 0;
+
+	/* Otherwise, we have only some registers from switch_to() */
+	thread_regs = kgdb_get_user_regs(task);
+	gdb_regs[_R0] = thread_regs->ARM_r0;	/* Not really valid? */
+	gdb_regs[_R1] = thread_regs->ARM_r1;	/* "               " */
+	gdb_regs[_R2] = thread_regs->ARM_r2;	/* "               " */
+	gdb_regs[_R3] = thread_regs->ARM_r3;	/* "               " */
+	gdb_regs[_R4] = thread_regs->ARM_r4;
+	gdb_regs[_R5] = thread_regs->ARM_r5;
+	gdb_regs[_R6] = thread_regs->ARM_r6;
+	gdb_regs[_R7] = thread_regs->ARM_r7;
+	gdb_regs[_R8] = thread_regs->ARM_r8;
+	gdb_regs[_R9] = thread_regs->ARM_r9;
+	gdb_regs[_R10] = thread_regs->ARM_r10;
+	gdb_regs[_FP] = thread_regs->ARM_fp;
+	gdb_regs[_IP] = thread_regs->ARM_ip;
+	gdb_regs[_SP] = thread_regs->ARM_sp;
+	gdb_regs[_LR] = thread_regs->ARM_lr;
+	gdb_regs[_PC] = thread_regs->ARM_pc;
+	gdb_regs[_CPSR] = thread_regs->ARM_cpsr;
+}
+
+static int compiled_break;
+
+int kgdb_arch_handle_exception(int exception_vector, int signo,
+			       int err_code, char *remcom_in_buffer,
+			       char *remcom_out_buffer,
+			       struct pt_regs *linux_regs)
+{
+	long addr;
+	char *ptr;
+
+	switch (remcom_in_buffer[0]) {
+	case 'c':
+		kgdb_contthread = NULL;
+
+		/*
+		 * Try to read optional parameter, pc unchanged if no parm.
+		 * If this was a compiled breakpoint, we need to move
+		 * to the next instruction or we will just breakpoint
+		 * over and over again.
+		 */
+		ptr = &remcom_in_buffer[1];
+		if (kgdb_hex2long(&ptr, &addr)) {
+			linux_regs->ARM_pc = addr;
+		} else if (compiled_break == 1) {
+			linux_regs->ARM_pc += 4;
+		}
+
+		compiled_break = 0;
+
+		return 0;
+	}
+
+	return -1;
+}
+
+static int kgdb_brk_fn(struct pt_regs *regs, unsigned int instr)
+{
+	kgdb_handle_exception(1, SIGTRAP, 0, regs);
+
+	return 0;
+}
+
+static int kgdb_compiled_brk_fn(struct pt_regs *regs, unsigned int instr)
+{
+	compiled_break = 1;
+	kgdb_handle_exception(1, SIGTRAP, 0, regs);
+
+	return 0;
+}
+
+static struct undef_hook kgdb_brkpt_hook = {
+	.instr_mask = 0xffffffff,
+	.instr_val = KGDB_BREAKINST,
+	.fn = kgdb_brk_fn
+};
+
+static struct undef_hook kgdb_compiled_brkpt_hook = {
+	.instr_mask = 0xffffffff,
+	.instr_val = KGDB_COMPILED_BREAK,
+	.fn = kgdb_compiled_brk_fn
+};
+
+/*
+ * Register our undef instruction hooks with ARM undef core.
+ * We regsiter a hook specifically looking for the KGB break inst
+ * and we handle the normal undef case within the do_undefinstr
+ * handler.
+ */
+int kgdb_arch_init(void)
+{
+	register_undef_hook(&kgdb_brkpt_hook);
+	register_undef_hook(&kgdb_compiled_brkpt_hook);
+
+	return 0;
+}
+
+struct kgdb_arch arch_kgdb_ops = {
+#ifndef __ARMEB__
+	.gdb_bpt_instr = {0xfe, 0xde, 0xff, 0xe7}
+#else
+	.gdb_bpt_instr = {0xe7, 0xff, 0xde, 0xfe}
+#endif
+};
arch/arm/kernel/kgdb-jmp.S new file +30 -0
diff -puN /dev/null arch/arm/kernel/kgdb-jmp.S
@@ -0,0 +1,30 @@
+/*
+ * arch/arm/kernel/kgdb-jmp.S
+ *
+ * Trivial setjmp and longjmp procedures to support bus error recovery
+ * which may occur during kgdb memory read/write operations.
+ *
+ * Author: MontaVista Software, Inc. <[email protected]>
+ *         [email protected]
+ *
+ * 2002-2005 (c) MontaVista Software, Inc.  This file is licensed under the
+ * terms of the GNU General Public License version 2. This program as licensed
+ * "as is" without any warranty of any kind, whether express or implied.
+ */
+#include <linux/linkage.h>
+
+ENTRY (kgdb_fault_setjmp)
+	/* Save registers */
+	stmia	r0, {r0-r14}
+	str	lr,[r0, #60]
+	mrs	r1,cpsr
+	str	r1,[r0,#64]
+	ldr	r1,[r0,#4]
+	mov	r0, #0
+	mov	pc,lr
+
+ENTRY (kgdb_fault_longjmp)
+	/* Restore registers */
+	mov	r1,#1
+	str	r1,[r0]
+	ldmia	r0,{r0-pc}^
arch/arm/kernel/Makefile renamed from arch/arm/kernel/Makefile~arm-lite +1 -0
diff -puN arch/arm/kernel/Makefile~arm-lite arch/arm/kernel/Makefile
@@ -19,6 +19,7 @@ obj-$(CONFIG_ARTHUR)		+= arthur.o
 obj-$(CONFIG_ISA_DMA)		+= dma-isa.o
 obj-$(CONFIG_PCI)		+= bios32.o
 obj-$(CONFIG_SMP)		+= smp.o
+obj-$(CONFIG_KGDB)		+= kgdb.o kgdb-jmp.o
 
 obj-$(CONFIG_IWMMXT)		+= iwmmxt.o
 AFLAGS_iwmmxt.o			:= -Wa,-mcpu=iwmmxt
arch/arm/kernel/setup.c renamed from arch/arm/kernel/setup.c~arm-lite +5 -0
diff -puN arch/arm/kernel/setup.c~arm-lite arch/arm/kernel/setup.c
@@ -785,6 +785,11 @@ void __init setup_arch(char **cmdline_p)
 	conswitchp = &dummy_con;
 #endif
 #endif
+
+#if	defined(CONFIG_KGDB)
+	extern void __init early_trap_init(void);
+	early_trap_init();
+#endif
 }
 
 
arch/arm/kernel/traps.c renamed from arch/arm/kernel/traps.c~arm-lite +11 -0
diff -puN arch/arm/kernel/traps.c~arm-lite arch/arm/kernel/traps.c
@@ -266,6 +266,7 @@ asmlinkage void do_undefinstr(struct pt_
 	unsigned int instr;
 	struct undef_hook *hook;
 	siginfo_t info;
+	mm_segment_t fs;
 	void __user *pc;
 
 	/*
@@ -275,12 +276,15 @@ asmlinkage void do_undefinstr(struct pt_
 	 */
 	regs->ARM_pc -= correction;
 
+	fs = get_fs();
+	set_fs(KERNEL_DS);
 	pc = (void __user *)instruction_pointer(regs);
 	if (thumb_mode(regs)) {
 		get_user(instr, (u16 __user *)pc);
 	} else {
 		get_user(instr, (u32 __user *)pc);
 	}
+	set_fs(fs);
 
 	spin_lock_irq(&undef_lock);
 	list_for_each_entry(hook, &undef_hook, node) {
@@ -663,6 +667,13 @@ EXPORT_SYMBOL(abort);
 
 void __init trap_init(void)
 {
+#if	defined(CONFIG_KGDB)
+	return;
+}
+
+void __init early_trap_init(void)
+{
+#endif
 	extern char __stubs_start[], __stubs_end[];
 	extern char __vectors_start[], __vectors_end[];
 	extern char __kuser_helper_start[], __kuser_helper_end[];
arch/arm/mach-ixp2000/core.c renamed from arch/arm/mach-ixp2000/core.c~arm-lite +5 -0
diff -puN arch/arm/mach-ixp2000/core.c~arm-lite arch/arm/mach-ixp2000/core.c
@@ -35,6 +35,7 @@
 #include <asm/system.h>
 #include <asm/tlbflush.h>
 #include <asm/pgtable.h>
+#include <asm/kgdb.h>
 
 #include <asm/mach/map.h>
 #include <asm/mach/time.h>
@@ -145,6 +146,10 @@ void __init ixp2000_map_io(void)
 
 	iotable_init(ixp2000_io_desc, ARRAY_SIZE(ixp2000_io_desc));
 
+#ifdef CONFIG_KGDB_8250
+	kgdb8250_add_port(0, &ixp2000_serial_port);
+#endif
+
 	/* Set slowport to 8-bit mode.  */
 	ixp2000_reg_write(IXP2000_SLOWPORT_FRM, 1);
 }
arch/arm/mach-ixp2000/ixdp2x01.c renamed from arch/arm/mach-ixp2000/ixdp2x01.c~arm-lite +6 -0
diff -puN arch/arm/mach-ixp2000/ixdp2x01.c~arm-lite arch/arm/mach-ixp2000/ixdp2x01.c
@@ -38,6 +38,7 @@
 #include <asm/system.h>
 #include <asm/hardware.h>
 #include <asm/mach-types.h>
+#include <asm/kgdb.h>
 
 #include <asm/mach/pci.h>
 #include <asm/mach/map.h>
@@ -175,6 +176,11 @@ static void __init ixdp2x01_map_io(void)
 
 	early_serial_setup(&ixdp2x01_serial_ports[0]);
 	early_serial_setup(&ixdp2x01_serial_ports[1]);
+
+#ifdef CONFIG_KGDB_8250
+	kgdb8250_add_port(0, &ixdp2x01_serial_ports[0]);
+	kgdb8250_add_port(1, &ixdp2x01_serial_ports[1]);
+#endif
 }
 
 
arch/arm/mach-ixp4xx/coyote-setup.c renamed from arch/arm/mach-ixp4xx/coyote-setup.c~arm-lite +4 -1
diff -puN arch/arm/mach-ixp4xx/coyote-setup.c~arm-lite arch/arm/mach-ixp4xx/coyote-setup.c
@@ -96,9 +96,12 @@ static void __init coyote_init(void)
 		coyote_uart_data[0].irq = IRQ_IXP4XX_UART1;
 	}
 
-
 	ixp4xx_sys_init();
 	platform_add_devices(coyote_devices, ARRAY_SIZE(coyote_devices));
+
+#ifdef CONFIG_KGDB_8250
+	kgdb8250_add_port(0, &coyote_serial_port);
+#endif
 }
 
 #ifdef CONFIG_ARCH_ADI_COYOTE
arch/arm/mach-ixp4xx/ixdp425-setup.c renamed from arch/arm/mach-ixp4xx/ixdp425-setup.c~arm-lite +8 -2
diff -puN arch/arm/mach-ixp4xx/ixdp425-setup.c~arm-lite arch/arm/mach-ixp4xx/ixdp425-setup.c
@@ -23,6 +23,7 @@
 #include <asm/irq.h>
 #include <asm/mach/arch.h>
 #include <asm/mach/flash.h>
+#include <asm/kgdb.h>
 
 void __init ixdp425_map_io(void) 
 {
@@ -82,7 +83,7 @@ static struct plat_serial8250_port ixdp4
 		.mapbase	= IXP4XX_UART1_BASE_PHYS,
 		.membase	= (char *)IXP4XX_UART1_BASE_VIRT + REG_OFFSET,
 		.irq		= IRQ_IXP4XX_UART1,
-		.flags		= UPF_BOOT_AUTOCONF,
+		.flags		= UPF_BOOT_AUTOCONF | UPF_SHARE_IRQ,
 		.iotype		= UPIO_MEM,
 		.regshift	= 2,
 		.uartclk	= IXP4XX_UART_XTAL,
@@ -91,7 +92,7 @@ static struct plat_serial8250_port ixdp4
 		.mapbase	= IXP4XX_UART2_BASE_PHYS,
 		.membase	= (char *)IXP4XX_UART2_BASE_VIRT + REG_OFFSET,
 		.irq		= IRQ_IXP4XX_UART1,
-		.flags		= UPF_BOOT_AUTOCONF,
+		.flags		= UPF_BOOT_AUTOCONF | UPF_SHARE_IRQ,
 		.iotype		= UPIO_MEM,
 		.regshift	= 2,
 		.uartclk	= IXP4XX_UART_XTAL,
@@ -126,6 +127,11 @@ static void __init ixdp425_init(void)
 	}
 
 	platform_add_devices(ixdp425_devices, ARRAY_SIZE(ixdp425_devices));
+
+#ifdef CONFIG_KGDB_8250
+	kgdb8250_add_port(0, &ixdp425_serial_ports[0]);
+	kgdb8250_add_port(1, &ixdp425_serial_ports[1]);
+#endif
 }
 
 MACHINE_START(IXDP425, "Intel IXDP425 Development Platform")
arch/arm/mach-omap1/board-osk.c renamed from arch/arm/mach-omap1/board-osk.c~arm-lite +4 -2
diff -puN arch/arm/mach-omap1/board-osk.c~arm-lite arch/arm/mach-omap1/board-osk.c
@@ -41,12 +41,14 @@
 #include <asm/arch/tc.h>
 #include <asm/arch/common.h>
 
+#if 0
 static struct map_desc osk5912_io_desc[] __initdata = {
 { OMAP_OSK_NOR_FLASH_BASE, OMAP_OSK_NOR_FLASH_START, OMAP_OSK_NOR_FLASH_SIZE,
 	MT_DEVICE },
 };
+#endif
 
-static int __initdata osk_serial_ports[OMAP_MAX_NR_PORTS] = {1, 0, 0};
+static int __initdata osk_serial_ports[OMAP_MAX_NR_PORTS] = {1, 1, 1};
 
 static struct resource osk5912_smc91x_resources[] = {
 	[0] = {
@@ -153,7 +155,7 @@ static void __init osk_init(void)
 static void __init osk_map_io(void)
 {
 	omap_map_common_io();
-	iotable_init(osk5912_io_desc, ARRAY_SIZE(osk5912_io_desc));
+	//iotable_init(osk5912_io_desc, ARRAY_SIZE(osk5912_io_desc));
 	omap_serial_init(osk_serial_ports);
 }
 
arch/arm/mach-omap1/serial.c renamed from arch/arm/mach-omap1/serial.c~arm-lite +4 -0
diff -puN arch/arm/mach-omap1/serial.c~arm-lite arch/arm/mach-omap1/serial.c
@@ -15,6 +15,7 @@
 #include <linux/delay.h>
 #include <linux/serial.h>
 #include <linux/tty.h>
+#include <linux/kgdb.h>
 #include <linux/serial_8250.h>
 #include <linux/serial_reg.h>
 
@@ -190,6 +191,9 @@ void __init omap_serial_init(int ports[O
 			break;
 		}
 		omap_serial_reset(&serial_platform_data[i]);
+#ifdef CONFIG_KGDB_8250
+		kgdb8250_add_platform_port(i, &serial_platform_data[i]);
+#endif
 	}
 }
 
arch/arm/mach-pxa/kgdb-serial.c new file +98 -0

98 lines not on this page · raw message

arch/arm/mach-pxa/Makefile renamed from arch/arm/mach-pxa/Makefile~arm-lite +1 -0
diff -puN arch/arm/mach-pxa/Makefile~arm-lite arch/arm/mach-pxa/Makefile
@@ -24,6 +24,7 @@ obj-$(CONFIG_LEDS) += $(led-y)
 
 # Misc features
 obj-$(CONFIG_PM) += pm.o sleep.o
+obj-$(CONFIG_KGDB_PXA_SERIAL) += kgdb-serial.o
 
 ifeq ($(CONFIG_PXA27x),y)
 obj-$(CONFIG_PM) += standby.o
arch/arm/mach-versatile/kgdb_serial.c new file +121 -0

121 lines not on this page · raw message

arch/arm/mm/extable.c renamed from arch/arm/mm/extable.c~arm-lite +7 -0
diff -puN arch/arm/mm/extable.c~arm-lite arch/arm/mm/extable.c
@@ -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;
 }
drivers/serial/amba-pl011.c renamed from drivers/serial/amba-pl011.c~arm-lite +1 -1
diff -puN drivers/serial/amba-pl011.c~arm-lite drivers/serial/amba-pl011.c
@@ -350,7 +350,7 @@ static int pl011_startup(struct uart_por
 	/*
 	 * Allocate the IRQ
 	 */
-	retval = request_irq(uap->port.irq, pl011_int, 0, "uart-pl011", uap);
+	retval = request_irq(uap->port.irq, pl011_int, SA_SHIRQ, "uart-pl011", uap);
 	if (retval)
 		goto clk_dis;
 
drivers/serial/kgdb_8250.c renamed from drivers/serial/kgdb_8250.c~arm-lite +16 -0
diff -puN drivers/serial/kgdb_8250.c~arm-lite drivers/serial/kgdb_8250.c
@@ -319,6 +319,22 @@ static int kgdb8250_init(void)
 
 	/* Disable UART interrupts, set DTR and RTS high and set speed. */
 	cval = 0x3;
+#if	defined(CONFIG_ARCH_OMAP1510)
+	/* Workaround to enable 115200 baud on OMAP1510 internal ports */
+	if (cpu_is_omap1510() && is_omap_port((void *)kgdb8250_addr)) {
+		if (kgdb8250_baud == 115200) {
+			base_baud = 1;
+			kgdb8250_baud = 1;
+			serial_outb(1, kgdb8250_addr +
+				    (UART_OMAP_OSC_12M_SEL <<
+				     KGDB8250_REG_SHIFT));
+		} else {
+			serial_outb(0, kgdb8250_addr +
+				    (UART_OMAP_OSC_12M_SEL <<
+				     KGDB8250_REG_SHIFT));
+		}
+	}
+#endif
 	/* set DLAB */
 	serial_outb(cval | UART_LCR_DLAB, kgdb8250_addr +
 		    (UART_LCR << KGDB8250_REG_SHIFT));
include/asm-arm/kgdb.h new file +90 -0

90 lines not on this page · raw message

include/asm-arm/system.h renamed from include/asm-arm/system.h~arm-lite +41 -0

47 lines not on this page · raw message

lib/Kconfig.debug renamed from lib/Kconfig.debug~arm-lite +34 -1
diff -puN lib/Kconfig.debug~arm-lite lib/Kconfig.debug
@@ -163,7 +163,7 @@ config FRAME_POINTER
 
 config KGDB
 	bool "KGDB: kernel debugging with remote gdb"
-	depends on DEBUG_KERNEL && (X86 || MIPS32 || (SUPERH && !SUPERH64) || IA64 || X86_64 || ((!SMP || BROKEN) && PPC32))
+	depends on DEBUG_KERNEL && (ARM || X86 || MIPS32 || (SUPERH && !SUPERH64) || IA64 || X86_64 || ((!SMP || BROKEN) && PPC32))
 	help
 	  If you say Y here, it will be possible to remotely debug the
 	  kernel using gdb. It is strongly suggested that you enable
@@ -189,8 +189,10 @@ choice
 	prompt "Method for KGDB communication"
 	depends on KGDB
 	default KGDB_ONLY_MODULES
+	default KGDB_ARM_VERSATILE if ARCH_VERSATILE
 	default KGDB_SIBYTE if SIBYTE_SB1xxx_SOC
 	default KGDB_MPSC if SERIAL_MPSC
+	default KGDB_PXA_SERIAL if ARCH_PXA
 	help
 	  There are a number of different ways in which you can communicate
 	  with KGDB.  The most common is via serial, with the 8250 driver
@@ -227,6 +229,16 @@ config KGDB_SIBYTE
 	bool "KGDB: On the Broadcom SWARM serial port"
 	depends on MIPS && SIBYTE_SB1xxx_SOC
 
+config KGDB_ARM_VERSATILE
+	bool "KGDB: On ARM Versatile"
+	depends on ARM && ARCH_VERSATILE
+	help
+	  Enables the KGDB serial driver for the ARM Versatile
+
+config KGDB_PXA_SERIAL
+	bool "KGDB: On the PXA2xx serial port"
+	depends on ARCH_PXA
+
 config KGDB_SH_SCI
 	bool "KGDB: On SH SCI(F) serial port"
 	depends on SUPERH && SERIAL_SH_SCI
@@ -296,6 +308,27 @@ config KGDB_PORT_3
 	bool "Third serial port"
 endchoice
 
+choice
+	prompt "PXA serial UART for KGDB"
+	depends on KGDB_PXA_SERIAL
+	default KGDB_PXA_FFUART
+
+config KGDB_PXA_FFUART
+	bool "FFUART"
+
+config KGDB_PXA_BTUART
+	bool "BTUART"
+
+config KGDB_PXA_STUART
+	bool "STUART"
+
+endchoice
+
+config KGDB_PXA_BAUDRATE
+	int "UART baudrate for KGDB"
+	depends on KGDB_PXA_SERIAL
+	default "115200"
+
 config KGDB_PORT
 	hex "hex I/O port address of the debug serial port"
 	depends on !KGDB_SIMPLE_SERIAL && KGDB_8250 && !IA64

_

author
#9 lore raw

PATCH 10/15 Basic support for PowerPC64

CC: Frank Rowand <[email protected]>, Paul Mackerras <[email protected]> This adds basic KGDB support to ppc64, and support for kgdb8250 on the 'Maple' board. All of this was done by Frank Rowand (who is on vacation right now, but I'll try and answer for him). This should work on any ppc64 board via kgdboe, so long as there is an eth driver that supports netpoll. At the moment this is mutually exclusive with XMON. It is probably possible to allow them to be chained, but that sounds dangerous to me. This is similar to ppc32, but ppc32 does not explicitly test.

---

 linux-2.6.13-rc3-trini/arch/ppc64/Kconfig.debug        |   14 
 linux-2.6.13-rc3-trini/arch/ppc64/kernel/Makefile      |    3 
 linux-2.6.13-rc3-trini/arch/ppc64/kernel/kgdb.c        |  422 +++++++++++++++++
 linux-2.6.13-rc3-trini/arch/ppc64/kernel/maple_setup.c |    5 
 linux-2.6.13-rc3-trini/arch/ppc64/kernel/setup.c       |   14 
 linux-2.6.13-rc3-trini/arch/ppc64/mm/fault.c           |    8 
 linux-2.6.13-rc3-trini/include/asm-ppc64/kgdb.h        |   55 ++
 linux-2.6.13-rc3-trini/lib/Kconfig.debug               |    2 
 8 files changed, 513 insertions(+), 10 deletions(-)
arch/ppc64/Kconfig.debug renamed from arch/ppc64/Kconfig.debug~ppc64-lite +6 -8
diff -puN arch/ppc64/Kconfig.debug~ppc64-lite arch/ppc64/Kconfig.debug
@@ -28,16 +28,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 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.
@@ -46,6 +39,11 @@ config XMON_DEFAULT
 	bool "Enable xmon by default"
 	depends on XMON
 
+config DEBUGGER
+	bool
+	depends on KGDB || XMON
+	default y
+
 config PPCDBG
 	bool "Include PPCDBG realtime debugging"
 	depends on DEBUG_KERNEL
arch/ppc64/kernel/kgdb.c new file +422 -0

422 lines not on this page · raw message

arch/ppc64/kernel/Makefile renamed from arch/ppc64/kernel/Makefile~ppc64-lite +2 -1
diff -puN arch/ppc64/kernel/Makefile~ppc64-lite arch/ppc64/kernel/Makefile
@@ -2,7 +2,7 @@
 # Makefile for the linux ppc64 kernel.
 #
 
-EXTRA_CFLAGS	+= -mno-minimal-toc
+#EXTRA_CFLAGS	+= -mno-minimal-toc
 extra-y		:= head.o vmlinux.lds
 
 obj-y               :=	setup.o entry.o traps.o irq.o idle.o dma.o \
@@ -53,6 +53,7 @@ obj-$(CONFIG_HVCS)		+= hvcserver.o
 obj-$(CONFIG_IBMVIO)		+= vio.o
 obj-$(CONFIG_XICS)		+= xics.o
 obj-$(CONFIG_MPIC)		+= mpic.o
+obj-$(CONFIG_KGDB)		+= kgdb.o
 
 obj-$(CONFIG_PPC_PMAC)		+= pmac_setup.o pmac_feature.o pmac_pci.o \
 				   pmac_time.o pmac_nvram.o pmac_low_i2c.o
arch/ppc64/kernel/maple_setup.c renamed from arch/ppc64/kernel/maple_setup.c~ppc64-lite +5 -0
diff -puN arch/ppc64/kernel/maple_setup.c~ppc64-lite arch/ppc64/kernel/maple_setup.c
@@ -77,6 +77,7 @@ extern void maple_pcibios_fixup(void);
 extern int maple_pci_get_legacy_ide_irq(struct pci_dev *dev, int channel);
 extern void generic_find_legacy_serial_ports(u64 *physport,
 		unsigned int *default_speed);
+extern void add_kgdb_port(void);
 
 static void maple_restart(char *cmd)
 {
@@ -213,6 +214,10 @@ static void __init maple_init_early(void
 		DBG("Hello World !\n");
 	}
 
+#ifdef CONFIG_KGDB_8250
+	add_kgdb_port();
+#endif
+
 	/* Setup interrupt mapping options */
 	ppc64_interrupt_controller = IC_OPEN_PIC;
 
arch/ppc64/kernel/setup.c renamed from arch/ppc64/kernel/setup.c~ppc64-lite +14 -0
diff -puN arch/ppc64/kernel/setup.c~ppc64-lite arch/ppc64/kernel/setup.c
@@ -33,6 +33,7 @@
 #include <linux/unistd.h>
 #include <linux/serial.h>
 #include <linux/serial_8250.h>
+#include <linux/kgdb.h>
 #include <asm/io.h>
 #include <asm/prom.h>
 #include <asm/processor.h>
@@ -1259,6 +1260,7 @@ void __init generic_find_legacy_serial_p
 		serial_ports[index].iobase = reg->address;
 		serial_ports[index].irq = interrupts ? interrupts[0] : 0;
 		serial_ports[index].flags = ASYNC_BOOT_AUTOCONF;
+		serial_ports[index].line = index;
 
 		DBG("Added legacy port, index: %d, port: %x, irq: %d, clk: %d\n",
 		    index,
@@ -1312,6 +1314,18 @@ void __init generic_find_legacy_serial_p
 	DBG(" <- generic_find_legacy_serial_port()\n");
 }
 
+
+#ifdef CONFIG_KGDB_8250
+void add_kgdb_port(void)
+{
+	int ttyS;
+
+	ttyS = kgdb8250_get_ttyS();
+	if (ttyS < old_serial_count)
+		kgdb8250_add_platform_port(ttyS, &serial_ports[ttyS]);
+}
+#endif
+
 static struct platform_device serial_device = {
 	.name	= "serial8250",
 	.id	= 0,
arch/ppc64/mm/fault.c renamed from arch/ppc64/mm/fault.c~ppc64-lite +8 -0
diff -puN arch/ppc64/mm/fault.c~ppc64-lite arch/ppc64/mm/fault.c
@@ -29,6 +29,7 @@
 #include <linux/interrupt.h>
 #include <linux/smp_lock.h>
 #include <linux/module.h>
+#include <linux/kgdb.h>
 
 #include <asm/page.h>
 #include <asm/pgtable.h>
@@ -306,6 +307,13 @@ void bad_page_fault(struct pt_regs *regs
 		regs->nip = entry->fixup;
 		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 */
 	die("Kernel access of bad area", regs, sig);
include/asm-ppc64/kgdb.h new file +55 -0

55 lines not on this page · raw message

lib/Kconfig.debug renamed from lib/Kconfig.debug~ppc64-lite +1 -1
diff -puN lib/Kconfig.debug~ppc64-lite lib/Kconfig.debug
@@ -163,7 +163,7 @@ config FRAME_POINTER
 
 config KGDB
 	bool "KGDB: kernel debugging with remote gdb"
-	depends on DEBUG_KERNEL && (ARM || X86 || MIPS32 || (SUPERH && !SUPERH64) || IA64 || X86_64 || ((!SMP || BROKEN) && PPC32))
+	depends on DEBUG_KERNEL && (ARM || X86 || MIPS32 || PPC64 || (SUPERH && !SUPERH64) || IA64 || X86_64 || ((!SMP || BROKEN) && PPC32))
 	help
 	  If you say Y here, it will be possible to remotely debug the
 	  kernel using gdb. It is strongly suggested that you enable

_

author
#10 lore raw

PATCH 11/15 KGDB: KGDBoE I/O driver

This is the simple KGDB over Ethernet I/O driver that uses netpoll for all of the heavy lifting. At one point this was very similar to the version Matt Mackall wrote and is currently in Andrew's tree. Since then it has been reworked to fit into our model.

---

 Makefile                                    |    0 
 linux-2.6.13-rc3-trini/drivers/net/Makefile |    1 
 linux-2.6.13-rc3-trini/drivers/net/kgdboe.c |  208 ++++++++++++++++++++++++++++
 linux-2.6.13-rc3-trini/lib/Kconfig.debug    |   24 +++
 4 files changed, 233 insertions(+)
drivers/net/kgdboe.c new file +208 -0
diff -puN /dev/null drivers/net/kgdboe.c
@@ -0,0 +1,208 @@
+/*
+ * drivers/net/kgdboe.c
+ *
+ * A network interface for GDB.
+ * Based upon 'gdbserial' by David Grothe <[email protected]>
+ * and Scott Foehner <[email protected]>
+ *
+ * Maintainers: Amit S. Kale <[email protected]> and
+ * 		Tom Rini <[email protected]>
+ *
+ * 2004 (c) Amit S. Kale <[email protected]>
+ * 2004-2005 (c) MontaVista Software, Inc.
+ * 2005 (c) Wind River Systems, Inc.
+ *
+ * Other folks:
+ * San Mehat <[email protected]>
+ * Robert Walsh <[email protected]>
+ * wangdi <[email protected]>.
+ * Matt Mackall <[email protected]>
+ * Pavel Machek <[email protected]>
+ * Jason Wessel <[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.
+ *
+ * Changes:
+ * 3/10/05 - Jason Wessel <[email protected]>
+ * - Added ability to compile/load as module
+ *
+ * Known problems:
+ * - There is no way to deny the unloading of the module
+ *   if KGDB is connected, but an attempt is made to handle it
+ */
+
+#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 OUT_BUF_SIZE 30		/* We don't want to send too big of a packet. */
+
+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 void rx_hook(struct netpoll *np, int port, char *msg, int len);
+static void eth_pre_exception_handler(void);
+static void eth_post_exception_handler(void);
+static int eth_get_char(void);
+static void eth_flush_buf(void);
+static void eth_put_char(int chr);
+int init_kgdboe(void);
+
+static struct netpoll np = {
+	.name = "kgdboe",
+	.dev_name = "eth0",
+	.rx_hook = rx_hook,
+	.local_port = 6443,
+	.remote_port = 6442,
+	.remote_mac = {0xff, 0xff, 0xff, 0xff, 0xff, 0xff},
+};
+
+MODULE_DESCRIPTION("KGDB driver for network interfaces");
+MODULE_LICENSE("GPL");
+static char config[256];
+module_param_string(kgdboe, config, 256, 0);
+MODULE_PARM_DESC(kgdboe, " kgdboe=[src-port]@[src-ip]/[dev],"
+		 "[tgt-port]@<tgt-ip>/<tgt-macaddr>\n");
+
+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
+};
+
+static void eth_pre_exception_handler(void)
+{
+	netpoll_set_trap(1);
+}
+
+static void eth_post_exception_handler(void)
+{
+	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(int chr)
+{
+	out_buf[out_count++] = chr;
+	if (out_count == OUT_BUF_SIZE)
+		eth_flush_buf();
+}
+
+static void rx_hook(struct netpoll *np, int port, char *msg, int len)
+{
+	int i;
+
+	np->remote_port = port;
+
+	/*
+	 * 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 int option_setup(char *opt)
+{
+	configured = !netpoll_parse_options(&np, opt);
+	return 0;
+}
+
+__setup("kgdboe=", option_setup);
+
+int init_kgdboe(void)
+{
+	/* Already done? */
+	if (configured == 2)
+		return 0;
+
+	if (strlen(config))
+		option_setup(config);
+
+	if (!configured) {
+		printk("kgdboe: configuration incorrect - kgdboe not "
+		       "loaded.\n");
+		printk("  Usage: kgdboe=[src-port]@[src-ip]/[dev],[tgt-port]"
+		       "@<tgt-ip>/[tgt-macaddr]\n");
+		return -EINVAL;
+	}
+
+	if (netpoll_setup(&np)) {
+		printk("kgdboe: netpoll_setup failed kgdboe failed\n");
+		return -EINVAL;
+	}
+
+	if (kgdb_register_io_module(&local_kgdb_io_ops))
+		return -EINVAL;
+
+	printk(KERN_INFO "kgdboe: debugging over ethernet enabled\n");
+
+	configured = 2;
+
+	return 0;
+}
+
+static void cleanup_kgdboe(void)
+{
+	netpoll_cleanup(&np);
+	configured = 0;
+
+	kgdb_unregister_io_module(&local_kgdb_io_ops);
+}
+
+module_init(init_kgdboe);
+module_exit(cleanup_kgdboe);
drivers/net/Makefile renamed from drivers/net/Makefile~eth +1 -0
diff -puN drivers/net/Makefile~eth drivers/net/Makefile
@@ -195,3 +195,4 @@ obj-$(CONFIG_IRDA) += irda/
 obj-$(CONFIG_ETRAX_ETHERNET) += cris/
 
 obj-$(CONFIG_NETCONSOLE) += netconsole.o
+obj-$(CONFIG_KGDBOE) += kgdboe.o
lib/Kconfig.debug renamed from lib/Kconfig.debug~eth +24 -0
diff -puN lib/Kconfig.debug~eth lib/Kconfig.debug
@@ -217,6 +217,18 @@ config KGDB_8250_NOMODULE
 	  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
@@ -247,6 +259,18 @@ config KGDB_SH_SCI
 
 endchoice
 
+config KGDBOE
+	tristate "KGDB: On ethernet" if !KGDBOE_NOMODULE
+	depends on m && KGDB_ONLY_MODULES
+	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

diff -puN Makefile~eth Makefile
_

author
#11 lore raw

PATCH 12/15 KGDB: Add CFI DWARF2 annotation support.

CC: George Anzginer <[email protected]>
There are some parts of the kernel where you simply cannot unwind past. This does not, however, stop GDB from trying, and getting stuck in an infinite loop (it will get garbage back, try and unwind that, repeat). The way to fix this is to manually insert some DWARF2 information into the kernel so that GDB will cleanly (or almost cleanly, it will get the same frame twice, and stop) stop. George wrote much of the IMHO hard part here (i386 & the macros) and I expanded this to all of the other arches. This adds a small amount to the DEBUG_INFO=y kernel size, but that's not unexpected.

---

 linux-2.6.13-rc3-trini/Makefile                     |    5 
 linux-2.6.13-rc3-trini/arch/arm/kernel/entry-armv.S |    2 
 linux-2.6.13-rc3-trini/arch/i386/kernel/entry.S     |  105 ++
 linux-2.6.13-rc3-trini/arch/i386/kernel/head.S      |    5 
 linux-2.6.13-rc3-trini/arch/i386/kernel/process.c   |   20 
 linux-2.6.13-rc3-trini/arch/i386/kernel/smpboot.c   |    3 
 linux-2.6.13-rc3-trini/arch/x86_64/kernel/entry.S   |    2 
 linux-2.6.13-rc3-trini/include/asm-arm/kgdb.h       |    7 
 linux-2.6.13-rc3-trini/include/asm-generic/kgdb.h   |   34 
 linux-2.6.13-rc3-trini/include/asm-i386/kgdb.h      |   60 -
 linux-2.6.13-rc3-trini/include/asm-mips/kgdb.h      |    4 
 linux-2.6.13-rc3-trini/include/asm-ppc/kgdb.h       |    1 
 linux-2.6.13-rc3-trini/include/asm-sh/kgdb.h        |    1 
 linux-2.6.13-rc3-trini/include/asm-x86_64/kgdb.h    |    4 
 linux-2.6.13-rc3-trini/include/linux/dwarf2-lang.h  |  301 +++++++
 linux-2.6.13-rc3-trini/include/linux/dwarf2.h       |  775 ++++++++++++++++++++
 linux-2.6.13-rc3-trini/scripts/dwarfh.awk           |   19 
 17 files changed, 1319 insertions(+), 29 deletions(-)
arch/arm/kernel/entry-armv.S renamed from arch/arm/kernel/entry-armv.S~cfi_annotations +2 -0
diff -puN arch/arm/kernel/entry-armv.S~cfi_annotations arch/arm/kernel/entry-armv.S
@@ -15,6 +15,7 @@
  */
 #include <linux/config.h>
 
+#include <asm/kgdb.h>
 #include <asm/glue.h>
 #include <asm/vfpmacros.h>
 #include <asm/hardware.h>		/* should be moved into entry-macro.S */
@@ -215,6 +216,7 @@ svc_preempt:
 	beq	preempt_return			@ go again
 	b	1b
 #endif
+	CFI_END_FRAME(__irq_svc)
 
 	.align	5
 __und_svc:
arch/i386/kernel/entry.S renamed from arch/i386/kernel/entry.S~cfi_annotations +105 -0

108 lines not on this page · raw message

arch/i386/kernel/head.S renamed from arch/i386/kernel/head.S~cfi_annotations +4 -1
diff -puN arch/i386/kernel/head.S~cfi_annotations arch/i386/kernel/head.S
@@ -11,6 +11,7 @@
 #include <linux/config.h>
 #include <linux/threads.h>
 #include <linux/linkage.h>
+#include <asm/kgdb.h>
 #include <asm/segment.h>
 #include <asm/page.h>
 #include <asm/pgtable.h>
@@ -328,7 +329,9 @@ is386:	movl $2,%ecx		# set MP
 L6:
 	jmp L6			# main should never return here, but
 				# just in case, we know what happens.
-
+	/* 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.
  */
arch/i386/kernel/process.c renamed from arch/i386/kernel/process.c~cfi_annotations +20 -0
diff -puN arch/i386/kernel/process.c~cfi_annotations arch/i386/kernel/process.c
@@ -341,7 +341,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
arch/i386/kernel/smpboot.c renamed from arch/i386/kernel/smpboot.c~cfi_annotations +3 -0
diff -puN arch/i386/kernel/smpboot.c~cfi_annotations arch/i386/kernel/smpboot.c
@@ -537,6 +537,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));
arch/x86_64/kernel/entry.S renamed from arch/x86_64/kernel/entry.S~cfi_annotations +2 -0
diff -puN arch/x86_64/kernel/entry.S~cfi_annotations arch/x86_64/kernel/entry.S
@@ -41,6 +41,7 @@
 #include <asm/unistd.h>
 #include <asm/thread_info.h>
 #include <asm/hw_irq.h>
+#include <asm/kgdb.h>
 
 	.code64
 
@@ -741,6 +742,7 @@ ENTRY(kernel_thread)
 	UNFAKE_STACK_FRAME
 	ret
 	CFI_ENDPROC
+	CFI_END_FRAME(kernel_thread)
 
 	
 child_rip:
include/asm-arm/kgdb.h renamed from include/asm-arm/kgdb.h~cfi_annotations +5 -2
diff -puN include/asm-arm/kgdb.h~cfi_annotations include/asm-arm/kgdb.h
@@ -14,6 +14,7 @@
 
 #include <linux/config.h>
 #include <asm/ptrace.h>
+#include <asm-generic/kgdb.h>
 
 
 /*
@@ -65,6 +66,7 @@ extern int kgdb_fault_expected;
 #define	NUMREGBYTES		(GDB_MAX_REGS << 2)
 #define	NUMCRITREGBYTES		(32 << 2)
 #define	CHECK_EXCEPTION_STACK()	1
+#endif				/* __ASSEMBLY__ */
 
 #define	_R0		0
 #define	_R1		1
@@ -84,7 +86,8 @@ extern int kgdb_fault_expected;
 #define	_PC		15
 #define	_CPSR		(GDB_MAX_REGS - 1)
 
-#define	CHECK_EXCEPTION_STACK()	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 // !__ASSEMBLY__
 #endif // __ASM_KGDB_H__
include/asm-generic/kgdb.h new file +34 -0
diff -puN /dev/null include/asm-generic/kgdb.h
@@ -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 <[email protected]>
+ *
+ * 2005 (c) MontaVista Software, Inc. This file is licensed under the terms
+ * of the GNU General Public License version 2. This program is licensed
+ * "as is" without any warranty of any kind, whether express or implied.
+ */
+
+#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__ */
include/asm-i386/kgdb.h renamed from include/asm-i386/kgdb.h~cfi_annotations +35 -25

78 lines not on this page · raw message

include/asm-mips/kgdb.h renamed from include/asm-mips/kgdb.h~cfi_annotations +4 -0
diff -puN include/asm-mips/kgdb.h~cfi_annotations include/asm-mips/kgdb.h
@@ -2,6 +2,9 @@
 #ifndef _ASM_KGDB_H_
 #define _ASM_KGDB_H_
 
+#include <asm-generic/kgdb.h>
+
+#ifndef __ASSEMBLY__
 #define BUFMAX			2048
 #define NUMREGBYTES		(90*sizeof(long))
 #define NUMCRITREGBYTES		(12*sizeof(long))
@@ -18,5 +21,6 @@
 
 extern int kgdb_early_setup;
 
+#endif				/* !__ASSEMBLY__ */
 #endif				/* _ASM_KGDB_H_ */
 #endif				/* __KERNEL__ */
include/asm-ppc/kgdb.h renamed from include/asm-ppc/kgdb.h~cfi_annotations +1 -0
diff -puN include/asm-ppc/kgdb.h~cfi_annotations include/asm-ppc/kgdb.h
@@ -12,6 +12,7 @@
 #ifndef _PPC_KGDB_H
 #define _PPC_KGDB_H
 
+#include <asm-generic/kgdb.h>
 #ifndef __ASSEMBLY__
 
 #define BREAK_INSTR_SIZE	4
include/asm-sh/kgdb.h renamed from include/asm-sh/kgdb.h~cfi_annotations +1 -0
diff -puN include/asm-sh/kgdb.h~cfi_annotations include/asm-sh/kgdb.h
@@ -15,6 +15,7 @@
 #define __KGDB_H
 
 #include <asm-generic/kgdb.h>
+#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 */
include/asm-x86_64/kgdb.h renamed from include/asm-x86_64/kgdb.h~cfi_annotations +4 -0
diff -puN include/asm-x86_64/kgdb.h~cfi_annotations include/asm-x86_64/kgdb.h
@@ -6,6 +6,8 @@
  * 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.
@@ -36,6 +38,8 @@
 #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
include/linux/dwarf2.h new file +775 -0

775 lines not on this page · raw message

include/linux/dwarf2-lang.h new file +301 -0

301 lines not on this page · raw message

Makefile renamed from Makefile~cfi_annotations +4 -1
diff -puN Makefile~cfi_annotations Makefile
@@ -1345,5 +1345,8 @@ clean := -f $(if $(KBUILD_SRC),$(srctree
 descend =$(Q)$(MAKE) -f $(if $(KBUILD_SRC),$(srctree)/)scripts/Makefile.build obj=$(1) $(2)
 
 endif	# skip-makefile
+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:
+FORCE: include/linux/dwarf2-defs.h
scripts/dwarfh.awk new file +19 -0
diff -puN /dev/null scripts/dwarfh.awk
@@ -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"
+}

_

author
#12 lore raw

PATCH 13/15 Minor SysRq keyboard bugfix for KGDB

CC: George Anzginer <[email protected]>
It is possible that when SysRq-G is triggered via the keyboard that we will miss the "up" event and once KGDB lets the kernel go another SysRq will be required to clear this, without this change.

---

 linux-2.6.13-rc3-trini/drivers/char/keyboard.c |    1 +
 1 files changed, 1 insertion(+)
drivers/char/keyboard.c renamed from drivers/char/keyboard.c~sysrq_bugfix +1 -0
diff -puN drivers/char/keyboard.c~sysrq_bugfix drivers/char/keyboard.c
@@ -1070,6 +1070,7 @@ static void kbd_keycode(unsigned int key
 	}
 	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

_

author
#13 lore raw

PATCH 14/15 Allow KGDB to work well with loaded modules

CC: Amit S. Kale <[email protected]>
This allows for KGDB to better deal with autoloaded modules.

---

 linux-2.6.13-rc3-trini/include/linux/module.h |   16 +++++++
 linux-2.6.13-rc3-trini/kernel/module.c        |   56 ++++++++++++++++++++++++++
 2 files changed, 72 insertions(+)
include/linux/module.h renamed from include/linux/module.h~module +16 -0
diff -puN include/linux/module.h~module include/linux/module.h
@@ -210,8 +210,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
@@ -239,6 +248,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;
kernel/module.c renamed from kernel/module.c~module +56 -0

98 lines not on this page · raw message

_

author
#14 lore raw

PATCH 15/15 Add hardware breakpoint support for i386

This adds hardware breakpoint support for i386. This is not as well tested as software breakpoints, but in some minimal testing appears to be functional.

---

 linux-2.6.13-rc3-trini/arch/i386/kernel/kgdb.c |   49 +++++++++++++++++++++++++
 1 files changed, 49 insertions(+)
arch/i386/kernel/kgdb.c renamed from arch/i386/kernel/kgdb.c~i386 +49 -0
diff -puN arch/i386/kernel/kgdb.c~i386 arch/i386/kernel/kgdb.c
@@ -184,6 +184,54 @@ void kgdb_correct_hw_break(void)
 		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 */
@@ -298,4 +346,5 @@ int kgdb_arch_init(void)
 
 struct kgdb_arch arch_kgdb_ops = {
 	.gdb_bpt_instr = {0xcc},
+	.flags = KGDB_HW_BREAKPOINT,
 };

_

#15 lore raw

Re: [patch 11/15] KGDB: KGDBoE I/O driver

In reply to Tom Rini
Quoted 5 lines · Tom Rini

This is the simple KGDB over Ethernet I/O driver that uses netpoll for all of the heavy lifting. At one point this was very similar to the version Matt Mackall wrote and is currently in Andrew's tree. Since then it has been reworked to fit into our model.

Looks good to me.

Signature · 1 line
Mathematics is the supreme nostalgia of our time.
#16 lore raw

Re: [patch 07/15] Basic x86_64 support

In reply to Tom Rini

Only reading the changes outside kgdb.c....

arch/x86_64/kernel/traps.c void __init trap_init(void) · line 950

Quoted 7 lines
arch/x86_64/kernel/traps.c renamed from arch/x86_64/kernel/traps.c~x86_64-lite +7 -0
+
+#ifdef CONFIG_KGDB
+	/*
+	 * Has KGDB been told to break as soon as possible?
+	 */
+	if (kgdb_initialized == -1)
+		tasklet_schedule(&kgdb_tasklet_breakpoint);

That doesn't make much sense here. tasklet will only run when interrupts are enabled, and that is much later. You could move it to there.

include/asm-x86_64/hw_irq.h struct hw_interrupt_type; · line 58

Quoted 8 lines

diff -puN include/asm-x86_64/hw_irq.h~x86_64-lite include/asm-x86_64/hw_irq.h

include/asm-x86_64/hw_irq.h renamed from include/asm-x86_64/hw_irq.h~x86_64-lite +1 -0
@@ -55,6 +55,7 @@ struct hw_interrupt_type;
 #define TASK_MIGRATION_VECTOR	0xfb
 #define CALL_FUNCTION_VECTOR	0xfa
 #define KDB_VECTOR	0xf9
+#define KGDB_VECTOR	0xf8

I already allocated these vectors for something else.

Quoted 6 lines
include/asm-x86_64/hw_irq.h renamed from include/asm-x86_64/hw_irq.h~x86_64-lite +0 -0
 #define THERMAL_APIC_VECTOR	0xf0
 

diff -puN include/asm-x86_64/ipi.h~x86_64-lite include/asm-x86_64/ipi.h

include/asm-x86_64/ipi.h static inline void __send_IPI_shortcut(u · line 70

Quoted 9 lines
include/asm-x86_64/ipi.h renamed from include/asm-x86_64/ipi.h~x86_64-lite +6 -0
@@ -62,6 +62,12 @@ static inline void __send_IPI_shortcut(u
 	 * No need to touch the target chip field
 	 */
 	cfg = __prepare_ICR(shortcut, vector, dest);
+        if (vector == KGDB_VECTOR) {
+                 /*
+                  * KGDB IPI is to be delivered as a NMI
+                  */
+                 cfg = (cfg&~APIC_VECTOR_MASK)|APIC_DM_NMI;
+         }

No way adding another ugly special case like this. I wanted to rip out the KDB version for a long time.

If anything pass a flag.

include/asm-x86_64/ipi.h static inline void __send_IPI_shortcut(u

Quoted 7 lines
include/asm-x86_64/ipi.h renamed from include/asm-x86_64/ipi.h~x86_64-lite +3 -1
 	,"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						  \

Why is this needed?

-Andi

author
#17 lore raw

Re: [patch 07/15] Basic x86_64 support

Quoted 13 lines · Andi Kleen

Only reading the changes outside kgdb.c....

arch/x86_64/kernel/traps.c void __init trap_init(void) · line 950

Quoted 7 lines
arch/x86_64/kernel/traps.c renamed from arch/x86_64/kernel/traps.c~x86_64-lite +7 -0
+
+#ifdef CONFIG_KGDB
+	/*
+	 * Has KGDB been told to break as soon as possible?
+	 */
+	if (kgdb_initialized == -1)
+		tasklet_schedule(&kgdb_tasklet_breakpoint);

That doesn't make much sense here. tasklet will only run when interrupts are enabled, and that is much later. You could move it to there.

Where? Keep in mind it's really only x86_64 that isn't able to break sooner.

Quoted 10 lines

include/asm-x86_64/hw_irq.h struct hw_interrupt_type; · line 58

Quoted 8 lines

diff -puN include/asm-x86_64/hw_irq.h~x86_64-lite include/asm-x86_64/hw_irq.h

include/asm-x86_64/hw_irq.h renamed from include/asm-x86_64/hw_irq.h~x86_64-lite +1 -0
@@ -55,6 +55,7 @@ struct hw_interrupt_type;
 #define TASK_MIGRATION_VECTOR	0xfb
 #define CALL_FUNCTION_VECTOR	0xfa
 #define KDB_VECTOR	0xf9
+#define KGDB_VECTOR	0xf8

I already allocated these vectors for something else.

Is there another we can use? Just following what looked to be the logical order.

Quoted 18 lines
Quoted 6 lines
include/asm-x86_64/hw_irq.h renamed from include/asm-x86_64/hw_irq.h~x86_64-lite +0 -0
 #define THERMAL_APIC_VECTOR	0xf0
 

diff -puN include/asm-x86_64/ipi.h~x86_64-lite include/asm-x86_64/ipi.h

include/asm-x86_64/ipi.h static inline void __send_IPI_shortcut(u · line 70

Quoted 9 lines
include/asm-x86_64/ipi.h renamed from include/asm-x86_64/ipi.h~x86_64-lite +6 -0
@@ -62,6 +62,12 @@ static inline void __send_IPI_shortcut(u
 	 * No need to touch the target chip field
 	 */
 	cfg = __prepare_ICR(shortcut, vector, dest);
+        if (vector == KGDB_VECTOR) {
+                 /*
+                  * KGDB IPI is to be delivered as a NMI
+                  */
+                 cfg = (cfg&~APIC_VECTOR_MASK)|APIC_DM_NMI;
+         }

No way adding another ugly special case like this. I wanted to rip out the KDB version for a long time.

I'd be happy to rework it in a cleaner manner, just point me at an example please.

Quoted 1 line

If anything pass a flag.

In __send_IPI_shortcut? OK.

Quoted 9 lines

include/asm-x86_64/ipi.h static inline void __send_IPI_shortcut(u

Quoted 7 lines
include/asm-x86_64/ipi.h renamed from include/asm-x86_64/ipi.h~x86_64-lite +3 -1
 	,"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						  \

Why is this needed?

So that backtraces show they're in switch_to rather than somewhere else (since it's a #define we wouldn't know otherwise).

Signature · 2 lines
Tom Rini
http://gate.crashing.org/~trini/
#18 lore raw

Re: [patch 07/15] Basic x86_64 support

Quoted 5 lines
Quoted 2 lines

That doesn't make much sense here. tasklet will only run when interrupts are enabled, and that is much later. You could move it to there.

Where? Keep in mind it's really only x86_64 that isn't able to break sooner.

The local_irq_enable() call in init/main.c:start_kernel()

If you want to run gdb earlier you need to do it without a tasklet.

Quoted 10 lines
Quoted 9 lines

include/asm-x86_64/hw_irq.h struct hw_interrupt_type; · line 58

Quoted 7 lines
include/asm-x86_64/hw_irq.h renamed from include/asm-x86_64/hw_irq.h~x86_64-lite +1 -0
@@ -55,6 +55,7 @@ struct hw_interrupt_type;
 #define TASK_MIGRATION_VECTOR	0xfb
 #define CALL_FUNCTION_VECTOR	0xfa
 #define KDB_VECTOR	0xf9
+#define KGDB_VECTOR	0xf8

I already allocated these vectors for something else.

Quoted 2 lines

Is there another we can use? Just following what looked to be the logical order.

How about you use KDB_VECTOR and rename it to DEBUG_VECTOR and then just check if kgdb is currently active?

KDB can do the same.

I changed the assignment in my tree like this:

#define SPURIOUS_APIC_VECTOR    0xff
#define ERROR_APIC_VECTOR       0xfe
#define RESCHEDULE_VECTOR       0xfd
#define CALL_FUNCTION_VECTOR    0xfc
#define KDB_VECTOR              0xfb    /* reserved for KDB */
#define THERMAL_APIC_VECTOR     0xfa

/* 0xf9 free */
#define INVALIDATE_TLB_VECTOR_END 0xf8
#define INVALIDATE_TLB_VECTOR_START 0xf0 /* f0-f8 used for TLB flush */

but that can be merged later. THere will be probably more changes with the per CPU IDT planned.

Quoted 8 lines
Quoted 8 lines
Quoted 7 lines
include/asm-x86_64/hw_irq.h renamed from include/asm-x86_64/hw_irq.h~x86_64-lite +6 -0
 	cfg = __prepare_ICR(shortcut, vector, dest);
+        if (vector == KGDB_VECTOR) {
+                 /*
+                  * KGDB IPI is to be delivered as a NMI
+                  */
+                 cfg = (cfg&~APIC_VECTOR_MASK)|APIC_DM_NMI;
+         }
Quoted 5 lines
Quoted 2 lines

No way adding another ugly special case like this. I wanted to rip out the KDB version for a long time.

I'd be happy to rework it in a cleaner manner, just point me at an example please.

The code is equivalent to passing shortcut|APIC_DM_NMI and vector == 0

Quoted 9 lines
Quoted 6 lines

include/asm-x86_64/hw_irq.h

Quoted 4 lines
include/asm-x86_64/hw_irq.h renamed from include/asm-x86_64/hw_irq.h~x86_64-lite +3 -1
-	asm volatile(SAVE_CONTEXT						    \
+       asm volatile(".globl __switch_to_begin\n\t"				    \
+		     "__switch_to_begin:\n\t"					  \
+		     SAVE_CONTEXT						  \

Why is this needed?

So that backtraces show they're in switch_to rather than somewhere else (since it's a #define we wouldn't know otherwise).

Ok.

-Andi

author
#19 lore raw

Re: [patch 07/15] Basic x86_64 support

Quoted 7 lines · Andi Kleen
Quoted 5 lines
Quoted 2 lines

That doesn't make much sense here. tasklet will only run when interrupts are enabled, and that is much later. You could move it to there.

Where? Keep in mind it's really only x86_64 that isn't able to break sooner.

The local_irq_enable() call in init/main.c:start_kernel()

But as I say, only x86_64 needs this kind of delay.

Quoted 1 line

If you want to run gdb earlier you need to do it without a tasklet.

We really would like to try again once stacks are setup (IOW, once if ((&__get_cpu_var(init_tss))[0].ist[0])) is true).

Quoted 10 lines
Quoted 10 lines
Quoted 9 lines

include/asm-x86_64/hw_irq.h struct hw_interrupt_type; · line 58

Quoted 7 lines
include/asm-x86_64/hw_irq.h renamed from include/asm-x86_64/hw_irq.h~x86_64-lite +1 -0
@@ -55,6 +55,7 @@ struct hw_interrupt_type;
 #define TASK_MIGRATION_VECTOR	0xfb
 #define CALL_FUNCTION_VECTOR	0xfa
 #define KDB_VECTOR	0xf9
+#define KGDB_VECTOR	0xf8

I already allocated these vectors for something else.

Quoted 5 lines
Quoted 2 lines

Is there another we can use? Just following what looked to be the logical order.

How about you use KDB_VECTOR and rename it to DEBUG_VECTOR and then just check if kgdb is currently active?

I can do the kgdb and generic changes at least.

[snip]

Quoted 8 lines
Quoted 8 lines
Quoted 8 lines
Quoted 7 lines
include/asm-x86_64/hw_irq.h renamed from include/asm-x86_64/hw_irq.h~x86_64-lite +6 -0
 	cfg = __prepare_ICR(shortcut, vector, dest);
+        if (vector == KGDB_VECTOR) {
+                 /*
+                  * KGDB IPI is to be delivered as a NMI
+                  */
+                 cfg = (cfg&~APIC_VECTOR_MASK)|APIC_DM_NMI;
+         }
Quoted 7 lines
Quoted 5 lines
Quoted 2 lines

No way adding another ugly special case like this. I wanted to rip out the KDB version for a long time.

I'd be happy to rework it in a cleaner manner, just point me at an example please.

The code is equivalent to passing shortcut|APIC_DM_NMI and vector == 0

OK. I'll see if I can change things around then, thanks.

Signature · 2 lines
Tom Rini
http://gate.crashing.org/~trini/
#20 lore raw

Re: [patch 07/15] Basic x86_64 support

Quoted 10 lines · Tom Rini
Quoted 7 lines · Andi Kleen
Quoted 5 lines
Quoted 2 lines

That doesn't make much sense here. tasklet will only run when interrupts are enabled, and that is much later. You could move it to there.

Where? Keep in mind it's really only x86_64 that isn't able to break sooner.

The local_irq_enable() call in init/main.c:start_kernel()

But as I say, only x86_64 needs this kind of delay.

I don't think that's correct. Interrupts should be disabled on all architectures until that.

-Andi

author
#21 lore raw

Re: [patch 07/15] Basic x86_64 support

Quoted 8 lines · Andi Kleen
Quoted 7 lines · Tom Rini
Quoted 6 lines · Andi Kleen
Quoted 5 lines
Quoted 2 lines

That doesn't make much sense here. tasklet will only run when interrupts are enabled, and that is much later. You could move it to there.

Where? Keep in mind it's really only x86_64 that isn't able to break sooner.

Quoted 6 lines
Quoted 3 lines
Quoted 1 line

The local_irq_enable() call in init/main.c:start_kernel()

But as I say, only x86_64 needs this kind of delay.

I don't think that's correct. Interrupts should be disabled on all architectures until that.

Right, but we can run sooner elsewhere. It's only x86_64 where we can't run when our commandline bits are parsed and need to wait.

Signature · 2 lines
Tom Rini
http://gate.crashing.org/~trini/
#22 lore raw

Re: [patch 07/15] Basic x86_64 support

Quoted 11 lines · Tom Rini
Quoted 10 lines · Andi Kleen
Quoted 9 lines · Tom Rini
Quoted 7 lines · Andi Kleen
Quoted 5 lines
Quoted 2 lines

That doesn't make much sense here. tasklet will only run when interrupts are enabled, and that is much later. You could move it to there.

Where? Keep in mind it's really only x86_64 that isn't able to break sooner.

The local_irq_enable() call in init/main.c:start_kernel()

Quoted 7 lines
Quoted 4 lines
Quoted 1 line

But as I say, only x86_64 needs this kind of delay.

I don't think that's correct. Interrupts should be disabled on all architectures until that.

Right, but we can run sooner elsewhere. It's only x86_64 where we can't run when our commandline bits are parsed and need to wait.

Why can't you run on x86-64 early?

-Andi

author
#23 lore raw

Re: [patch 07/15] Basic x86_64 support

Quoted 14 lines · Andi Kleen
Quoted 13 lines · Tom Rini
Quoted 12 lines · Andi Kleen
Quoted 10 lines · Tom Rini
Quoted 7 lines · Andi Kleen
Quoted 5 lines
Quoted 2 lines

That doesn't make much sense here. tasklet will only run when interrupts are enabled, and that is much later. You could move it to there.

Where? Keep in mind it's really only x86_64 that isn't able to break sooner.

The local_irq_enable() call in init/main.c:start_kernel()

But as I say, only x86_64 needs this kind of delay.

Quoted 7 lines
Quoted 5 lines
Quoted 2 lines

I don't think that's correct. Interrupts should be disabled on all architectures until that.

Right, but we can run sooner elsewhere. It's only x86_64 where we can't run when our commandline bits are parsed and need to wait.

Why can't you run on x86-64 early?

As I said earlier:
"

Quoted 1 line

If you want to run gdb earlier you need to do it without a tasklet.

We really would like to try again once stacks are setup (IOW, once if ((&__get_cpu_var(init_tss))[0].ist[0])) is true).
"

IOW, when we parse the params on x86_64 this isn't true (or rather it wasn't true as of 2.6.9'ish, if this has changed I'd be glad to retest things).

Signature · 2 lines
Tom Rini
http://gate.crashing.org/~trini/
#24 lore raw

Re: [patch 07/15] Basic x86_64 support

Quoted 7 lines · Tom Rini
Quoted 2 lines

Why can't you run on x86-64 early?

As I said earlier:
"

Quoted 1 line

If you want to run gdb earlier you need to do it without a tasklet.

Quoted 7 lines

We really would like to try again once stacks are setup (IOW, once if ((&__get_cpu_var(init_tss))[0].ist[0])) is true).
"

IOW, when we parse the params on x86_64 this isn't true (or rather it wasn't true as of 2.6.9'ish, if this has changed I'd be glad to retest things).

The ISTs are set up for the boot processor extremly early - even before start_kernel. But they are useless before trap_init() runs because you won't get any exceptions that need an IDT (or rather they will all still point to the early exception handler that just panics)

-Andi

author
#25 lore raw

Re: [patch 07/15] Basic x86_64 support

Quoted 12 lines · Andi Kleen
Quoted 11 lines · Tom Rini
Quoted 2 lines

Why can't you run on x86-64 early?

As I said earlier:
"

Quoted 1 line

If you want to run gdb earlier you need to do it without a tasklet.

We really would like to try again once stacks are setup (IOW, once if ((&__get_cpu_var(init_tss))[0].ist[0])) is true).
"

Quoted 8 lines
Quoted 3 lines

IOW, when we parse the params on x86_64 this isn't true (or rather it wasn't true as of 2.6.9'ish, if this has changed I'd be glad to retest things).

The ISTs are set up for the boot processor extremly early - even before start_kernel. But they are useless before trap_init() runs because you won't get any exceptions that need an IDT (or rather they will all still point to the early exception handler that just panics)

I wonder if there was a reason we couldn't do what we did with i386 and make an early_trap_init() so that we can get what we care about that early at least. I'll have to poke at this a bit more, thanks!

Signature · 2 lines
Tom Rini
http://gate.crashing.org/~trini/
#26 lore raw

Re: [patch 07/15] Basic x86_64 support

In reply to Andi Kleen
Quoted 36 lines · Andi Kleen
Quoted 5 lines
Quoted 2 lines

That doesn't make much sense here. tasklet will only run when interrupts are enabled, and that is much later. You could move it to there.

Where? Keep in mind it's really only x86_64 that isn't able to break sooner.

The local_irq_enable() call in init/main.c:start_kernel()

If you want to run gdb earlier you need to do it without a tasklet.

Quoted 10 lines
Quoted 9 lines

include/asm-x86_64/hw_irq.h struct hw_interrupt_type; · line 58

Quoted 7 lines
include/asm-x86_64/hw_irq.h renamed from include/asm-x86_64/hw_irq.h~x86_64-lite +1 -0
@@ -55,6 +55,7 @@ struct hw_interrupt_type;
 #define TASK_MIGRATION_VECTOR	0xfb
 #define CALL_FUNCTION_VECTOR	0xfa
 #define KDB_VECTOR	0xf9
+#define KGDB_VECTOR	0xf8

I already allocated these vectors for something else.

Quoted 2 lines

Is there another we can use? Just following what looked to be the logical order.

How about you use KDB_VECTOR and rename it to DEBUG_VECTOR and then just check if kgdb is currently active?

KDB can do the same.

I changed the assignment in my tree like this:

#define SPURIOUS_APIC_VECTOR    0xff
#define ERROR_APIC_VECTOR       0xfe
#define RESCHEDULE_VECTOR       0xfd
#define CALL_FUNCTION_VECTOR    0xfc
#define KDB_VECTOR              0xfb    /* reserved for KDB */
#define THERMAL_APIC_VECTOR     0xfa
Quoted 3 lines

/* 0xf9 free */
#define INVALIDATE_TLB_VECTOR_END 0xf8
#define INVALIDATE_TLB_VECTOR_START 0xf0 /* f0-f8 used for TLB flush */

Don't call it {KDB,KGDB,DEBUG}_VECTOR, call it NMI_VECTOR, which is what it really is. default_do_nmi() determines if the nmi is due to a debugger or some other event. That requires the debuggers to record if they are expecting their own nmi, putting all the load on the debuggers, where it belongs.

IOW, add NMI_VECTOR to the base code, then add debugger support on top of NMI_VECTOR.

author
#27 lore raw

Re: [patch 07/15] Basic x86_64 support

Quoted 42 lines · Keith Owens
Quoted 36 lines · Andi Kleen
Quoted 5 lines
Quoted 2 lines

That doesn't make much sense here. tasklet will only run when interrupts are enabled, and that is much later. You could move it to there.

Where? Keep in mind it's really only x86_64 that isn't able to break sooner.

The local_irq_enable() call in init/main.c:start_kernel()

If you want to run gdb earlier you need to do it without a tasklet.

Quoted 10 lines
Quoted 9 lines

include/asm-x86_64/hw_irq.h struct hw_interrupt_type; · line 58

Quoted 7 lines
include/asm-x86_64/hw_irq.h renamed from include/asm-x86_64/hw_irq.h~x86_64-lite +1 -0
@@ -55,6 +55,7 @@ struct hw_interrupt_type;
 #define TASK_MIGRATION_VECTOR	0xfb
 #define CALL_FUNCTION_VECTOR	0xfa
 #define KDB_VECTOR	0xf9
+#define KGDB_VECTOR	0xf8

I already allocated these vectors for something else.

Quoted 2 lines

Is there another we can use? Just following what looked to be the logical order.

How about you use KDB_VECTOR and rename it to DEBUG_VECTOR and then just check if kgdb is currently active?

KDB can do the same.

I changed the assignment in my tree like this:

#define SPURIOUS_APIC_VECTOR    0xff
#define ERROR_APIC_VECTOR       0xfe
#define RESCHEDULE_VECTOR       0xfd
#define CALL_FUNCTION_VECTOR    0xfc
#define KDB_VECTOR              0xfb    /* reserved for KDB */
#define THERMAL_APIC_VECTOR     0xfa
Quoted 3 lines

/* 0xf9 free */
#define INVALIDATE_TLB_VECTOR_END 0xf8
#define INVALIDATE_TLB_VECTOR_START 0xf0 /* f0-f8 used for TLB flush */

Quoted 8 lines

Don't call it {KDB,KGDB,DEBUG}_VECTOR, call it NMI_VECTOR, which is what it really is. default_do_nmi() determines if the nmi is due to a debugger or some other event. That requires the debuggers to record if they are expecting their own nmi, putting all the load on the debuggers, where it belongs.

IOW, add NMI_VECTOR to the base code, then add debugger support on top of NMI_VECTOR.

Works for me. I'll post something vs 2.6.13-rc6 later today hopefully that does the rename.

Signature · 2 lines
Tom Rini
http://gate.crashing.org/~trini/
#28 lore raw

Re: [patch 05/15] Basic MIPS support

In reply to Tom Rini

Forwarding this as a heads up. Who cares about kgdb may want to start working on the necessary bits as the patchset from below will be in 2.6.13.

Ralf

Quoted 2,777 lines · Tom Rini

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

---

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

diff -puN arch/mips/Kconfig.debug~mips-lite arch/mips/Kconfig.debug

arch/mips/Kconfig.debug renamed from arch/mips/Kconfig.debug~mips-lite +0 -19
@@ -27,25 +27,6 @@ config DEBUG_STACK_USAGE
 
 	  This option will slow down process creation somewhat.
 
-config KGDB
-	bool "Remote GDB kernel debugging"
-	depends on DEBUG_KERNEL
-	select DEBUG_INFO
-	help
-	  If you say Y here, it will be possible to remotely debug the MIPS
-	  kernel using gdb. This enlarges your kernel image disk size by
-	  several megabytes and requires a machine with more than 16 MB,
-	  better 32 MB RAM to avoid excessive linking time. This is only
-	  useful for kernel hackers. If unsure, say N.
-
-config GDB_CONSOLE
-	bool "Console output to GDB"
-	depends on KGDB
-	help
-	  If you are using GDB for remote debugging over a serial port and
-	  would like kernel messages to be formatted into GDB $O packets so
-	  that GDB prints them as program output, say 'Y'.
-
 config SB1XXX_CORELIS
 	bool "Corelis Debugger"
 	depends on SIBYTE_SB1xxx_SOC

diff -L arch/mips/kernel/gdb-low.S -puN arch/mips/kernel/gdb-low.S~mips-lite /dev/null

arch/mips/kernel/gdb-low.S deleted +0 -370
@@ -1,370 +0,0 @@
-/*
- * gdb-low.S contains the low-level trap handler for the GDB stub.
- *
- * Copyright (C) 1995 Andreas Busse
- */
-#include <linux/config.h>
-#include <linux/sys.h>
-
-#include <asm/asm.h>
-#include <asm/errno.h>
-#include <asm/mipsregs.h>
-#include <asm/regdef.h>
-#include <asm/stackframe.h>
-#include <asm/gdb-stub.h>
-
-#ifdef CONFIG_MIPS32
-#define DMFC0	mfc0
-#define DMTC0	mtc0
-#define LDC1	lwc1
-#define SDC1	lwc1
-#endif
-#ifdef CONFIG_MIPS64
-#define DMFC0	dmfc0
-#define DMTC0	dmtc0
-#define LDC1	ldc1
-#define SDC1	ldc1
-#endif
-
-/*
- * [jsun] We reserves about 2x GDB_FR_SIZE in stack.  The lower (addressed)
- * part is used to store registers and passed to exception handler.
- * The upper part is reserved for "call func" feature where gdb client
- * saves some of the regs, setups call frame and passes args.
- *
- * A trace shows about 200 bytes are used to store about half of all regs.
- * The rest should be big enough for frame setup and passing args.
- */
-
-/*
- * The low level trap handler
- */
-		.align 	5
-		NESTED(trap_low, GDB_FR_SIZE, sp)
- 		.set	noat
-		.set 	noreorder
-
-		mfc0	k0, CP0_STATUS
-		sll	k0, 3     		/* extract cu0 bit */
-		bltz	k0, 1f
-		move	k1, sp
-
-		/*
-		 * Called from user mode, go somewhere else.
-		 */
-		lui	k1, %hi(saved_vectors)
-		mfc0	k0, CP0_CAUSE
-		andi	k0, k0, 0x7c
-		add	k1, k1, k0
-		lw	k0, %lo(saved_vectors)(k1)
-		jr	k0
-		nop
-1:
-		move	k0, sp
-		subu	sp, k1, GDB_FR_SIZE*2	# see comment above
-		LONG_S	k0, GDB_FR_REG29(sp)
-		LONG_S	$2, GDB_FR_REG2(sp)
-
-/*
- * First save the CP0 and special registers
- */
-
-		mfc0	v0, CP0_STATUS
-		LONG_S	v0, GDB_FR_STATUS(sp)
-		mfc0	v0, CP0_CAUSE
-		LONG_S	v0, GDB_FR_CAUSE(sp)
-		DMFC0	v0, CP0_EPC
-		LONG_S	v0, GDB_FR_EPC(sp)
-		DMFC0	v0, CP0_BADVADDR
-		LONG_S	v0, GDB_FR_BADVADDR(sp)
-		mfhi	v0
-		LONG_S	v0, GDB_FR_HI(sp)
-		mflo	v0
-		LONG_S	v0, GDB_FR_LO(sp)
-
-/*
- * Now the integer registers
- */
-
-		LONG_S	zero, GDB_FR_REG0(sp)		/* I know... */
-		LONG_S	$1, GDB_FR_REG1(sp)
-		/* v0 already saved */
-		LONG_S	$3, GDB_FR_REG3(sp)
-		LONG_S	$4, GDB_FR_REG4(sp)
-		LONG_S	$5, GDB_FR_REG5(sp)
-		LONG_S	$6, GDB_FR_REG6(sp)
-		LONG_S	$7, GDB_FR_REG7(sp)
-		LONG_S	$8, GDB_FR_REG8(sp)
-		LONG_S	$9, GDB_FR_REG9(sp)
-		LONG_S	$10, GDB_FR_REG10(sp)
-		LONG_S	$11, GDB_FR_REG11(sp)
-		LONG_S	$12, GDB_FR_REG12(sp)
-		LONG_S	$13, GDB_FR_REG13(sp)
-		LONG_S	$14, GDB_FR_REG14(sp)
-		LONG_S	$15, GDB_FR_REG15(sp)
-		LONG_S	$16, GDB_FR_REG16(sp)
-		LONG_S	$17, GDB_FR_REG17(sp)
-		LONG_S	$18, GDB_FR_REG18(sp)
-		LONG_S	$19, GDB_FR_REG19(sp)
-		LONG_S	$20, GDB_FR_REG20(sp)
-		LONG_S	$21, GDB_FR_REG21(sp)
-		LONG_S	$22, GDB_FR_REG22(sp)
-		LONG_S	$23, GDB_FR_REG23(sp)
-		LONG_S	$24, GDB_FR_REG24(sp)
-		LONG_S	$25, GDB_FR_REG25(sp)
-		LONG_S	$26, GDB_FR_REG26(sp)
-		LONG_S	$27, GDB_FR_REG27(sp)
-		LONG_S	$28, GDB_FR_REG28(sp)
-		/* sp already saved */
-		LONG_S	$30, GDB_FR_REG30(sp)
-		LONG_S	$31, GDB_FR_REG31(sp)
-
-		CLI				/* disable interrupts */
-
-/*
- * Followed by the floating point registers
- */
-		mfc0	v0, CP0_STATUS		/* FPU enabled? */
-		srl	v0, v0, 16
-		andi	v0, v0, (ST0_CU1 >> 16)
-
-		beqz	v0,2f			/* disabled, skip */
-		 nop
-
-		SDC1	$0, GDB_FR_FPR0(sp)
-		SDC1	$1, GDB_FR_FPR1(sp)
-		SDC1	$2, GDB_FR_FPR2(sp)
-		SDC1	$3, GDB_FR_FPR3(sp)
-		SDC1	$4, GDB_FR_FPR4(sp)
-		SDC1	$5, GDB_FR_FPR5(sp)
-		SDC1	$6, GDB_FR_FPR6(sp)
-		SDC1	$7, GDB_FR_FPR7(sp)
-		SDC1	$8, GDB_FR_FPR8(sp)
-		SDC1	$9, GDB_FR_FPR9(sp)
-		SDC1	$10, GDB_FR_FPR10(sp)
-		SDC1	$11, GDB_FR_FPR11(sp)
-		SDC1	$12, GDB_FR_FPR12(sp)
-		SDC1	$13, GDB_FR_FPR13(sp)
-		SDC1	$14, GDB_FR_FPR14(sp)
-		SDC1	$15, GDB_FR_FPR15(sp)
-		SDC1	$16, GDB_FR_FPR16(sp)
-		SDC1	$17, GDB_FR_FPR17(sp)
-		SDC1	$18, GDB_FR_FPR18(sp)
-		SDC1	$19, GDB_FR_FPR19(sp)
-		SDC1	$20, GDB_FR_FPR20(sp)
-		SDC1	$21, GDB_FR_FPR21(sp)
-		SDC1	$22, GDB_FR_FPR22(sp)
-		SDC1	$23, GDB_FR_FPR23(sp)
-		SDC1	$24, GDB_FR_FPR24(sp)
-		SDC1	$25, GDB_FR_FPR25(sp)
-		SDC1	$26, GDB_FR_FPR26(sp)
-		SDC1	$27, GDB_FR_FPR27(sp)
-		SDC1	$28, GDB_FR_FPR28(sp)
-		SDC1	$29, GDB_FR_FPR29(sp)
-		SDC1	$30, GDB_FR_FPR30(sp)
-		SDC1	$31, GDB_FR_FPR31(sp)
-
-/*
- * FPU control registers
- */
-
-		cfc1	v0, CP1_STATUS
-		LONG_S	v0, GDB_FR_FSR(sp)
-		cfc1	v0, CP1_REVISION
-		LONG_S	v0, GDB_FR_FIR(sp)
-
-/*
- * Current stack frame ptr
- */
-
-2:
-		LONG_S	sp, GDB_FR_FRP(sp)
-
-/*
- * CP0 registers (R4000/R4400 unused registers skipped)
- */
-
-		mfc0	v0, CP0_INDEX
-		LONG_S	v0, GDB_FR_CP0_INDEX(sp)
-		mfc0	v0, CP0_RANDOM
-		LONG_S	v0, GDB_FR_CP0_RANDOM(sp)
-		DMFC0	v0, CP0_ENTRYLO0
-		LONG_S	v0, GDB_FR_CP0_ENTRYLO0(sp)
-		DMFC0	v0, CP0_ENTRYLO1
-		LONG_S	v0, GDB_FR_CP0_ENTRYLO1(sp)
-		DMFC0	v0, CP0_CONTEXT
-		LONG_S	v0, GDB_FR_CP0_CONTEXT(sp)
-		mfc0	v0, CP0_PAGEMASK
-		LONG_S	v0, GDB_FR_CP0_PAGEMASK(sp)
-		mfc0	v0, CP0_WIRED
-		LONG_S	v0, GDB_FR_CP0_WIRED(sp)
-		DMFC0	v0, CP0_ENTRYHI
-		LONG_S	v0, GDB_FR_CP0_ENTRYHI(sp)
-		mfc0	v0, CP0_PRID
-		LONG_S	v0, GDB_FR_CP0_PRID(sp)
-
-		.set	at
-
-/*
- * Continue with the higher level handler
- */
-
-		move	a0,sp
-
-		jal	handle_exception
-		 nop
-
-/*
- * Restore all writable registers, in reverse order
- */
-
-		.set	noat
-
-		LONG_L	v0, GDB_FR_CP0_ENTRYHI(sp)
-		LONG_L	v1, GDB_FR_CP0_WIRED(sp)
-		DMTC0	v0, CP0_ENTRYHI
-		mtc0	v1, CP0_WIRED
-		LONG_L	v0, GDB_FR_CP0_PAGEMASK(sp)
-		LONG_L	v1, GDB_FR_CP0_ENTRYLO1(sp)
-		mtc0	v0, CP0_PAGEMASK
-		DMTC0	v1, CP0_ENTRYLO1
-		LONG_L	v0, GDB_FR_CP0_ENTRYLO0(sp)
-		LONG_L	v1, GDB_FR_CP0_INDEX(sp)
-		DMTC0	v0, CP0_ENTRYLO0
-		LONG_L	v0, GDB_FR_CP0_CONTEXT(sp)
-		mtc0	v1, CP0_INDEX
-		DMTC0	v0, CP0_CONTEXT
-
-
-/*
- * Next, the floating point registers
- */
-		mfc0	v0, CP0_STATUS		/* check if the FPU is enabled */
-		srl	v0, v0, 16
-		andi	v0, v0, (ST0_CU1 >> 16)
-
-		beqz	v0, 3f			/* disabled, skip */
-		 nop
-
-		LDC1	$31, GDB_FR_FPR31(sp)
-		LDC1	$30, GDB_FR_FPR30(sp)
-		LDC1	$29, GDB_FR_FPR29(sp)
-		LDC1	$28, GDB_FR_FPR28(sp)
-		LDC1	$27, GDB_FR_FPR27(sp)
-		LDC1	$26, GDB_FR_FPR26(sp)
-		LDC1	$25, GDB_FR_FPR25(sp)
-		LDC1	$24, GDB_FR_FPR24(sp)
-		LDC1	$23, GDB_FR_FPR23(sp)
-		LDC1	$22, GDB_FR_FPR22(sp)
-		LDC1	$21, GDB_FR_FPR21(sp)
-		LDC1	$20, GDB_FR_FPR20(sp)
-		LDC1	$19, GDB_FR_FPR19(sp)
-		LDC1	$18, GDB_FR_FPR18(sp)
-		LDC1	$17, GDB_FR_FPR17(sp)
-		LDC1	$16, GDB_FR_FPR16(sp)
-		LDC1	$15, GDB_FR_FPR15(sp)
-		LDC1	$14, GDB_FR_FPR14(sp)
-		LDC1	$13, GDB_FR_FPR13(sp)
-		LDC1	$12, GDB_FR_FPR12(sp)
-		LDC1	$11, GDB_FR_FPR11(sp)
-		LDC1	$10, GDB_FR_FPR10(sp)
-		LDC1	$9, GDB_FR_FPR9(sp)
-		LDC1	$8, GDB_FR_FPR8(sp)
-		LDC1	$7, GDB_FR_FPR7(sp)
-		LDC1	$6, GDB_FR_FPR6(sp)
-		LDC1	$5, GDB_FR_FPR5(sp)
-		LDC1	$4, GDB_FR_FPR4(sp)
-		LDC1	$3, GDB_FR_FPR3(sp)
-		LDC1	$2, GDB_FR_FPR2(sp)
-		LDC1	$1, GDB_FR_FPR1(sp)
-		LDC1	$0, GDB_FR_FPR0(sp)
-
-/*
- * Now the CP0 and integer registers
- */
-
-3:
-		mfc0	t0, CP0_STATUS
-		ori	t0, 0x1f
-		xori	t0, 0x1f
-		mtc0	t0, CP0_STATUS
-
-		LONG_L	v0, GDB_FR_STATUS(sp)
-		LONG_L	v1, GDB_FR_EPC(sp)
-		mtc0	v0, CP0_STATUS
-		DMTC0	v1, CP0_EPC
-		LONG_L	v0, GDB_FR_HI(sp)
-		LONG_L	v1, GDB_FR_LO(sp)
-		mthi	v0
-		mtlo	v1
-		LONG_L	$31, GDB_FR_REG31(sp)
-		LONG_L	$30, GDB_FR_REG30(sp)
-		LONG_L	$28, GDB_FR_REG28(sp)
-		LONG_L	$27, GDB_FR_REG27(sp)
-		LONG_L	$26, GDB_FR_REG26(sp)
-		LONG_L	$25, GDB_FR_REG25(sp)
-		LONG_L	$24, GDB_FR_REG24(sp)
-		LONG_L	$23, GDB_FR_REG23(sp)
-		LONG_L	$22, GDB_FR_REG22(sp)
-		LONG_L	$21, GDB_FR_REG21(sp)
-		LONG_L	$20, GDB_FR_REG20(sp)
-		LONG_L	$19, GDB_FR_REG19(sp)
-		LONG_L	$18, GDB_FR_REG18(sp)
-		LONG_L	$17, GDB_FR_REG17(sp)
-		LONG_L	$16, GDB_FR_REG16(sp)
-		LONG_L	$15, GDB_FR_REG15(sp)
-		LONG_L	$14, GDB_FR_REG14(sp)
-		LONG_L	$13, GDB_FR_REG13(sp)
-		LONG_L	$12, GDB_FR_REG12(sp)
-		LONG_L	$11, GDB_FR_REG11(sp)
-		LONG_L	$10, GDB_FR_REG10(sp)
-		LONG_L	$9, GDB_FR_REG9(sp)
-		LONG_L	$8, GDB_FR_REG8(sp)
-		LONG_L	$7, GDB_FR_REG7(sp)
-		LONG_L	$6, GDB_FR_REG6(sp)
-		LONG_L	$5, GDB_FR_REG5(sp)
-		LONG_L	$4, GDB_FR_REG4(sp)
-		LONG_L	$3, GDB_FR_REG3(sp)
-		LONG_L	$2, GDB_FR_REG2(sp)
-		LONG_L	$1, GDB_FR_REG1(sp)
-#if defined(CONFIG_CPU_R3000) || defined(CONFIG_CPU_TX39XX)
-		LONG_L	k0, GDB_FR_EPC(sp)
-		LONG_L	$29, GDB_FR_REG29(sp)		/* Deallocate stack */
-		jr	k0
-		rfe
-#else
-		LONG_L	sp, GDB_FR_REG29(sp)		/* Deallocate stack */
-
-		.set	mips3
-		eret
-		.set	mips0
-#endif
-		.set	at
-		.set	reorder
-		END(trap_low)
-
-LEAF(kgdb_read_byte)
-4:		lb	t0, (a0)
-		sb	t0, (a1)
-		li	v0, 0
-		jr	ra
-		.section __ex_table,"a"
-		PTR	4b, kgdbfault
-		.previous
-		END(kgdb_read_byte)
-
-LEAF(kgdb_write_byte)
-5:		sb	a0, (a1)
-		li	v0, 0
-		jr	ra
-		.section __ex_table,"a"
-		PTR	5b, kgdbfault
-		.previous
-		END(kgdb_write_byte)
-
-		.type	kgdbfault@function
-		.ent	kgdbfault
-
-kgdbfault:	li	v0, -EFAULT
-		jr	ra
-		.end	kgdbfault

diff -L arch/mips/kernel/gdb-stub.c -puN arch/mips/kernel/gdb-stub.c~mips-lite /dev/null

arch/mips/kernel/gdb-stub.c deleted +0 -1091
@@ -1,1091 +0,0 @@
-/*
- *  arch/mips/kernel/gdb-stub.c
- *
- *  Originally written by Glenn Engel, Lake Stevens Instrument Division
- *
- *  Contributed by HP Systems
- *
- *  Modified for SPARC by Stu Grossman, Cygnus Support.
- *
- *  Modified for Linux/MIPS (and MIPS in general) by Andreas Busse
- *  Send complaints, suggestions etc. to <[email protected]>
- *
- *  Copyright (C) 1995 Andreas Busse
- *
- *  Copyright (C) 2003 MontaVista Software Inc.
- *  Author: Jun Sun, [email protected] or [email protected]
- */
-
-/*
- *  To enable debugger support, two things need to happen.  One, a
- *  call to set_debug_traps() is necessary in order to allow any breakpoints
- *  or error conditions to be properly intercepted and reported to gdb.
- *  Two, a breakpoint needs to be generated to begin communication.  This
- *  is most easily accomplished by a call to breakpoint().  Breakpoint()
- *  simulates a breakpoint by executing a BREAK instruction.
- *
- *
- *    The following gdb commands are supported:
- *
- * command          function                               Return value
- *
- *    g             return the value of the CPU registers  hex data or ENN
- *    G             set the value of the CPU registers     OK or ENN
- *
- *    mAA..AA,LLLL  Read LLLL bytes at address AA..AA      hex data or ENN
- *    MAA..AA,LLLL: Write LLLL bytes at address AA.AA      OK or ENN
- *
- *    c             Resume at current address              SNN   ( signal NN)
- *    cAA..AA       Continue at address AA..AA             SNN
- *
- *    s             Step one instruction                   SNN
- *    sAA..AA       Step one instruction from AA..AA       SNN
- *
- *    k             kill
- *
- *    ?             What was the last sigval ?             SNN   (signal NN)
- *
- *    bBB..BB	    Set baud rate to BB..BB		   OK or BNN, then sets
- *							   baud rate
- *
- * All commands and responses are sent with a packet which includes a
- * checksum.  A packet consists of
- *
- * $<packet info>#<checksum>.
- *
- * where
- * <packet info> :: <characters representing the command or response>
- * <checksum>    :: < two hex digits computed as modulo 256 sum of <packetinfo>>
- *
- * When a packet is received, it is first acknowledged with either '+' or '-'.
- * '+' indicates a successful transfer.  '-' indicates a failed transfer.
- *
- * Example:
- *
- * Host:                  Reply:
- * $m0,10#2a               +$00010203040506070809101112131415#42
- *
- *
- *  ==============
- *  MORE EXAMPLES:
- *  ==============
- *
- *  For reference -- the following are the steps that one
- *  company took (RidgeRun Inc) to get remote gdb debugging
- *  going. In this scenario the host machine was a PC and the
- *  target platform was a Galileo EVB64120A MIPS evaluation
- *  board.
- *
- *  Step 1:
- *  First download gdb-5.0.tar.gz from the internet.
- *  and then build/install the package.
- *
- *  Example:
- *    $ tar zxf gdb-5.0.tar.gz
- *    $ cd gdb-5.0
- *    $ ./configure --target=mips-linux-elf
- *    $ make
- *    $ install
- *    $ which mips-linux-elf-gdb
- *    /usr/local/bin/mips-linux-elf-gdb
- *
- *  Step 2:
- *  Configure linux for remote debugging and build it.
- *
- *  Example:
- *    $ cd ~/linux
- *    $ make menuconfig <go to "Kernel Hacking" and turn on remote debugging>
- *    $ make
- *
- *  Step 3:
- *  Download the kernel to the remote target and start
- *  the kernel running. It will promptly halt and wait
- *  for the host gdb session to connect. It does this
- *  since the "Kernel Hacking" option has defined
- *  CONFIG_KGDB which in turn enables your calls
- *  to:
- *     set_debug_traps();
- *     breakpoint();
- *
- *  Step 4:
- *  Start the gdb session on the host.
- *
- *  Example:
- *    $ mips-linux-elf-gdb vmlinux
- *    (gdb) set remotebaud 115200
- *    (gdb) target remote /dev/ttyS1
- *    ...at this point you are connected to
- *       the remote target and can use gdb
- *       in the normal fasion. Setting
- *       breakpoints, single stepping,
- *       printing variables, etc.
- */
-#include <linux/config.h>
-#include <linux/string.h>
-#include <linux/kernel.h>
-#include <linux/signal.h>
-#include <linux/sched.h>
-#include <linux/mm.h>
-#include <linux/console.h>
-#include <linux/init.h>
-#include <linux/smp.h>
-#include <linux/spinlock.h>
-#include <linux/slab.h>
-#include <linux/reboot.h>
-
-#include <asm/asm.h>
-#include <asm/cacheflush.h>
-#include <asm/mipsregs.h>
-#include <asm/pgtable.h>
-#include <asm/system.h>
-#include <asm/gdb-stub.h>
-#include <asm/inst.h>
-
-/*
- * external low-level support routines
- */
-
-extern int putDebugChar(char c);    /* write a single character      */
-extern char getDebugChar(void);     /* read and return a single char */
-extern void trap_low(void);
-
-/*
- * breakpoint and test functions
- */
-extern void breakpoint(void);
-extern void breakinst(void);
-extern void async_breakpoint(void);
-extern void async_breakinst(void);
-extern void adel(void);
-
-/*
- * local prototypes
- */
-
-static void getpacket(char *buffer);
-static void putpacket(char *buffer);
-static int computeSignal(int tt);
-static int hex(unsigned char ch);
-static int hexToInt(char **ptr, int *intValue);
-static int hexToLong(char **ptr, long *longValue);
-static unsigned char *mem2hex(char *mem, char *buf, int count, int may_fault);
-void handle_exception(struct gdb_regs *regs);
-
-int kgdb_enabled;
-
-/*
- * spin locks for smp case
- */
-static spinlock_t kgdb_lock = SPIN_LOCK_UNLOCKED;
-static spinlock_t kgdb_cpulock[NR_CPUS] = { [0 ... NR_CPUS-1] = SPIN_LOCK_UNLOCKED};
-
-/*
- * BUFMAX defines the maximum number of characters in inbound/outbound buffers
- * at least NUMREGBYTES*2 are needed for register packets
- */
-#define BUFMAX 2048
-
-static char input_buffer[BUFMAX];
-static char output_buffer[BUFMAX];
-static int initialized;	/* !0 means we've been initialized */
-static int kgdb_started;
-static const char hexchars[]="0123456789abcdef";
-
-/* Used to prevent crashes in memory access.  Note that they'll crash anyway if
-   we haven't set up fault handlers yet... */
-int kgdb_read_byte(unsigned char *address, unsigned char *dest);
-int kgdb_write_byte(unsigned char val, unsigned char *dest);
-
-/*
- * Convert ch from a hex digit to an int
- */
-static int hex(unsigned char ch)
-{
-	if (ch >= 'a' && ch <= 'f')
-		return ch-'a'+10;
-	if (ch >= '0' && ch <= '9')
-		return ch-'0';
-	if (ch >= 'A' && ch <= 'F')
-		return ch-'A'+10;
-	return -1;
-}
-
-/*
- * scan for the sequence $<data>#<checksum>
- */
-static void getpacket(char *buffer)
-{
-	unsigned char checksum;
-	unsigned char xmitcsum;
-	int i;
-	int count;
-	unsigned char ch;
-
-	do {
-		/*
-		 * wait around for the start character,
-		 * ignore all other characters
-		 */
-		while ((ch = (getDebugChar() & 0x7f)) != '$') ;
-
-		checksum = 0;
-		xmitcsum = -1;
-		count = 0;
-
-		/*
-		 * now, read until a # or end of buffer is found
-		 */
-		while (count < BUFMAX) {
-			ch = getDebugChar();
-			if (ch == '#')
-				break;
-			checksum = checksum + ch;
-			buffer[count] = ch;
-			count = count + 1;
-		}
-
-		if (count >= BUFMAX)
-			continue;
-
-		buffer[count] = 0;
-
-		if (ch == '#') {
-			xmitcsum = hex(getDebugChar() & 0x7f) << 4;
-			xmitcsum |= hex(getDebugChar() & 0x7f);
-
-			if (checksum != xmitcsum)
-				putDebugChar('-');	/* failed checksum */
-			else {
-				putDebugChar('+'); /* successful transfer */
-
-				/*
-				 * if a sequence char is present,
-				 * reply the sequence ID
-				 */
-				if (buffer[2] == ':') {
-					putDebugChar(buffer[0]);
-					putDebugChar(buffer[1]);
-
-					/*
-					 * remove sequence chars from buffer
-					 */
-					count = strlen(buffer);
-					for (i=3; i <= count; i++)
-						buffer[i-3] = buffer[i];
-				}
-			}
-		}
-	}
-	while (checksum != xmitcsum);
-}
-
-/*
- * send the packet in buffer.
- */
-static void putpacket(char *buffer)
-{
-	unsigned char checksum;
-	int count;
-	unsigned char ch;
-
-	/*
-	 * $<packet info>#<checksum>.
-	 */
-
-	do {
-		putDebugChar('$');
-		checksum = 0;
-		count = 0;
-
-		while ((ch = buffer[count]) != 0) {
-			if (!(putDebugChar(ch)))
-				return;
-			checksum += ch;
-			count += 1;
-		}
-
-		putDebugChar('#');
-		putDebugChar(hexchars[checksum >> 4]);
-		putDebugChar(hexchars[checksum & 0xf]);
-
-	}
-	while ((getDebugChar() & 0x7f) != '+');
-}
-
-
-/*
- * Convert the memory pointed to by mem into hex, placing result in buf.
- * Return a pointer to the last char put in buf (null), in case of mem fault,
- * return 0.
- * may_fault is non-zero if we are reading from arbitrary memory, but is currently
- * not used.
- */
-static unsigned char *mem2hex(char *mem, char *buf, int count, int may_fault)
-{
-	unsigned char ch;
-
-	while (count-- > 0) {
-		if (kgdb_read_byte(mem++, &ch) != 0)
-			return 0;
-		*buf++ = hexchars[ch >> 4];
-		*buf++ = hexchars[ch & 0xf];
-	}
-
-	*buf = 0;
-
-	return buf;
-}
-
-/*
- * convert the hex array pointed to by buf into binary to be placed in mem
- * return a pointer to the character AFTER the last byte written
- * may_fault is non-zero if we are reading from arbitrary memory, but is currently
- * not used.
- */
-static char *hex2mem(char *buf, char *mem, int count, int binary, int may_fault)
-{
-	int i;
-	unsigned char ch;
-
-	for (i=0; i<count; i++)
-	{
-		if (binary) {
-			ch = *buf++;
-			if (ch == 0x7d)
-				ch = 0x20 ^ *buf++;
-		}
-		else {
-			ch = hex(*buf++) << 4;
-			ch |= hex(*buf++);
-		}
-		if (kgdb_write_byte(ch, mem++) != 0)
-			return 0;
-	}
-
-	return mem;
-}
-
-/*
- * This table contains the mapping between SPARC hardware trap types, and
- * signals, which are primarily what GDB understands.  It also indicates
- * which hardware traps we need to commandeer when initializing the stub.
- */
-static struct hard_trap_info {
-	unsigned char tt;		/* Trap type code for MIPS R3xxx and R4xxx */
-	unsigned char signo;		/* Signal that we map this trap into */
-} hard_trap_info[] = {
-	{ 6, SIGBUS },			/* instruction bus error */
-	{ 7, SIGBUS },			/* data bus error */
-	{ 9, SIGTRAP },			/* break */
-	{ 10, SIGILL },			/* reserved instruction */
-/*	{ 11, SIGILL },		*/	/* CPU unusable */
-	{ 12, SIGFPE },			/* overflow */
-	{ 13, SIGTRAP },		/* trap */
-	{ 14, SIGSEGV },		/* virtual instruction cache coherency */
-	{ 15, SIGFPE },			/* floating point exception */
-	{ 23, SIGSEGV },		/* watch */
-	{ 31, SIGSEGV },		/* virtual data cache coherency */
-	{ 0, 0}				/* Must be last */
-};
-
-/* Save the normal trap handlers for user-mode traps. */
-void *saved_vectors[32];
-
-/*
- * Set up exception handlers for tracing and breakpoints
- */
-void set_debug_traps(void)
-{
-	struct hard_trap_info *ht;
-	unsigned long flags;
-	unsigned char c;
-
-	local_irq_save(flags);
-	for (ht = hard_trap_info; ht->tt && ht->signo; ht++)
-		saved_vectors[ht->tt] = set_except_vector(ht->tt, trap_low);
-
-	putDebugChar('+'); /* 'hello world' */
-	/*
-	 * In case GDB is started before us, ack any packets
-	 * (presumably "$?#xx") sitting there.
-	 */
-	while((c = getDebugChar()) != '$');
-	while((c = getDebugChar()) != '#');
-	c = getDebugChar(); /* eat first csum byte */
-	c = getDebugChar(); /* eat second csum byte */
-	putDebugChar('+'); /* ack it */
-
-	initialized = 1;
-	local_irq_restore(flags);
-}
-
-void restore_debug_traps(void)
-{
-	struct hard_trap_info *ht;
-	unsigned long flags;
-
-	local_irq_save(flags);
-	for (ht = hard_trap_info; ht->tt && ht->signo; ht++)
-		set_except_vector(ht->tt, saved_vectors[ht->tt]);
-	local_irq_restore(flags);
-}
-
-/*
- * Convert the MIPS hardware trap type code to a Unix signal number.
- */
-static int computeSignal(int tt)
-{
-	struct hard_trap_info *ht;
-
-	for (ht = hard_trap_info; ht->tt && ht->signo; ht++)
-		if (ht->tt == tt)
-			return ht->signo;
-
-	return SIGHUP;		/* default for things we don't know about */
-}
-
-/*
- * While we find nice hex chars, build an int.
- * Return number of chars processed.
- */
-static int hexToInt(char **ptr, int *intValue)
-{
-	int numChars = 0;
-	int hexValue;
-
-	*intValue = 0;
-
-	while (**ptr) {
-		hexValue = hex(**ptr);
-		if (hexValue < 0)
-			break;
-
-		*intValue = (*intValue << 4) | hexValue;
-		numChars ++;
-
-		(*ptr)++;
-	}
-
-	return (numChars);
-}
-
-static int hexToLong(char **ptr, long *longValue)
-{
-	int numChars = 0;
-	int hexValue;
-
-	*longValue = 0;
-
-	while (**ptr) {
-		hexValue = hex(**ptr);
-		if (hexValue < 0)
-			break;
-
-		*longValue = (*longValue << 4) | hexValue;
-		numChars ++;
-
-		(*ptr)++;
-	}
-
-	return numChars;
-}
-
-
-#if 0
-/*
- * Print registers (on target console)
- * Used only to debug the stub...
- */
-void show_gdbregs(struct gdb_regs * regs)
-{
-	/*
-	 * Saved main processor registers
-	 */
-	printk("$0 : %08lx %08lx %08lx %08lx %08lx %08lx %08lx %08lx\n",
-	       regs->reg0, regs->reg1, regs->reg2, regs->reg3,
-               regs->reg4, regs->reg5, regs->reg6, regs->reg7);
-	printk("$8 : %08lx %08lx %08lx %08lx %08lx %08lx %08lx %08lx\n",
-	       regs->reg8, regs->reg9, regs->reg10, regs->reg11,
-               regs->reg12, regs->reg13, regs->reg14, regs->reg15);
-	printk("$16: %08lx %08lx %08lx %08lx %08lx %08lx %08lx %08lx\n",
-	       regs->reg16, regs->reg17, regs->reg18, regs->reg19,
-               regs->reg20, regs->reg21, regs->reg22, regs->reg23);
-	printk("$24: %08lx %08lx %08lx %08lx %08lx %08lx %08lx %08lx\n",
-	       regs->reg24, regs->reg25, regs->reg26, regs->reg27,
-	       regs->reg28, regs->reg29, regs->reg30, regs->reg31);
-
-	/*
-	 * Saved cp0 registers
-	 */
-	printk("epc  : %08lx\nStatus: %08lx\nCause : %08lx\n",
-	       regs->cp0_epc, regs->cp0_status, regs->cp0_cause);
-}
-#endif /* dead code */
-
-/*
- * We single-step by setting breakpoints. When an exception
- * is handled, we need to restore the instructions hoisted
- * when the breakpoints were set.
- *
- * This is where we save the original instructions.
- */
-static struct gdb_bp_save {
-	unsigned long addr;
-	unsigned int val;
-} step_bp[2];
-
-#define BP 0x0000000d  /* break opcode */
-
-/*
- * Set breakpoint instructions for single stepping.
- */
-static void single_step(struct gdb_regs *regs)
-{
-	union mips_instruction insn;
-	unsigned long targ;
-	int is_branch, is_cond, i;
-
-	targ = regs->cp0_epc;
-	insn.word = *(unsigned int *)targ;
-	is_branch = is_cond = 0;
-
-	switch (insn.i_format.opcode) {
-	/*
-	 * jr and jalr are in r_format format.
-	 */
-	case spec_op:
-		switch (insn.r_format.func) {
-		case jalr_op:
-		case jr_op:
-			targ = *(&regs->reg0 + insn.r_format.rs);
-			is_branch = 1;
-			break;
-		}
-		break;
-
-	/*
-	 * This group contains:
-	 * bltz_op, bgez_op, bltzl_op, bgezl_op,
-	 * bltzal_op, bgezal_op, bltzall_op, bgezall_op.
-	 */
-	case bcond_op:
-		is_branch = is_cond = 1;
-		targ += 4 + (insn.i_format.simmediate << 2);
-		break;
-
-	/*
-	 * These are unconditional and in j_format.
-	 */
-	case jal_op:
-	case j_op:
-		is_branch = 1;
-		targ += 4;
-		targ >>= 28;
-		targ <<= 28;
-		targ |= (insn.j_format.target << 2);
-		break;
-
-	/*
-	 * These are conditional.
-	 */
-	case beq_op:
-	case beql_op:
-	case bne_op:
-	case bnel_op:
-	case blez_op:
-	case blezl_op:
-	case bgtz_op:
-	case bgtzl_op:
-	case cop0_op:
-	case cop1_op:
-	case cop2_op:
-	case cop1x_op:
-		is_branch = is_cond = 1;
-		targ += 4 + (insn.i_format.simmediate << 2);
-		break;
-	}
-
-	if (is_branch) {
-		i = 0;
-		if (is_cond && targ != (regs->cp0_epc + 8)) {
-			step_bp[i].addr = regs->cp0_epc + 8;
-			step_bp[i++].val = *(unsigned *)(regs->cp0_epc + 8);
-			*(unsigned *)(regs->cp0_epc + 8) = BP;
-		}
-		step_bp[i].addr = targ;
-		step_bp[i].val  = *(unsigned *)targ;
-		*(unsigned *)targ = BP;
-	} else {
-		step_bp[0].addr = regs->cp0_epc + 4;
-		step_bp[0].val  = *(unsigned *)(regs->cp0_epc + 4);
-		*(unsigned *)(regs->cp0_epc + 4) = BP;
-	}
-}
-
-/*
- *  If asynchronously interrupted by gdb, then we need to set a breakpoint
- *  at the interrupted instruction so that we wind up stopped with a
- *  reasonable stack frame.
- */
-static struct gdb_bp_save async_bp;
-
-/*
- * Swap the interrupted EPC with our asynchronous breakpoint routine.
- * This is safer than stuffing the breakpoint in-place, since no cache
- * flushes (or resulting smp_call_functions) are required.  The
- * assumption is that only one CPU will be handling asynchronous bp's,
- * and only one can be active at a time.
- */
-extern spinlock_t smp_call_lock;
-void set_async_breakpoint(unsigned long *epc)
-{
-	/* skip breaking into userland */
-	if ((*epc & 0x80000000) == 0)
-		return;
-
-	/* avoid deadlock if someone is make IPC */
-	if (spin_is_locked(&smp_call_lock))
-		return;
-
-	async_bp.addr = *epc;
-	*epc = (unsigned long)async_breakpoint;
-}
-
-void kgdb_wait(void *arg)
-{
-	unsigned flags;
-	int cpu = smp_processor_id();
-
-	local_irq_save(flags);
-
-	spin_lock(&kgdb_cpulock[cpu]);
-	spin_unlock(&kgdb_cpulock[cpu]);
-
-	local_irq_restore(flags);
-}
-
-
-/*
- * This function does all command processing for interfacing to gdb.  It
- * returns 1 if you should skip the instruction at the trap address, 0
- * otherwise.
- */
-void handle_exception (struct gdb_regs *regs)
-{
-	int trap;			/* Trap type */
-	int sigval;
-	long addr;
-	int length;
-	char *ptr;
-	unsigned long *stack;
-	int i;
-	int bflag = 0;
-
-	kgdb_started = 1;
-
-	/*
-	 * acquire the big kgdb spinlock
-	 */
-	if (!spin_trylock(&kgdb_lock)) {
-		/* 
-		 * some other CPU has the lock, we should go back to 
-		 * receive the gdb_wait IPC
-		 */
-		return;
-	}
-
-	/*
-	 * If we're in async_breakpoint(), restore the real EPC from
-	 * the breakpoint.
-	 */
-	if (regs->cp0_epc == (unsigned long)async_breakinst) {
-		regs->cp0_epc = async_bp.addr;
-		async_bp.addr = 0;
-	}
-
-	/* 
-	 * acquire the CPU spinlocks
-	 */
-	for (i = num_online_cpus()-1; i >= 0; i--)
-		if (spin_trylock(&kgdb_cpulock[i]) == 0)
-			panic("kgdb: couldn't get cpulock %d\n", i);
-
-	/*
-	 * force other cpus to enter kgdb
-	 */
-	smp_call_function(kgdb_wait, NULL, 0, 0);
-
-	/*
-	 * If we're in breakpoint() increment the PC
-	 */
-	trap = (regs->cp0_cause & 0x7c) >> 2;
-	if (trap == 9 && regs->cp0_epc == (unsigned long)breakinst)
-		regs->cp0_epc += 4;
-
-	/*
-	 * If we were single_stepping, restore the opcodes hoisted
-	 * for the breakpoint[s].
-	 */
-	if (step_bp[0].addr) {
-		*(unsigned *)step_bp[0].addr = step_bp[0].val;
-		step_bp[0].addr = 0;
-
-		if (step_bp[1].addr) {
-			*(unsigned *)step_bp[1].addr = step_bp[1].val;
-			step_bp[1].addr = 0;
-		}
-	}
-
-	stack = (long *)regs->reg29;			/* stack ptr */
-	sigval = computeSignal(trap);
-
-	/*
-	 * reply to host that an exception has occurred
-	 */
-	ptr = output_buffer;
-
-	/*
-	 * Send trap type (converted to signal)
-	 */
-	*ptr++ = 'T';
-	*ptr++ = hexchars[sigval >> 4];
-	*ptr++ = hexchars[sigval & 0xf];
-
-	/*
-	 * Send Error PC
-	 */
-	*ptr++ = hexchars[REG_EPC >> 4];
-	*ptr++ = hexchars[REG_EPC & 0xf];
-	*ptr++ = ':';
-	ptr = mem2hex((char *)&regs->cp0_epc, ptr, sizeof(long), 0);
-	*ptr++ = ';';
-
-	/*
-	 * Send frame pointer
-	 */
-	*ptr++ = hexchars[REG_FP >> 4];
-	*ptr++ = hexchars[REG_FP & 0xf];
-	*ptr++ = ':';
-	ptr = mem2hex((char *)&regs->reg30, ptr, sizeof(long), 0);
-	*ptr++ = ';';
-
-	/*
-	 * Send stack pointer
-	 */
-	*ptr++ = hexchars[REG_SP >> 4];
-	*ptr++ = hexchars[REG_SP & 0xf];
-	*ptr++ = ':';
-	ptr = mem2hex((char *)&regs->reg29, ptr, sizeof(long), 0);
-	*ptr++ = ';';
-
-	*ptr++ = 0;
-	putpacket(output_buffer);	/* send it off... */
-
-	/*
-	 * Wait for input from remote GDB
-	 */
-	while (1) {
-		output_buffer[0] = 0;
-		getpacket(input_buffer);
-
-		switch (input_buffer[0])
-		{
-		case '?':
-			output_buffer[0] = 'S';
-			output_buffer[1] = hexchars[sigval >> 4];
-			output_buffer[2] = hexchars[sigval & 0xf];
-			output_buffer[3] = 0;
-			break;
-
-		/*
-		 * Detach debugger; let CPU run
-		 */
-		case 'D':
-			putpacket(output_buffer);
-			goto finish_kgdb;
-			break;
-
-		case 'd':
-			/* toggle debug flag */
-			break;
-
-		/*
-		 * Return the value of the CPU registers
-		 */
-		case 'g':
-			ptr = output_buffer;
-			ptr = mem2hex((char *)&regs->reg0, ptr, 32*sizeof(long), 0); /* r0...r31 */
-			ptr = mem2hex((char *)&regs->cp0_status, ptr, 6*sizeof(long), 0); /* cp0 */
-			ptr = mem2hex((char *)&regs->fpr0, ptr, 32*sizeof(long), 0); /* f0...31 */
-			ptr = mem2hex((char *)&regs->cp1_fsr, ptr, 2*sizeof(long), 0); /* cp1 */
-			ptr = mem2hex((char *)&regs->frame_ptr, ptr, 2*sizeof(long), 0); /* frp */
-			ptr = mem2hex((char *)&regs->cp0_index, ptr, 16*sizeof(long), 0); /* cp0 */
-			break;
-
-		/*
-		 * set the value of the CPU registers - return OK
-		 */
-		case 'G':
-		{
-			ptr = &input_buffer[1];
-			hex2mem(ptr, (char *)&regs->reg0, 32*sizeof(long), 0, 0);
-			ptr += 32*(2*sizeof(long));
-			hex2mem(ptr, (char *)&regs->cp0_status, 6*sizeof(long), 0, 0);
-			ptr += 6*(2*sizeof(long));
-			hex2mem(ptr, (char *)&regs->fpr0, 32*sizeof(long), 0, 0);
-			ptr += 32*(2*sizeof(long));
-			hex2mem(ptr, (char *)&regs->cp1_fsr, 2*sizeof(long), 0, 0);
-			ptr += 2*(2*sizeof(long));
-			hex2mem(ptr, (char *)&regs->frame_ptr, 2*sizeof(long), 0, 0);
-			ptr += 2*(2*sizeof(long));
-			hex2mem(ptr, (char *)&regs->cp0_index, 16*sizeof(long), 0, 0);
-			strcpy(output_buffer,"OK");
-		 }
-		break;
-
-		/*
-		 * mAA..AA,LLLL  Read LLLL bytes at address AA..AA
-		 */
-		case 'm':
-			ptr = &input_buffer[1];
-
-			if (hexToLong(&ptr, &addr)
-				&& *ptr++ == ','
-				&& hexToInt(&ptr, &length)) {
-				if (mem2hex((char *)addr, output_buffer, length, 1))
-					break;
-				strcpy (output_buffer, "E03");
-			} else
-				strcpy(output_buffer,"E01");
-			break;
-
-		/*
-		 * XAA..AA,LLLL: Write LLLL escaped binary bytes at address AA.AA
-		 */
-		case 'X':
-			bflag = 1;
-			/* fall through */
-
-		/*
-		 * MAA..AA,LLLL: Write LLLL bytes at address AA.AA return OK
-		 */
-		case 'M':
-			ptr = &input_buffer[1];
-
-			if (hexToLong(&ptr, &addr)
-				&& *ptr++ == ','
-				&& hexToInt(&ptr, &length)
-				&& *ptr++ == ':') {
-				if (hex2mem(ptr, (char *)addr, length, bflag, 1))
-					strcpy(output_buffer, "OK");
-				else
-					strcpy(output_buffer, "E03");
-			}
-			else
-				strcpy(output_buffer, "E02");
-			break;
-
-		/*
-		 * cAA..AA    Continue at address AA..AA(optional)
-		 */
-		case 'c':
-			/* try to read optional parameter, pc unchanged if no parm */
-
-			ptr = &input_buffer[1];
-			if (hexToLong(&ptr, &addr))
-				regs->cp0_epc = addr;
-	  
-			goto exit_kgdb_exception;
-			break;
-
-		/*
-		 * kill the program; let us try to restart the machine
-		 * Reset the whole machine.
-		 */
-		case 'k':
-		case 'r':
-			machine_restart("kgdb restarts machine");
-			break;
-
-		/*
-		 * Step to next instruction
-		 */
-		case 's':
-			/*
-			 * There is no single step insn in the MIPS ISA, so we
-			 * use breakpoints and continue, instead.
-			 */
-			single_step(regs);
-			goto exit_kgdb_exception;
-			/* NOTREACHED */
-			break;
-
-		/*
-		 * Set baud rate (bBB)
-		 * FIXME: Needs to be written
-		 */
-		case 'b':
-		{
-#if 0
-			int baudrate;
-			extern void set_timer_3();
-
-			ptr = &input_buffer[1];
-			if (!hexToInt(&ptr, &baudrate))
-			{
-				strcpy(output_buffer,"B01");
-				break;
-			}
-
-			/* Convert baud rate to uart clock divider */
-
-			switch (baudrate)
-			{
-				case 38400:
-					baudrate = 16;
-					break;
-				case 19200:
-					baudrate = 33;
-					break;
-				case 9600:
-					baudrate = 65;
-					break;
-				default:
-					baudrate = 0;
-					strcpy(output_buffer,"B02");
-					goto x1;
-			}
-
-			if (baudrate) {
-				putpacket("OK");	/* Ack before changing speed */
-				set_timer_3(baudrate); /* Set it */
-			}
-#endif
-		}
-		break;
-
-		}			/* switch */
-
-		/*
-		 * reply to the request
-		 */
-
-		putpacket(output_buffer);
-
-	} /* while */
-
-	return;
-
-finish_kgdb:
-	restore_debug_traps();
-
-exit_kgdb_exception:
-	/* release locks so other CPUs can go */
-	for (i = num_online_cpus()-1; i >= 0; i--)
-		spin_unlock(&kgdb_cpulock[i]);
-	spin_unlock(&kgdb_lock);
-
-	__flush_cache_all();
-	return;
-}
-
-/*
- * This function will generate a breakpoint exception.  It is used at the
- * beginning of a program to sync up with a debugger and can be used
- * otherwise as a quick means to stop program execution and "break" into
- * the debugger.
- */
-void breakpoint(void)
-{
-	if (!initialized)
-		return;
-
-	__asm__ __volatile__(
-			".globl	breakinst\n\t" 
-			".set\tnoreorder\n\t"
-			"nop\n"
-			"breakinst:\tbreak\n\t"
-			"nop\n\t"
-			".set\treorder"
-			);
-}
-
-/* Nothing but the break; don't pollute any registers */
-void async_breakpoint(void)
-{
-	__asm__ __volatile__(
-			".globl	async_breakinst\n\t" 
-			".set\tnoreorder\n\t"
-			"nop\n"
-			"async_breakinst:\tbreak\n\t"
-			"nop\n\t"
-			".set\treorder"
-			);
-}
-
-void adel(void)
-{
-	__asm__ __volatile__(
-			".globl\tadel\n\t"
-			"lui\t$8,0x8000\n\t"
-			"lw\t$9,1($8)\n\t"
-			);
-}
-
-/*
- * malloc is needed by gdb client in "call func()", even a private one
- * will make gdb happy
- */
-static void *malloc(size_t size)
-{
-	return kmalloc(size, GFP_ATOMIC);
-}
-
-static void free(void *where)
-{
-	kfree(where);
-}
-
-#ifdef CONFIG_GDB_CONSOLE
-
-void gdb_putsn(const char *str, int l)
-{
-	char outbuf[18];
-
-	if (!kgdb_started)
-		return;
-
-	outbuf[0]='O';
-
-	while(l) {
-		int i = (l>8)?8:l;
-		mem2hex((char *)str, &outbuf[1], i, 0);
-		outbuf[(i*2)+1]=0;
-		putpacket(outbuf);
-		str += i;
-		l -= i;
-	}
-}
-
-static void gdb_console_write(struct console *con, const char *s, unsigned n)
-{
-	gdb_putsn(s, n);
-}
-
-static struct console gdb_console = {
-	.name	= "gdb",
-	.write	= gdb_console_write,
-	.flags	= CON_PRINTBUFFER,
-	.index	= -1
-};
-
-static int __init register_gdb_console(void)
-{
-	register_console(&gdb_console);
-
-	return 0;
-}
-
-console_initcall(register_gdb_console);
-
-#endif

diff -puN arch/mips/kernel/irq.c~mips-lite arch/mips/kernel/irq.c

arch/mips/kernel/irq.c renamed from arch/mips/kernel/irq.c~mips-lite +13 -19
@@ -26,6 +26,10 @@
 #include <asm/atomic.h>
 #include <asm/system.h>
 #include <asm/uaccess.h>
+#include <asm/kgdb.h>
+
+/* Keep track of if we've done certain initialization already or not. */
+int kgdb_early_setup;
 
 /*
  * 'what should we do if we get a hw irq event on an illegal vector'.
@@ -103,23 +107,13 @@ skip:
 	return 0;
 }
 
-#ifdef CONFIG_KGDB
-extern void breakpoint(void);
-extern void set_debug_traps(void);
-
-static int kgdb_flag = 1;
-static int __init nokgdb(char *str)
-{
-	kgdb_flag = 0;
-	return 1;
-}
-__setup("nokgdb", nokgdb);
-#endif
-
 void __init init_IRQ(void)
 {
 	int i;
 
+	if (kgdb_early_setup)
+		return;
+
 	for (i = 0; i < NR_IRQS; i++) {
 		irq_desc[i].status  = IRQ_DISABLED;
 		irq_desc[i].action  = NULL;
@@ -129,12 +123,12 @@ void __init init_IRQ(void)
 	}
 
 	arch_init_irq();
-
 #ifdef CONFIG_KGDB
-	if (kgdb_flag) {
-		printk("Wait for gdb client connection ...\n");
-		set_debug_traps();
-		breakpoint();
-	}
+	/*
+	 * We have been called before kgdb_arch_init(). Hence,
+	 * we dont want the traps to be reinitialized
+	 */
+	if (kgdb_early_setup == 0)
+		kgdb_early_setup = 1;
 #endif
 }

diff -puN /dev/null arch/mips/kernel/kgdb.c

arch/mips/kernel/kgdb.c new file +292 -0
@@ -0,0 +1,292 @@
+/*
+ * arch/mips/kernel/kgdb.c
+ *
+ *  Originally written by Glenn Engel, Lake Stevens Instrument Division
+ *
+ *  Contributed by HP Systems
+ *
+ *  Modified for SPARC by Stu Grossman, Cygnus Support.
+ *
+ *  Modified for Linux/MIPS (and MIPS in general) by Andreas Busse
+ *  Send complaints, suggestions etc. to <[email protected]>
+ *
+ *  Copyright (C) 1995 Andreas Busse
+ *
+ *  Copyright (C) 2003 MontaVista Software Inc.
+ *  Author: Jun Sun, [email protected] or [email protected]
+ *
+ *  Copyright (C) 2004-2005 MontaVista Software Inc.
+ *  Author: Manish Lachwani, [email protected] or [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/sched.h>
+#include <linux/smp.h>
+#include <linux/spinlock.h>
+#include <linux/delay.h>
+#include <asm/system.h>
+#include <asm/ptrace.h>		/* for linux pt_regs struct */
+#include <linux/kgdb.h>
+#include <linux/init.h>
+#include <asm/inst.h>
+#include <asm/gdb-stub.h>
+#include <asm/cacheflush.h>
+#include <asm/kdebug.h>
+
+static struct hard_trap_info {
+	unsigned char tt;	/* Trap type code for MIPS R3xxx and R4xxx */
+	unsigned char signo;	/* Signal that we map this trap into */
+} hard_trap_info[] = {
+	{ 6, SIGBUS },		/* instruction bus error */
+	{ 7, SIGBUS },		/* data bus error */
+	{ 9, SIGTRAP },		/* break */
+/*	{ 11, SIGILL },	*/	/* CPU unusable */
+	{ 12, SIGFPE },		/* overflow */
+	{ 13, SIGTRAP },	/* trap */
+	{ 14, SIGSEGV },	/* virtual instruction cache coherency */
+	{ 15, SIGFPE },		/* floating point exception */
+	{ 23, SIGSEGV },	/* watch */
+	{ 31, SIGSEGV },	/* virtual data cache coherency */
+	{ 0, 0}			/* Must be last */
+};
+
+/* Save the normal trap handlers for user-mode traps. */
+void *saved_vectors[32];
+
+extern void trap_low(void);
+extern void breakinst(void);
+extern void init_IRQ(void);
+
+void kgdb_call_nmi_hook(void *ignored)
+{
+	kgdb_nmihook(smp_processor_id(), (void *)0);
+}
+
+void kgdb_roundup_cpus(unsigned long flags)
+{
+	local_irq_restore(flags);
+	smp_call_function(kgdb_call_nmi_hook, 0, 0, 0);
+	local_irq_save(flags);
+}
+
+static int compute_signal(int tt)
+{
+	struct hard_trap_info *ht;
+
+	for (ht = hard_trap_info; ht->tt && ht->signo; ht++)
+		if (ht->tt == tt)
+			return ht->signo;
+
+	return SIGHUP;		/* default for things we don't know about */
+}
+
+/*
+ * Set up exception handlers for tracing and breakpoints
+ */
+void handle_exception(struct pt_regs *regs)
+{
+	int trap = (regs->cp0_cause & 0x7c) >> 2;
+
+	if (atomic_read(&debugger_active))
+		kgdb_nmihook(smp_processor_id(), regs);
+
+	if (atomic_read(&kgdb_setting_breakpoint))
+		if ((trap == 9) && (regs->cp0_epc == (unsigned long)breakinst))
+			regs->cp0_epc += 4;
+
+	kgdb_handle_exception(0, compute_signal(trap), 0, regs);
+
+	/* In SMP mode, __flush_cache_all does IPI */
+	__flush_cache_all();
+}
+
+void set_debug_traps(void)
+{
+	struct hard_trap_info *ht;
+	unsigned long flags;
+
+	local_irq_save(flags);
+
+	for (ht = hard_trap_info; ht->tt && ht->signo; ht++)
+		saved_vectors[ht->tt] = set_except_vector(ht->tt, trap_low);
+
+	local_irq_restore(flags);
+}
+
+#if 0
+/* This should be called before we exit kgdb_handle_exception() I believe.
+ * -- Tom
+ */
+void restore_debug_traps(void)
+{
+	struct hard_trap_info *ht;
+	unsigned long flags;
+
+	local_irq_save(flags);
+	for (ht = hard_trap_info; ht->tt && ht->signo; ht++)
+		set_except_vector(ht->tt, saved_vectors[ht->tt]);
+	local_irq_restore(flags);
+}
+#endif
+
+void regs_to_gdb_regs(unsigned long *gdb_regs, struct pt_regs *regs)
+{
+	int reg = 0;
+	unsigned long *ptr = gdb_regs;
+
+	for (reg = 0; reg < 32; reg++)
+		*(ptr++) = regs->regs[reg];
+
+	*(ptr++) = regs->cp0_status;
+	*(ptr++) = regs->lo;
+	*(ptr++) = regs->hi;
+	*(ptr++) = regs->cp0_badvaddr;
+	*(ptr++) = regs->cp0_cause;
+	*(ptr++) = regs->cp0_epc;
+
+	return;
+}
+
+void gdb_regs_to_regs(unsigned long *gdb_regs, struct pt_regs *regs)
+{
+	int reg = 0;
+	unsigned long *ptr = gdb_regs;
+
+	for (reg = 0; reg < 32; reg++)
+		regs->regs[reg] = *(ptr++);
+
+	regs->cp0_status = *(ptr++);
+	regs->lo = *(ptr++);
+	regs->hi = *(ptr++);
+	regs->cp0_badvaddr = *(ptr++);
+	regs->cp0_cause = *(ptr++);
+	regs->cp0_epc = *(ptr++);
+
+	return;
+}
+
+/*
+ * Similar to regs_to_gdb_regs() except that process is sleeping and so
+ * we may not be able to get all the info.
+ */
+void sleeping_thread_to_gdb_regs(unsigned long *gdb_regs, struct task_struct *p)
+{
+	int reg = 0;
+	struct thread_info *ti = p->thread_info;
+	unsigned long ksp = (unsigned long)ti + THREAD_SIZE - 32;
+	struct pt_regs *regs = (struct pt_regs *)ksp - 1;
+	unsigned long *ptr = gdb_regs;
+
+	for (reg = 0; reg < 16; reg++)
+		*(ptr++) = regs->regs[reg];
+
+	/* S0 - S7 */
+	for (reg = 16; reg < 24; reg++)
+		*(ptr++) = regs->regs[reg];
+
+	for (reg = 24; reg < 28; reg++)
+		*(ptr++) = 0;
+
+	/* GP, SP, FP, RA */
+	for (reg = 28; reg < 32; reg++)
+		*(ptr++) = regs->regs[reg];
+
+	*(ptr++) = regs->cp0_status;
+	*(ptr++) = regs->lo;
+	*(ptr++) = regs->hi;
+	*(ptr++) = regs->cp0_badvaddr;
+	*(ptr++) = regs->cp0_cause;
+	*(ptr++) = regs->cp0_epc;
+
+	return;
+}
+
+/*
+ * Calls linux_debug_hook before the kernel dies. If KGDB is enabled,
+ * then try to fall into the debugger
+ */
+static int kgdb_mips_notify(struct notifier_block *self, unsigned long cmd,
+			    void *ptr)
+{
+	struct die_args *args = (struct die_args *)ptr;
+	struct pt_regs *regs = args->regs;
+	int trap = (regs->cp0_cause & 0x7c) >> 2;
+
+	/* See if KGDB is interested. */
+	if (user_mode(regs))
+		/* Userpace events, ignore. */
+		return NOTIFY_DONE;
+
+	kgdb_handle_exception(trap, compute_signal(trap), 0, regs);
+	return NOTIFY_OK;
+}
+
+static struct notifier_block kgdb_notifier = {
+	.notifier_call = kgdb_mips_notify,
+};
+
+/*
+ * Handle the 's' and 'c' commands
+ */
+int kgdb_arch_handle_exception(int vector, int signo, int err_code,
+			       char *remcom_in_buffer, char *remcom_out_buffer,
+			       struct pt_regs *regs)
+{
+	char *ptr;
+	unsigned long address;
+	int cpu = smp_processor_id();
+
+	switch (remcom_in_buffer[0]) {
+	case 's':
+	case 'c':
+		/* handle the optional parameter */
+		ptr = &remcom_in_buffer[1];
+		if (kgdb_hex2long(&ptr, &address))
+			regs->cp0_epc = address;
+
+		atomic_set(&cpu_doing_single_step, -1);
+		if (remcom_in_buffer[0] == 's')
+			if (kgdb_contthread)
+				atomic_set(&cpu_doing_single_step, cpu);
+
+		return 0;
+	}
+
+	return -1;
+}
+
+struct kgdb_arch arch_kgdb_ops = {
+#ifdef CONFIG_CPU_LITTLE_ENDIAN
+	.gdb_bpt_instr = {0xd},
+#else
+	.gdb_bpt_instr = {0x00, 0x00, 0x00, 0x0d},
+#endif
+};
+
+/*
+ * We use kgdb_early_setup so that functions we need to call now don't
+ * cause trouble when called again later.
+ */
+int kgdb_arch_init(void)
+{
+	/* Board-specifics. */
+	/* Force some calls to happen earlier. */
+	if (kgdb_early_setup == 0) {
+		trap_init();
+		init_IRQ();
+		kgdb_early_setup = 1;
+	}
+
+	/* Set our traps. */
+	/* This needs to be done more finely grained again, paired in
+	 * a before/after in kgdb_handle_exception(...) -- Tom */
+	set_debug_traps();
+	notifier_chain_register(&mips_die_chain, &kgdb_notifier);
+
+	return 0;
+}

diff -puN /dev/null arch/mips/kernel/kgdb_handler.S

arch/mips/kernel/kgdb_handler.S new file +58 -0
@@ -0,0 +1,58 @@
+/*
+ * arch/mips/kernel/kgdb_handler.S
+ *
+ * Copyright (C) 2004 MontaVista Software Inc.
+ * Author: Manish Lachwani, [email protected] or [email protected]
+ *
+ * This file is licensed under the terms of the GNU General Public
+ * version 2. This program is licensed "as is" without any warranty of any
+ * kind, whether express or implied.
+ */
+
+/*
+ * Trap Handler for the new KGDB framework. The main KGDB handler is
+ * handle_exception that will be called from here
+ *
+ */
+
+#include <linux/config.h>
+#include <linux/sys.h>
+
+#include <asm/asm.h>
+#include <asm/errno.h>
+#include <asm/mipsregs.h>
+#include <asm/regdef.h>
+#include <asm/stackframe.h>
+
+	.align  5
+	NESTED(trap_low, PT_SIZE, sp)
+		.set    noat
+		.set	noreorder
+		SAVE_ALL
+		/*
+		 * Check for privileged instructions in user mode. For
+		 * this, check the cu0 bit in the CPU status register.
+		 */
+		mfc0	k0, CP0_STATUS
+		sll	k0, 3
+		bltz	k0, 1f
+		move	k1, sp
+
+		/*
+		 * GDB userland from within KGDB. If a user mode address
+		 * then jump to the saved exception handler
+		 */
+		lui	k1, %hi(saved_vectors)
+		mfc0	k0, CP0_CAUSE
+		andi	k0, k0, 0x7c
+		add	k1, k1, k0
+		lw	k0, %lo(saved_vectors)(k1)
+		jr	k0
+		nop
+1:
+		.set    at
+		.set	reorder
+		move    a0, sp
+		jal     handle_exception
+		j       ret_from_exception
+	END(trap_low)

diff -puN /dev/null arch/mips/kernel/kgdb-jmp.c

arch/mips/kernel/kgdb-jmp.c new file +62 -0
@@ -0,0 +1,62 @@
+/*
+ * arch/mips/kernel/kgdb-jmp.c
+ *
+ * Save and restore system registers so that within a limited frame we
+ * may have a fault and "jump back" to a known safe location.
+ *
+ * Author: Tom Rini <[email protected]>
+ *
+ * Cribbed from glibc, which carries the following:
+ * Copyright (C) 1996, 1997, 2000, 2002, 2003 Free Software Foundation, Inc.
+ * Copyright (C) 2005 by MontaVista Software.
+ *
+ * This file is licensed under the terms of the GNU General Public License
+ * version 2. This program as licensed "as is" without any warranty of
+ * any kind, whether express or implied.
+ */
+
+#include <linux/kgdb.h>
+#include <asm/interrupt.h>
+
+int kgdb_fault_setjmp_aux(unsigned long *curr_context, int sp, int fp)
+{
+	__asm__ __volatile__("sw $gp, %0" : : "m" (curr_context[0]));
+	__asm__ __volatile__("sw $16, %0" : : "m" (curr_context[1]));
+	__asm__ __volatile__("sw $17, %0" : : "m" (curr_context[2]));
+	__asm__ __volatile__("sw $18, %0" : : "m" (curr_context[3]));
+	__asm__ __volatile__("sw $19, %0" : : "m" (curr_context[4]));
+	__asm__ __volatile__("sw $20, %0" : : "m" (curr_context[5]));
+	__asm__ __volatile__("sw $21, %0" : : "m" (curr_context[6]));
+	__asm__ __volatile__("sw $22, %0" : : "m" (curr_context[7]));
+	__asm__ __volatile__("sw $23, %0" : : "m" (curr_context[8]));
+	__asm__ __volatile__("sw $31, %0" : : "m" (curr_context[9]));
+	curr_context[10] = (long *)sp;
+	curr_context[11] = (long *)fp;
+
+	return 0;
+}
+
+void kgdb_fault_longjmp(unsigned long *curr_context)
+{
+	unsigned long sp_val, fp_val;
+
+	__asm__ __volatile__("lw $gp, %0" : : "m" (curr_context[0]));
+	__asm__ __volatile__("lw $16, %0" : : "m" (curr_context[1]));
+	__asm__ __volatile__("lw $17, %0" : : "m" (curr_context[2]));
+	__asm__ __volatile__("lw $18, %0" : : "m" (curr_context[3]));
+	__asm__ __volatile__("lw $19, %0" : : "m" (curr_context[4]));
+	__asm__ __volatile__("lw $20, %0" : : "m" (curr_context[5]));
+	__asm__ __volatile__("lw $21, %0" : : "m" (curr_context[6]));
+	__asm__ __volatile__("lw $22, %0" : : "m" (curr_context[7]));
+	__asm__ __volatile__("lw $23, %0" : : "m" (curr_context[8]));
+	__asm__ __volatile__("lw $25, %0" : : "m" (curr_context[9]));
+	sp_val = curr_context[10];
+	fp_val = curr_context[11];
+	__asm__ __volatile__("lw $29, %0\n\t"
+			      "lw $30, %1\n\t" : : "m" (sp_val), "m" (fp_val));
+
+	__asm__ __volatile__("li $2, 1");
+	__asm__ __volatile__("jr $25");
+
+	for (;;);
+}

diff -puN /dev/null arch/mips/kernel/kgdb-setjmp.S

arch/mips/kernel/kgdb-setjmp.S new file +23 -0
@@ -0,0 +1,23 @@
+/*
+ * arch/mips/kernel/kgdb-jmp.c
+ *
+ * Save and restore system registers so that within a limited frame we
+ * may have a fault and "jump back" to a known safe location.
+ *
+ * Copyright (C) 2005 by MontaVista Software.
+ *
+ * This file is licensed under the terms of the GNU General Public License
+ * version 2. This program as licensed "as is" without any warranty of
+ * any kind, whether express or implied.
+ */
+
+#include <asm/asm.h>
+#include <asm/mipsregs.h>
+#include <asm/regdef.h>
+#include <asm/stackframe.h>
+
+ENTRY (kgdb_fault_setjmp)
+	move    a1, sp
+	move	a2, fp
+	j	kgdb_fault_setjmp_aux
+	.end	kgdb_fault_setjmp

diff -puN arch/mips/kernel/Makefile~mips-lite arch/mips/kernel/Makefile

arch/mips/kernel/Makefile renamed from arch/mips/kernel/Makefile~mips-lite +2 -1
@@ -52,7 +52,8 @@ obj-$(CONFIG_MIPS32_COMPAT)	+= ioctl32.o
 obj-$(CONFIG_MIPS32_N32)	+= binfmt_elfn32.o scall64-n32.o signal_n32.o
 obj-$(CONFIG_MIPS32_O32)	+= binfmt_elfo32.o scall64-o32.o ptrace32.o
 
-obj-$(CONFIG_KGDB)		+= gdb-low.o gdb-stub.o
+obj-$(CONFIG_KGDB)		+= kgdb_handler.o kgdb.o kgdb-jmp.o	\
+					kgdb-setjmp.o
 obj-$(CONFIG_PROC_FS)		+= proc.o
 
 obj-$(CONFIG_MIPS64)		+= cpu-bugs64.o

diff -puN arch/mips/kernel/traps.c~mips-lite arch/mips/kernel/traps.c

arch/mips/kernel/traps.c renamed from arch/mips/kernel/traps.c~mips-lite +25 -1
@@ -10,6 +10,8 @@
  * Kevin D. Kissell, [email protected] and Carsten Langgaard, [email protected]
  * Copyright (C) 2000, 01 MIPS Technologies, Inc.
  * Copyright (C) 2002, 2003, 2004  Maciej W. Rozycki
+ *
+ * KGDB specific changes - Manish Lachwani ([email protected])
  */
 #include <linux/config.h>
 #include <linux/init.h>
@@ -20,6 +22,7 @@
 #include <linux/smp_lock.h>
 #include <linux/spinlock.h>
 #include <linux/kallsyms.h>
+#include <linux/kgdb.h>
 
 #include <asm/bootinfo.h>
 #include <asm/branch.h>
@@ -37,6 +40,7 @@
 #include <asm/mmu_context.h>
 #include <asm/watch.h>
 #include <asm/types.h>
+#include <asm/kdebug.h>
 
 extern asmlinkage void handle_tlbm(void);
 extern asmlinkage void handle_tlbl(void);
@@ -69,6 +73,21 @@ int (*board_be_handler)(struct pt_regs *
  */
 #define MODULE_RANGE (8*1024*1024)
 
+struct notifier_block *mips_die_chain;
+static spinlock_t die_notifier_lock = SPIN_LOCK_UNLOCKED;
+
+int register_die_notifier(struct notifier_block *nb)
+{
+	int err = 0;
+	unsigned long flags;
+
+	spin_lock_irqsave(&die_notifier_lock, flags);
+	err = notifier_chain_register(&mips_die_chain, nb);
+	spin_unlock_irqrestore(&die_notifier_lock, flags);
+
+	return err;
+}
+
 /*
  * This routine abuses get_user()/put_user() to reference pointers
  * with at least a bit of error checking ...
@@ -271,8 +290,10 @@ NORET_TYPE void __die(const char * str, 
 void __die_if_kernel(const char * str, struct pt_regs * regs,
 		     const char * file, const char * func, unsigned long line)
 {
-	if (!user_mode(regs))
+	if (!user_mode(regs)) {
+		notify_die(DIE_TRAP, (char *)str, regs, 0);
 		__die(str, regs, file, func, line);
+	}
 }
 
 extern const struct exception_table_entry __start___dbe_table[];
@@ -958,6 +979,9 @@ void __init trap_init(void)
 	extern char except_vec4;
 	unsigned long i;
 
+	if (kgdb_early_setup)
+		return;	/* Already done */
+
 	per_cpu_trap_init();
 
 	/*

diff -puN arch/mips/mips-boards/generic/init.c~mips-lite arch/mips/mips-boards/generic/init.c

arch/mips/mips-boards/generic/init.c renamed from arch/mips/mips-boards/generic/init.c~mips-lite +0 -62
@@ -35,15 +35,6 @@
 #include <asm/mips-boards/malta.h>
 #endif
 
-#ifdef CONFIG_KGDB
-extern int rs_kgdb_hook(int, int);
-extern int rs_putDebugChar(char);
-extern char rs_getDebugChar(void);
-extern int saa9730_kgdb_hook(int);
-extern int saa9730_putDebugChar(char);
-extern char saa9730_getDebugChar(void);
-#endif
-
 int prom_argc;
 int *_prom_argv, *_prom_envp;
 
@@ -170,59 +161,6 @@ static void __init console_config(void)
 }
 #endif
 
-#ifdef CONFIG_KGDB
-void __init kgdb_config (void)
-{
-	extern int (*generic_putDebugChar)(char);
-	extern char (*generic_getDebugChar)(void);
-	char *argptr;
-	int line, speed;
-
-	argptr = prom_getcmdline();
-	if ((argptr = strstr(argptr, "kgdb=ttyS")) != NULL) {
-		argptr += strlen("kgdb=ttyS");
-		if (*argptr != '0' && *argptr != '1')
-			printk("KGDB: Unknown serial line /dev/ttyS%c, "
-			       "falling back to /dev/ttyS1\n", *argptr);
-		line = *argptr == '0' ? 0 : 1;
-		printk("KGDB: Using serial line /dev/ttyS%d for session\n", line);
-
-		speed = 0;
-		if (*++argptr == ',')
-		{
-			int c;
-			while ((c = *++argptr) && ('0' <= c && c <= '9'))
-				speed = speed * 10 + c - '0';
-		}
-#ifdef CONFIG_MIPS_ATLAS
-		if (line == 1) {
-			speed = saa9730_kgdb_hook(speed);
-			generic_putDebugChar = saa9730_putDebugChar;
-			generic_getDebugChar = saa9730_getDebugChar;
-		}
-		else 
-#endif
-		{
-			speed = rs_kgdb_hook(line, speed);
-			generic_putDebugChar = rs_putDebugChar;
-			generic_getDebugChar = rs_getDebugChar;
-		}
-
-		prom_printf("KGDB: Using serial line /dev/ttyS%d at %d for session, "
-			    "please connect your debugger\n", line ? 1 : 0, speed);
-
-		{
-			char *s;
-			for (s = "Please connect GDB to this port\r\n"; *s; )
-				generic_putDebugChar (*s++);
-		}
-
-		kgdb_enabled = 1;
-		/* Breakpoint is invoked after interrupts are initialised */
-	}
-}
-#endif
-
 void __init prom_init(void)
 {
 	prom_argc = fw_arg0;

diff -puN arch/mips/mips-boards/generic/Makefile~mips-lite arch/mips/mips-boards/generic/Makefile

arch/mips/mips-boards/generic/Makefile renamed from arch/mips/mips-boards/generic/Makefile~mips-lite +0 -1
@@ -21,6 +21,5 @@
 obj-y				:= mipsIRQ.o reset.o display.o init.o memory.o \
 				   printf.o cmdline.o time.o
 obj-$(CONFIG_PCI)		+= pci.o
-obj-$(CONFIG_KGDB)		+= gdb_hook.o
 
 EXTRA_AFLAGS := $(CFLAGS)

diff -puN arch/mips/mips-boards/malta/malta_setup.c~mips-lite arch/mips/mips-boards/malta/malta_setup.c

arch/mips/mips-boards/malta/malta_setup.c renamed from arch/mips/mips-boards/malta/malta_setup.c~mips-lite +0 -8
@@ -48,10 +48,6 @@ extern void mips_time_init(void);
 extern void mips_timer_setup(struct irqaction *irq);
 extern unsigned long mips_rtc_get_time(void);
 
-#ifdef CONFIG_KGDB
-extern void kgdb_config(void);
-#endif
-
 struct resource standard_io_resources[] = {
 	{ "dma1", 0x00, 0x1f, IORESOURCE_BUSY },
 	{ "timer", 0x40, 0x5f, IORESOURCE_BUSY },
@@ -124,10 +120,6 @@ static int __init malta_setup(void)
 	 */
 	enable_dma(4);
 
-#ifdef CONFIG_KGDB
-	kgdb_config ();
-#endif
-
 	if ((mips_revision_corid == MIPS_REVISION_CORID_BONITO64) ||
 	    (mips_revision_corid == MIPS_REVISION_CORID_CORE_20K) ||
 	    (mips_revision_corid == MIPS_REVISION_CORID_CORE_EMUL_BON)) {

diff -puN arch/mips/mm/extable.c~mips-lite arch/mips/mm/extable.c

arch/mips/mm/extable.c renamed from arch/mips/mm/extable.c~mips-lite +7 -0
@@ -3,6 +3,7 @@
  */
 #include <linux/module.h>
 #include <linux/spinlock.h>
+#include <linux/kgdb.h>
 #include <asm/branch.h>
 #include <asm/uaccess.h>
 
@@ -16,6 +17,12 @@ int fixup_exception(struct pt_regs *regs
 
 		return 1;
 	}
+#ifdef CONFIG_KGDB
+	if (atomic_read(&debugger_active) && kgdb_may_fault)
+		/* Restore our previous state. */
+		kgdb_fault_longjmp(kgdb_fault_jmp_regs);
+		/* Not reached. */
+#endif
 
 	return 0;
 }

diff -puN arch/mips/sibyte/cfe/setup.c~mips-lite arch/mips/sibyte/cfe/setup.c

arch/mips/sibyte/cfe/setup.c renamed from arch/mips/sibyte/cfe/setup.c~mips-lite +0 -14
@@ -58,10 +58,6 @@ int cfe_cons_handle;
 extern unsigned long initrd_start, initrd_end;
 #endif
 
-#ifdef CONFIG_KGDB
-extern int kgdb_port;
-#endif
-
 static void ATTRIB_NORET cfe_linux_exit(void *arg)
 {
 	int warm = *(int *)arg;
@@ -242,9 +238,6 @@ void __init prom_init(void)
 	int argc = fw_arg0;
 	char **envp = (char **) fw_arg2;
 	int *prom_vec = (int *) fw_arg3;
-#ifdef CONFIG_KGDB
-	char *arg;
-#endif
 
 	_machine_restart   = cfe_linux_restart;
 	_machine_halt      = cfe_linux_halt;
@@ -308,13 +301,6 @@ void __init prom_init(void)
 		}
 	}
 
-#ifdef CONFIG_KGDB
-	if ((arg = strstr(arcs_cmdline,"kgdb=duart")) != NULL)
-		kgdb_port = (arg[10] == '0') ? 0 : 1;
-	else
-		kgdb_port = 1;
-#endif
-
 #ifdef CONFIG_BLK_DEV_INITRD
 	{
 		char *ptr;

diff -puN arch/mips/sibyte/sb1250/irq.c~mips-lite arch/mips/sibyte/sb1250/irq.c

arch/mips/sibyte/sb1250/irq.c renamed from arch/mips/sibyte/sb1250/irq.c~mips-lite +6 -51
@@ -31,6 +31,7 @@
 #include <asm/system.h>
 #include <asm/ptrace.h>
 #include <asm/io.h>
+#include <asm/kgdb.h>
 
 #include <asm/sibyte/sb1250_regs.h>
 #include <asm/sibyte/sb1250_int.h>
@@ -60,16 +61,6 @@ static void sb1250_set_affinity(unsigned
 extern unsigned long ldt_eoi_space;
 #endif
 
-#ifdef CONFIG_KGDB
-static int kgdb_irq;
-
-/* Default to UART1 */
-int kgdb_port = 1;
-#ifdef CONFIG_SIBYTE_SB1250_DUART
-extern char sb1250_duart_present[];
-#endif
-#endif
-
 static struct hw_interrupt_type sb1250_irq_type = {
 	"SB1250-IMR",
 	startup_sb1250_irq,
@@ -338,6 +329,11 @@ void __init arch_init_irq(void)
 	unsigned int imask = STATUSF_IP4 | STATUSF_IP3 | STATUSF_IP2 |
 		STATUSF_IP1 | STATUSF_IP0;
 
+#ifdef CONFIG_KGDB
+	if (kgdb_early_setup)
+		return;
+#endif
+
 	/* Default everything to IP2 */
 	for (i = 0; i < SB1250_NR_IRQS; i++) {	/* was I0 */
 		bus_writeq(IMR_IP2_VAL,
@@ -387,45 +383,4 @@ void __init arch_init_irq(void)
 	/* Enable necessary IPs, disable the rest */
 	change_c0_status(ST0_IM, imask);
 	set_except_vector(0, sb1250_irq_handler);
-
-#ifdef CONFIG_KGDB
-	if (kgdb_flag) {
-		kgdb_irq = K_INT_UART_0 + kgdb_port;
-
-#ifdef CONFIG_SIBYTE_SB1250_DUART	
-		sb1250_duart_present[kgdb_port] = 0;
-#endif
-		/* Setup uart 1 settings, mapper */
-		bus_writeq(M_DUART_IMR_BRK, IOADDR(A_DUART_IMRREG(kgdb_port)));
-
-		sb1250_steal_irq(kgdb_irq);
-		bus_writeq(IMR_IP6_VAL,
-			   IOADDR(A_IMR_REGISTER(0, R_IMR_INTERRUPT_MAP_BASE) +
-				  (kgdb_irq<<3)));
-		sb1250_unmask_irq(0, kgdb_irq);
-	}
-#endif
 }
-
-#ifdef CONFIG_KGDB
-
-#include <linux/delay.h>
-
-#define duart_out(reg, val)     csr_out32(val, IOADDR(A_DUART_CHANREG(kgdb_port,reg)))
-#define duart_in(reg)           csr_in32(IOADDR(A_DUART_CHANREG(kgdb_port,reg)))
-
-void sb1250_kgdb_interrupt(struct pt_regs *regs)
-{
-	/*
-	 * Clear break-change status (allow some time for the remote
-	 * host to stop the break, since we would see another
-	 * interrupt on the end-of-break too)
-	 */
-	kstat_this_cpu.irqs[kgdb_irq]++;
-	mdelay(500);
-	duart_out(R_DUART_CMD, V_DUART_MISC_CMD_RESET_BREAK_INT |
-				M_DUART_RX_EN | M_DUART_TX_EN);
-	set_async_breakpoint(&regs->cp0_epc);
-}
-
-#endif 	/* CONFIG_KGDB */

diff -puN arch/mips/sibyte/sb1250/irq_handler.S~mips-lite arch/mips/sibyte/sb1250/irq_handler.S

arch/mips/sibyte/sb1250/irq_handler.S renamed from arch/mips/sibyte/sb1250/irq_handler.S~mips-lite +1 -1
@@ -102,7 +102,7 @@
 2:
 #endif
 
-#ifdef CONFIG_KGDB
+#ifdef CONFIG_KGDB_SIBYTE
 	/* KGDB (uart 1) interrupt is routed to IP[6] */
 	andi	t1, s0, CAUSEF_IP6
 	beqz	t1, 1f

diff -puN /dev/null arch/mips/sibyte/sb1250/kgdb_sibyte.c

arch/mips/sibyte/sb1250/kgdb_sibyte.c new file +164 -0
@@ -0,0 +1,164 @@
+/*
+ * arch/mips/sibyte/sb1250/kgdb_sibyte.c
+ *
+ * Author: Manish Lachwani, [email protected] or [email protected]
+ *
+ * 2004 (c) MontaVista Software, Inc. This file is licensed under
+ * the terms of the GNU General Public License version 2. This program
+ * is licensed "as is" without any warranty of any kind, whether express
+ * or implied.
+ */
+
+/*
+ * Support for KGDB on the Broadcom Sibyte. The SWARM board
+ * for example does not have a 8250/16550 compatible serial
+ * port. Hence, we need to have a driver for the serial
+ * ports to handle KGDB.  This board needs nothing in addition
+ * to what is normally provided by the gdb portion of the stub.
+ */
+
+#include <linux/delay.h>
+#include <linux/kernel_stat.h>
+#include <linux/init.h>
+#include <linux/kgdb.h>
+
+#include <asm/io.h>
+#include <asm/sibyte/sb1250.h>
+#include <asm/sibyte/sb1250_regs.h>
+#include <asm/sibyte/sb1250_uart.h>
+#include <asm/sibyte/sb1250_int.h>
+#include <asm/addrspace.h>
+
+int kgdb_port = 1;
+static int kgdb_irq;
+
+extern char sb1250_duart_present[];
+extern int sb1250_steal_irq(int irq);
+
+/* Forward declarations. */
+static void kgdbsibyte_init_duart(void);
+static int kgdb_init_io(void);
+
+#define IMR_IP6_VAL	K_INT_MAP_I4
+#define	duart_out(reg, val)	csr_out32(val, IOADDR(A_DUART_CHANREG(kgdb_port,reg)))
+#define duart_in(reg)		csr_in32(IOADDR(A_DUART_CHANREG(kgdb_port,reg)))
+
+static void kgdb_swarm_write_char(int c)
+{
+	while ((duart_in(R_DUART_STATUS) & M_DUART_TX_RDY) == 0) ;
+	duart_out(R_DUART_TX_HOLD, c);
+}
+
+static int kgdb_swarm_read_char(void)
+{
+	int ret_char;
+	unsigned int status;
+
+	status = duart_in(R_DUART_STATUS);
+	while ((status & M_DUART_RX_RDY) == 0) {
+		status = duart_in(R_DUART_STATUS);
+	}
+
+	/*
+	 * Check for framing error
+	 */
+	if (status & M_DUART_FRM_ERR) {
+		kgdbsibyte_init_duart();
+		kgdb_swarm_write_char('-');
+		return '-';
+	}
+
+	ret_char = duart_in(R_DUART_RX_HOLD);
+
+	return ret_char;
+}
+
+void sb1250_kgdb_interrupt(struct pt_regs *regs)
+{
+	int kgdb_irq = K_INT_UART_0 + kgdb_port;
+	/*
+	 * Clear break-change status (allow some time for the remote
+	 * host to stop the break, since we would see another
+	 * interrupt on the end-of-break too)
+	 */
+	kstat_this_cpu.irqs[kgdb_irq]++;
+	mdelay(500);
+	duart_out(R_DUART_CMD, V_DUART_MISC_CMD_RESET_BREAK_INT |
+		  M_DUART_RX_EN | M_DUART_TX_EN);
+	if (kgdb_io_ops.init != kgdb_init_io) {
+		/* Throw away the data if another I/O routine is
+		 * active.
+		 */
+		unsigned int status;
+
+		status = duart_in(R_DUART_STATUS);
+		while ((status & M_DUART_RX_RDY) == 0) {
+			status = duart_in(R_DUART_STATUS);
+		}
+		/*
+		 * Check for framing error
+		 */
+		if (status & M_DUART_FRM_ERR) {
+			kgdbsibyte_init_duart();
+		}
+		duart_in(R_DUART_RX_HOLD);
+	} else
+		breakpoint();
+
+}
+
+/*
+ * We use port #1 and we set it for 115200 BAUD, 8n1.
+ */
+static void kgdbsibyte_init_duart(void)
+{
+	/* Set 8n1. */
+	duart_out(R_DUART_MODE_REG_1,
+		  V_DUART_BITS_PER_CHAR_8 | V_DUART_PARITY_MODE_NONE);
+	duart_out(R_DUART_MODE_REG_2, M_DUART_STOP_BIT_LEN_1);
+	/* Set baud rate of 115200. */
+	duart_out(R_DUART_CLK_SEL, V_DUART_BAUD_RATE(115200));
+	/* Enable rx and tx */
+	duart_out(R_DUART_CMD, M_DUART_RX_EN | M_DUART_TX_EN);
+}
+
+static int kgdb_init_io(void)
+{
+#ifdef CONFIG_SIBYTE_SB1250_DUART
+	sb1250_duart_present[kgdb_port] = 0;
+#endif
+
+	kgdbsibyte_init_duart();
+
+	return 0;
+}
+
+/*
+ * Hookup our IRQ line.  We will already have been initialized a
+ * this point.
+ */
+static void __init kgdbsibyte_hookup_irq(void)
+{
+	/* Steal the IRQ. */
+	kgdb_irq = K_INT_UART_0 + kgdb_port;
+
+	/* Setup uart 1 settings, mapper */
+	__raw_writeq(M_DUART_IMR_BRK, IOADDR(A_DUART_IMRREG(kgdb_port)));
+
+	sb1250_steal_irq(kgdb_irq);
+
+	__raw_writeq(IMR_IP6_VAL,
+		     IOADDR(A_IMR_REGISTER(0, R_IMR_INTERRUPT_MAP_BASE) +
+			    (kgdb_irq << 3)));
+
+	sb1250_unmask_irq(0, kgdb_irq);
+}
+
+struct kgdb_io kgdb_io_ops = {
+	.read_char = kgdb_swarm_read_char,
+	.write_char = kgdb_swarm_write_char,
+	.init = kgdb_init_io,
+	.late_init = kgdbsibyte_hookup_irq,
+	.pre_exception = NULL,
+	.post_exception = NULL
+};

diff -puN arch/mips/sibyte/sb1250/Makefile~mips-lite arch/mips/sibyte/sb1250/Makefile

arch/mips/sibyte/sb1250/Makefile renamed from arch/mips/sibyte/sb1250/Makefile~mips-lite +1 -0
@@ -4,5 +4,6 @@ obj-$(CONFIG_SMP)			+= smp.o
 obj-$(CONFIG_SIBYTE_TBPROF)		+= bcm1250_tbprof.o
 obj-$(CONFIG_SIBYTE_STANDALONE)		+= prom.o
 obj-$(CONFIG_SIBYTE_BUS_WATCHER)	+= bus_watcher.o
+obj-$(CONFIG_KGDB_SIBYTE)		+= kgdb_sibyte.o
 
 EXTRA_AFLAGS := $(CFLAGS)

diff -L arch/mips/sibyte/swarm/dbg_io.c -puN arch/mips/sibyte/swarm/dbg_io.c~mips-lite /dev/null

arch/mips/sibyte/swarm/dbg_io.c deleted +0 -76
@@ -1,76 +0,0 @@
-/*
- * kgdb debug routines for SiByte boards.
- *
- * Copyright (C) 2001 MontaVista Software Inc.
- * Author: Jun Sun, [email protected] or [email protected]
- *
- * This program is free software; you can redistribute  it and/or modify it
- * under  the terms of  the GNU General  Public License as published by the
- * Free Software Foundation;  either version 2 of the  License, or (at your
- * option) any later version.
- *
- */
-
-/* -------------------- BEGINNING OF CONFIG --------------------- */
-
-#include <linux/delay.h>
-#include <asm/io.h>
-#include <asm/sibyte/sb1250.h>
-#include <asm/sibyte/sb1250_regs.h>
-#include <asm/sibyte/sb1250_uart.h>
-#include <asm/sibyte/sb1250_int.h>
-#include <asm/addrspace.h>
-
-/*
- * We use the second serial port for kgdb traffic.
- * 	115200, 8, N, 1.
- */
-
-#define	BAUD_RATE		115200
-#define	CLK_DIVISOR		V_DUART_BAUD_RATE(BAUD_RATE)
-#define	DATA_BITS		V_DUART_BITS_PER_CHAR_8		/* or 7    */
-#define	PARITY			V_DUART_PARITY_MODE_NONE	/* or even */
-#define	STOP_BITS		M_DUART_STOP_BIT_LEN_1		/* or 2    */
-
-static int duart_initialized = 0;	/* 0: need to be init'ed by kgdb */
-
-/* -------------------- END OF CONFIG --------------------- */
-extern int kgdb_port;
-
-#define	duart_out(reg, val)	csr_out32(val, IOADDR(A_DUART_CHANREG(kgdb_port,reg)))
-#define duart_in(reg)		csr_in32(IOADDR(A_DUART_CHANREG(kgdb_port,reg)))
-
-void putDebugChar(unsigned char c);
-unsigned char getDebugChar(void);
-static void
-duart_init(int clk_divisor, int data, int parity, int stop)
-{
-	duart_out(R_DUART_MODE_REG_1, data | parity);
-	duart_out(R_DUART_MODE_REG_2, stop);
-	duart_out(R_DUART_CLK_SEL, clk_divisor);
-
-	duart_out(R_DUART_CMD, M_DUART_RX_EN | M_DUART_TX_EN);	/* enable rx and tx */
-}
-
-void
-putDebugChar(unsigned char c)
-{
-	if (!duart_initialized) {
-		duart_initialized = 1;
-		duart_init(CLK_DIVISOR, DATA_BITS, PARITY, STOP_BITS);
-	}
-	while ((duart_in(R_DUART_STATUS) & M_DUART_TX_RDY) == 0);
-	duart_out(R_DUART_TX_HOLD, c);
-}
-
-unsigned char
-getDebugChar(void)
-{
-	if (!duart_initialized) {
-		duart_initialized = 1;
-		duart_init(CLK_DIVISOR, DATA_BITS, PARITY, STOP_BITS);
-	}
-	while ((duart_in(R_DUART_STATUS) & M_DUART_RX_RDY) == 0) ;
-	return duart_in(R_DUART_RX_HOLD);
-}
-

diff -puN arch/mips/sibyte/swarm/Makefile~mips-lite arch/mips/sibyte/swarm/Makefile

arch/mips/sibyte/swarm/Makefile renamed from arch/mips/sibyte/swarm/Makefile~mips-lite +0 -2
@@ -1,3 +1 @@
 lib-y				= setup.o rtc_xicor1241.o rtc_m41t81.o
-
-lib-$(CONFIG_KGDB)		+= dbg_io.o

diff -puN /dev/null include/asm-mips/kdebug.h

include/asm-mips/kdebug.h new file +47 -0
@@ -0,0 +1,47 @@
+/*
+ *
+ * Copyright (C) 2004  MontaVista Software Inc.
+ * Author: Manish Lachwani, [email protected] or [email protected]
+ *
+ * This program is free software; you can redistribute  it and/or modify it
+ * under  the terms of  the GNU General  Public License as published by the
+ * Free Software Foundation;  either version 2 of the  License, or (at your
+ * option) any later version.
+ *
+ */
+#ifndef _MIPS_KDEBUG_H
+#define _MIPS_KDEBUG_H
+
+#include <linux/notifier.h>
+
+struct pt_regs;
+
+struct die_args {
+	struct pt_regs *regs;
+	const char *str;
+	long err;
+};
+
+int register_die_notifier(struct notifier_block *nb);
+extern struct notifier_block *mips_die_chain;
+
+enum die_val {
+	DIE_OOPS = 1,
+	DIE_PANIC,
+	DIE_DIE,
+	DIE_KERNELDEBUG,
+	DIE_TRAP,
+	DIE_PAGE_FAULT,
+};
+
+/*
+ * trap number can be computed from regs and signr can be computed using
+ * compute_signal()
+ */
+static inline int notify_die(enum die_val val,char *str,struct pt_regs *regs,long err)
+{
+	struct die_args args = { .regs=regs, .str=str, .err=err };
+	return notifier_call_chain(&mips_die_chain, val, &args);
+}
+
+#endif /* _MIPS_KDEBUG_H */

diff -puN /dev/null include/asm-mips/kgdb.h

include/asm-mips/kgdb.h new file +22 -0
@@ -0,0 +1,22 @@
+#ifdef __KERNEL__
+#ifndef _ASM_KGDB_H_
+#define _ASM_KGDB_H_
+
+#define BUFMAX			2048
+#define NUMREGBYTES		(90*sizeof(long))
+#define NUMCRITREGBYTES		(12*sizeof(long))
+#define BREAK_INSTR_SIZE	4
+#define BREAKPOINT()		__asm__ __volatile__(		\
+					".globl breakinst\n\t"	\
+					".set\tnoreorder\n\t"	\
+					"nop\n"			\
+					"breakinst:\tbreak\n\t"	\
+					"nop\n\t"		\
+					".set\treorder")
+#define CHECK_EXCEPTION_STACK()	1
+#define CACHE_FLUSH_IS_SAFE	0
+
+extern int kgdb_early_setup;
+
+#endif				/* _ASM_KGDB_H_ */
+#endif				/* __KERNEL__ */

diff -puN lib/Kconfig.debug~mips-lite lib/Kconfig.debug

lib/Kconfig.debug renamed from lib/Kconfig.debug~mips-lite +6 -1
@@ -163,7 +163,7 @@ config FRAME_POINTER
 
 config KGDB
 	bool "KGDB: kernel debugging with remote gdb"
-	depends on DEBUG_KERNEL && (X86 || ((!SMP || BROKEN) && (PPC32)))
+	depends on DEBUG_KERNEL && (X86 || MIPS32 || ((!SMP || BROKEN) && PPC32))
 	help
 	  If you say Y here, it will be possible to remotely debug the
 	  kernel using gdb. It is strongly suggested that you enable
@@ -189,6 +189,7 @@ choice
 	prompt "Method for KGDB communication"
 	depends on KGDB
 	default KGDB_ONLY_MODULES
+	default KGDB_SIBYTE if SIBYTE_SB1xxx_SOC
 	default KGDB_MPSC if SERIAL_MPSC
 	help
 	  There are a number of different ways in which you can communicate
@@ -222,6 +223,10 @@ config KGDB_MPSC
 	  Controller (MPSC) channel. Note that the GT64260A is not
 	  supported.
 
+config KGDB_SIBYTE
+	bool "KGDB: On the Broadcom SWARM serial port"
+	depends on MIPS && SIBYTE_SB1xxx_SOC
+
 endchoice
 
 config KGDB_8250

_

#29 lore raw

Re: [patch 05/15] Basic MIPS support

Quoted 2 lines · Ralf Baechle

Forwarding this as a heads up. Who cares about kgdb may want to start working on the necessary bits as the patchset from below will be in 2.6.13.

I doubt it'll be in 2.6.13..