Subject: port-arm/15530: remote kgdb support for NetBSD/evbarm
To: None <gnats-bugs@gnats.netbsd.org>
From: None <bsh@grotto.jp>
List: netbsd-bugs
Date: 02/08/2002 12:33:17
>Number:         15530
>Category:       port-arm
>Synopsis:       remote kgdb support for NetBSD/evbarm
>Confidential:   no
>Severity:       critical
>Priority:       high
>Responsible:    port-arm-maintainer
>State:          open
>Class:          change-request
>Submitter-Id:   net
>Arrival-Date:   Thu Feb 07 19:34:00 PST 2002
>Closed-Date:
>Last-Modified:
>Originator:     Hiroyuki Bessho
>Release:        NetBSD-current 2002-Jan-24
>Organization:
	Genetec corp.
>Environment:
	NetBSD/evbarm 1.5ZA
	cross-compiled on NetBSD/i386 1.5-release 
Target: Intel Lubbock evaluation board with Cotulla application processor
System: NetBSD sawara 1.5.3_ALPHA NetBSD 1.5.3_ALPHA (SAWARA) #0: Fri Dec 14 11:03:13 JST 2001     bsh@kamasu.a.grotto.jp:/amd/nekozame/root/u1/proj/netbsd/release/sys/arch/i386/compile/SAWARA i386
Architecture: arm
Machine: evbarm
>Description:
	NetBSD/arm doesn't support remote kernel debug over serial line.
>How-To-Repeat:
	compile NetBSD/evbarm kernel with options KGDB.
>Fix:
	Here is a patch.

	You also need to
	  1. initialize an appropriate serial port for remtoe connection.
	  2. call kgdb_connect().
 	in initarm().

Index: sys/arch/arm/arm/undefined.c
diff -u sys/arch/arm/arm/undefined.c:1.1.1.4 sys/arch/arm/arm/undefined.c:1.3
--- sys/arch/arm/arm/undefined.c:1.1.1.4	Mon Jan  7 19:01:07 2002
+++ sys/arch/arm/arm/undefined.c	Fri Feb  1 14:23:22 2002
@@ -48,8 +48,12 @@
 
 #include "opt_cputypes.h"
 #include "opt_ddb.h"
+#include "opt_kgdb.h"
 
 #include <sys/param.h>
+#ifdef KGDB
+#include <sys/kgdb.h>
+#endif
 
 __KERNEL_RCSID(0, "$NetBSD: undefined.c,v 1.12 2001/12/20 01:20:22 thorpej Exp $");
 
@@ -122,11 +126,14 @@
 static int
 gdb_trapper(u_int addr, u_int insn, struct trapframe *frame, int code)
 {
-
-	if ((insn == GDB_BREAKPOINT || insn == GDB5_BREAKPOINT) &&
-	    code == FAULT_USER) {
-		trapsignal(curproc, SIGTRAP, 0);
-		return 0;
+	if (insn == GDB_BREAKPOINT || insn == GDB5_BREAKPOINT){
+		if( code == FAULT_USER) {
+			trapsignal(curproc, SIGTRAP, 0);
+			return 0;
+		}
+#ifdef KGDB
+		return !kgdb_trap( T_BREAKPOINT, frame );
+#endif
 	}
 	return 1;
 }
@@ -233,6 +240,8 @@
 		/* Fault has not been handled */
 		
 #ifdef VERBOSE_ARM32
+		int s;
+
 		s = spltty();
 
 		if ((fault_instruction & 0x0f000010) == 0x0e000000) {
Index: sys/arch/arm/arm32/db_interface.c
diff -u sys/arch/arm/arm32/db_interface.c:1.1.1.8 sys/arch/arm/arm32/db_interface.c:1.2
--- sys/arch/arm/arm32/db_interface.c:1.1.1.8	Wed Jan 30 03:56:03 2002
+++ sys/arch/arm/arm32/db_interface.c	Thu Jan 31 20:47:24 2002
@@ -34,6 +34,7 @@
  * Interface to new debugger.
  */
 #include "opt_ddb.h"
+#include "opt_kgdb.h"
 
 #include <sys/param.h>
 #include <sys/proc.h>
@@ -55,6 +56,11 @@
 #include <ddb/db_interface.h>
 #include <dev/cons.h>
 
+#ifdef KGDB
+#define db_printf printf
+#endif
+extern void hex_led(int,int);
+
 static int nil;
 
 int db_access_und_sp __P((const struct db_variable *, db_expr_t *, int));
@@ -122,6 +128,7 @@
 	return(0);
 }
 
+#ifdef DDB
 /*
  *  kdb_trap - field a TRACE or BPT trap
  */
@@ -158,9 +165,9 @@
 
 	return (1);
 }
-
+#endif
 
-static int
+int
 db_validate_address(vaddr_t addr)
 {
 	struct proc *p = curproc;
@@ -312,6 +319,7 @@
 	asm(".word	0xe7ffffff");
 }
 
+#ifdef DDB
 const struct db_command db_machine_command_table[] = {
 	{ "frame",	db_show_frame_cmd,	0, NULL },
 	{ "panic",	db_show_panic_cmd,	0, NULL },
@@ -374,6 +382,8 @@
 	db_uh.uh_handler = db_trapper;
 	install_coproc_handler_static(0, &db_uh);
 }
+
+#endif
 
 u_int
 db_fetch_reg(int reg, db_regs_t *db_regs)
Index: sys/arch/arm/arm32/fault.c
diff -u sys/arch/arm/arm32/fault.c:1.1.1.5 sys/arch/arm/arm32/fault.c:1.2
--- sys/arch/arm/arm32/fault.c:1.1.1.5	Thu Jan 17 13:01:18 2002
+++ sys/arch/arm/arm32/fault.c	Thu Jan 31 20:47:50 2002
@@ -44,6 +44,7 @@
  */
 
 #include "opt_ddb.h"
+#include "opt_kgdb.h"
 #include "opt_pmap_debug.h"
 
 #include <sys/types.h>
@@ -62,6 +63,11 @@
 #ifdef DDB
 #include <machine/db_machdep.h>
 #endif
+#ifdef KGDB
+#include <machine/db_machdep.h>
+#include <sys/kgdb.h>
+#define kdb_trap kgdb_trap
+#endif
 
 #include <arch/arm/arm/disassem.h>
 #include <arm/arm32/machdep.h>
@@ -382,14 +388,13 @@
 		 * Were are dead, try and provide some debug
 		 * information before dying.
 		 */
-#ifdef DDB
+#if defined(DDB) || defined(KGDB)
 		printf("Unhandled trap (frame = %p)\n", frame);
 		report_abort(NULL, fault_status, fault_address, fault_pc);
 		kdb_trap(-1, frame);
 		return;
-#else
 		panic("Unhandled trap (frame = %p)", frame);
-#endif	/* DDB */
+#endif	/* DDB||KGDB */
           
 	case FAULT_TRANS_P:              /* Page Translation Fault */
 	case FAULT_PERM_P:		 /* Page Permission Fault */
@@ -486,14 +491,14 @@
 			goto out;
 
 		if (current_intr_depth > 0) {
-#ifdef DDB
+#if defined(DDB)||defined(KGDB)
 			printf("Non-emulated page fault with intr_depth > 0\n");
 			report_abort(NULL, fault_status, fault_address, fault_pc);
 			kdb_trap(-1, frame);
 			return;
 #else
 			panic("Fault with intr_depth > 0");
-#endif	/* DDB */
+#endif	/* DDB||KGDB */
 		}
 
 		onfault = pcb->pcb_onfault;
Index: sys/arch/arm/arm32/kgdb_machdep.c
diff -u /dev/null sys/arch/arm/arm32/kgdb_machdep.c:1.2
--- /dev/null	Thu Feb  7 14:57:24 2002
+++ sys/arch/arm/arm32/kgdb_machdep.c	Wed Feb  6 18:18:54 2002
@@ -0,0 +1,180 @@
+/* $Id: kgdb_machdep.c,v 1.2 2002/02/06 09:18:54 bsh Exp $ */
+
+/*
+ *  Copyright (C) 2002, Hiroyuki Bessho, Genetec corp.
+ */
+
+#include "opt_ddb.h"
+#include "opt_kgdb.h"
+
+#if defined(DDB)
+#error "Can't build DDB and KGDB together."
+#endif
+
+#include <sys/param.h>
+#include <sys/kgdb.h>
+#include <sys/systm.h>
+
+#include <uvm/uvm_extern.h>
+
+#if 0
+#include <machine/pte.h>
+#else
+#include <arm/arm32/pte.h>
+#endif
+#include <machine/reg.h>
+#include <machine/trap.h>
+
+/*
+ * Trap into kgdb to wait for debugger to connect,
+ * noting on the console why nothing else is going on.
+ */
+void
+kgdb_connect(verbose)
+	int verbose;
+{
+	if (kgdb_dev < 0)
+		return;
+
+	if (verbose)
+		printf("kgdb waiting...");
+
+	asm( ".word 0xe6000011" );
+
+	if (verbose)
+		printf("connected.\n");
+
+	kgdb_debug_panic = 1;
+}
+
+/*
+ * Translate a trap number into a unix compatible signal value.
+ * (gdb only understands unix signal numbers).
+ */
+int
+kgdb_signal(type)
+	int type;
+{
+	switch (type) {
+	case T_BREAKPOINT:
+	    return SIGTRAP;
+	case -1:
+	    return SIGSEGV;
+	default:
+	    return SIGINT;
+	}
+}
+
+/*
+ * Translate the values stored in the kernel regs struct to the format
+ * understood by gdb.
+ */
+void
+kgdb_getregs(regs, gdb_regs)
+	db_regs_t *regs;
+	kgdb_reg_t *gdb_regs;
+{
+	gdb_regs[ 0] = regs->tf_r0;
+	gdb_regs[ 1] = regs->tf_r1;
+	gdb_regs[ 2] = regs->tf_r2;
+	gdb_regs[ 3] = regs->tf_r3;
+	gdb_regs[ 4] = regs->tf_r4;
+	gdb_regs[ 5] = regs->tf_r5;
+	gdb_regs[ 6] = regs->tf_r6;
+	gdb_regs[ 7] = regs->tf_r7;
+	gdb_regs[ 8] = regs->tf_r8;
+	gdb_regs[ 9] = regs->tf_r9;
+	gdb_regs[10] = regs->tf_r10;
+	gdb_regs[11] = regs->tf_r11;
+	gdb_regs[12] = regs->tf_r12;
+#if 1
+	gdb_regs[13] = regs->tf_svc_sp;
+	gdb_regs[14] = regs->tf_svc_lr;
+#else
+	gdb_regs[13] = regs->tf_usr_sp;
+	gdb_regs[14] = regs->tf_usr_lr;
+#endif
+	gdb_regs[15] = regs->tf_pc;
+
+#ifdef DEBUG_KGDB
+	{
+		int i;
+		for( i =0; i < 7; ++i ){
+			gdb_regs[16+3*i+0] = 0xDEAD0000 + (i<<8) + 0;
+			gdb_regs[16+3*i+1] = 0xDEAD0000 + (i<<8) + 1;
+			gdb_regs[16+3*i+2] = 0xDEAD0000 + (i<<8) + 2;
+		}
+		gdb_regs[16+3*8] = 0xDEADFFFF;
+	}
+#endif
+	gdb_regs[16+3*8+1] = regs->tf_spsr;
+}
+
+/*
+ * Reverse the above.
+ */
+void
+kgdb_setregs(regs, gdb_regs)
+	db_regs_t *regs;
+	kgdb_reg_t *gdb_regs;
+{
+	regs->tf_r0 = gdb_regs[ 0];
+	regs->tf_r1 = gdb_regs[ 1];
+	regs->tf_r2 = gdb_regs[ 2];
+	regs->tf_r3 = gdb_regs[ 3];
+	regs->tf_r4 = gdb_regs[ 4];
+	regs->tf_r5 = gdb_regs[ 5];
+	regs->tf_r6 = gdb_regs[ 6];
+	regs->tf_r7 = gdb_regs[ 7];
+	regs->tf_r8 = gdb_regs[ 8];
+	regs->tf_r9 = gdb_regs[ 9];
+	regs->tf_r10 = gdb_regs[10];
+	regs->tf_r11 = gdb_regs[11];
+	regs->tf_r12 = gdb_regs[12];
+
+#if 1
+	regs->tf_svc_sp = gdb_regs[13];
+	regs->tf_svc_lr = gdb_regs[14];
+#else
+	regs->tf_usr_sp = gdb_regs[13];
+	regs->tf_usr_sp = gdb_regs[14];
+#endif
+	regs->tf_spsr = gdb_regs[16+3*8+1];
+}
+
+
+/*
+ * Determine if the memory at va..(va+len) is valid.
+ */
+int
+kgdb_acc(va, len)
+	vaddr_t va;
+	size_t len;
+{
+	vaddr_t last_va;
+
+	last_va = va + len;
+	va  &= ~PGOFSET;
+	last_va &= ~PGOFSET;
+
+	do {
+		if( db_validate_address(va) )
+			return 0;
+		va  += NBPG;
+	} while (va < last_va);
+
+	return (1);
+}
+
+/*
+ * Decide what to do on panic.
+ * (This is called by panic, like Debugger())
+ */
+void
+kgdb_panic()
+{
+	if (kgdb_dev >= 0 && kgdb_debug_panic) {
+		printf("entering kgdb\n");
+		kgdb_connect(kgdb_active == 0);
+	}
+}
Index: sys/arch/arm/conf/files.arm
diff -u sys/arch/arm/conf/files.arm:1.1.1.15 sys/arch/arm/conf/files.arm:1.2
--- sys/arch/arm/conf/files.arm:1.1.1.15	Wed Jan 30 03:56:05 2002
+++ sys/arch/arm/conf/files.arm	Thu Jan 31 20:49:09 2002
@@ -27,9 +27,10 @@
 
 # DDB
 file	arch/arm/arm/db_disasm.c		ddb
-file	arch/arm/arm32/db_interface.c		ddb & arm32
+file	arch/arm/arm32/db_interface.c		(ddb|kgdb) & arm32
 file	arch/arm/arm/db_trace.c			ddb
 file	arch/arm/arm32/db_machdep.c		ddb & arm32
+file	arch/arm/arm32/kgdb_machdep.c		kgdb & arm32
 
 # FIQ support
 file	arch/arm/arm/fiq.c
Index: sys/arch/arm/include/db_machdep.h
diff -u sys/arch/arm/include/db_machdep.h:1.1.1.2 sys/arch/arm/include/db_machdep.h:1.2
--- sys/arch/arm/include/db_machdep.h:1.1.1.2	Tue Nov 27 13:52:46 2001
+++ sys/arch/arm/include/db_machdep.h	Thu Jan 31 20:50:29 2002
@@ -102,6 +102,7 @@
 u_int branch_taken __P((u_int insn, u_int pc, db_regs_t *db_regs));
 int kdb_trap __P((int, db_regs_t *));
 void db_machine_init __P((void));
+int db_validate_address(vm_offset_t addr);
 
 #ifdef __ELF__
 #define DB_ELF_SYMBOLS
@@ -109,5 +110,13 @@
 #else
 #define	DB_AOUT_SYMBOLS
 #endif
+
+/*
+ * kgdb
+ */
+typedef register_t  kgdb_reg_t;
+#define KGDB_NUMREGS	(16+8*3+2) /* r0..r15, f0..f7, fps, cpsr
+				      fp-registers are 12-byte wide */
+#define KGDB_BUFLEN	1024
 
 #endif	/* _ARM_DB_MACHDEP_H_ */
>Release-Note:
>Audit-Trail:
>Unformatted: