Subject: Re: kgdb in virtex port
To: Jean-Francois Boudreault <jfboudre@gel.ulaval.ca>
From: Jachym Holecek <freza@dspfpga.com>
List: port-powerpc
Date: 02/01/2007 21:20:42
Hello,

# Jean-Francois Boudreault 2007-01-31:
> I've been playing with Jachym's virtex port for a while. I added support 
> for KGDB in your port but can't get it working right.

I think the code needs to work a bit differently, can you please try the
below (diff against -current sys/arch/{powerpc,evbppc/virtex})? It moves
most of kgdb handling to consinit(), xlcom() only provides leaf routines
(as was done with console support) and makes sure not to step on kgdb's
toe. As a side-effect, I've changed virtex_console_tag() to return bus
space tag by name and renamed the function to virtex_bus_space_tag().

A few general notes for the future:

  * Please use unified diffs, it's easier on the eyes.
  * Make sure your code works even when the options you're interested in
    are turned off (be it defines or higher-level logic).

Thanks,
	-- Jachym

Index: evbppc/virtex/consinit.c
===================================================================
RCS file: /cvsroot/src/sys/arch/evbppc/virtex/consinit.c,v
retrieving revision 1.1
diff -d -p -u -r1.1 consinit.c
--- evbppc/virtex/consinit.c	2 Dec 2006 22:18:47 -0000	1.1
+++ evbppc/virtex/consinit.c	1 Feb 2007 20:17:00 -0000
@@ -49,12 +49,18 @@ __KERNEL_RCSID(0, "$NetBSD: consinit.c,v
 #if NXLCOM > 0
 extern struct consdev 	consdev_xlcom;
 void    		xlcom_cninit(struct consdev *, bus_addr_t);
+#if defined(KGDB)
+void 			xlcom_kgdbinit(void);
+#endif
 #endif
 
 struct consdev 		*cn_tab = NULL;
 bus_space_tag_t 	consdev_iot;
 bus_space_handle_t 	consdev_ioh;
 
+bus_space_tag_t 	kgdb_iot;
+bus_space_handle_t 	kgdb_ioh;
+
 
 /*
  * Initialize the system console (hmm, as if anyone can see those panics).
@@ -68,10 +74,25 @@ consinit(void)
 		return;
 
 	/* Pick MD knowledge about console. */
-	if (virtex_console_tag(CONS_NAME, &consdev_iot))
+	if (virtex_bus_space_tag(CONS_NAME, &consdev_iot))
 		panic("No bus space for %s console", CONS_NAME);
 
+#if defined(KGDB)
+	if (virtex_bus_space_tag(KGDB_NAME, &kgdb_iot))
+		panic("No bus space for %s kgdb", KGDB_NAME);
+#endif
+
 #if NXLCOM > 0
+#if defined(KGDB)
+	if (strncmp("xlcom", KGDB_NAME, 5)) {
+		xlcom_kgdbinit();
+
+		/* Overtake console device, we're higher priority. */
+		if (strcmp(KGDB_NAME, CONS_NAME) == 0 &&
+		    KGDB_ADDR == CONS_ADDR)
+			goto done;
+	}
+#endif
 	if (strncmp("xlcom", CONS_NAME, 5) == 0) {
 		cn_tab = &consdev_xlcom;
 		xlcom_cninit(cn_tab, CONS_ADDR);
@@ -82,5 +103,6 @@ consinit(void)
 
 	panic("No console"); 	/* XXX really panic? */
  done:
+	/* If kgdb overtook console, cn_tab is NULL and dev/cons.c deals. */
 	initted = 1;
 }
Index: evbppc/virtex/design_gsrd1.c
===================================================================
RCS file: /cvsroot/src/sys/arch/evbppc/virtex/design_gsrd1.c,v
retrieving revision 1.1
diff -d -p -u -r1.1 design_gsrd1.c
--- evbppc/virtex/design_gsrd1.c	2 Dec 2006 22:18:47 -0000	1.1
+++ evbppc/virtex/design_gsrd1.c	1 Feb 2007 20:17:03 -0000
@@ -400,7 +400,7 @@ ll_dmac_intr_disestablish(int chan, void
 }
 
 int
-virtex_console_tag(const char *xname, bus_space_tag_t *bst)
+virtex_bus_space_tag(const char *xname, bus_space_tag_t *bst)
 {
 	if (strncmp(xname, "xlcom", 5) == 0) {
 		*bst = &xlcom_bst;
Index: evbppc/virtex/design_gsrd2.c
===================================================================
RCS file: /cvsroot/src/sys/arch/evbppc/virtex/design_gsrd2.c,v
retrieving revision 1.1
diff -d -p -u -r1.1 design_gsrd2.c
--- evbppc/virtex/design_gsrd2.c	2 Dec 2006 22:18:47 -0000	1.1
+++ evbppc/virtex/design_gsrd2.c	1 Feb 2007 20:17:03 -0000
@@ -442,7 +442,7 @@ ll_dmac_intr_disestablish(int chan, void
 }
 
 int
-virtex_console_tag(const char *xname, bus_space_tag_t *bst)
+virtex_bus_space_tag(const char *xname, bus_space_tag_t *bst)
 {
 	if (strncmp(xname, "xlcom", 5) == 0) {
 		*bst = &opb_bst;
Index: evbppc/virtex/machdep.c
===================================================================
RCS file: /cvsroot/src/sys/arch/evbppc/virtex/machdep.c,v
retrieving revision 1.1
diff -d -p -u -r1.1 machdep.c
--- evbppc/virtex/machdep.c	2 Dec 2006 22:18:47 -0000	1.1
+++ evbppc/virtex/machdep.c	1 Feb 2007 20:17:03 -0000
@@ -40,6 +40,7 @@ __KERNEL_RCSID(0, "$NetBSD: machdep.c,v 
 #include "opt_ddb.h"
 #include "opt_ipkdb.h"
 #include "opt_virtex.h"
+#include "opt_kgdb.h"
 
 #include <sys/param.h>
 #include <sys/buf.h>
@@ -81,6 +82,9 @@ __KERNEL_RCSID(0, "$NetBSD: machdep.c,v 
 #include <ddb/db_extern.h>
 #endif
 
+#if defined(KGDB)
+#include <sys/kgdb.h>
+#endif
 
 /*
  * Global variables used here and there
@@ -258,6 +262,12 @@ initppc(u_int startkernel, u_int endkern
 	if (boothowto & RB_KDB)
 		ipkdb_connect(0);
 #endif
+#ifdef KGDB
+	/*
+	 * Now trap to KGDB
+	 */
+	kgdb_connect(1);
+#endif /* KGDB */
 }
 
 /*
@@ -424,6 +434,11 @@ cpu_reboot(int howto, char *what)
 		while(1)
 			Debugger();
 #endif
+#ifdef KGDB
+		printf("dropping to kgdb\n");
+		while(1)
+			kgdb_connect(1);
+#endif
 	}
 
 	printf("rebooting\n\n");
@@ -455,6 +470,10 @@ cpu_reboot(int howto, char *what)
 #ifdef DDB
 	while(1)
 		Debugger();
+#endif
+#ifdef KGDB
+	while(1)
+		kgdb_connect(1);
 #else
 	while (1)
 		/* nothing */;
Index: evbppc/virtex/virtex.h
===================================================================
RCS file: /cvsroot/src/sys/arch/evbppc/virtex/virtex.h,v
retrieving revision 1.1
diff -d -p -u -r1.1 virtex.h
--- evbppc/virtex/virtex.h	2 Dec 2006 22:18:47 -0000	1.1
+++ evbppc/virtex/virtex.h	1 Feb 2007 20:17:03 -0000
@@ -34,8 +34,15 @@
 
 #ifdef _KERNEL_OPT
 #include "opt_cons.h"
+#include "opt_kgdb.h"
 #endif
 
+/*
+ * Console and kgdb name are just private tags for design_<foo>.c
+ * to identify the right device instance. Should be the same as
+ * device_xname() if there's only one UART available, though.
+ */
+
 #ifndef CONS_NAME
 #define CONS_NAME 	"xlcom0"
 #endif
@@ -44,17 +51,36 @@
 #define CONS_ADDR 	0x00
 #endif
 
+#if defined(KGDB)
+
+#ifndef KGDB_NAME
+#define	KGDB_NAME 	CONS_NAME
+#endif
+
+#ifndef KGDB_ADDR
+#define	KGDB_ADDR 	CONS_ADDR
+#endif
+
+#endif /* KGDB */
+
 struct mem_region;
 
-/* Setup console bus space. */
-int 	virtex_console_tag(const char *, bus_space_tag_t *);
+/* Early bus space setup, for console and kgdb. Name is purely symbolic. */
+int 	virtex_bus_space_tag(const char *, bus_space_tag_t *);
 
 /* Called after RAM is linear mapped. Translation & console still off. */
 void 	virtex_machdep_init(vaddr_t, vsize_t, struct mem_region *,
 	    struct mem_region *);
 
-/* For use by console. Tag is initialized before <foo>_cninit. */
-extern bus_space_tag_t 		consdev_iot;
-extern bus_space_handle_t 	consdev_ioh;
+/* For use by console and kgdb. Tag is initialized before <foo>_cninit. */
+extern bus_space_tag_t 		consdev_iot; 	/* consinit.c */
+extern bus_space_handle_t 	consdev_ioh; 	/* console device */
+
+#if defined(KGDB)
+
+extern bus_space_tag_t 		kgdb_iot; 	/* consinit.c */
+extern bus_space_handle_t 	kgdb_ioh; 	/* kgdb device */
+
+#endif /* KGDB */
 
 #endif /*_VIRTEX_H_*/
Index: evbppc/virtex/dev/xlcom.c
===================================================================
RCS file: /cvsroot/src/sys/arch/evbppc/virtex/dev/xlcom.c,v
retrieving revision 1.1
diff -d -p -u -r1.1 xlcom.c
--- evbppc/virtex/dev/xlcom.c	2 Dec 2006 22:18:47 -0000	1.1
+++ evbppc/virtex/dev/xlcom.c	1 Feb 2007 20:17:06 -0000
@@ -29,11 +29,11 @@
  * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
  */
 
-/* TODO: kgdb support */
-
 #include <sys/cdefs.h>
 __KERNEL_RCSID(0, "$NetBSD: xlcom.c,v 1.1 2006/12/02 22:18:47 freza Exp $");
 
+#include "opt_kgdb.h"
+
 #include <sys/param.h>
 #include <sys/systm.h>
 #include <sys/conf.h>
@@ -47,6 +47,10 @@ __KERNEL_RCSID(0, "$NetBSD: xlcom.c,v 1.
 #include <sys/time.h>
 #include <sys/syslog.h>
 
+#if defined(KGDB)
+#include <sys/kgdb.h>
+#endif /* KGDB */
+
 #include <dev/cons.h>
 
 #include <machine/intr.h>
@@ -96,12 +100,22 @@ static int 	xlcom_intr(void *);
 static void 	xlcom_rx_soft(void *);
 static void 	xlcom_tx_soft(void *);
 static void 	xlcom_reset(bus_space_tag_t, bus_space_handle_t);
+static int 	xlcom_busy_getc(bus_space_tag_t, bus_space_handle_t);
+static void 	xlcom_busy_putc(bus_space_tag_t, bus_space_handle_t, int);
 
 /* System console interface. */
 static int 	xlcom_cngetc(dev_t);
 static void 	xlcom_cnputc(dev_t, int);
 void 		xlcom_cninit(struct consdev *);
 
+#if defined(KGDB)
+
+void 		xlcom_kgdbinit(void);
+static void 	xlcom_kgdb_putc(void *, int);
+static int 	xlcom_kgdb_getc(void *);
+
+#endif /* KGDB */
+
 static struct cnm_state 	xlcom_cnm_state;
 
 struct consdev consdev_xlcom = {
@@ -152,6 +166,14 @@ xlcom_attach(struct device *parent, stru
 
 	printf(": UartLite serial port\n");
 
+#if defined(KGDB)
+	/* We don't want to share kgdb port with the user. */
+	if (sc->sc_iot == kgdb_iot && sc->sc_ioh == kgdb_ioh) {
+		printf("%s: already in use by kgdb\n", device_xname(self));
+		return;
+	}
+#endif /* KGDB */
+
 	if ((sc->sc_ih = intr_establish(vaa->vaa_intr, IST_LEVEL, IPL_SERIAL,
 	    xlcom_intr, sc)) == NULL) {
 		printf("%s: could not establish interrupt\n",
@@ -616,6 +638,24 @@ xlcom_reset(bus_space_tag_t iot, bus_spa
 	bus_space_write_4(iot, ioh, XLCOM_CNTL, CNTL_RX_CLEAR | CNTL_TX_CLEAR);
 }
 
+static int
+xlcom_busy_getc(bus_space_tag_t t, bus_space_handle_t h)
+{
+	while (! (bus_space_read_4(t, h, XLCOM_STAT) & STAT_RX_DATA))
+		;
+
+	return (bus_space_read_4(t, h, XLCOM_RX_FIFO));
+}
+
+static void
+xlcom_busy_putc(bus_space_tag_t t, bus_space_handle_t h, int c)
+{
+	while (bus_space_read_4(t, h, XLCOM_STAT) & STAT_TX_FULL)
+		;
+
+	bus_space_write_4(t, h, XLCOM_TX_FIFO, c);
+}
+
 /*
  * Console on UartLite.
  */
@@ -636,20 +676,42 @@ xlcom_cninit(struct consdev *cn)
 static int 
 xlcom_cngetc(dev_t dev)
 {
-	while (! (bus_space_read_4(consdev_iot, consdev_ioh, XLCOM_STAT) &
-	    STAT_RX_DATA))
-		;
-
-	return (bus_space_read_4(consdev_iot, consdev_ioh,
-	    XLCOM_RX_FIFO));
+	return (xlcom_busy_getc(consdev_iot, consdev_ioh));
 }
 
 static void 
 xlcom_cnputc(dev_t dev, int c)
 {
-	while (bus_space_read_4(consdev_iot, consdev_ioh, XLCOM_STAT) &
-	    STAT_TX_FULL)
-		;
+	xlcom_busy_putc(consdev_iot, consdev_ioh, c);
+}
 
-	bus_space_write_4(consdev_iot, consdev_ioh, XLCOM_TX_FIFO, c);
+/*
+ * Remote GDB (aka "kgdb") interface.
+ */
+#if defined(KGDB)
+
+static int
+xlcom_kgdb_getc(void *arg)
+{
+	return (xlcom_busy_getc(kgdb_iot, kgdb_ioh));
 }
+
+static void
+xlcom_kgdb_putc(void *arg, int c)
+{
+	xlcom_busy_putc(kgdb_iot, kgdb_ioh, c);
+}
+
+void
+xlcom_kgdbinit(void)
+{
+	if (bus_space_map(kgdb_iot, KGDB_ADDR, XLCOM_SIZE, 0, &kgdb_ioh))
+		panic("xlcom_kgdbinit: could not map kgdb_ioh");
+
+	xlcom_reset(kgdb_iot, kgdb_ioh);
+
+	kgdb_attach(xlcom_kgdb_getc, xlcom_kgdb_putc, NULL);
+	kgdb_dev = 123; /* arbitrary strictly positive value */
+}
+
+#endif /* KGDB */
Index: powerpc/ibm4xx/trap.c
===================================================================
RCS file: /cvsroot/src/sys/arch/powerpc/ibm4xx/trap.c,v
retrieving revision 1.37
diff -d -p -u -r1.37 trap.c
--- powerpc/ibm4xx/trap.c	5 Oct 2006 14:48:32 -0000	1.37
+++ powerpc/ibm4xx/trap.c	1 Feb 2007 20:17:42 -0000
@@ -71,6 +71,7 @@ __KERNEL_RCSID(0, "$NetBSD: trap.c,v 1.3
 
 #include "opt_altivec.h"
 #include "opt_ddb.h"
+#include "opt_kgdb.h"
 
 #include <sys/param.h>
 #include <sys/proc.h>
@@ -84,6 +85,10 @@ __KERNEL_RCSID(0, "$NetBSD: trap.c,v 1.3
 #include <sys/userret.h>
 #include <sys/kauth.h>
 
+#if defined(KGDB)
+#include <sys/kgdb.h>
+#endif
+
 #include <uvm/uvm_extern.h>
 
 #include <dev/cons.h>
@@ -364,7 +369,7 @@ trap(struct trapframe *frame)
 	default:
  brain_damage:
 		printf("trap type 0x%x at 0x%lx\n", type, frame->srr0);
-#ifdef DDB
+#if defined(DDB) || defined(KGDB)
 		if (kdb_trap(type, frame))
 			goto done;
 #endif
Index: powerpc/ibm4xx/trap_subr.S
===================================================================
RCS file: /cvsroot/src/sys/arch/powerpc/ibm4xx/trap_subr.S,v
retrieving revision 1.10
diff -d -p -u -r1.10 trap_subr.S
--- powerpc/ibm4xx/trap_subr.S	11 Dec 2005 12:18:42 -0000	1.10
+++ powerpc/ibm4xx/trap_subr.S	1 Feb 2007 20:17:44 -0000
@@ -177,7 +177,7 @@ _C_LABEL(extint):
 _C_LABEL(extsize) = .-_C_LABEL(extint)
 
 
-#ifdef DDB
+#if defined(DDB) || defined(KGDB)
 #define	ddbsave	0xde0		/* primary save area for DDB */
 /*
  * In case of DDB we want a separate trap catcher for it
@@ -195,7 +195,7 @@ _C_LABEL(ddblow):
 	addi	1,1,ddbstk+INTSTK@l
 	bla	ddbtrap
 _C_LABEL(ddbsize) = .-_C_LABEL(ddblow)
-#endif	/* DDB */
+#endif	/* DDB || KGDB */
 
 #ifdef IPKDB
 #define	ipkdbsave	0xde0		/* primary save area for IPKDB */
@@ -543,7 +543,7 @@ fitint:
 	bl	_C_LABEL(stat_intr)
 	b	intr_exit
 
-#ifdef DDB
+#if defined(DDB) || defined(KGDB)
 /*
  * Deliberate entry to ddbtrap
  */
@@ -562,7 +562,7 @@ _C_LABEL(ddb_trap):
 	mtsrr0	28
 
 /*
- * Now the ddb trap catching code.
+ * Now the ddb/kgdb trap catching code.
  */
 ddbtrap:
 	FRAME_SETUP(ddbsave)
@@ -586,7 +586,7 @@ ddbleave:
 	FRAME_LEAVE(ddbsave)
 	rfi
 	ba	.	/* Protect against prefetch */
-#endif /* DDB */
+#endif /* DDB || KGDB */
 
 #ifdef IPKDB
 /*
Index: powerpc/powerpc/db_interface.c
===================================================================
RCS file: /cvsroot/src/sys/arch/powerpc/powerpc/db_interface.c,v
retrieving revision 1.36
diff -d -p -u -r1.36 db_interface.c
--- powerpc/powerpc/db_interface.c	24 Dec 2005 22:45:36 -0000	1.36
+++ powerpc/powerpc/db_interface.c	1 Feb 2007 20:17:46 -0000
@@ -36,6 +36,7 @@ __KERNEL_RCSID(0, "$NetBSD: db_interface
 
 #ifdef KGDB
 #include <sys/kgdb.h>
+#define db_printf printf
 #endif
 
 #include <dev/ofw/openfirm.h>
@@ -47,6 +48,7 @@ db_regs_t ddb_regs;
 void ddb_trap(void);				/* Call into trap_subr.S */
 int ddb_trap_glue(struct trapframe *);		/* Called from trap_subr.S */
 #ifdef PPC_IBM4XX
+#ifdef DDB
 static void db_ppc4xx_ctx(db_expr_t, int, db_expr_t, const char *);
 static void db_ppc4xx_pv(db_expr_t, int, db_expr_t, const char *);
 static void db_ppc4xx_reset(db_expr_t, int, db_expr_t, const char *);
@@ -58,6 +60,7 @@ static void db_ppc4xx_mtdcr(db_expr_t, d
 #ifdef USERACC
 static void db_ppc4xx_useracc(db_expr_t, int, db_expr_t, const char *);
 #endif
+#endif /* DDB */
 #endif /* PPC_IBM4XX */
 
 #ifdef DDB
@@ -191,6 +194,7 @@ branch_taken(int inst, db_addr_t pc, db_
 	return (0);
 }
 
+#ifdef DDB
 const struct db_command db_machine_command_table[] = {
 	{ "ctx",	db_ppc4xx_ctx,		0,	0 },
 	{ "pv",		db_ppc4xx_pv,		0,	0 },
@@ -485,4 +489,6 @@ db_ppc4xx_useracc(db_expr_t addr, int ha
 }
 #endif
 
+#endif /* DDB */
+
 #endif /* PPC_IBM4XX */