Subject: Re: arm32 kernel crashes
To: Edwin Foo <efoo@crl.dec.com>
From: Charles M. Hannum <root@ihack.net>
List: port-arm32
Date: 12/14/1998 07:28:55
A few things:
1) You might want to check what time the overnight crashes occur. If
it's during the nightly scripts, you might be able to reproduce the
problem.
2) Without a stack trace (`db> t') and register dump (`db> show reg'),
it's basically impossible to deduce what's going on. At the very
least, you can use `nm -n' on the (SAME!) kernel to determine what
routine is at address 0xf00e9514.
3) Todd Whitesel's problem was due to a short-lived bug, and is
already fixed. So it certainly isn't the same thing.
4) The following patch cleans up a few things in the ARM DDB, and
should make it stop in the debugger where a bad fault was taken,
rather than putting more crap on the stack by calling Debugger().
You should also be able to continue from a fault by typing `c'.
(Note: I haven't tested this yet.)
-----8<-----snip-----8<-----snip-----8<-----snip-----8<-----snip-----8<-----
Index: arm32/db_interface.c
===================================================================
RCS file: /cvsroot/src/sys/arch/arm32/arm32/db_interface.c,v
retrieving revision 1.25
diff -c -2 -r1.25 db_interface.c
*** db_interface.c 1998/11/25 13:09:14 1.25
--- db_interface.c 1998/12/14 12:22:22
***************
*** 63,85 ****
struct db_variable db_regs[] = {
! { "spsr", (long *)&DDB_TF->tf_spsr, FCN_NULL, },
! { "r0", (long *)&DDB_TF->tf_r0, FCN_NULL, },
! { "r1", (long *)&DDB_TF->tf_r1, FCN_NULL, },
! { "r2", (long *)&DDB_TF->tf_r2, FCN_NULL, },
! { "r3", (long *)&DDB_TF->tf_r3, FCN_NULL, },
! { "r4", (long *)&DDB_TF->tf_r4, FCN_NULL, },
! { "r5", (long *)&DDB_TF->tf_r5, FCN_NULL, },
! { "r6", (long *)&DDB_TF->tf_r6, FCN_NULL, },
! { "r7", (long *)&DDB_TF->tf_r7, FCN_NULL, },
! { "r8", (long *)&DDB_TF->tf_r8, FCN_NULL, },
! { "r9", (long *)&DDB_TF->tf_r9, FCN_NULL, },
! { "r10", (long *)&DDB_TF->tf_r10, FCN_NULL, },
! { "r11", (long *)&DDB_TF->tf_r11, FCN_NULL, },
! { "r12", (long *)&DDB_TF->tf_r12, FCN_NULL, },
! { "usr_sp", (long *)&DDB_TF->tf_usr_sp, FCN_NULL, },
! { "usr_lr", (long *)&DDB_TF->tf_usr_lr, FCN_NULL, },
! { "svc_sp", (long *)&DDB_TF->tf_svc_sp, FCN_NULL, },
! { "svc_lr", (long *)&DDB_TF->tf_svc_lr, FCN_NULL, },
! { "pc", (long *)&DDB_TF->tf_pc, FCN_NULL, },
{ "und_sp", (long *)&nil, db_access_und_sp, },
{ "abt_sp", (long *)&nil, db_access_abt_sp, },
--- 63,85 ----
struct db_variable db_regs[] = {
! { "spsr", (long *)&DDB_REGS->tf_spsr, FCN_NULL, },
! { "r0", (long *)&DDB_REGS->tf_r0, FCN_NULL, },
! { "r1", (long *)&DDB_REGS->tf_r1, FCN_NULL, },
! { "r2", (long *)&DDB_REGS->tf_r2, FCN_NULL, },
! { "r3", (long *)&DDB_REGS->tf_r3, FCN_NULL, },
! { "r4", (long *)&DDB_REGS->tf_r4, FCN_NULL, },
! { "r5", (long *)&DDB_REGS->tf_r5, FCN_NULL, },
! { "r6", (long *)&DDB_REGS->tf_r6, FCN_NULL, },
! { "r7", (long *)&DDB_REGS->tf_r7, FCN_NULL, },
! { "r8", (long *)&DDB_REGS->tf_r8, FCN_NULL, },
! { "r9", (long *)&DDB_REGS->tf_r9, FCN_NULL, },
! { "r10", (long *)&DDB_REGS->tf_r10, FCN_NULL, },
! { "r11", (long *)&DDB_REGS->tf_r11, FCN_NULL, },
! { "r12", (long *)&DDB_REGS->tf_r12, FCN_NULL, },
! { "usr_sp", (long *)&DDB_REGS->tf_usr_sp, FCN_NULL, },
! { "usr_lr", (long *)&DDB_REGS->tf_usr_lr, FCN_NULL, },
! { "svc_sp", (long *)&DDB_REGS->tf_svc_sp, FCN_NULL, },
! { "svc_lr", (long *)&DDB_REGS->tf_svc_lr, FCN_NULL, },
! { "pc", (long *)&DDB_REGS->tf_pc, FCN_NULL, },
{ "und_sp", (long *)&nil, db_access_und_sp, },
{ "abt_sp", (long *)&nil, db_access_abt_sp, },
***************
*** 127,133 ****
*/
int
! kdb_trap(type, tf)
! int type;
! register struct trapframe *tf;
{
int s;
--- 127,133 ----
*/
int
! kdb_trap(type, regs)
! int type;
! db_regs_t *regs;
{
int s;
***************
*** 147,152 ****
/* Should switch to kdb`s own stack here. */
! ddb_regs.ddb_tf = *tf;
! ddb_regs.ddb_tf.tf_pc -= INSN_SIZE;
s = splhigh();
--- 147,151 ----
/* Should switch to kdb`s own stack here. */
! ddb_regs = *regs;
s = splhigh();
***************
*** 158,164 ****
splx(s);
! *tf = ddb_regs.ddb_tf;
! return(1);
}
--- 157,163 ----
splx(s);
! *regs = ddb_regs;
! return (1);
}
***************
*** 168,177 ****
*/
void
! kdb_kbd_trap(tf)
! struct trapframe *tf;
{
if (db_active == 0 && (boothowto & RB_KDB)) {
printf("\n\nkernel: keyboard interrupt\n");
! kdb_trap(-1, tf);
}
}
--- 167,176 ----
*/
void
! kdb_kbd_trap(regs)
! db_regs_t *regs;
{
if (db_active == 0 && (boothowto & RB_KDB)) {
printf("\n\nkernel: keyboard interrupt\n");
! kdb_trap(-1, regs);
}
}
***************
*** 335,346 ****
{
if (fault_code == 0) {
if ((inst & ~INSN_COND_MASK) == (BKPT_INST & ~INSN_COND_MASK))
kdb_trap(T_BREAKPOINT, frame);
else
! panic("Undefined instruction 0x%08x @ 0x%08x in kernel\n",
! inst, addr);
} else
! return(1);
! return(0);
}
--- 334,345 ----
{
if (fault_code == 0) {
+ frame->tf_pc -= INSN_SIZE;
if ((inst & ~INSN_COND_MASK) == (BKPT_INST & ~INSN_COND_MASK))
kdb_trap(T_BREAKPOINT, frame);
else
! kdb_trap(-1, frame);
} else
! return (1);
! return (0);
}
***************
*** 388,422 ****
switch (reg) {
case 0:
! return (db_regs->ddb_tf.tf_r0);
case 1:
! return (db_regs->ddb_tf.tf_r1);
case 2:
! return (db_regs->ddb_tf.tf_r2);
case 3:
! return (db_regs->ddb_tf.tf_r3);
case 4:
! return (db_regs->ddb_tf.tf_r4);
case 5:
! return (db_regs->ddb_tf.tf_r5);
case 6:
! return (db_regs->ddb_tf.tf_r6);
case 7:
! return (db_regs->ddb_tf.tf_r7);
case 8:
! return (db_regs->ddb_tf.tf_r8);
case 9:
! return (db_regs->ddb_tf.tf_r9);
case 10:
! return (db_regs->ddb_tf.tf_r10);
case 11:
! return (db_regs->ddb_tf.tf_r11);
case 12:
! return (db_regs->ddb_tf.tf_r12);
case 13:
! return (db_regs->ddb_tf.tf_svc_sp);
case 14:
! return (db_regs->ddb_tf.tf_svc_lr);
case 15:
! return (db_regs->ddb_tf.tf_pc);
default:
panic("db_fetch_reg: botch");
--- 387,421 ----
switch (reg) {
case 0:
! return (db_regs->tf_r0);
case 1:
! return (db_regs->tf_r1);
case 2:
! return (db_regs->tf_r2);
case 3:
! return (db_regs->tf_r3);
case 4:
! return (db_regs->tf_r4);
case 5:
! return (db_regs->tf_r5);
case 6:
! return (db_regs->tf_r6);
case 7:
! return (db_regs->tf_r7);
case 8:
! return (db_regs->tf_r8);
case 9:
! return (db_regs->tf_r9);
case 10:
! return (db_regs->tf_r10);
case 11:
! return (db_regs->tf_r11);
case 12:
! return (db_regs->tf_r12);
case 13:
! return (db_regs->tf_svc_sp);
case 14:
! return (db_regs->tf_svc_lr);
case 15:
! return (db_regs->tf_pc);
default:
panic("db_fetch_reg: botch");
Index: arm32/db_trace.c
===================================================================
RCS file: /cvsroot/src/sys/arch/arm32/arm32/db_trace.c,v
retrieving revision 1.7
diff -c -2 -r1.7 db_trace.c
*** db_trace.c 1997/10/14 10:12:04 1.7
--- db_trace.c 1998/12/14 12:22:22
***************
*** 66,70 ****
if (!have_addr)
! frame = (struct frame *)(DDB_TF->tf_r11
- (sizeof(struct frame) - sizeof(u_int)));
else
--- 66,70 ----
if (!have_addr)
! frame = (struct frame *)(DDB_REGS->tf_r11
- (sizeof(struct frame) - sizeof(u_int)));
else
Index: arm32/fault.c
===================================================================
RCS file: /cvsroot/src/sys/arch/arm32/arm32/fault.c,v
retrieving revision 1.33
diff -c -2 -r1.33 fault.c
*** fault.c 1998/09/22 01:40:28 1.33
--- fault.c 1998/12/14 12:22:23
***************
*** 67,70 ****
--- 67,73 ----
#include <machine/pte.h>
#include <machine/irqhandler.h>
+ #ifdef DDB
+ #include <machine/db_machdep.h>
+ #endif
#include <arm32/arm32/disassem.h>
***************
*** 175,183 ****
printf("Fault with intr_depth > 0\n");
report_abort(NULL, fault_status, fault_address, fault_pc);
! printf("Instruction @V%08x = %08x\n",
! fault_pc, fault_instruction);
! Debugger();
#else
! panic("Fault with intr_depth > 0\n");
#endif /* DDB */
}
--- 178,185 ----
printf("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 */
}
***************
*** 330,335 ****
* infomation before dying
*/
! panic("Halting (frame = %p)\n", frame);
! break;
case FAULT_PERM_S: /* Section Permission Fault */
--- 332,343 ----
* infomation before dying
*/
! #ifdef DDB
! 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 */
case FAULT_PERM_S: /* Section Permission Fault */
***************
*** 339,346 ****
* If this happens from SVC mode then we are in trouble.
*/
! if (user == 0) {
! report_abort(NULL, fault_status, fault_address, fault_pc);
! panic("Halting (frame = %p)\n", frame);
! }
report_abort("", fault_status, fault_address, fault_pc);
trapsignal(p, SIGSEGV, TRAP_CODE);
--- 347,353 ----
* If this happens from SVC mode then we are in trouble.
*/
! if (user == 0)
! goto we_re_toast;
!
report_abort("", fault_status, fault_address, fault_pc);
trapsignal(p, SIGSEGV, TRAP_CODE);
***************
*** 404,410 ****
}
! report_abort(NULL, fault_status, fault_address,
! fault_pc);
! panic("permission fault in kernel by kernel\n");
} else
map = &vm->vm_map;
--- 411,415 ----
}
! goto we_re_toast;
} else
map = &vm->vm_map;
Index: include/db_machdep.h
===================================================================
RCS file: /cvsroot/src/sys/arch/arm32/include/db_machdep.h,v
retrieving revision 1.11
diff -c -2 -r1.11 db_machdep.h
*** db_machdep.h 1998/11/25 13:58:49 1.11
--- db_machdep.h 1998/12/14 12:22:25
***************
*** 46,58 ****
typedef long db_expr_t; /* expression - signed */
! typedef struct {
! trapframe_t ddb_tf;
! } db_regs_t;
db_regs_t ddb_regs; /* register state */
#define DDB_REGS (&ddb_regs)
- #define DDB_TF (&ddb_regs.ddb_tf)
! #define PC_REGS(regs) ((db_addr_t)(regs)->ddb_tf.tf_pc)
#define BKPT_INST (KERNEL_BREAKPOINT) /* breakpoint instruction */
--- 46,55 ----
typedef long db_expr_t; /* expression - signed */
! typedef trapframe_t db_regs_t;
db_regs_t ddb_regs; /* register state */
#define DDB_REGS (&ddb_regs)
! #define PC_REGS(regs) ((db_addr_t)(regs)->tf_pc)
#define BKPT_INST (KERNEL_BREAKPOINT) /* breakpoint instruction */
***************
*** 60,64 ****
#define BKPT_SET(inst) (BKPT_INST)
! /*#define FIXUP_PC_AFTER_BREAK(regs) ((regs)->ddb_tf.tf_pc -= BKPT_SIZE)*/
#define T_BREAKPOINT (1)
--- 57,61 ----
#define BKPT_SET(inst) (BKPT_INST)
! /*#define FIXUP_PC_AFTER_BREAK(regs) ((regs)->tf_pc -= BKPT_SIZE)*/
#define T_BREAKPOINT (1)
***************
*** 99,102 ****
--- 96,100 ----
u_int branch_taken __P((u_int insn, u_int pc, db_regs_t *db_regs));
+ int kdb_trap __P((int, db_regs_t *));
/*
-----8<-----snip-----8<-----snip-----8<-----snip-----8<-----snip-----8<-----