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: