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<-----