Skip to contentSkip to conversation

implement KGDB on Toshiba RBTX4927, 2.6.24-rc7

PATCH In review Frank Rowand 3 participants 10 messages Jan 15, 2008 – Jan 18, 2008 MIPS

lore
Share & tools
lore
#1 lore raw

PATCH 1/4 early_printk

From: Frank Rowand <[email protected]>

Implement early printk in the serial_txx9 driver, and enable for the Toshiba RBTX4927 board. This is needed for the connect to GDB console message.

---

 arch/mips/Kconfig                                          |    1 	1 +	0 -	0 !
 arch/mips/tx4927/toshiba_rbtx4927/toshiba_rbtx4927_setup.c |    6 	6 +	0 -	0 !
 drivers/serial/serial_txx9.c                               |   39 	39 +	0 -	0 !
 3 files changed, 46 insertions(+)
arch/mips/Kconfig +1 -0
Index: linux-2.6.24-rc7/arch/mips/Kconfig
===================================================================
@@ -631,6 +631,7 @@ config TOSHIBA_RBTX4927
 	select I8259 if TOSHIBA_FPCIB0
 	select SWAP_IO_SPACE
 	select SYS_HAS_CPU_TX49XX
+	select SYS_HAS_EARLY_PRINTK
 	select SYS_SUPPORTS_32BIT_KERNEL
 	select SYS_SUPPORTS_64BIT_KERNEL
 	select SYS_SUPPORTS_LITTLE_ENDIAN
drivers/serial/serial_txx9.c +39 -0
Index: linux-2.6.24-rc7/drivers/serial/serial_txx9.c
===================================================================
@@ -1198,6 +1198,45 @@ MODULE_DEVICE_TABLE(pci, serial_txx9_pci
 
 static struct platform_device *serial_txx9_plat_devs;
 
+#ifdef CONFIG_EARLY_PRINTK
+
+/*
+ * Do NOT request the console resources, allows normal driver to initialize
+ * console later.
+ */
+
+static int prom_putchar_port = -1;
+
+void early_printk_serial_txx9_console_setup(void)
+{
+	prom_putchar_port = 0;
+}
+
+void prom_putchar(char ch)
+{
+	unsigned int status;
+	struct uart_txx9_port *up;
+
+	if (prom_putchar_port == -1)
+		return;
+
+	up = &serial_txx9_ports[prom_putchar_port];
+
+	if (ch == '\n')
+		prom_putchar('\r');
+
+	while (1) {
+		status = sio_in(up, TXX9_SICISR);
+		if (status & TXX9_SICISR_TRDY) {
+			sio_out(up, TXX9_SITFIFO, (u32)ch);
+			break;
+		}
+	}
+}
+
+#endif
+
+
 static int __init serial_txx9_init(void)
 {
 	int ret;
arch/mips/tx4927/toshiba_rbtx4927/toshiba_rbtx4927_setup.c +6 -0
Index: linux-2.6.24-rc7/arch/mips/tx4927/toshiba_rbtx4927/toshiba_rbtx4927_setup.c
===================================================================
@@ -913,6 +913,12 @@ void __init toshiba_rbtx4927_setup(void)
         if (strstr(argptr, "console=") == NULL) {
                 strcat(argptr, " console=ttyS0,38400");
         }
+#ifdef CONFIG_EARLY_PRINTK
+	{
+		extern void early_printk_serial_txx9_console_setup(void);
+		early_printk_serial_txx9_console_setup();
+	}
+#endif
 #endif
 #endif
 
#2 lore raw

Re: [PATCH 1/4] early_printk

Quoted 10 lines · Frank Rowand

Implement early printk in the serial_txx9 driver, and enable for the Toshiba RBTX4927 board. This is needed for the connect to GDB console message.

---

 arch/mips/Kconfig                                          |    1 	1 +	0 -	0 !
 arch/mips/tx4927/toshiba_rbtx4927/toshiba_rbtx4927_setup.c |    6 	6 +	0 -	0 !
 drivers/serial/serial_txx9.c                               |   39 	39 +	0 -	0 !
 3 files changed, 46 insertions(+)

Please do not add MIPS local prom_putchar() to the serial_txx9 driver. This driver is used on some powerpc platform too.

---
Atsushi Nemoto

#3 lore raw

PATCH 2/4 kgdb on not SMP

In reply to Frank Rowand

From: Frank Rowand <[email protected]>

Fix gdb-stub.c compile warning for non-SMP systems (which becomes compile error due to -Werror).

---
arch/mips/kernel/gdb-stub.c | 2 2 + 0 - 0 !

 1 files changed, 2 insertions(+)
arch/mips/kernel/gdb-stub.c +2 -0
Index: linux-2.6.24-rc5/arch/mips/kernel/gdb-stub.c
===================================================================
@@ -656,6 +656,7 @@ void set_async_breakpoint(unsigned long 
 	*epc = (unsigned long)async_breakpoint;
 }
 
+#ifdef CONFIG_SMP
 static void kgdb_wait(void *arg)
 {
 	unsigned flags;
@@ -668,6 +669,7 @@ static void kgdb_wait(void *arg)
 
 	local_irq_restore(flags);
 }
+#endif
 
 /*
  * GDB stub needs to call kgdb_wait on all processor with interrupts
#4 lore raw

PATCH 3/4 serial_txx9 driver support

In reply to Frank Rowand

From: Frank Rowand <[email protected]>

Add polled debug driver support to serial_txx9.c for kgdb, and initialize the driver for the Toshiba RBTX4927.

---
arch/mips/tx4927/toshiba_rbtx4927/toshiba_rbtx4927_setup.c | 6 6 + 0 - 0 !
drivers/serial/serial_txx9.c | 90 90 + 0 - 0 !

 2 files changed, 96 insertions(+)
drivers/serial/serial_txx9.c +90 -0
Index: linux-2.6.24-rc7/drivers/serial/serial_txx9.c
===================================================================
@@ -1237,6 +1237,96 @@ void prom_putchar(char ch)
 #endif
 
 
+/******************************************************************************/
+/* BEG: KDBG Routines                                                         */
+/******************************************************************************/
+
+#ifdef CONFIG_KGDB
+int kgdb_initialized;
+
+void txx9_sio_kgdb_hook(unsigned int port, unsigned int baud_rate)
+{
+	static struct resource kgdb_resource;
+	int ret;
+	struct uart_txx9_port *up = &serial_txx9_ports[port];
+
+	/* prevent initialization by driver */
+	kgdb_resource.name = "serial_txx9(debug)";
+	kgdb_resource.start = (resource_size_t)up->port.membase;
+	kgdb_resource.end = (resource_size_t)up->port.membase + 36 - 1;
+	kgdb_resource.flags = IORESOURCE_MEM | IORESOURCE_BUSY;
+
+	ret = request_resource(&iomem_resource, &kgdb_resource);
+	if (ret == -EBUSY)
+		printk(KERN_ERR
+			"txx9_sio_kgdb_hook(): request_resource failed\n");
+
+	return;
+}
+void
+txx9_sio_kdbg_init(unsigned int port_number)
+{
+	if (port_number == 1) {
+		txx9_sio_kgdb_hook(port_number, 38400);
+		kgdb_initialized = 1;
+	} else {
+		printk(KERN_ERR
+			"txx9_sio_kdbg_init(): Bad Port Number [%u] != [1]\n",
+			port_number);
+	}
+
+	return;
+}
+
+u8
+txx9_sio_kdbg_rd(void)
+{
+	unsigned int status, ch;
+	struct uart_txx9_port *up = &serial_txx9_ports[1];
+
+	if (!kgdb_initialized)
+		return 0;
+
+	while (1) {
+		status = sio_in(up, TXX9_SIDISR);
+		if (status & 0x1f) {
+			ch = sio_in(up, TXX9_SIRFIFO);
+			break;
+		}
+	}
+
+	return ch;
+}
+
+int
+txx9_sio_kdbg_wr(u8 ch)
+{
+	unsigned int status;
+	struct uart_txx9_port *up = &serial_txx9_ports[1];
+
+	if (!kgdb_initialized)
+		return 0;
+
+	while (1) {
+		status = sio_in(up, TXX9_SICISR);
+		if (status & TXX9_SICISR_TRDY) {
+			if (ch == '\n')
+				txx9_sio_kdbg_wr('\r');
+			sio_out(up, TXX9_SITFIFO, (u32)ch);
+
+			break;
+		}
+	}
+
+	return 1;
+}
+#endif /* CONFIG_KGDB */
+
+
+/******************************************************************************/
+/* END: KDBG Routines                                                         */
+/******************************************************************************/
+
 static int __init serial_txx9_init(void)
 {
 	int ret;
arch/mips/tx4927/toshiba_rbtx4927/toshiba_rbtx4927_setup.c +6 -0
Index: linux-2.6.24-rc7/arch/mips/tx4927/toshiba_rbtx4927/toshiba_rbtx4927_setup.c
===================================================================
@@ -919,6 +919,12 @@ void __init toshiba_rbtx4927_setup(void)
 		early_printk_serial_txx9_console_setup();
 	}
 #endif
+#ifdef CONFIG_KGDB
+	{
+		extern void txx9_sio_kdbg_init(unsigned int port_number);
+		txx9_sio_kdbg_init(1);
+	}
+#endif
 #endif
 #endif
 
#5 lore raw

Re: [PATCH 3/4] serial_txx9 driver support

Quoted 2 lines · Frank Rowand

Add polled debug driver support to serial_txx9.c for kgdb, and initialize the driver for the Toshiba RBTX4927.

I think Jason Wessel's kgdb patchset is a way to go.

Anyway, some comments below.

Quoted 1 line

+int kgdb_initialized;

Should be static.

Quoted 1 line

+void txx9_sio_kgdb_hook(unsigned int port, unsigned int baud_rate)

Should be static. The baud_rate is not used.

Quoted 4 lines
drivers/serial/serial_txx9.c +4 -0
+void
+txx9_sio_kdbg_init(unsigned int port_number)
+{
+	if (port_number == 1) {

drivers/serial/serial_txx9.c void prom_putchar(char ch) · line 1279

Quoted 10 lines
drivers/serial/serial_txx9.c +10 -0
+		txx9_sio_kgdb_hook(port_number, 38400);
+		kgdb_initialized = 1;
+	} else {
+		printk(KERN_ERR
+			"txx9_sio_kdbg_init(): Bad Port Number [%u] != [1]\n",
+			port_number);
+	}
+
+	return;
+}

Why port_number other than 1 is bad?

The "return" at the end of the function is redundant.

drivers/serial/serial_txx9.c void prom_putchar(char ch) · line 1285

Quoted 5 lines
drivers/serial/serial_txx9.c +5 -0
+u8
+txx9_sio_kdbg_rd(void)
+{
+	unsigned int status, ch;
+	struct uart_txx9_port *up = &serial_txx9_ports[1];

Oh this assumes port number 1. The gdb port number should be customizable.

drivers/serial/serial_txx9.c void prom_putchar(char ch) · line 1315

Quoted 1 line
drivers/serial/serial_txx9.c +1 -0
+			sio_out(up, TXX9_SITFIFO, (u32)ch);

The cast is not needed.

---
Atsushi Nemoto

#6 lore raw

Re: [PATCH 3/4] serial_txx9 driver support

Quoted 5 lines · Atsushi Nemoto
Quoted 2 lines · Frank Rowand

Add polled debug driver support to serial_txx9.c for kgdb, and initialize the driver for the Toshiba RBTX4927.

I think Jason Wessel's kgdb patchset is a way to go.

Somehow I overlooked Jason's patchset. Yes, I agree that is the way to go, so my four patches should not be applied. Thanks for bringing that to my attention.

-Frank

#7 lore raw

Re: [PATCH 3/4] serial_txx9 driver support

Hello Frank. :-)

Quoted 6 lines
Quoted 4 lines
Quoted 2 lines

Add polled debug driver support to serial_txx9.c for kgdb, and initialize the driver for the Toshiba RBTX4927.

I think Jason Wessel's kgdb patchset is a way to go.

Somehow I overlooked Jason's patchset. Yes, I agree that is the way to go,

BTW, that patchset already has TX[34]9xx KGDB serial driver...

Quoted 1 line

so my four patches should not be applied.

Well, it's not in the mainline yet anyway...

Quoted 1 line

-Frank

WBR, Sergei

#8 lore raw

Re: [PATCH 3/4] serial_txx9 driver support

In reply to Frank Rowand
Quoted 10 lines · Frank Rowand

From: Frank Rowand <[email protected]>

Add polled debug driver support to serial_txx9.c for kgdb, and initialize the driver for the Toshiba RBTX4927.

---
arch/mips/tx4927/toshiba_rbtx4927/toshiba_rbtx4927_setup.c | 6 6 + 0 - 0 !
drivers/serial/serial_txx9.c | 90 90 + 0 - 0 !

 2 files changed, 96 insertions(+)

Just for the record... original attribution is very important.

I meant to mention in the original email, but I overlooked it, that the serial_txx9.c code is mostly from the kgdb patch version 2.4 at
http://kgdb.linsyssoft.com/downloads.htm with a few slight changes. The code is attributed to Ralf in the comments at the head of that patch file. I suspect that Ralf recognized his code when I first sent it to him :-).

-Frank

#9 lore raw

PATCH 4/4 invoke kgdb via magic sysrq

In reply to Frank Rowand

From: Frank Rowand <[email protected]>

Add hooks so that the host can connect to KGDB or asynchronously invoke an already connected KGDB via a magic sysrq. This should work for most MIPS targets that support KGDB, though it has only been tested on the Toshiba RBTX4927. This can be useful to invoke an already connected KGDB for some types of system hang. It also allows normally booting without connecting to KGDB, then later connecting to KGDB if kernel debugging is desired.

This functionality exists for PowerPC and sh.

---
arch/mips/kernel/gdb-stub.c | 26 26 + 0 - 0 !

 1 files changed, 26 insertions(+)
arch/mips/kernel/gdb-stub.c +26 -0
Index: linux-2.6.24-rc7/arch/mips/kernel/gdb-stub.c
===================================================================
@@ -131,6 +131,7 @@
 #include <linux/spinlock.h>
 #include <linux/slab.h>
 #include <linux/reboot.h>
+#include <linux/sysrq.h>
 
 #include <asm/asm.h>
 #include <asm/cacheflush.h>
@@ -1154,3 +1155,28 @@ static int __init register_gdb_console(v
 console_initcall(register_gdb_console);
 
 #endif
+
+#ifdef CONFIG_MAGIC_SYSRQ
+static void sysrq_handle_gdb(int key, struct tty_struct *tty)
+{
+	if (!initialized) {
+		printk(KERN_ALERT "Wait for gdb client connection ...\n");
+		set_debug_traps();
+	}
+
+	breakpoint();
+}
+static struct sysrq_key_op sysrq_gdb_op = {
+	.handler        = sysrq_handle_gdb,
+	.help_msg       = "Gdb",
+	.action_msg     = "GDB",
+};
+
+static int gdb_register_sysrq(void)
+{
+	printk(KERN_INFO "Registering GDB sysrq handler\n");
+	register_sysrq_key('g', &sysrq_gdb_op);
+	return 0;
+}
+module_init(gdb_register_sysrq);
+#endif