Skip to contentSkip to conversation

A different KGDB stub

PATCH In review Tom Rini 2 participants 2 messages Feb 12, 2004 PowerPC

lore
Share & tools
lore

Tom Rini

author
#0 lore raw

PATCH 5/6 A different KGDB stub

The following is the ppc32-specific bits to this KGDB stub.

 arch/ppc/8260_io/uart.c          |   23 
 arch/ppc/Kconfig                 |   46 -
 arch/ppc/kernel/entry.S          |   69 ++
 arch/ppc/kernel/irq.c            |   13 
 arch/ppc/kernel/ppc-stub.c       |  998 ++++++++-------------------------------
 arch/ppc/kernel/setup.c          |   16 
 arch/ppc/mm/fault.c              |   14 
 arch/ppc/platforms/lopec_setup.c |   44 -
 arch/ppc/platforms/pmac_setup.c  |    3 
 arch/ppc/platforms/prep_setup.c  |    5 
 arch/ppc/platforms/sandpoint.c   |   36 -
 arch/ppc/syslib/gen550_dbg.c     |   23 
 arch/ppc/syslib/gen550_kgdb.c    |    2 
 include/asm-ppc/kgdb.h           |   18 
 include/asm-ppc/processor.h      |    3 
 15 files changed, 389 insertions(+), 924 deletions(-)
arch/ppc/8260_io/uart.c +18 -5
@@ -40,6 +40,7 @@
 #include <linux/slab.h>
 #include <linux/init.h>
 #include <linux/delay.h>
+#include <linux/kgdb.h>
 #include <asm/uaccess.h>
 #include <asm/immap_8260.h>
 #include <asm/mpc8260.h>
@@ -391,8 +392,21 @@
 		status = bdp->cbd_sc;
 #ifdef CONFIG_KGDB
 		if (info->state->smc_scc_num == KGDB_SER_IDX) {
-			if (*cp == 0x03 || *cp == '$')
-				breakpoint();
+			while (i-- > 0) {
+				if (*cp == 0x03) {
+					breakpoint();
+					return;
+				}
+				if (*cp == '$') {
+					atomic_set(&kgdb_might_be_resumed, 1);
+					breakpoint();
+					atomic_set(&kgdb_might_be_resumed, 0);
+					return;
+				}
+				cp++;
+			}
+			bdp->cbd_sc |= BD_SC_EMPTY;
+			bdp->cbd_sc &= ~(BD_SC_BR | BD_SC_FR | BD_SC_PR | BD_SC_OV);
 			return;
 		}
 #endif
@@ -2274,9 +2288,8 @@
 static void serial_console_write(struct console *c, const char *s,
 				unsigned count)
 {
-#if defined(CONFIG_KGDB_CONSOLE) && !defined(CONFIG_USE_SERIAL2_KGDB)
-	/* Try to let stub handle output. Returns true if it did. */
-	if (kgdb_output_string(s, count))
+#ifdef CONFIG_KGDB
+	if (kgdb_initialized)
 		return;
 #endif
 	my_console_write(c->index, s, count);
arch/ppc/Kconfig +10 -36

64 lines not on this page · raw message

arch/ppc/kernel/entry.S +66 -3

93 lines not on this page · raw message

arch/ppc/kernel/irq.c +12 -1
@@ -46,6 +46,7 @@
 #include <linux/random.h>
 #include <linux/seq_file.h>
 #include <linux/cpumask.h>
+#include <linux/kgdb.h>
 
 #include <asm/uaccess.h>
 #include <asm/bitops.h>
@@ -513,6 +514,14 @@
 void do_IRQ(struct pt_regs *regs)
 {
 	int irq, first = 1;
+#if 0
+	unsigned long *lrptr;
+	if (!(regs->msr & MSR_PR)) {
+		/* Came in from the kernel. Save call link. */
+		lrptr = (unsigned long *)(regs->gpr[1] + 4);
+		*lrptr = regs->nip;
+	}
+#endif
         irq_enter();
 
 	/*
@@ -530,7 +539,9 @@
 	if (irq != -2 && first)
 		/* That's not SMP safe ... but who cares ? */
 		ppc_spurious_interrupts++;
-        irq_exit();
+	irq_exit();
+
+	kgdb_process_breakpoint();
 }
 
 unsigned long probe_irq_on (void)
arch/ppc/kernel/ppc-stub.c +225 -773

1,082 lines not on this page · raw message

arch/ppc/kernel/setup.c +0 -16
@@ -38,10 +38,6 @@
 #include <asm/nvram.h>
 #include <asm/xmon.h>
 
-#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);
@@ -641,18 +637,6 @@
 		xmon(0);
 #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.
arch/ppc/mm/fault.c +13 -1
@@ -28,6 +28,7 @@
 #include <linux/interrupt.h>
 #include <linux/highmem.h>
 #include <linux/module.h>
+#include <linux/debugger.h>
 
 #include <asm/page.h>
 #include <asm/pgtable.h>
@@ -139,6 +140,13 @@
 		bad_page_fault(regs, address, SIGSEGV);
 		return;
 	}
+
+	if (debugger_memerr_expected) {
+		/* This fault was caused by memory access through a debugger.
+		 * Don't handle it like user accesses */
+		goto no_context;
+	}
+
 	down_read(&mm->mmap_sem);
 	vma = find_vma(mm, address);
 	if (!vma)
@@ -293,6 +301,7 @@
 		return;
 	}
 
+no_context:
 	bad_page_fault(regs, address, SIGSEGV);
 	return;
 
@@ -342,10 +351,13 @@
 	}
 
 	/* kernel has accessed a bad area */
-#if defined(CONFIG_XMON) || defined(CONFIG_KGDB)
+#if defined(CONFIG_XMON)
 	if (debugger_kernel_faults)
 		debugger(regs);
 #endif
+
+	CHK_DEBUGGER(14, sig,0, regs,)
+
 	die("kernel access of bad area", regs, sig);
 }
 
arch/ppc/platforms/lopec_setup.c +5 -39

62 lines not on this page · raw message

arch/ppc/platforms/pmac_setup.c +0 -3
@@ -297,9 +297,6 @@
 			ppc_override_l2cr_value, (ppc_override_l2cr_value & 0x80000000)
 				? "enabled" : "disabled");
 
-#ifdef CONFIG_KGDB
-	zs_kgdb_hook(0);
-#endif
 
 #ifdef CONFIG_ADB_CUDA
 	find_via_cuda();
arch/ppc/platforms/prep_setup.c +5 -0
@@ -58,6 +58,7 @@
 #include <asm/i8259.h>
 #include <asm/open_pic.h>
 #include <asm/pci-bridge.h>
+#include <asm/kgdb.h>
 
 unsigned char ucSystemType;
 unsigned char ucBoardRev;
@@ -1176,6 +1177,10 @@
 	}
 
 	ppc_md.setup_io_mappings = prep_map_io;
+
+#ifdef CONFIG_SERIAL_TEXT_DEBUG
+	ppc_md.progress = gen550_progress;
+#endif
 
 #if defined(CONFIG_BLK_DEV_IDE) || defined(CONFIG_BLK_DEV_IDE_MODULE)
 	ppc_ide_md.default_irq = prep_ide_default_irq;
arch/ppc/platforms/sandpoint.c +0 -36
@@ -252,38 +252,6 @@
 	return;
 }
 
-#if defined(CONFIG_SERIAL_8250) && \
-	(defined(CONFIG_KGDB) || defined(CONFIG_SERIAL_TEXT_DEBUG))
-static void __init
-sandpoint_early_serial_map(void)
-{
-	struct uart_port serial_req;
-
-	/* Setup serial port access */
-	memset(&serial_req, 0, sizeof(serial_req));
-	serial_req.uartclk = UART_CLK;
-	serial_req.irq = 4;
-	serial_req.flags = STD_COM_FLAGS;
-	serial_req.iotype = SERIAL_IO_MEM;
-	serial_req.membase = (u_char *)SANDPOINT_SERIAL_0;
-
-	gen550_init(0, &serial_req);
-
-	if (early_serial_setup(&serial_req) != 0)
-		printk(KERN_ERR "Early serial init of port 0 failed\n");
-
-	/* Assume early_serial_setup() doesn't modify serial_req */
-	serial_req.line = 1;
-	serial_req.irq = 3; /* XXXX */
-	serial_req.membase = (u_char *)SANDPOINT_SERIAL_1;
-
-	gen550_init(1, &serial_req);
-
-	if (early_serial_setup(&serial_req) != 0)
-		printk(KERN_ERR "Early serial init of port 1 failed\n");
-}
-#endif
-
 static void __init
 sandpoint_setup_arch(void)
 {
@@ -701,15 +669,11 @@
 	ppc_md.nvram_read_val = todc_mc146818_read_val;
 	ppc_md.nvram_write_val = todc_mc146818_write_val;
 
-#if defined(CONFIG_SERIAL_8250) && \
-	(defined(CONFIG_KGDB) || defined(CONFIG_SERIAL_TEXT_DEBUG))
-	sandpoint_early_serial_map();
 #ifdef CONFIG_KGDB
 	ppc_md.kgdb_map_scc = gen550_kgdb_map_scc;
 #endif
 #ifdef CONFIG_SERIAL_TEXT_DEBUG
 	ppc_md.progress = gen550_progress;
-#endif
 #endif
 
 #if defined(CONFIG_BLK_DEV_IDE) || defined(CONFIG_BLK_DEV_IDE_MODULE)
arch/ppc/syslib/gen550_dbg.c +19 -4
@@ -27,7 +27,19 @@
 #include <asm/serial.h>
 #include <asm/io.h>
 
-#define SERIAL_BAUD	9600
+#ifdef CONFIG_KGDB_9600BAUD
+#define SERIAL_BAUD 9600
+#elif defined(CONFIG_KGDB_19200BAUD)
+#define SERIAL_BAUD 19200
+#elif defined(CONFIG_KGDB_38400BAUD)
+#define SERIAL_BAUD 38400
+#elif defined(CONFIG_KGDB_57600BAUD)
+#define SERIAL_BAUD 57600
+#elif defined(CONFIG_KGDB_115200BAUD)
+#define SERIAL_BAUD 115200
+#else /* default to 9600 */
+#define SERIAL_BAUD 9600
+#endif
 
 static struct serial_state rs_table[RS_TABLE_SIZE] = {
 	SERIAL_PORT_DFNS	/* defined in <asm/serial.h> */
@@ -109,12 +121,15 @@
 		serial_outb(com_port + (UART_DLM << shift),
 				(rs_table[chan].baud_base / SERIAL_BAUD) >> 8);
 		/* 8 data, 1 stop, no parity */
-		serial_outb(com_port + (UART_LCR << shift), 0x03);
+		serial_outb(com_port + (UART_LCR << shift), UART_LCR_WLEN8);
 		/* RTS/DTR */
-		serial_outb(com_port + (UART_MCR << shift), 0x03);
+		serial_outb(com_port + (UART_MCR << shift),
+				UART_MCR_RTS | UART_MCR_DTR);
 
 		/* Clear & enable FIFOs */
-		serial_outb(com_port + (UART_FCR << shift), 0x07);
+		serial_outb(com_port + (UART_FCR << shift),
+				UART_FCR_ENABLE_FIFO | UART_FCR_TRIGGER_1 |
+				UART_FCR_CLEAR_XMIT | UART_FCR_CLEAR_RCVR);
 	}
 
 	return (com_port);
arch/ppc/syslib/gen550_kgdb.c +1 -1
@@ -74,7 +74,7 @@
 
 /*
  * Note: gen550_init() must be called already on the port we are going
- * to use.
+ * to use, or <asm/serial.h> must provide static definitions.
  */
 void
 gen550_kgdb_map_scc(void)
include/asm-ppc/kgdb.h +12 -6
@@ -2,6 +2,8 @@
  * kgdb.h: Defines and declarations for serial line source level
  *         remote debugging of the Linux kernel using gdb.
  *
+ * PPC Mods (C) 2004 Tom Rini ([email protected])
+ * PPC Mods (C) 2003 John Whitney ([email protected])
  * PPC Mods (C) 1998 Michael Tesch ([email protected])
  *
  * Copyright (C) 1995 David S. Miller ([email protected])
@@ -12,6 +14,16 @@
 
 #ifndef __ASSEMBLY__
 
+#define BREAK_INSTR_SIZE	4
+#define MAXREG			(PT_FPSCR+1)
+#define NUMREGBYTES		(MAXREG * sizeof(int))
+#define BUFMAX			((NUMREGBYTES * 2) + 512)
+#define OUTBUFMAX		((NUMREGBYTES * 2) + 512)
+#define PC_REGNUM		64
+#define SP_REGNUM		1
+#define PTRACE_PC		nip	/* Program Counter, in ptrace regs. */
+#define BREAKPOINT()		asm(".long 0x7d821008") /* twge r2, r2 */
+
 /* Things specific to the gen550 backend. */
 struct uart_port;
 
@@ -21,12 +33,6 @@
 
 /* Things specific to the pmac backend. */
 extern void zs_kgdb_hook(int tty_num);
-
-/* To init the kgdb engine. (called by serial hook)*/
-extern void set_debug_traps(void);
-
-/* To enter the debugger explicitly. */
-extern void breakpoint(void);
 
 /* For taking exceptions
  * these are defined in traps.c
include/asm-ppc/processor.h +3 -0
@@ -119,6 +119,9 @@
 	unsigned long	vrsave;
 	int		used_vr;	/* set if process has used altivec */
 #endif /* CONFIG_ALTIVEC */
+#ifdef CONFIG_KGDB
+	void		*debuggerinfo;
+#endif
 };
 
 #define INIT_SP		(sizeof(init_stack) + (unsigned long) &init_stack)
Signature · 2 lines
Tom Rini
http://gate.crashing.org/~trini/
#1 lore raw
Quoted 1 line · Tom Rini

The following is the ppc32-specific bits to this KGDB stub.

<snip>

arch/ppc/kernel/ppc-stub.c line 36

Quoted 9 lines
arch/ppc/kernel/ppc-stub.c +7 -2
-	/* We are dorking with a live trap table, all irqs off */
-}
+	unsigned int tt;		/* Trap type code for powerpc */
+	unsigned char signo;		/* Signal that we map this trap into */
+} hard_trap_info[] = {
+#if defined(CONFIG_40x)
+	{ 0x0100, 0x02 /* SIGINT */  },		/* critical input interrupt */
+	{ 0x0200, 0x0b /* SIGSEGV */ },		/* machine check */
+	{ 0x0300, 0x0b /* SIGSEGV */ },		/* data storage */

This table should be at least CONFIG_4xx and probably (CONFIG_4xx || CONFIG_BOOKE) if/when e500 support comes into 2.6.

-Matt