Module Name:    src
Committed By:   matt
Date:           Mon Feb 13 08:13:42 UTC 2012

Modified Files:
        src/sys/arch/mips/include [matt-nb5-mips64]: cpu.h locore.h
        src/sys/arch/mips/mips [matt-nb5-mips64]: mips_emul.c mips_machdep.c
            trap.c

Log Message:
Fix emulation to not panic when it encounters something it doesn't like.
(so running crashme won't crash the system).
Centralize the trapsignal processing so we can print out the trap info if
so desired.
Add a machdep.printfataltraps sysctl knob.


To generate a diff of this commit:
cvs rdiff -u -r1.90.16.41 -r1.90.16.42 src/sys/arch/mips/include/cpu.h
cvs rdiff -u -r1.78.36.1.2.32 -r1.78.36.1.2.33 \
    src/sys/arch/mips/include/locore.h
cvs rdiff -u -r1.14.78.13 -r1.14.78.14 src/sys/arch/mips/mips/mips_emul.c
cvs rdiff -u -r1.205.4.1.2.1.2.63 -r1.205.4.1.2.1.2.64 \
    src/sys/arch/mips/mips/mips_machdep.c
cvs rdiff -u -r1.217.12.41 -r1.217.12.42 src/sys/arch/mips/mips/trap.c

Please note that diffs are not public domain; they are subject to the
copyright notices on the relevant files.

Modified files:

Index: src/sys/arch/mips/include/cpu.h
diff -u src/sys/arch/mips/include/cpu.h:1.90.16.41 src/sys/arch/mips/include/cpu.h:1.90.16.42
--- src/sys/arch/mips/include/cpu.h:1.90.16.41	Sat Jan 28 00:56:34 2012
+++ src/sys/arch/mips/include/cpu.h	Mon Feb 13 08:13:41 2012
@@ -163,6 +163,7 @@ struct cpu_info {
 #define CPU_BOOTED_KERNEL	2	/* string: booted kernel name */
 #define CPU_ROOT_DEVICE		3	/* string: root device name */
 #define CPU_LLSC		4	/* OS/CPU supports LL/SC instruction */
+#define CPU_PRINTFATALTRAPS	5	/* bool: print fatal traps */
 
 /*
  * Platform can override, but note this breaks userland compatibility

Index: src/sys/arch/mips/include/locore.h
diff -u src/sys/arch/mips/include/locore.h:1.78.36.1.2.32 src/sys/arch/mips/include/locore.h:1.78.36.1.2.33
--- src/sys/arch/mips/include/locore.h:1.78.36.1.2.32	Thu Feb  9 20:01:21 2012
+++ src/sys/arch/mips/include/locore.h	Mon Feb 13 08:13:41 2012
@@ -42,6 +42,13 @@ struct trapframe;
 void	trap(uint32_t, uint32_t, vaddr_t, vaddr_t, struct trapframe *);
 void	ast(void);
 
+/*
+ * Perform a trapsignal, and if cpu_printfataltraps is true, print the trap info
+ * to the console.
+ */
+extern bool cpu_printfataltraps;
+void cpu_trapsignal(struct lwp *, ksiginfo_t *, struct trapframe *);
+
 void	mips_fpu_trap(vaddr_t, struct trapframe *);
 void	mips_fpu_intr(vaddr_t, struct trapframe *);
 

Index: src/sys/arch/mips/mips/mips_emul.c
diff -u src/sys/arch/mips/mips/mips_emul.c:1.14.78.13 src/sys/arch/mips/mips/mips_emul.c:1.14.78.14
--- src/sys/arch/mips/mips/mips_emul.c:1.14.78.13	Fri Apr 29 08:26:28 2011
+++ src/sys/arch/mips/mips/mips_emul.c	Mon Feb 13 08:13:42 2012
@@ -1,4 +1,4 @@
-/*	$NetBSD: mips_emul.c,v 1.14.78.13 2011/04/29 08:26:28 matt Exp $ */
+/*	$NetBSD: mips_emul.c,v 1.14.78.14 2012/02/13 08:13:42 matt Exp $ */
 
 /*
  * Copyright (c) 1999 Shuichiro URATA.  All rights reserved.
@@ -27,7 +27,7 @@
  */
 
 #include <sys/cdefs.h>
-__KERNEL_RCSID(0, "$NetBSD: mips_emul.c,v 1.14.78.13 2011/04/29 08:26:28 matt Exp $");
+__KERNEL_RCSID(0, "$NetBSD: mips_emul.c,v 1.14.78.14 2012/02/13 08:13:42 matt Exp $");
 
 #include <sys/param.h>
 #include <sys/systm.h>
@@ -43,9 +43,10 @@ __KERNEL_RCSID(0, "$NetBSD: mips_emul.c,
 #include <mips/vmparam.h>			/* for VM_MAX_ADDRESS */
 #include <mips/trap.h>
 
-static inline void	send_sigsegv(intptr_t, uint32_t, struct trapframe *,
-			    uint32_t);
-static inline void	update_pc(struct trapframe *, uint32_t);
+static void	send_sigsegv(intptr_t, uint32_t, struct trapframe *, uint32_t);
+static void	send_sigill(intptr_t, uint32_t, struct trapframe *, uint32_t,
+		    uint32_t);
+static void	update_pc(struct trapframe *, uint32_t);
 
 /*
  * MIPS2 LL instruction emulation state
@@ -78,9 +79,11 @@ mips_emul_branch(struct trapframe *tf, v
 			nextpc = tf->tf_regs[inst.RType.rs];
 		else if (allowNonBranch)
 			nextpc = instpc + 4;
-		else
-			panic("%s: %s instruction %08x at pc 0x%"PRIxVADDR,
-			    __func__, "non-branch", inst.word, instpc);
+		else {
+			send_sigill(instpc, T_RES_INST, tf,
+			    tf->tf_regs[_R_CAUSE], inst.word);
+			nextpc = instpc;
+		}
 		break;
 
 	case OP_BCOND:
@@ -106,8 +109,10 @@ mips_emul_branch(struct trapframe *tf, v
 			break;
 
 		default:
-			panic("%s: %s instruction 0x%08x at pc 0x%"PRIxVADDR,
-			    __func__, "bad branch", inst.word, instpc);
+			send_sigill(instpc, T_RES_INST, tf,
+			    tf->tf_regs[_R_CAUSE], inst.word);
+			nextpc = instpc;
+			break;
 		}
 		break;
 
@@ -161,16 +166,22 @@ mips_emul_branch(struct trapframe *tf, v
 		}
 		else if (allowNonBranch)
 			nextpc = instpc + 4;
-		else
-			panic("%s: %s instruction 0x%08x at pc 0x%"PRIxVADDR,
-			    __func__, "bad COP1 branch", inst.word, instpc);
+		else {
+			send_sigill(instpc, T_RES_INST, tf,
+			    tf->tf_regs[_R_CAUSE], inst.word);
+			nextpc = instpc;
+		}
 		break;
 
 	default:
-		if (!allowNonBranch)
-			panic("%s: %s instruction 0x%08x at pc 0x%"PRIxVADDR,
-			    __func__, "non-branch", inst.word, instpc);
-		nextpc = instpc + 4;
+		if (__predict_false(!allowNonBranch)) {
+			send_sigill(instpc, T_RES_INST, tf,
+			    tf->tf_regs[_R_CAUSE], inst.word);
+			nextpc = instpc;
+		} else {
+			nextpc = instpc + 4;
+		}
+		break;
 	}
 	KASSERT((nextpc & 0x3) == 0);
 	return nextpc;
@@ -185,8 +196,6 @@ mips_emul_inst(uint32_t status, uint32_t
     struct trapframe *tf)
 {
 	uint32_t inst;
-	ksiginfo_t ksi;
-	int code = ILL_ILLOPC;
 
 	/*
 	 *  Fetch the instruction.
@@ -232,28 +241,17 @@ mips_emul_inst(uint32_t status, uint32_t
 	case OP_SDC1:
 #if defined(FPEMUL)
 		mips_emul_sdc1(inst, tf, cause);
-		break;
 #else
-		code = ILL_COPROC;
-		/* FALLTHROUGH */
+		send_sigill(opc, T_COP_UNUSABLE, tf, cause, inst);
 #endif
+		break;
 	default:
-#ifdef DEBUG
-		printf("pid %d (%s): trap: bad insn @ %#"PRIxVADDR" cause %#x insn %#x code %d\n", curproc->p_pid, curproc->p_comm, opc, cause, inst, code);
-#endif
-		tf->tf_regs[_R_CAUSE] = cause;
-		tf->tf_regs[_R_BADVADDR] = opc;
-		KSI_INIT_TRAP(&ksi);
-		ksi.ksi_signo = SIGILL;
-		ksi.ksi_trap = cause; /* XXX */
-		ksi.ksi_code = code;
-		ksi.ksi_addr = (void *)opc;
-		(*curproc->p_emul->e_trapsignal)(curlwp, &ksi);
+		send_sigill(opc, T_RES_INST, tf, cause, inst);
 		break;
 	}
 }
 
-static inline void
+static void
 send_sigsegv(intptr_t vaddr, uint32_t exccode, struct trapframe *tf,
     uint32_t cause)
 {
@@ -266,7 +264,23 @@ send_sigsegv(intptr_t vaddr, uint32_t ex
 	ksi.ksi_trap = cause;
 	ksi.ksi_code = SEGV_MAPERR;
 	ksi.ksi_addr = (void *)vaddr;
-	(*curproc->p_emul->e_trapsignal)(curlwp, &ksi);
+	cpu_trapsignal(curlwp, &ksi, tf);
+}
+
+static void
+send_sigill(intptr_t vaddr, uint32_t exccode, struct trapframe *tf,
+    uint32_t cause, uint32_t inst)
+{
+	ksiginfo_t ksi;
+	cause = (cause & ~0xFF) | (exccode << MIPS_CR_EXC_CODE_SHIFT);
+	tf->tf_regs[_R_CAUSE] = cause;
+	tf->tf_regs[_R_BADVADDR] = vaddr;
+	KSI_INIT_TRAP(&ksi);
+	ksi.ksi_signo = SIGILL;
+	ksi.ksi_trap = cause; /* XXX */
+	ksi.ksi_code = (exccode == T_COP_UNUSABLE ? ILL_COPROC : ILL_ILLOPC);
+	ksi.ksi_addr = (void *)vaddr;
+	cpu_trapsignal(curlwp, &ksi, tf);
 }
 
 static inline void
@@ -371,7 +385,6 @@ mips_emul_swc0(uint32_t inst, struct tra
 void
 mips_emul_special(uint32_t inst, struct trapframe *tf, uint32_t cause)
 {
-	ksiginfo_t ksi;
 	const InstFmt instfmt = { .word = inst };
 
 	switch (instfmt.RType.func) {
@@ -379,15 +392,8 @@ mips_emul_special(uint32_t inst, struct 
 		/* nothing */
 		break;
 	default:
-		tf->tf_regs[_R_CAUSE] = cause;
-		tf->tf_regs[_R_BADVADDR] = tf->tf_regs[_R_PC];
-		KSI_INIT_TRAP(&ksi);
-		ksi.ksi_signo = SIGILL;
-		ksi.ksi_trap = cause;
-		ksi.ksi_code = ILL_ILLOPC;
-		ksi.ksi_addr = (void *)(intptr_t)tf->tf_regs[_R_PC];
-		(*curproc->p_emul->e_trapsignal)(curlwp, &ksi);
-		break;
+		send_sigill(tf->tf_regs[_R_PC], T_RES_INST, tf, cause, inst);
+		return;
 	}
 
 	update_pc(tf, cause);
@@ -396,7 +402,6 @@ mips_emul_special(uint32_t inst, struct 
 void
 mips_emul_special3(uint32_t inst, struct trapframe *tf, uint32_t cause)
 {
-	ksiginfo_t ksi;
 	const InstFmt instfmt = { .word = inst };
 	switch (instfmt.RType.func) {
 	case OP_RDHWR:
@@ -408,14 +413,7 @@ mips_emul_special3(uint32_t inst, struct
 		}
 		/* FALLTHROUGH */
 	default:
-		tf->tf_regs[_R_CAUSE] = cause;
-		tf->tf_regs[_R_BADVADDR] = tf->tf_regs[_R_PC];
-		KSI_INIT_TRAP(&ksi);
-		ksi.ksi_signo = SIGILL;
-		ksi.ksi_trap = cause;
-		ksi.ksi_code = ILL_ILLOPC;
-		ksi.ksi_addr = (void *)(intptr_t)tf->tf_regs[_R_PC];
-		(*curproc->p_emul->e_trapsignal)(curlwp, &ksi);
+		send_sigill(tf->tf_regs[_R_PC], T_RES_INST, tf, cause, inst);
 		return;
 	}
 

Index: src/sys/arch/mips/mips/mips_machdep.c
diff -u src/sys/arch/mips/mips/mips_machdep.c:1.205.4.1.2.1.2.63 src/sys/arch/mips/mips/mips_machdep.c:1.205.4.1.2.1.2.64
--- src/sys/arch/mips/mips/mips_machdep.c:1.205.4.1.2.1.2.63	Thu Feb  9 03:14:45 2012
+++ src/sys/arch/mips/mips/mips_machdep.c	Mon Feb 13 08:13:42 2012
@@ -1758,6 +1758,11 @@ SYSCTL_SETUP(sysctl_machdep_setup, "sysc
                        CTLTYPE_INT, "llsc", NULL,
                        NULL, MIPS_HAS_LLSC, NULL, 0,
                        CTL_MACHDEP, CPU_LLSC, CTL_EOL);
+	sysctl_createv(clog, 0, NULL, NULL,
+		       CTLFLAG_PERMANENT|CTLFLAG_READWRITE,
+		       CTLTYPE_INT, "printfataltraps", NULL,
+		       NULL, 0, &cpu_printfataltraps, 0,
+		       CTL_MACHDEP, CPU_PRINTFATALTRAPS, CTL_EOL);
 }
 
 /*

Index: src/sys/arch/mips/mips/trap.c
diff -u src/sys/arch/mips/mips/trap.c:1.217.12.41 src/sys/arch/mips/mips/trap.c:1.217.12.42
--- src/sys/arch/mips/mips/trap.c:1.217.12.41	Thu Feb  9 03:10:05 2012
+++ src/sys/arch/mips/mips/trap.c	Mon Feb 13 08:13:42 2012
@@ -120,6 +120,8 @@ const char * const trap_names[] = {
 	"r4000 virtual coherency data",
 };
 
+bool cpu_printfataltraps;
+
 void trap(uint32_t, uint32_t, vaddr_t, vaddr_t, struct trapframe *);
 void ast(void);
 
@@ -628,21 +630,7 @@ trap(uint32_t status, uint32_t cause, va
 	}
 	utf->tf_regs[_R_CAUSE] = cause;
 	utf->tf_regs[_R_BADVADDR] = vaddr;
-#if defined(DEBUG)
-	printf("trap: cpu%d, pid %d(%s): sig %d: cause=%#x epc=%#"PRIxREGISTER
-	    " va=%#"PRIxVADDR" (asid %d)\n",
-	    cpu_number(), p->p_pid, p->p_comm, ksi.ksi_signo, cause,
-	    utf->tf_regs[_R_PC], vaddr, curcpu()->ci_pmap_asid_cur);
-	printf("registers:\n");
-	for (size_t i = 0; i < 32; i += 4) {
-		printf(
-		    "[%2zu]=%08"PRIxREGISTER" [%2zu]=%08"PRIxREGISTER
-		    " [%2zu]=%08"PRIxREGISTER" [%2zu]=%08"PRIxREGISTER "\n",
-		    i+0, utf->tf_regs[i+0], i+1, utf->tf_regs[i+1],
-		    i+2, utf->tf_regs[i+2], i+3, utf->tf_regs[i+3]);
-	}
-#endif
-	(*p->p_emul->e_trapsignal)(l, &ksi);
+	cpu_trapsignal(l, &ksi, utf);
 	if ((type & T_USER) == 0) {
 #ifdef DDB
 		Debugger();
@@ -653,6 +641,31 @@ trap(uint32_t status, uint32_t cause, va
 	return;
 }
 
+void
+cpu_trapsignal(lwp_t *l, ksiginfo_t *ksi, struct trapframe *tf)
+{
+	struct proc * const p = l->l_proc;
+	if (cpu_printfataltraps) {
+		printf("trap: cpu%d, pid %d(%s): sig %d: cause=%#x epc=%#"PRIxREGISTER
+		    " va=%#"PRIxREGISTER" (asid %d)\n",
+		    cpu_number(), p->p_pid, p->p_comm, ksi->ksi_signo,
+		    (uint32_t) tf->tf_regs[_R_CAUSE],
+		    tf->tf_regs[_R_PC], tf->tf_regs[_R_BADVADDR],
+		    curcpu()->ci_pmap_asid_cur);
+		printf("registers:\n");
+		for (size_t i = 0; i < 32; i += 4) {
+			printf(
+			    "[%2zu]=%08"PRIxREGISTER
+			    " [%2zu]=%08"PRIxREGISTER
+			    " [%2zu]=%08"PRIxREGISTER
+			    " [%2zu]=%08"PRIxREGISTER "\n",
+			    i+0, tf->tf_regs[i+0], i+1, tf->tf_regs[i+1],
+			    i+2, tf->tf_regs[i+2], i+3, tf->tf_regs[i+3]);
+		}
+	}
+	(*p->p_emul->e_trapsignal)(l, ksi);
+}
+
 /*
  * Handle asynchronous software traps.
  * This is called on the return to userspace to flush icache, deliver signals,

Reply via email to