Skip to contentSkip to conversation

Add a KGDB core

PATCH In review Tom Rini 6 participants 37 messages Aug 29, 2005 – Aug 31, 2005

Subsystems (19)
lore
Share & tools
lore

Tom Rini

author
#0 lore raw

PATCH 1/16 Add a KGDB core

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-trini/Documentation/DocBook/Makefile  |    2 
 linux-2.6.13-trini/Documentation/DocBook/kgdb.tmpl |  221 ++
 linux-2.6.13-trini/MAINTAINERS                     |    9 
 linux-2.6.13-trini/include/linux/kgdb.h            |  260 ++
 linux-2.6.13-trini/kernel/Makefile                 |    1 
 linux-2.6.13-trini/kernel/kgdb.c                   | 1857 +++++++++++++++++
 linux-2.6.13-trini/kernel/pid.c                    |   11 
 linux-2.6.13-trini/kernel/sched.c                  |    4 
 linux-2.6.13-trini/lib/Kconfig.debug               |   52 
 9 files changed, 2415 insertions(+), 2 deletions(-)
Documentation/DocBook/kgdb.tmpl new file +221 -0
diff -puN /dev/null Documentation/DocBook/kgdb.tmpl
@@ -0,0 +1,221 @@
+<?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>
+      </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 +1857 -0

1,857 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>
@@ -5217,6 +5218,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 +52 -0

55 lines not on this page · raw message

MAINTAINERS renamed from MAINTAINERS~core-lite +9 -0
diff -puN MAINTAINERS~core-lite MAINTAINERS
@@ -1349,6 +1349,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/16 Add support for i386 platforms to KGDB

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-trini/arch/i386/kernel/Makefile   |    1 
 linux-2.6.13-trini/arch/i386/kernel/kgdb-jmp.S |   74 +++++
 linux-2.6.13-trini/arch/i386/kernel/kgdb.c     |  301 +++++++++++++++++++++
 linux-2.6.13-trini/arch/i386/kernel/setup.c    |    3 
 linux-2.6.13-trini/arch/i386/kernel/traps.c    |   15 -
 linux-2.6.13-trini/arch/i386/mm/fault.c        |    4 
 linux-2.6.13-trini/include/asm-i386/kgdb.h     |   50 +++
 linux-2.6.13-trini/include/asm-i386/system.h   |   10 
 linux-2.6.13-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;
@@ -1473,6 +1474,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
@@ -1529,6 +1531,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"
 	select WANT_EXTRA_DEBUG_INFORMATION
-	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/16 Add support for PowerPC32 platforms to KGDB

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.

arch/ppc/Kconfig.debug +0 -36
Index: linux-2.6.13/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 +1 -1
Index: linux-2.6.13/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 +0 -16
Index: linux-2.6.13/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);
@@ -703,18 +699,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 +9 -0
Index: linux-2.6.13/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 +14 -9
Index: linux-2.6.13/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 +17 -10
Index: linux-2.6.13/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>
@@ -242,14 +243,20 @@ 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");
-	}
+#endif
 
-#if defined(CONFIG_SERIAL_TEXT_DEBUG) || defined(CONFIG_KGDB)
+#ifdef CONFIG_SERIAL_TEXT_DEBUG
 	/* Configure debug serial access */
 	gen550_init(0, &port);
+#endif
+#ifdef CONFIG_KGDB_8250
+	kgdb8250_add_port(0, &port);
+#endif
 
+#if defined(CONFIG_SERIAL_TEXT_DEBUG) || defined(CONFIG_KGDB_8250)
 	/* Purge TLB entry added in head_44x.S for early serial access */
 	_tlbie(UART0_IO_BASE);
 #endif
@@ -259,14 +266,18 @@ ebony_early_serial_map(void)
 	port.uartclk = clocks.uart1;
 	port.line = 1;
 
-	if (early_serial_setup(&port) != 0) {
+#ifdef CONFIG_SERIAL_8250
+	if (early_serial_setup(&port) != 1)
 		printk("Early serial init of port 1 failed\n");
-	}
+#endif
 
-#if defined(CONFIG_SERIAL_TEXT_DEBUG) || defined(CONFIG_KGDB)
+#ifdef CONFIG_SERIAL_TEXT_DEBUG
 	/* Configure debug serial access */
 	gen550_init(1, &port);
 #endif
+#ifdef CONFIG_KGDB_8250
+	kgdb8250_add_port(1, &port);
+#endif
 }
 
 static void __init
@@ -352,8 +363,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 +17 -9
Index: linux-2.6.13/arch/ppc/platforms/4xx/ocotea.c
===================================================================
@@ -34,6 +34,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>
@@ -260,14 +261,20 @@ 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");
-	}
+#endif
 
-#if defined(CONFIG_SERIAL_TEXT_DEBUG) || defined(CONFIG_KGDB)
+#ifdef CONFIG_SERIAL_TEXT_DEBUG
 	/* Configure debug serial access */
 	gen550_init(0, &port);
+#endif
+#ifdef CONFIG_KGDB_8250
+	kgdb8250_add_port(0, &port);
+#endif
 
+#if defined(CONFIG_SERIAL_TEXT_DEBUG) || defined(CONFIG_KGDB_8250)
 	/* Purge TLB entry added in head_44x.S for early serial access */
 	_tlbie(UART0_IO_BASE);
 #endif
@@ -277,14 +284,18 @@ ocotea_early_serial_map(void)
 	port.uartclk = clocks.uart1;
 	port.line = 1;
 
-	if (early_serial_setup(&port) != 0) {
+#ifdef CONFIG_SERIAL_8250
+	if (early_serial_setup(&port) != 1)
 		printk("Early serial init of port 1 failed\n");
-	}
+#endif
 
-#if defined(CONFIG_SERIAL_TEXT_DEBUG) || defined(CONFIG_KGDB)
+#ifdef CONFIG_SERIAL_TEXT_DEBUG
 	/* Configure debug serial access */
 	gen550_init(1, &port);
 #endif
+#ifdef CONFIG_KGDB_8250
+	kgdb8250_add_port(1, &port);
+#endif
 }
 
 static void __init
@@ -363,8 +374,5 @@ void __init platform_init(unsigned long 
 
 	ppc_md.nvram_read_val = todc_direct_read_val;
 	ppc_md.nvram_write_val = todc_direct_write_val;
-#ifdef CONFIG_KGDB
-	ppc_md.early_serial_map = ocotea_early_serial_map;
-#endif
 	ppc_md.init = ocotea_init;
 }
arch/ppc/platforms/4xx/xilinx_ml300.c +6 -12
Index: linux-2.6.13/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 +20 -16
Index: linux-2.6.13/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 +1 -4
Index: linux-2.6.13/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 +4 -6
Index: linux-2.6.13/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 +0 -5
Index: linux-2.6.13/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 +0 -3
Index: linux-2.6.13/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 +0 -3
Index: linux-2.6.13/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 +0 -3
Index: linux-2.6.13/arch/ppc/platforms/sandpoint.c
===================================================================
@@ -751,9 +751,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 +12 -9
Index: linux-2.6.13/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 +0 -1
Index: linux-2.6.13/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 +0 -3
Index: linux-2.6.13/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 +0 -1
Index: linux-2.6.13/arch/ppc/syslib/Makefile
===================================================================
@@ -87,7 +87,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 +54 -2

84 lines not on this page · raw message

arch/ppc/syslib/mv64x60_dbg.c +1 -51

61 lines not on this page · raw message

arch/ppc/syslib/ppc85xx_setup.c +8 -5
Index: linux-2.6.13/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 +1 -0
Index: linux-2.6.13/drivers/serial/Makefile
===================================================================
@@ -50,6 +50,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 +4 -0
Index: linux-2.6.13/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 +18 -30

70 lines not on this page · raw message

include/asm-ppc/machdep.h +0 -2
Index: linux-2.6.13/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 +2 -1
Index: linux-2.6.13/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 +2 -0
Index: linux-2.6.13/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 +9 -1
Index: linux-2.6.13/lib/Kconfig.debug
===================================================================
@@ -168,7 +168,7 @@ config WANT_EXTRA_DEBUG_INFORMATION
 config KGDB
 	bool "KGDB: kernel debugging with remote gdb"
 	select WANT_EXTRA_DEBUG_INFORMATION
-	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
@@ -194,6 +194,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
@@ -210,4 +211,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/16 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.

Since the last time this was submitted, I believe that all of the objections that Russell King noted have been fixed.

---

 linux-2.6.13-trini/drivers/serial/8250.c       |   21 
 linux-2.6.13-trini/drivers/serial/8250.h       |    1 
 linux-2.6.13-trini/drivers/serial/Kconfig      |    2 
 linux-2.6.13-trini/drivers/serial/Makefile     |    1 
 linux-2.6.13-trini/drivers/serial/kgdb_8250.c  |  594 +++++++++++++++++++++
 linux-2.6.13-trini/include/linux/kgdb.h        |    3 
 linux-2.6.13-trini/include/linux/serial_8250.h |    1 
 linux-2.6.13-trini/lib/Kconfig.debug           |   92 +++
 8 files changed, 712 insertions(+), 3 deletions(-)
drivers/serial/8250.c renamed from drivers/serial/8250.c~8250 +21 -0
diff -puN drivers/serial/8250.c~8250 drivers/serial/8250.c
@@ -2516,6 +2516,27 @@ void serial8250_unregister_port(int line
 }
 EXPORT_SYMBOL(serial8250_unregister_port);
 
+/**
+ *	serial8250_unregister_by_port - remove a 16x50 serial port
+ *	at runtime.
+ *	@port: A &struct uart_port that describes the port to remove.
+ *
+ *	Remove one serial port.  This may not be called from interrupt
+ *	context.  We hand the port back to the our control.
+ */
+void serial8250_unregister_by_port(struct uart_port *port)
+{
+	struct uart_8250_port *uart;
+
+	down(&serial_sem);
+	uart = serial8250_find_match_or_unused(port);
+	up(&serial_sem);
+
+	if (uart)
+		serial8250_unregister_port(uart->port.line);
+}
+EXPORT_SYMBOL(serial8250_unregister_by_port);
+
 static int __init serial8250_init(void)
 {
 	int ret, i;
drivers/serial/8250.h renamed from drivers/serial/8250.h~8250 +1 -0
diff -puN drivers/serial/8250.h~8250 drivers/serial/8250.h
@@ -19,6 +19,7 @@
 
 int serial8250_register_port(struct uart_port *);
 void serial8250_unregister_port(int line);
+void serial8250_unregister_by_port(struct uart_port *port);
 void serial8250_suspend_port(int line);
 void serial8250_resume_port(int line);
 
drivers/serial/Kconfig renamed from drivers/serial/Kconfig~8250 +1 -1
diff -puN drivers/serial/Kconfig~8250 drivers/serial/Kconfig
@@ -87,7 +87,7 @@ config SERIAL_8250_ACPI
 
 config SERIAL_8250_NR_UARTS
 	int "Maximum number of 8250/16550 serial ports"
-	depends on SERIAL_8250
+	depends on SERIAL_8250 || KGDB_8250
 	default "4"
 	help
 	  Set this to the number of serial ports you want the driver
drivers/serial/kgdb_8250.c new file +594 -0

594 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
@@ -57,3 +57,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
include/linux/kgdb.h renamed from include/linux/kgdb.h~8250 +2 -1
diff -puN include/linux/kgdb.h~8250 include/linux/kgdb.h
@@ -224,7 +224,7 @@ typedef unsigned char threadref[8];
  */
 struct kgdb_io {
 	int (*read_char) (void);
-	void (*write_char) (int);
+	void (*write_char) (u8);
 	void (*flush) (void);
 	int (*init) (void);
 	void (*late_init) (void);
@@ -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 +91 -1

108 lines not on this page · raw message

_

author
#4 lore raw

PATCH 5/16 Add support for MIPS platforms to KGDB

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-trini/arch/mips/Kconfig.debug                   |   19 
 linux-2.6.13-trini/arch/mips/kernel/Makefile                 |    3 
 linux-2.6.13-trini/arch/mips/kernel/irq.c                    |   32 
 linux-2.6.13-trini/arch/mips/kernel/kgdb-jmp.c               |  116 +
 linux-2.6.13-trini/arch/mips/kernel/kgdb-setjmp.S            |   27 
 linux-2.6.13-trini/arch/mips/kernel/kgdb.c                   |  296 ++
 linux-2.6.13-trini/arch/mips/kernel/kgdb_handler.S           |   58 
 linux-2.6.13-trini/arch/mips/kernel/traps.c                  |   26 
 linux-2.6.13-trini/arch/mips/mips-boards/generic/Makefile    |    1 
 linux-2.6.13-trini/arch/mips/mips-boards/generic/init.c      |   62 
 linux-2.6.13-trini/arch/mips/mips-boards/malta/malta_setup.c |    8 
 linux-2.6.13-trini/arch/mips/mm/extable.c                    |    7 
 linux-2.6.13-trini/arch/mips/sibyte/cfe/setup.c              |   14 
 linux-2.6.13-trini/arch/mips/sibyte/sb1250/Makefile          |    1 
 linux-2.6.13-trini/arch/mips/sibyte/sb1250/irq.c             |   57 
 linux-2.6.13-trini/arch/mips/sibyte/sb1250/irq_handler.S     |    2 
 linux-2.6.13-trini/arch/mips/sibyte/sb1250/kgdb_sibyte.c     |  164 +
 linux-2.6.13-trini/arch/mips/sibyte/swarm/Makefile           |    2 
 linux-2.6.13-trini/include/asm-mips/kdebug.h                 |   47 
 linux-2.6.13-trini/include/asm-mips/kgdb.h                   |   22 
 linux-2.6.13-trini/lib/Kconfig.debug                         |    7 
 linux-2.6.13/arch/mips/kernel/gdb-low.S                      |  370 ---
 linux-2.6.13/arch/mips/kernel/gdb-stub.c                     | 1091 ----------
 linux-2.6.13/arch/mips/sibyte/swarm/dbg_io.c                 |   76 
 24 files changed, 791 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 +296 -0

296 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 +116 -0

116 lines not on this page · raw message

arch/mips/kernel/kgdb-setjmp.S new file +27 -0
diff -puN /dev/null arch/mips/kernel/kgdb-setjmp.S
@@ -0,0 +1,27 @@
+/*
+ * arch/mips/kernel/kgdb-jmp.c
+ *
+ * Save and restore system registers so that within a limited frame we
+ * may have a fault and "jump back" to a known safe location.
+ *
+ * Copyright (C) 2005 by MontaVista Software.
+ * Author: Manish Lachwani ([email protected])
+ *
+ * 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
+#ifdef CONFIG_MIPS64
+	nop
+#endif
+	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"
 	select WANT_EXTRA_DEBUG_INFORMATION
-	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_8250_NOMODULE
+	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/16 Add support for IA64 platforms to KGDB

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-trini/arch/ia64/kernel/Makefile   |    1 
 linux-2.6.13-trini/arch/ia64/kernel/entry.S    |    4 
 linux-2.6.13-trini/arch/ia64/kernel/ivt.S      |   15 
 linux-2.6.13-trini/arch/ia64/kernel/kgdb-jmp.S |  238 ++++
 linux-2.6.13-trini/arch/ia64/kernel/kgdb.c     | 1038 +++++++++++++++++++++
 linux-2.6.13-trini/arch/ia64/kernel/mca.c      |   10 
 linux-2.6.13-trini/arch/ia64/kernel/process.c  |    6 
 linux-2.6.13-trini/arch/ia64/kernel/smp.c      |   17 
 linux-2.6.13-trini/arch/ia64/kernel/traps.c    |   36 
 linux-2.6.13-trini/arch/ia64/kernel/unwind.c   |   87 +
 linux-2.6.13-trini/arch/ia64/mm/extable.c      |    6 
 linux-2.6.13-trini/arch/ia64/mm/fault.c        |    5 
 linux-2.6.13-trini/include/asm-ia64/kgdb.h     |   37 
 linux-2.6.13-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"
 	select WANT_EXTRA_DEBUG_INFORMATION
-	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/16 x86_64: Rename KDB_VECTOR to DEBUGGER_VECTOR

CC: Andi Kleen <[email protected]>, Keith Owens <[email protected]>
The existing hook from KDB in the IPI code is really just a hook for the NMI vector. We rename the vector thusly and then it's up to the debugger to handle things from do_default_nmi().

---

 linux-2.6.13-trini/arch/x86_64/kernel/i8259.c  |    3 +--
 linux-2.6.13-trini/arch/x86_64/kernel/smp.c    |    2 +-
 linux-2.6.13-trini/arch/x86_64/kernel/traps.c  |    2 +-
 linux-2.6.13-trini/include/asm-x86_64/hw_irq.h |    2 +-
 linux-2.6.13-trini/include/asm-x86_64/ipi.h    |    2 +-
 5 files changed, 5 insertions(+), 6 deletions(-)
arch/x86_64/kernel/i8259.c renamed from arch/x86_64/kernel/i8259.c~x86_64-rename_kdb_vector +1 -2
diff -puN arch/x86_64/kernel/i8259.c~x86_64-rename_kdb_vector arch/x86_64/kernel/i8259.c
@@ -544,10 +544,9 @@ void __init init_IRQ(void)
 		int vector = FIRST_EXTERNAL_VECTOR + i;
 		if (i >= NR_IRQS)
 			break;
-		if (vector != IA32_SYSCALL_VECTOR && vector != KDB_VECTOR) { 
+		if (vector != IA32_SYSCALL_VECTOR && vector != NMI_VECTOR)
 			set_intr_gate(vector, interrupt[i]);
 	}
-	}
 
 #ifdef CONFIG_SMP
 	/*
arch/x86_64/kernel/smp.c renamed from arch/x86_64/kernel/smp.c~x86_64-rename_kdb_vector +1 -1
diff -puN arch/x86_64/kernel/smp.c~x86_64-rename_kdb_vector arch/x86_64/kernel/smp.c
@@ -252,7 +252,7 @@ void flush_tlb_all(void)
 
 void smp_kdb_stop(void)
 {
-	send_IPI_allbutself(KDB_VECTOR);
+	send_IPI_allbutself(NMI_VECTOR);
 }
 
 /*
arch/x86_64/kernel/traps.c renamed from arch/x86_64/kernel/traps.c~x86_64-rename_kdb_vector +1 -1
diff -puN arch/x86_64/kernel/traps.c~x86_64-rename_kdb_vector arch/x86_64/kernel/traps.c
@@ -931,7 +931,7 @@ void __init trap_init(void)
 	set_system_gate(IA32_SYSCALL_VECTOR, ia32_syscall);
 #endif
        
-	set_intr_gate(KDB_VECTOR, call_debug);
+	set_intr_gate(NMI_VECTOR, call_debug);
        
 	/*
 	 * Should be a barrier for any external CPU state.
include/asm-x86_64/hw_irq.h renamed from include/asm-x86_64/hw_irq.h~x86_64-rename_kdb_vector +1 -1
diff -puN include/asm-x86_64/hw_irq.h~x86_64-rename_kdb_vector include/asm-x86_64/hw_irq.h
@@ -54,7 +54,7 @@ struct hw_interrupt_type;
 #define RESCHEDULE_VECTOR	0xfc
 #define TASK_MIGRATION_VECTOR	0xfb
 #define CALL_FUNCTION_VECTOR	0xfa
-#define KDB_VECTOR	0xf9
+#define NMI_VECTOR	0xf9
 
 #define THERMAL_APIC_VECTOR	0xf0
 
include/asm-x86_64/ipi.h renamed from include/asm-x86_64/ipi.h~x86_64-rename_kdb_vector +1 -1
diff -puN include/asm-x86_64/ipi.h~x86_64-rename_kdb_vector include/asm-x86_64/ipi.h
@@ -32,7 +32,7 @@
 static inline unsigned int __prepare_ICR (unsigned int shortcut, int vector, unsigned int dest)
 {
 	unsigned int icr =  APIC_DM_FIXED | shortcut | vector | dest;
-	if (vector == KDB_VECTOR)
+	if (vector == NMI_VECTOR)
 		icr = (icr & (~APIC_VECTOR_MASK)) | APIC_DM_NMI;
 	return icr;
 }

_

author
#7 lore raw

PATCH 8/16 Add support for X86_64 platforms to KGDB

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-trini/arch/x86_64/Kconfig.debug     |    3 
 linux-2.6.13-trini/arch/x86_64/kernel/Makefile   |    2 
 linux-2.6.13-trini/arch/x86_64/kernel/kgdb-jmp.S |   65 ++
 linux-2.6.13-trini/arch/x86_64/kernel/kgdb.c     |  460 +++++++++++++++++++
 linux-2.6.13-trini/arch/x86_64/kernel/setup.c    |    3 
 linux-2.6.13-trini/arch/x86_64/kernel/setup64.c  |   14 
 linux-2.6.13-trini/arch/x86_64/kernel/traps.c    |   24 
 linux-2.6.13-trini/arch/x86_64/mm/fault.c        |    4 
 linux-2.6.13-trini/include/asm-x86_64/kgdb.h     |   50 ++
 linux-2.6.13-trini/include/asm-x86_64/proto.h    |    2 
 linux-2.6.13-trini/include/asm-x86_64/system.h   |    6 
 linux-2.6.13-trini/lib/Kconfig.debug             |    2 
 12 files changed, 617 insertions(+), 18 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 +460 -0

460 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 +12 -12
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>
@@ -902,12 +903,21 @@ void do_call_debug(struct pt_regs *regs)
 	notify_die(DIE_CALL, "debug call", regs, 0, 255, SIGINT); 
 }
 
-void __init trap_init(void)
+void __init early_trap_init(void)
 {
-	set_intr_gate(0,&divide_error);
 	set_intr_gate_ist(1,&debug,DEBUG_STACK);
 	set_intr_gate_ist(2,&nmi,NMI_STACK);
 	set_system_gate(3,&int3);
+	set_intr_gate(13,&general_protection);
+	set_intr_gate(14,&page_fault);
+	set_intr_gate(11,&segment_not_present);
+	set_intr_gate(NMI_VECTOR, call_debug);
+	cpu_init();
+}
+
+void __init trap_init(void)
+{
+	set_intr_gate(0,&divide_error);
 	set_system_gate(4,&overflow);	/* int4-5 can be called from all */
 	set_system_gate(5,&bounds);
 	set_intr_gate(6,&invalid_op);
@@ -915,10 +925,7 @@ void __init trap_init(void)
 	set_intr_gate_ist(8,&double_fault, DOUBLEFAULT_STACK);
 	set_intr_gate(9,&coprocessor_segment_overrun);
 	set_intr_gate(10,&invalid_TSS);
-	set_intr_gate(11,&segment_not_present);
 	set_intr_gate_ist(12,&stack_segment,STACKFAULT_STACK);
-	set_intr_gate(13,&general_protection);
-	set_intr_gate(14,&page_fault);
 	set_intr_gate(15,&spurious_interrupt_bug);
 	set_intr_gate(16,&coprocessor_error);
 	set_intr_gate(17,&alignment_check);
@@ -930,13 +937,6 @@ void __init trap_init(void)
 #ifdef CONFIG_IA32_EMULATION
 	set_system_gate(IA32_SYSCALL_VECTOR, ia32_syscall);
 #endif
-       
-	set_intr_gate(NMI_VECTOR, call_debug);
-       
-	/*
-	 * Should be a barrier for any external CPU state.
-	 */
-	cpu_init();
 }
 
 

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

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"
 	select WANT_EXTRA_DEBUG_INFORMATION
-	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
arch/x86_64/kernel/setup.c renamed from arch/x86_64/kernel/setup.c~x86_64-lite +3 -0
diff -puN arch/x86_64/kernel/setup.c~x86_64-lite arch/x86_64/kernel/setup.c
@@ -525,6 +525,9 @@ void __init setup_arch(char **cmdline_p)
 {
 	unsigned long kernel_end;
 
+	early_setup_per_cpu_area();
+	early_trap_init();
+
  	ROOT_DEV = old_decode_dev(ORIG_ROOT_DEV);
  	drive_info = DRIVE_INFO;
  	screen_info = SCREEN_INFO;
arch/x86_64/kernel/setup64.c renamed from arch/x86_64/kernel/setup64.c~x86_64-lite +13 -1
diff -puN arch/x86_64/kernel/setup64.c~x86_64-lite arch/x86_64/kernel/setup64.c
@@ -77,6 +77,16 @@ static int __init nonx32_setup(char *str
 }
 __setup("noexec32=", nonx32_setup);
 
+void __init early_setup_per_cpu_area(void)
+{
+	static char cpu0[PERCPU_ENOUGH_ROOM]
+		__attribute__ ((aligned (SMP_CACHE_BYTES)));
+	char *ptr = cpu0;
+
+	cpu_pda[0].data_offset = ptr - __per_cpu_start;
+	memcpy(ptr, __per_cpu_start, __per_cpu_end - __per_cpu_start);
+}
+
 /*
  * Great future plan:
  * Declare PDA itself and support (irqstack,tss,pgd) as per cpu data.
@@ -97,7 +107,9 @@ void __init setup_per_cpu_areas(void)
 	for (i = 0; i < NR_CPUS; i++) { 
 		char *ptr;
 
-		if (!NODE_DATA(cpu_to_node(i))) {
+		if (cpu_pda[i].data_offset)
+			continue;
+		else if (!NODE_DATA(cpu_to_node(i))) {
 			printk("cpu with no node %d, num_online_nodes %d\n",
 			       i, num_online_nodes());
 			ptr = alloc_bootmem(size);
include/asm-x86_64/proto.h renamed from include/asm-x86_64/proto.h~x86_64-lite +2 -0
diff -puN include/asm-x86_64/proto.h~x86_64-lite include/asm-x86_64/proto.h
@@ -10,6 +10,8 @@ struct pt_regs;
 
 extern void get_cpu_vendor(struct cpuinfo_x86*);
 extern void start_kernel(void);
+extern void early_trap_init(void);
+extern void early_setup_per_cpu_area(void);
 extern void pda_init(int); 
 
 extern void early_idt_handler(void);
arch/x86_64/mm/fault.c renamed from arch/x86_64/mm/fault.c~x86_64-lite +4 -0
diff -puN arch/x86_64/mm/fault.c~x86_64-lite arch/x86_64/mm/fault.c
@@ -516,6 +516,10 @@ no_context:
 	if (is_errata93(regs, address))
 		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.

_

author
#8 lore raw

PATCH 9/16 Add support for SuperH platforms to KGDB

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).

arch/sh/boards/se/7751/setup.c +0 -139
Index: linux-2.6.13/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 +0 -92

96 lines not on this page · raw message

arch/sh/kernel/cpu/sh3/ex.S +1 -1
Index: linux-2.6.13/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 +1 -1
Index: linux-2.6.13/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 +16 -14
Index: linux-2.6.13/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
Index: linux-2.6.13/arch/sh/kernel/kgdb_jmp.S
===================================================================
@@ -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
Index: linux-2.6.13/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 +1 -1
Index: linux-2.6.13/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 +0 -94

103 lines not on this page · raw message

arch/sh/kernel/time.c +0 -11
Index: linux-2.6.13/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 +7 -13
Index: linux-2.6.13/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 +0 -1
Index: linux-2.6.13/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 +7 -0
Index: linux-2.6.13/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 +1 -11
Index: linux-2.6.13/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 +0 -14
Index: linux-2.6.13/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 +16 -0
Index: linux-2.6.13/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 +187 -127

426 lines not on this page · raw message

include/asm-sh/kgdb.h +20 -98

118 lines not on this page · raw message

include/asm-sh/system.h +40 -0
Index: linux-2.6.13/include/asm-sh/system.h
===================================================================

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

lib/Kconfig.debug +11 -5
Index: linux-2.6.13/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
#9 lore raw

PATCH 10/16 Add support for ARM platforms to KGDB

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-trini/arch/arm/kernel/Makefile              |    1 
 linux-2.6.13-trini/arch/arm/kernel/kgdb-jmp.S            |   30 +
 linux-2.6.13-trini/arch/arm/kernel/kgdb.c                |  208 +++++++++++
 linux-2.6.13-trini/arch/arm/kernel/setup.c               |    5 
 linux-2.6.13-trini/arch/arm/kernel/traps.c               |   11 
 linux-2.6.13-trini/arch/arm/mach-ixp2000/core.c          |    5 
 linux-2.6.13-trini/arch/arm/mach-ixp2000/ixdp2x01.c      |    6 
 linux-2.6.13-trini/arch/arm/mach-ixp4xx/coyote-setup.c   |    5 
 linux-2.6.13-trini/arch/arm/mach-ixp4xx/ixdp425-setup.c  |   12 
 linux-2.6.13-trini/arch/arm/mach-omap1/board-osk.c       |    6 
 linux-2.6.13-trini/arch/arm/mach-omap1/serial.c          |    4 
 linux-2.6.13-trini/arch/arm/mach-pxa/Makefile            |    1 
 linux-2.6.13-trini/arch/arm/mach-pxa/kgdb-serial.c       |   98 +++++
 linux-2.6.13-trini/arch/arm/mach-versatile/kgdb_serial.c |  121 ++++++
 linux-2.6.13-trini/arch/arm/mm/extable.c                 |    7 
 linux-2.6.13-trini/drivers/serial/amba-pl011.c           |    2 
 linux-2.6.13-trini/include/asm-arm/kgdb.h                |   90 ++++
 linux-2.6.13-trini/include/asm-arm/system.h              |   41 ++
 linux-2.6.13-trini/lib/Kconfig.debug                     |   35 +
 19 files changed, 681 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
@@ -270,6 +270,7 @@ asmlinkage void do_undefinstr(struct pt_
 	unsigned int instr;
 	struct undef_hook *hook;
 	siginfo_t info;
+	mm_segment_t fs;
 	void __user *pc;
 
 	/*
@@ -279,12 +280,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) {
@@ -667,6 +671,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 +10 -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,8 @@ static struct plat_serial8250_port ixdp4
 		.mapbase	= IXP4XX_UART1_BASE_PHYS,
 		.membase	= (char *)IXP4XX_UART1_BASE_VIRT + REG_OFFSET,
 		.irq		= IRQ_IXP4XX_UART1,
-		.flags		= UPF_BOOT_AUTOCONF | UPF_SKIP_TEST,
+		.flags		= UPF_BOOT_AUTOCONF | UPF_SKIP_TEST |
+					UPF_SHARE_IRQ,
 		.iotype		= UPIO_MEM,
 		.regshift	= 2,
 		.uartclk	= IXP4XX_UART_XTAL,
@@ -91,7 +93,8 @@ 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 | UPF_SKIP_TEST,
+		.flags		= UPF_BOOT_AUTOCONF | UPF_SKIP_TEST |
+					UPF_SHARE_IRQ,
 		.iotype		= UPIO_MEM,
 		.regshift	= 2,
 		.uartclk	= IXP4XX_UART_XTAL,
@@ -126,6 +129,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;
 

diff -puN drivers/serial/kgdb_8250.c~arm-lite drivers/serial/kgdb_8250.c

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"
 	select WANT_EXTRA_DEBUG_INFORMATION
-	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_8250_NOMODULE
+	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
@@ -297,6 +309,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
#10 lore raw

PATCH 11/16 Add support for PowerPC64 platforms to KGDB

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-trini/arch/ppc64/Kconfig.debug        |   14 
 linux-2.6.13-trini/arch/ppc64/kernel/Makefile      |    3 
 linux-2.6.13-trini/arch/ppc64/kernel/kgdb.c        |  422 +++++++++++++++++
 linux-2.6.13-trini/arch/ppc64/kernel/maple_setup.c |    5 
 linux-2.6.13-trini/arch/ppc64/kernel/setup.c       |   14 
 linux-2.6.13-trini/arch/ppc64/mm/fault.c           |    8 
 linux-2.6.13-trini/include/asm-ppc64/kgdb.h        |   55 ++
 linux-2.6.13-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>
@@ -1258,6 +1259,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,
@@ -1311,6 +1313,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"
 	select WANT_EXTRA_DEBUG_INFORMATION
-	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
#11 lore raw

PATCH 12/16 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.

---

 linux-2.6.13-trini/drivers/net/Makefile |    1 
 linux-2.6.13-trini/drivers/net/kgdboe.c |  208 ++++++++++++++++++++++++++++
 linux-2.6.13-trini/lib/Kconfig.debug    |   24 +++
 3 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

_

author
#12 lore raw

PATCH 13/16 Add CFI DWARF2 annotation support

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-trini/Makefile                     |    5 
 linux-2.6.13-trini/arch/arm/kernel/entry-armv.S |    2 
 linux-2.6.13-trini/arch/i386/kernel/entry.S     |  105 ++
 linux-2.6.13-trini/arch/i386/kernel/head.S      |    5 
 linux-2.6.13-trini/arch/i386/kernel/process.c   |   20 
 linux-2.6.13-trini/arch/i386/kernel/smpboot.c   |    3 
 linux-2.6.13-trini/arch/x86_64/kernel/entry.S   |    2 
 linux-2.6.13-trini/include/asm-arm/kgdb.h       |    7 
 linux-2.6.13-trini/include/asm-generic/kgdb.h   |   34 
 linux-2.6.13-trini/include/asm-i386/kgdb.h      |   60 -
 linux-2.6.13-trini/include/asm-mips/kgdb.h      |    4 
 linux-2.6.13-trini/include/asm-ppc/kgdb.h       |    1 
 linux-2.6.13-trini/include/asm-sh/kgdb.h        |    1 
 linux-2.6.13-trini/include/asm-x86_64/kgdb.h    |    4 
 linux-2.6.13-trini/include/linux/dwarf2-lang.h  |  301 +++++++
 linux-2.6.13-trini/include/linux/dwarf2.h       |  775 ++++++++++++++++++++
 linux-2.6.13-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
#13 lore raw

PATCH 14/16 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-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
#14 lore raw

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

This allows for KGDB to better deal with autoloaded modules. The way this works, requires a patch to GDB. This patch can be found at ftp://source.mvista.com/pub/kgdb/gdb-6.3-kgdb-module-notification.patch

The way this works is that the solib-search-path must contain the location of any module to be debugged, and then when a module is loaded GDB acts like a shared library has been loaded now, and can be used that way.

---

 linux-2.6.13-trini/include/linux/module.h |   16 ++++++++
 linux-2.6.13-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
#15 lore raw

PATCH 16/16 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-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,
 };

_

#16 lore raw

Re: [patch 16/16] Add hardware breakpoint support for i386

Quoted 2 lines · Tom Rini

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.

This really would need so coordination with user space using them. Otherwise it'll be quite unreliable because any user program can break it.

Long ago (in 2.4 time frame) there used to be a IBM patch floating around to reserve them globally and user space to use specific ones. I guess something like that would be needed again.

-Andi

author
#17 lore raw

Re: [patch 16/16] Add hardware breakpoint support for i386

Quoted 8 lines · Andi Kleen
Quoted 2 lines · Tom Rini

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.

This really would need so coordination with user space using them. Otherwise it'll be quite unreliable because any user program can break it.

Probably easiest to just drop this for now then, thanks.

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

Re: [patch 16/16] Add hardware breakpoint support for i386

In reply to Tom Rini
Quoted 3 lines · Tom Rini

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.

Hardware breakpoints must be per cpu, not global. Also you will fall over applications that are using gdb, because gdb uses the same registers. KDB has never really supported kernel hardware breakpoints, they are hard to do without stamping on user space.

#19 lore raw

Re: [patch 08/16] Add support for X86_64 platforms to KGDB

In reply to Tom Rini

arch/x86_64/kernel/setup64.c static int __init nonx32_setup(char *str · line 88

Quoted 9 lines · Tom Rini
arch/x86_64/kernel/setup64.c renamed from arch/x86_64/kernel/setup64.c~x86_64-lite +9 -0
+void __init early_setup_per_cpu_area(void)
+{
+	static char cpu0[PERCPU_ENOUGH_ROOM]
+		__attribute__ ((aligned (SMP_CACHE_BYTES)));
+	char *ptr = cpu0;
+
+	cpu_pda[0].data_offset = ptr - __per_cpu_start;
+	memcpy(ptr, __per_cpu_start, __per_cpu_end - __per_cpu_start);
+}

What is that? It looks totally bogus. Can you tell exactly where you believe early per cpu data is needed?

arch/x86_64/kernel/setup64.c void __init setup_per_cpu_areas(void) · line 111

Quoted 11 lines
arch/x86_64/kernel/setup64.c renamed from arch/x86_64/kernel/setup64.c~x86_64-lite +3 -1
+
 /*
  * Great future plan:
  * Declare PDA itself and support (irqstack,tss,pgd) as per cpu data.
@@ -97,7 +107,9 @@ void __init setup_per_cpu_areas(void)
 	for (i = 0; i < NR_CPUS; i++) {
 		char *ptr;
 
-		if (!NODE_DATA(cpu_to_node(i))) {
+		if (cpu_pda[i].data_offset)
+			continue;

And that looks broken too.

In general I would also advise to mix any other changes outside kgdb* into the x86-64 kgdb patch. Either the patch should be merged into mainline in a separate patch or kgdb reworked to not need this.

arch/x86_64/mm/fault.c no_context: · line 522

Quoted 4 lines
arch/x86_64/mm/fault.c renamed from arch/x86_64/mm/fault.c~x86_64-lite +4 -0
+	if (notify_die(DIE_PAGE_FAULT, "no context", regs, error_code, 14,
+				SIGSEGV) == NOTIFY_STOP)
+		return;
+

I can see the point of that. It's ok if you submit it as a separate patch.

Regarding early trap init: I would have no problem to move all of traps_init into setup_arch (and leave traps_init empty for generic code). I actually don't know why it runs so late. But doing it half way is ugly.

-Andi

author
#20 lore raw

Re: [patch 08/16] Add support for X86_64 platforms to KGDB

Quoted 14 lines · Andi Kleen

arch/x86_64/kernel/setup64.c static int __init nonx32_setup(char *str · line 88

Quoted 9 lines · Tom Rini
arch/x86_64/kernel/setup64.c renamed from arch/x86_64/kernel/setup64.c~x86_64-lite +9 -0
+void __init early_setup_per_cpu_area(void)
+{
+	static char cpu0[PERCPU_ENOUGH_ROOM]
+		__attribute__ ((aligned (SMP_CACHE_BYTES)));
+	char *ptr = cpu0;
+
+	cpu_pda[0].data_offset = ptr - __per_cpu_start;
+	memcpy(ptr, __per_cpu_start, __per_cpu_end - __per_cpu_start);
+}

What is that? It looks totally bogus. Can you tell exactly where you believe early per cpu data is needed?

Bob did this part (forgot to CC him, oops). But I believe it's needed for setting traps so much earlier.

Quoted 8 lines
Quoted 8 lines
arch/x86_64/kernel/setup64.c renamed from arch/x86_64/kernel/setup64.c~x86_64-lite +1 -0
+
 /*
  * Great future plan:
  * Declare PDA itself and support (irqstack,tss,pgd) as per cpu data.
@@ -97,7 +107,9 @@ void __init setup_per_cpu_areas(void)
 	for (i = 0; i < NR_CPUS; i++) {
 		char *ptr;
 
Quoted 5 lines

arch/x86_64/kernel/setup64.c void __init setup_per_cpu_areas(void) · line 111

Quoted 3 lines
arch/x86_64/kernel/setup64.c renamed from arch/x86_64/kernel/setup64.c~x86_64-lite +2 -1
-		if (!NODE_DATA(cpu_to_node(i))) {
+		if (cpu_pda[i].data_offset)
+			continue;

And that looks broken too.

I believe that's to takecare of the case where something is covered in early_setup_cpu_areas().

Quoted 3 lines

In general I would also advise to mix any other changes outside kgdb* into the x86-64 kgdb patch. Either the patch should be merged into mainline in a separate patch or kgdb reworked to not need this.

ok.

Quoted 6 lines

arch/x86_64/mm/fault.c no_context: · line 522

Quoted 4 lines
arch/x86_64/mm/fault.c renamed from arch/x86_64/mm/fault.c~x86_64-lite +4 -0
+	if (notify_die(DIE_PAGE_FAULT, "no context", regs, error_code, 14,
+				SIGSEGV) == NOTIFY_STOP)
+		return;
+

I can see the point of that. It's ok if you submit it as a separate patch.

I can split that out into one that follows the KDB_VECTOR rename easily enough.

Quoted 3 lines

Regarding early trap init: I would have no problem to move all of traps_init into setup_arch (and leave traps_init empty for generic code). I actually don't know why it runs so late. But doing it half way is ugly.

Should I make setup_per_cpu_area and trap_init empty and turn the real ones into early_foo?

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

Re: [patch 08/16] Add support for X86_64 platforms to KGDB

Quoted 3 lines · Tom Rini

Bob did this part (forgot to CC him, oops). But I believe it's needed for setting traps so much earlier.

Ok looking again I guess he needed it for the GDT access in cpu_init

Quoted 10 lines
Quoted 7 lines

arch/x86_64/mm/fault.c no_context: · line 522

Quoted 4 lines
arch/x86_64/mm/fault.c renamed from arch/x86_64/mm/fault.c~x86_64-lite +4 -0
+	if (notify_die(DIE_PAGE_FAULT, "no context", regs, error_code, 14,
+				SIGSEGV) == NOTIFY_STOP)
+		return;
+

I can see the point of that. It's ok if you submit it as a separate patch.

I can split that out into one that follows the KDB_VECTOR rename easily enough.

That's fine. The rename is fine for me too btw.

Quoted 7 lines
Quoted 4 lines

Regarding early trap init: I would have no problem to move all of traps_init into setup_arch (and leave traps_init empty for generic code). I actually don't know why it runs so late. But doing it half way is ugly.

Should I make setup_per_cpu_area and trap_init empty and turn the real ones into early_foo?

setup_per_cpu_area is still needed later because it needs to allocate for non BP and you cannot do that that early.

-Andi

author
#22 lore raw

Re: [patch 08/16] Add support for X86_64 platforms to KGDB

Quoted 26 lines · Andi Kleen
Quoted 3 lines · Tom Rini

Bob did this part (forgot to CC him, oops). But I believe it's needed for setting traps so much earlier.

Ok looking again I guess he needed it for the GDT access in cpu_init

Quoted 10 lines
Quoted 7 lines

arch/x86_64/mm/fault.c no_context: · line 522

Quoted 4 lines
arch/x86_64/mm/fault.c renamed from arch/x86_64/mm/fault.c~x86_64-lite +4 -0
+	if (notify_die(DIE_PAGE_FAULT, "no context", regs, error_code, 14,
+				SIGSEGV) == NOTIFY_STOP)
+		return;
+

I can see the point of that. It's ok if you submit it as a separate patch.

I can split that out into one that follows the KDB_VECTOR rename easily enough.

That's fine. The rename is fine for me too btw.

Quoted 5 lines
Quoted 4 lines

Regarding early trap init: I would have no problem to move all of traps_init into setup_arch (and leave traps_init empty for generic code). I actually don't know why it runs so late. But doing it half way is ugly.

Quoted 5 lines
Quoted 2 lines

Should I make setup_per_cpu_area and trap_init empty and turn the real ones into early_foo?

setup_per_cpu_area is still needed later because it needs to allocate for non BP and you cannot do that that early.

OK. So I'll send out a patch that makes trap_init() empty and use the early_setup_per_cpu_areas() Bob wrote as well.

Andrew: In sum, there will be 3 patches that replace the x86_64 main patch (2 split-out-stuff, 1 new kgdb patch).

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

Re: [patch 04/16] I/O driver for 8250-compatible UARTs

In reply to Tom Rini
Quoted 1 line · Tom Rini

This is the I/O driver for any 8250-compatible UARTs.

Ah, obviously its patchbomb time. 2.6.13 must have been released! 8)

I wish for this stuff to wait until my queue of stuff has gone to Linus first - otherwise Linus will probably have a merge headache on his hands... unless these patches are against the -mm kernels.

Signature · 3 lines
Russell King
 Linux kernel    2.6 ARM Linux   - http://www.arm.linux.org.uk/
 maintainer of:  2.6 Serial core
author
#24 lore raw

Re: [patch 04/16] I/O driver for 8250-compatible UARTs

Quoted 8 lines · Russell King
Quoted 1 line · Tom Rini

This is the I/O driver for any 8250-compatible UARTs.

Ah, obviously its patchbomb time. 2.6.13 must have been released! 8)

I wish for this stuff to wait until my queue of stuff has gone to Linus first - otherwise Linus will probably have a merge headache on his hands... unless these patches are against the -mm kernels.

I forsee it as being unlikely that this will hit Linus' tree without sometime spent in -mm, and probably more time than it will take for your queue to drain. But, these are unlikey to cause a headache (new func, extern for said func, Kconfig around SERIAL_8250_NR_UARTS, it really is simplier than before :))

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

Re: [patch 04/16] I/O driver for 8250-compatible UARTs

In reply to Tom Rini
Quoted 1 line · Tom Rini
 linux-2.6.13-trini/drivers/serial/kgdb_8250.c  |  594 +++++++++++++++++++++

The existing stuff in drivers/serial is named "8250_*"; is there a reason you're using "kgdb_8250" rather than "8250_kgdb"?

Quoted 6 lines

+ * serial8250_unregister_by_port - remove a 16x50 serial port
+ * at runtime.
+ * @port: A &struct uart_port that describes the port to remove.
+ *
+ * Remove one serial port. This may not be called from interrupt
+ * context. We hand the port back to the our control.

Hand the port back to whose control?

Quoted 1 line

+MODULE_PARM_DESC(kgdb8250, " kgdb8250=<port number>,<baud rate>\n");

Document IRQ/MMIO/IOport stuff here too (whatever it turns out to be, see below).

It seems wrong to me to have kgdb8250 use "ttyS" names for devices. In general you don't know the ttyS name for a device until after the 8250 driver claims it. Sure, it's a convenience to use "ttyS0" instead of "io,0x3f8", but it also makes it hard to run kgdb on a PCI or MMIO UART, because you don't know what its name will be.

If you gave up the convenience and just always required an I/O port or MMIO address, you could nuke all the old_rs_table[] and kgdb8250_ports[] stuff, not to mention a bunch of config options.

drivers/serial/kgdb_8250.c line 372

Quoted 4 lines
drivers/serial/kgdb_8250.c new file +4 -0
+static int kgdb8250_local_init(void)
+{
+	if (old_rs_table_copied == 0)
+		kgdb8250_copy_rs_table();

This would be easier to maintain if the "if (old_rs_table_copied)" test were in the callee, not in every caller.

drivers/serial/kgdb_8250.c line 380

Quoted 7 lines
drivers/serial/kgdb_8250.c new file +7 -0
+	switch (CURRENTPORT.iotype) {
+	case UPIO_MEM:
+		if (CURRENTPORT.mapbase)
+			kgdb8250_needs_request_mem_region = 1;
+		if (CURRENTPORT.flags & UPF_IOREMAP) {
+			CURRENTPORT.membase = ioport_map(CURRENTPORT.mapbase,
+						      8 << KGDB8250_REG_SHIFT);

Shouldn't this be ioremap instead of ioport_map?

drivers/serial/kgdb_8250.c line 408

Quoted 12 lines
drivers/serial/kgdb_8250.c new file +12 -0
+static int kgdb_init_io(void)
+{
+#ifdef CONFIG_KGDB_8250_MODULE
+	if (strlen(config)) {
+		if (kgdb8250_opt(config))
+			return -EINVAL;
+	} else {
+		printk(KERN_ERR "kgdb8250: argument error, usage: "
+		       "kgdb8250=<port number>,<baud rate>");
+#ifdef CONFIG_IA64
+		printk(",<irq>,<iomem base>");
+#endif

This isn't ia64-specific.

drivers/serial/kgdb_8250.c line 453

Quoted 13 lines
drivers/serial/kgdb_8250.c new file +13 -0
+static void __init kgdb8250_hookup_irq(void)
+{
+#if defined(CONFIG_SERIAL_8250) || defined (CONFIG_SERIAL_8250_MODULE)
+	/* Take the port away from the main driver. */
+	serial8250_unregister_by_port(&CURRENTPORT);
+
+	/* Now reinit the port as the above has disabled things. */
+	kgdb8250_init();
+#endif
+	/* We may need to call request_mem_region() first. */
+	if (kgdb8250_needs_request_mem_region)
+		request_mem_region(CURRENTPORT.mapbase,
+				   8 << KGDB8250_REG_SHIFT, "kgdb");

The unregister/init/request_mem_region stuff doesn't sound very much like "hookup_irq".

Quoted 2 lines

+ * Syntax for this cmdline option is "kgdb8250=ttyno,baudrate"
+ * with ",irq,iomembase" tacked on the end on IA64.

This syntax doesn't really make sense on ia64, because there are no fixed "ttyno/iomembase" mappings. It would be unambiguous to specify either ttyno OR iomembase, but there's no good way to use both.

And there should be syntax to specify either MMIO or I/O port space devices. Intel ia64 boxes typically have I/O port UARTs (0x3f8, etc), and HP boxes typically have MMIO devices.

drivers/serial/kgdb_8250.c line 561

Quoted 12 lines
drivers/serial/kgdb_8250.c new file +12 -0
+#ifdef CONFIG_IA64
+	if (*str == ',') {
+		str++;
+		KGDB8250_IRQ = simple_strtoul(str, &str, 10);
+		if (*str == ',') {
+			str++;
+			CURRENTPORT.iotype = SERIAL_IO_MEM;
+			CURRENTPORT.membase =
+			    (unsigned char *)simple_strtoul(str, &str, 0);
+		}
+	}
+#endif

Not ia64-specific.

lib/Kconfig.debug config KGDB_MPSC · line 244

Quoted 10 lines
lib/Kconfig.debug renamed from lib/Kconfig.debug~8250 +10 -0
+config KGDB_SIMPLE_SERIAL
+	bool "Simple selection of KGDB serial port"
+	depends on KGDB_8250
+	default y
+	help
+	  If you say Y here, you will only have to pick the baud rate
+	  and serial port (ttyS) that you wish to use for KGDB.  If you
+	  say N, you will have provide the I/O port and IRQ number.  Note
+	  that if your serial ports are iomapped, such as on ia64, then
+	  you must say Y here.  If in doubt, say Y.

How about: "... you will have to provide the address (I/O port or MMIO address) and IRQ ..."

I don't understand the "iomapped" bit -- does that mean MMIO? And why would it make any difference whether they're in I/O port or MMIO space?

I expect that if you use "ttyS" naming to select a port, that doesn't work early in boot on ia64, because ia64 doesn't have compiled-in knowledge of where ttyS devices live. Is that related to what this is trying to say?

lib/Kconfig.debug config KGDB_MPSC · line 297

Quoted 9 lines
lib/Kconfig.debug renamed from lib/Kconfig.debug~8250 +9 -0
+config KGDB_PORT
+	hex "hex I/O port address of the debug serial port"
+	depends on !KGDB_SIMPLE_SERIAL && KGDB_8250 && !IA64
+	default 3f8
+	help
+	  This is the unmapped (and on platforms with 1:1 mapping
+	  this is typically, but not always the same as the mapped)
+	  address of the serial port.  The stanards on your architecture
+	  may be found in include/asm-$(ARCH)/serial.h.

Not ia64-specific. The description sounds like it applies to MMIO,
not to I/O port space. And s/stanards/standards/.

lib/Kconfig.debug config KGDB_MPSC · line 306

Quoted 8 lines
lib/Kconfig.debug renamed from lib/Kconfig.debug~8250 +8 -0
+config KGDB_IRQ
+	int "IRQ of the debug serial port"
+	depends on !KGDB_SIMPLE_SERIAL && KGDB_8250 && !IA64
+	default 4
+	help
+	  This is the IRQ for the debug port.  This must be known so that
+	  KGDB can interrupt the running system (either for a new
+	  connection or when in gdb and control-C is issued).

Not ia64-specific.

author
#26 lore raw

Re: [patch 04/16] I/O driver for 8250-compatible UARTs

Quoted 5 lines · Bjorn Helgaas
Quoted 1 line · Tom Rini
 linux-2.6.13-trini/drivers/serial/kgdb_8250.c  |  594 +++++++++++++++++++++

The existing stuff in drivers/serial is named "8250_*"; is there a reason you're using "kgdb_8250" rather than "8250_kgdb"?

All the other kgdb stuff tends to be prefixed, not suffixed. But I don't really care either way.

Quoted 8 lines
Quoted 6 lines

+ * serial8250_unregister_by_port - remove a 16x50 serial port
+ * at runtime.
+ * @port: A &struct uart_port that describes the port to remove.
+ *
+ * Remove one serial port. This may not be called from interrupt
+ * context. We hand the port back to the our control.

Hand the port back to whose control?

Ok, that is non-sensical. "We hand the port to the callers control." is what I meant to say.

Quoted 10 lines
Quoted 1 line

+MODULE_PARM_DESC(kgdb8250, " kgdb8250=<port number>,<baud rate>\n");

Document IRQ/MMIO/IOport stuff here too (whatever it turns out to be, see below).

It seems wrong to me to have kgdb8250 use "ttyS" names for devices. In general you don't know the ttyS name for a device until after the 8250 driver claims it. Sure, it's a convenience to use "ttyS0" instead of "io,0x3f8", but it also makes it hard to run kgdb on a PCI or MMIO UART, because you don't know what its name will be.

I've tried intentionally to not mention 'ttyS' anywhere (exposed to the user) because it's really not 'ttySN' but it is the port registered to us.

Quoted 3 lines

If you gave up the convenience and just always required an I/O port or MMIO address, you could nuke all the old_rs_table[] and kgdb8250_ports[] stuff, not to mention a bunch of config options.

But that's really rather handy so I'd rather not get rid of it.

There's really two cases we have to deal with. The first case is a known at compile time or can be registered at boot-time easily port (ie dumb old PC or ARM boards). The second case is "serial port over there". Perhaps we should change the kgdb8250 arg to be an override of the default port, so:
kgdb8250={io,mmio},<irq>,<token>,<baud rate>

Would that work?

Quoted 7 lines

drivers/serial/kgdb_8250.c line 372

Quoted 4 lines
drivers/serial/kgdb_8250.c new file +4 -0
+static int kgdb8250_local_init(void)
+{
+	if (old_rs_table_copied == 0)
+		kgdb8250_copy_rs_table();

This would be easier to maintain if the "if (old_rs_table_copied)" test were in the callee, not in every caller.

I'm not sure. In the compiled-in case we know it's always been run prior to freeing __init data, and thus it's quasi-safe. I suppose it wouldn't be too big a deal to just remove the __init and do it like that.

Quoted 9 lines

drivers/serial/kgdb_8250.c line 380

Quoted 7 lines
drivers/serial/kgdb_8250.c new file +7 -0
+	switch (CURRENTPORT.iotype) {
+	case UPIO_MEM:
+		if (CURRENTPORT.mapbase)
+			kgdb8250_needs_request_mem_region = 1;
+		if (CURRENTPORT.flags & UPF_IOREMAP) {
+			CURRENTPORT.membase = ioport_map(CURRENTPORT.mapbase,
+						      8 << KGDB8250_REG_SHIFT);

Shouldn't this be ioremap instead of ioport_map?

If I remember right from the testing, no. Or if my memory is wrong and that's retorihcal, sure.

Quoted 6 lines
Quoted 6 lines
drivers/serial/kgdb_8250.c new file +6 -0
+static int kgdb_init_io(void)
+{
+#ifdef CONFIG_KGDB_8250_MODULE
+	if (strlen(config)) {
+		if (kgdb8250_opt(config))
+			return -EINVAL;
Quoted 8 lines

drivers/serial/kgdb_8250.c line 408

Quoted 6 lines
drivers/serial/kgdb_8250.c new file +6 -0
+	} else {
+		printk(KERN_ERR "kgdb8250: argument error, usage: "
+		       "kgdb8250=<port number>,<baud rate>");
+#ifdef CONFIG_IA64
+		printk(",<irq>,<iomem base>");
+#endif

This isn't ia64-specific.

It is and it isn't. Since no one's tried a PCI card uart for KGDB nor had a case where we have to pass in the mmio addr except on ia64, it is ia64-specific. But as I said above, if we make kgdb8250= an override of the compiled in choice, it wouldn't be.

Quoted 8 lines
Quoted 8 lines
drivers/serial/kgdb_8250.c new file +8 -0
+static void __init kgdb8250_hookup_irq(void)
+{
+#if defined(CONFIG_SERIAL_8250) || defined (CONFIG_SERIAL_8250_MODULE)
+	/* Take the port away from the main driver. */
+	serial8250_unregister_by_port(&CURRENTPORT);
+
+	/* Now reinit the port as the above has disabled things. */
+	kgdb8250_init();
Quoted 8 lines

drivers/serial/kgdb_8250.c line 453

Quoted 5 lines
drivers/serial/kgdb_8250.c new file +5 -0
+#endif
+	/* We may need to call request_mem_region() first. */
+	if (kgdb8250_needs_request_mem_region)
+		request_mem_region(CURRENTPORT.mapbase,
+				   8 << KGDB8250_REG_SHIFT, "kgdb");

The unregister/init/request_mem_region stuff doesn't sound very much like "hookup_irq".

All the stuff that's required before you can really hookup the IRQ. Suggested name appricated.

Quoted 7 lines
Quoted 2 lines

+ * Syntax for this cmdline option is "kgdb8250=ttyno,baudrate"
+ * with ",irq,iomembase" tacked on the end on IA64.

This syntax doesn't really make sense on ia64, because there are no fixed "ttyno/iomembase" mappings. It would be unambiguous to specify either ttyno OR iomembase, but there's no good way to use both.

It's true that ttyno isn't really useful on ia64.

Quoted 5 lines
Quoted 5 lines
lib/Kconfig.debug renamed from lib/Kconfig.debug~8250 +5 -0
+config KGDB_SIMPLE_SERIAL
+	bool "Simple selection of KGDB serial port"
+	depends on KGDB_8250
+	default y
+	help
Quoted 8 lines

lib/Kconfig.debug config KGDB_MPSC · line 244

Quoted 5 lines
lib/Kconfig.debug renamed from lib/Kconfig.debug~8250 +5 -0
+	  If you say Y here, you will only have to pick the baud rate
+	  and serial port (ttyS) that you wish to use for KGDB.  If you
+	  say N, you will have provide the I/O port and IRQ number.  Note
+	  that if your serial ports are iomapped, such as on ia64, then
+	  you must say Y here.  If in doubt, say Y.

How about: "... you will have to provide the address (I/O port or MMIO address) and IRQ ..."

I'd really rather not force everyone to pass in the address token and IRQ#.

Quoted 2 lines

I don't understand the "iomapped" bit -- does that mean MMIO? And why would it make any difference whether they're in I/O port or MMIO space?

It's the special "boot once, figure out your I/O address and IRQ, reboot and pass it in" case of IA64. I'm under the impression that it's because of the more dynamic than other arches that we couldn't just register the ports as we find them to KGDB and let the user pick from a pre-registered port that we play that game.

Quoted 4 lines

I expect that if you use "ttyS" naming to select a port, that doesn't work early in boot on ia64, because ia64 doesn't have compiled-in knowledge of where ttyS devices live. Is that related to what this is trying to say?

Yes.

Quoted 4 lines
Quoted 4 lines
lib/Kconfig.debug renamed from lib/Kconfig.debug~8250 +4 -0
+config KGDB_PORT
+	hex "hex I/O port address of the debug serial port"
+	depends on !KGDB_SIMPLE_SERIAL && KGDB_8250 && !IA64
+	default 3f8
Quoted 8 lines

lib/Kconfig.debug config KGDB_MPSC · line 297

Quoted 5 lines
lib/Kconfig.debug renamed from lib/Kconfig.debug~8250 +5 -0
+	help
+	  This is the unmapped (and on platforms with 1:1 mapping
+	  this is typically, but not always the same as the mapped)
+	  address of the serial port.  The stanards on your architecture
+	  may be found in include/asm-$(ARCH)/serial.h.

Not ia64-specific. The description sounds like it applies to MMIO,
not to I/O port space. And s/stanards/standards/.

Having !mmio uarts on ia64 is news to me (but I've never used an ia64 box), hence the depends line.

Quoted 10 lines

lib/Kconfig.debug config KGDB_MPSC · line 306

Quoted 8 lines
lib/Kconfig.debug renamed from lib/Kconfig.debug~8250 +8 -0
+config KGDB_IRQ
+	int "IRQ of the debug serial port"
+	depends on !KGDB_SIMPLE_SERIAL && KGDB_8250 && !IA64
+	default 4
+	help
+	  This is the IRQ for the debug port.  This must be known so that
+	  KGDB can interrupt the running system (either for a new
+	  connection or when in gdb and control-C is issued).

Not ia64-specific.

True, don't recall why I did that one like that now, thanks.

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

Re: [patch 04/16] I/O driver for 8250-compatible UARTs

Quoted 9 lines · Tom Rini
Quoted 5 lines · Bjorn Helgaas
Quoted 1 line · Tom Rini
 linux-2.6.13-trini/drivers/serial/kgdb_8250.c  |  594 +++++++++++++++++++++

The existing stuff in drivers/serial is named "8250_*"; is there a reason you're using "kgdb_8250" rather than "8250_kgdb"?

All the other kgdb stuff tends to be prefixed, not suffixed. But I don't really care either way.

I'd prefer it was 8250_kgdb.c actually - that keeps it along side the other 8250 files.

Quoted 10 lines
Quoted 9 lines

drivers/serial/kgdb_8250.c line 380

Quoted 7 lines
drivers/serial/kgdb_8250.c new file +7 -0
+	switch (CURRENTPORT.iotype) {
+	case UPIO_MEM:
+		if (CURRENTPORT.mapbase)
+			kgdb8250_needs_request_mem_region = 1;
+		if (CURRENTPORT.flags & UPF_IOREMAP) {
+			CURRENTPORT.membase = ioport_map(CURRENTPORT.mapbase,
+						      8 << KGDB8250_REG_SHIFT);

Shouldn't this be ioremap instead of ioport_map?

Quoted 2 lines

If I remember right from the testing, no. Or if my memory is wrong and that's retorihcal, sure.

ioport_map() is supposed to be used to map the IO range for the ioread/ iowrite operations. IOW, it takes something compatible with inb() and friends and converts it to something compatible with ioread8() and friends.

It does not take a MMIO cookie, so the code above appears to be conceptually wrong.

Signature · 3 lines
Russell King
 Linux kernel    2.6 ARM Linux   - http://www.arm.linux.org.uk/
 maintainer of:  2.6 Serial core
author
#28 lore raw

Re: [patch 04/16] I/O driver for 8250-compatible UARTs

Quoted 5 lines · Russell King
Quoted 4 lines · Tom Rini
Quoted 3 lines · Bjorn Helgaas
Quoted 1 line · Tom Rini
 linux-2.6.13-trini/drivers/serial/kgdb_8250.c  |  594 +++++++++++++++++++++
Quoted 8 lines
Quoted 5 lines
Quoted 2 lines

The existing stuff in drivers/serial is named "8250_*"; is there a reason you're using "kgdb_8250" rather than "8250_kgdb"?

All the other kgdb stuff tends to be prefixed, not suffixed. But I don't really care either way.

I'd prefer it was 8250_kgdb.c actually - that keeps it along side the other 8250 files.

Will do.

Quoted 13 lines
Quoted 10 lines
Quoted 9 lines

drivers/serial/kgdb_8250.c line 380

Quoted 7 lines
drivers/serial/kgdb_8250.c new file +7 -0
+	switch (CURRENTPORT.iotype) {
+	case UPIO_MEM:
+		if (CURRENTPORT.mapbase)
+			kgdb8250_needs_request_mem_region = 1;
+		if (CURRENTPORT.flags & UPF_IOREMAP) {
+			CURRENTPORT.membase = ioport_map(CURRENTPORT.mapbase,
+						      8 << KGDB8250_REG_SHIFT);

Shouldn't this be ioremap instead of ioport_map?

Quoted 2 lines

If I remember right from the testing, no. Or if my memory is wrong and that's retorihcal, sure.

Quoted 8 lines

ioport_map() is supposed to be used to map the IO range for the ioread/ iowrite operations. IOW, it takes something compatible with inb() and friends and converts it to something compatible with ioread8() and friends.

It does not take a MMIO cookie, so the code above appears to be conceptually wrong.

So it's luck (or another mapping I didn't see elsewhere) that this worked, and it should still be ioremap(...) to use with ioread/write8 later on in the code?

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

Re: [patch 04/16] I/O driver for 8250-compatible UARTs

In reply to Tom Rini
Quoted 5 lines · Tom Rini
Quoted 1 line · Bjorn Helgaas

On Monday 29 August 2005 10:09 am, Tom Rini wrote:

I've tried intentionally to not mention 'ttyS' anywhere (exposed to the user) because it's really not 'ttySN' but it is the port registered to us.

So kgdb's port N is different from ttySN? That sounds really confusing. And KGDB_SIMPLE_SERIAL does mention "ttyS".

Quoted 6 lines

There's really two cases we have to deal with. The first case is a known at compile time or can be registered at boot-time easily port (ie dumb old PC or ARM boards). The second case is "serial port over there". Perhaps we should change the kgdb8250 arg to be an override of the default port, so:
kgdb8250={io,mmio},<irq>,<token>,<baud rate>

That makes sense. But I'd make it {io,mmio},<token>,<baud>,<irq> so it's more like the existing "console=uart" argument.

Quoted 10 lines
Quoted 9 lines

drivers/serial/kgdb_8250.c line 380

Quoted 7 lines
drivers/serial/kgdb_8250.c new file +7 -0
+	switch (CURRENTPORT.iotype) {
+	case UPIO_MEM:
+		if (CURRENTPORT.mapbase)
+			kgdb8250_needs_request_mem_region = 1;
+		if (CURRENTPORT.flags & UPF_IOREMAP) {
+			CURRENTPORT.membase = ioport_map(CURRENTPORT.mapbase,
+						      8 << KGDB8250_REG_SHIFT);

Shouldn't this be ioremap instead of ioport_map?

Quoted 2 lines

If I remember right from the testing, no. Or if my memory is wrong and that's retorihcal, sure.

ioport_map() certainly isn't going to do anything good with an MMIO address.

Quoted 11 lines
Quoted 7 lines

drivers/serial/kgdb_8250.c line 408

Quoted 5 lines
drivers/serial/kgdb_8250.c new file +5 -0
+		printk(KERN_ERR "kgdb8250: argument error, usage: "
+		       "kgdb8250=<port number>,<baud rate>");
+#ifdef CONFIG_IA64
+		printk(",<irq>,<iomem base>");
+#endif

This isn't ia64-specific.

It is and it isn't. Since no one's tried a PCI card uart for KGDB nor had a case where we have to pass in the mmio addr except on ia64, it is ia64-specific.

Maybe it's only been *tested* on ia64, but I don't think that's a reason to make it compiled only on ia64.

Quoted 9 lines
Quoted 7 lines
Quoted 2 lines

+ * Syntax for this cmdline option is "kgdb8250=ttyno,baudrate"
+ * with ",irq,iomembase" tacked on the end on IA64.

This syntax doesn't really make sense on ia64, because there are no fixed "ttyno/iomembase" mappings. It would be unambiguous to specify either ttyno OR iomembase, but there's no good way to use both.

It's true that ttyno isn't really useful on ia64.

Then I think it would be a mistake to have syntax that requires both ttyno and iomembase in the same command-line option. I'm visualizing something like this:

	kgdb8250=ttyS0,115200
	kgdb8250=io,0x3f8,115200,49
	kgdb8250=mmio,0xff5e0000,115200,49

where you can easily decide which type of device specification you've got.

Quoted 14 lines
Quoted 5 lines
Quoted 5 lines
lib/Kconfig.debug renamed from lib/Kconfig.debug~8250 +5 -0
+config KGDB_SIMPLE_SERIAL
+	bool "Simple selection of KGDB serial port"
+	depends on KGDB_8250
+	default y
+	help
Quoted 8 lines

lib/Kconfig.debug config KGDB_MPSC · line 244

Quoted 5 lines
lib/Kconfig.debug renamed from lib/Kconfig.debug~8250 +5 -0
+	  If you say Y here, you will only have to pick the baud rate
+	  and serial port (ttyS) that you wish to use for KGDB.  If you
+	  say N, you will have provide the I/O port and IRQ number.  Note
+	  that if your serial ports are iomapped, such as on ia64, then
+	  you must say Y here.  If in doubt, say Y.

How about: "... you will have to provide the address (I/O port or MMIO address) and IRQ ..."

Quoted 2 lines

I'd really rather not force everyone to pass in the address token and IRQ#.

My point was merely that you should support explicit MMIO addresses as well as explicit I/O ports. I guess it makes sense to accept ttyS names as well, and accept the limitation that before the 8250 driver initializes, ttyS names only work for devices defined at compile-time in SERIAL_PORT_DFNS.

Quoted 8 lines
Quoted 2 lines

I don't understand the "iomapped" bit -- does that mean MMIO? And why would it make any difference whether they're in I/O port or MMIO space?

It's the special "boot once, figure out your I/O address and IRQ, reboot and pass it in" case of IA64. I'm under the impression that it's because of the more dynamic than other arches that we couldn't just register the ports as we find them to KGDB and let the user pick from a pre-registered port that we play that game.

Yup, ia64 doesn't require serial ports at fixed addresses. They're all discovered via ACPI and PCI enumeration.

But "iomapped" doesn't suggest that to me. And I would expect the text to say that if you don't have any compiled-in UART names, you'd have to say "N". But it says use "Y" for ia64.

Actually, I think KGDB_SIMPLE_SERIAL, KGDB_*BAUD, KGDB_PORT_*, KGDB_PORT, and KGDB_IRQ are overkill. Could they all be nuked in favor of a KGDB_8250_DEVICE that could be set to things like "ttyS0,115200" or "io,0x3f8,115200,49"?

Quoted 13 lines
Quoted 4 lines
Quoted 4 lines
lib/Kconfig.debug renamed from lib/Kconfig.debug~8250 +4 -0
+config KGDB_PORT
+	hex "hex I/O port address of the debug serial port"
+	depends on !KGDB_SIMPLE_SERIAL && KGDB_8250 && !IA64
+	default 3f8
Quoted 8 lines

lib/Kconfig.debug config KGDB_MPSC · line 297

Quoted 5 lines
lib/Kconfig.debug renamed from lib/Kconfig.debug~8250 +5 -0
+	help
+	  This is the unmapped (and on platforms with 1:1 mapping
+	  this is typically, but not always the same as the mapped)
+	  address of the serial port.  The stanards on your architecture
+	  may be found in include/asm-$(ARCH)/serial.h.

Not ia64-specific. The description sounds like it applies to MMIO,
not to I/O port space. And s/stanards/standards/.

Quoted 2 lines

Having !mmio uarts on ia64 is news to me (but I've never used an ia64 box), hence the depends line.

Intel-based boxes have only I/O port UARTs. But regardless, the MMIO-ness or I/O port-ness of a UART is completely arch-independent.

The description point is that "unmapped" and "1:1 mapping" sound like things related to MMIO addresses, not to I/O port addresses.

author
#30 lore raw

Re: [patch 04/16] I/O driver for 8250-compatible UARTs

Quoted 9 lines · Bjorn Helgaas
Quoted 5 lines · Tom Rini
Quoted 1 line · Bjorn Helgaas

On Monday 29 August 2005 10:09 am, Tom Rini wrote:

I've tried intentionally to not mention 'ttyS' anywhere (exposed to the user) because it's really not 'ttySN' but it is the port registered to us.

So kgdb's port N is different from ttySN? That sounds really confusing. And KGDB_SIMPLE_SERIAL does mention "ttyS".

It's not intentionally different, and really only might be different in the we have ttySX case, but ttySX isn't registered to KGDB case.

Quoted 9 lines
Quoted 6 lines

There's really two cases we have to deal with. The first case is a known at compile time or can be registered at boot-time easily port (ie dumb old PC or ARM boards). The second case is "serial port over there". Perhaps we should change the kgdb8250 arg to be an override of the default port, so:
kgdb8250={io,mmio},<irq>,<token>,<baud rate>

That makes sense. But I'd make it {io,mmio},<token>,<baud>,<irq> so it's more like the existing "console=uart" argument.

ok.

Quoted 8 lines
Quoted 8 lines
Quoted 7 lines

drivers/serial/kgdb_8250.c line 408

Quoted 5 lines
drivers/serial/kgdb_8250.c new file +5 -0
+		printk(KERN_ERR "kgdb8250: argument error, usage: "
+		       "kgdb8250=<port number>,<baud rate>");
+#ifdef CONFIG_IA64
+		printk(",<irq>,<iomem base>");
+#endif

This isn't ia64-specific.

Quoted 6 lines
Quoted 3 lines

It is and it isn't. Since no one's tried a PCI card uart for KGDB nor had a case where we have to pass in the mmio addr except on ia64, it is ia64-specific.

Maybe it's only been *tested* on ia64, but I don't think that's a reason to make it compiled only on ia64.

It's only been needed on ia64. But it's moot since I've reworked things for kgdb8250= is always a complete override.

Quoted 4 lines

Actually, I think KGDB_SIMPLE_SERIAL, KGDB_*BAUD, KGDB_PORT_*, KGDB_PORT, and KGDB_IRQ are overkill. Could they all be nuked in favor of a KGDB_8250_DEVICE that could be set to things like "ttyS0,115200" or "io,0x3f8,115200,49"?

Hmm. I'll give that a shot momentarily... That sounds like a good idea 'tho..

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

Re: [patch 2/3] x86_64: Run setup_per_cpu_areas and trap_init sooner

In reply to Tom Rini

Review

Quoted 5 lines
(quoted diff) +4 -0
+void __init early_setup_per_cpu_areas(void)
+{
+	static char cpu0[PERCPU_ENOUGH_ROOM]
+		__attribute__ ((aligned (SMP_CACHE_BYTES)));

This needs a __cacheline_aligned too, otherwise there could be false sharing.

-Andi

author
#32 lore raw

Re: [patch 2/3] x86_64: Run setup_per_cpu_areas and trap_init sooner

Quoted 7 lines · Andi Kleen

Review

Quoted 5 lines
(quoted diff) +4 -0
+void __init early_setup_per_cpu_areas(void)
+{
+	static char cpu0[PERCPU_ENOUGH_ROOM]
+		__attribute__ ((aligned (SMP_CACHE_BYTES)));

This needs a __cacheline_aligned too, otherwise there could be false sharing.

Done, thanks:

CC: Andi Kleen <[email protected]>, Bob Picco <[email protected]>
It can be handy in some situations to have run trap_init() sooner than the generic code does. In order to do this on x86_64 we need to add a custom early_setup_per_cpu_areas() call as well.

---

 linux-2.6.13-trini/arch/x86_64/kernel/setup.c   |    3 +++
 linux-2.6.13-trini/arch/x86_64/kernel/setup64.c |   16 +++++++++++++++-
 linux-2.6.13-trini/arch/x86_64/kernel/traps.c   |    4 ++++
 linux-2.6.13-trini/include/asm-x86_64/proto.h   |    2 ++
 4 files changed, 24 insertions(+), 1 deletion(-)
arch/x86_64/kernel/setup.c renamed from arch/x86_64/kernel/setup.c~x86_64-early_funcs +3 -0
diff -puN arch/x86_64/kernel/setup.c~x86_64-early_funcs arch/x86_64/kernel/setup.c
@@ -525,6 +525,9 @@ void __init setup_arch(char **cmdline_p)
 {
 	unsigned long kernel_end;
 
+	early_setup_per_cpu_areas();
+	early_trap_init();
+
  	ROOT_DEV = old_decode_dev(ORIG_ROOT_DEV);
  	drive_info = DRIVE_INFO;
  	screen_info = SCREEN_INFO;
arch/x86_64/kernel/setup64.c renamed from arch/x86_64/kernel/setup64.c~x86_64-early_funcs +15 -1
diff -puN arch/x86_64/kernel/setup64.c~x86_64-early_funcs arch/x86_64/kernel/setup64.c
@@ -77,7 +77,19 @@ static int __init nonx32_setup(char *str
 }
 __setup("noexec32=", nonx32_setup);
 
+void __init early_setup_per_cpu_areas(void)
+{
+	static char cpu0[PERCPU_ENOUGH_ROOM] __cacheline_aligned
+		__attribute__ ((aligned (SMP_CACHE_BYTES)));
+	char *ptr = cpu0;
+
+	cpu_pda[0].data_offset = ptr - __per_cpu_start;
+	memcpy(ptr, __per_cpu_start, __per_cpu_end - __per_cpu_start);
+}
+
 /*
+ * We run this a bit sooner than the normal code, so provide a dummy
+ * function as well.
  * Great future plan:
  * Declare PDA itself and support (irqstack,tss,pgd) as per cpu data.
  * Always point %gs to its beginning
@@ -97,7 +109,9 @@ void __init setup_per_cpu_areas(void)
 	for (i = 0; i < NR_CPUS; i++) { 
 		char *ptr;
 
-		if (!NODE_DATA(cpu_to_node(i))) {
+		if (cpu_pda[i].data_offset)
+			continue;
+		else if (!NODE_DATA(cpu_to_node(i))) {
 			printk("cpu with no node %d, num_online_nodes %d\n",
 			       i, num_online_nodes());
 			ptr = alloc_bootmem(size);
arch/x86_64/kernel/traps.c renamed from arch/x86_64/kernel/traps.c~x86_64-early_funcs +4 -0
diff -puN arch/x86_64/kernel/traps.c~x86_64-early_funcs arch/x86_64/kernel/traps.c
@@ -904,6 +904,10 @@ void do_call_debug(struct pt_regs *regs)
 
 void __init trap_init(void)
 {
+}
+
+void __init early_trap_init(void)
+{
 	set_intr_gate(0,&divide_error);
 	set_intr_gate_ist(1,&debug,DEBUG_STACK);
 	set_intr_gate_ist(2,&nmi,NMI_STACK);
include/asm-x86_64/proto.h renamed from include/asm-x86_64/proto.h~x86_64-early_funcs +2 -0
diff -puN include/asm-x86_64/proto.h~x86_64-early_funcs include/asm-x86_64/proto.h
@@ -10,6 +10,8 @@ struct pt_regs;
 
 extern void get_cpu_vendor(struct cpuinfo_x86*);
 extern void start_kernel(void);
+extern void early_trap_init(void);
+extern void early_setup_per_cpu_areas(void);
 extern void pda_init(int); 
 
 extern void early_idt_handler(void);
Signature · 2 lines
Tom Rini
http://gate.crashing.org/~trini/
#33 lore raw

Re: [patch 1/3] x86_64: Add a notify_die() call to the "no context" part of do_page_fault()

In reply to Tom Rini
Quoted 13 lines · Tom Rini

CC: Andi Kleen <[email protected]>
This adds a call to notify_die() in the "no context" portion of do_page_fault() as someone on the chain might care and want to do a fixup.

---

 linux-2.6.13-trini/arch/x86_64/mm/fault.c |    4 ++++
 1 files changed, 4 insertions(+)

diff -puN arch/x86_64/mm/fault.c~x86_64-no_context_hook arch/x86_64/mm/fault.c

arch/x86_64/mm/fault.c no_context: · line 523

Quoted 10 lines
arch/x86_64/mm/fault.c renamed from arch/x86_64/mm/fault.c~x86_64-no_context_hook +4 -0
@@ -514,6 +514,10 @@ no_context:
 	if (is_errata93(regs, address))
 		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.

Please use a more descriptive text than "no context". This bit of info SHOULD be available to the gdb/kgdb user and should indicate why kgdb was entered. It thus should be something like "bad kernel address" or "illegal kernel address".

Quoted 1 line
Signature · 2 lines
George Anzinger   [email protected]
HRT (High-res-timers):  http://sourceforge.net/projects/high-res-timers/
author
#34 lore raw

Re: [patch 1/3] x86_64: Add a notify_die() call to the "no context" part of do_page_fault()

Quoted 20 lines · George Anzinger
Quoted 19 lines · Tom Rini

CC: Andi Kleen <[email protected]>
This adds a call to notify_die() in the "no context" portion of do_page_fault() as someone on the chain might care and want to do a fixup.

---

linux-2.6.13-trini/arch/x86_64/mm/fault.c | 4 ++++

1 files changed, 4 insertions(+)

diff -puN arch/x86_64/mm/fault.c~x86_64-no_context_hook arch/x86_64/mm/fault.c
--- linux-2.6.13/arch/x86_64/mm/fault.c~x86_64-no_context_hook 2005-08-29 11:09:13.000000000 -0700
+++ linux-2.6.13-trini/arch/x86_64/mm/fault.c 2005-08-29
11:09:13.000000000 -0700

(quoted diff) +0 -0
@@ -514,6 +514,10 @@ no_context:
 	if (is_errata93(regs, address))
 		return; 
 
Quoted 12 lines

Review no_context: · line 523

Quoted 7 lines
(quoted diff) +4 -0
+	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.

Please use a more descriptive text than "no context". This bit of info SHOULD be available to the gdb/kgdb user and should indicate why kgdb was entered. It thus should be something like "bad kernel address" or "illegal kernel address".

"no context" is the label we're in, in the code. What it's actually used for is "hey, we (== kgdb) tried to read/write a very very bogus addr, time to longjmp". If it's not true that kgdb is at fault then we drop to the debugger anyhow, and the user can see where they came from.

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

Re: [patch 1/3] x86_64: Add a notify_die() call to the "no context" part of do_page_fault()

Quoted 33 lines · Tom Rini
Quoted 20 lines · George Anzinger
Quoted 18 lines · Tom Rini

CC: Andi Kleen <[email protected]>
This adds a call to notify_die() in the "no context" portion of do_page_fault() as someone on the chain might care and want to do a fixup.

---

linux-2.6.13-trini/arch/x86_64/mm/fault.c | 4 ++++

1 files changed, 4 insertions(+)

diff -puN arch/x86_64/mm/fault.c~x86_64-no_context_hook arch/x86_64/mm/fault.c --- linux-2.6.13/arch/x86_64/mm/fault.c~x86_64-no_context_hook 2005-08-29 11:09:13.000000000 -0700
+++ linux-2.6.13-trini/arch/x86_64/mm/fault.c 2005-08-29
11:09:13.000000000 -0700

(quoted diff) +0 -0
@@ -514,6 +514,10 @@ no_context:
 	if (is_errata93(regs, address))
 		return; 
 
Quoted 9 lines

Review no_context: · line 523

Quoted 7 lines
(quoted diff) +4 -0
+	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.

Please use a more descriptive text than "no context". This bit of info SHOULD be available to the gdb/kgdb user and should indicate why kgdb was entered. It thus should be something like "bad kernel address" or "illegal kernel address".

Quoted 5 lines

"no context" is the label we're in, in the code. What it's actually used for is "hey, we (== kgdb) tried to read/write a very very bogus addr, time to longjmp". If it's not true that kgdb is at fault then we drop to the debugger anyhow, and the user can see where they came from.

No. What the user sees is the offending code (i.e. prior to the trap to page_fault), NOT how kgdb happend to be called. The "no_context" is IN the _context_ of page_fault, but that is lost by the time you get to kgdb and ask to see _why_ (via, hint, hint: "p kgdb_info").

Signature · 2 lines
George Anzinger   [email protected]
HRT (High-res-timers):  http://sourceforge.net/projects/high-res-timers/
author
#36 lore raw

Re: [patch 1/3] x86_64: Add a notify_die() call to the "no context" part of do_page_fault()

Quoted 1 line · George Anzinger

Tom Rini wrote:

[snip]

Quoted 9 lines
Quoted 5 lines

"no context" is the label we're in, in the code. What it's actually used for is "hey, we (== kgdb) tried to read/write a very very bogus addr, time to longjmp". If it's not true that kgdb is at fault then we drop to the debugger anyhow, and the user can see where they came from.

No. What the user sees is the offending code (i.e. prior to the trap to page_fault), NOT how kgdb happend to be called. The "no_context" is IN the _context_ of page_fault, but that is lost by the time you get to kgdb and ask to see _why_ (via, hint, hint: "p kgdb_info").

So you're suggesting changing what we pass in so that if we also modify kgdb_info to contain the 'where' thing you talked about before, it would be more useful, yes? If so, I think that can wait just a bit. :)

Signature · 2 lines
Tom Rini
http://gate.crashing.org/~trini/