Module Name: src
Committed By: rmind
Date: Wed Jul 29 18:47:15 UTC 2009
Modified Files:
src/sys/arch/amd64/amd64: trap.c
src/sys/arch/i386/i386: trap.c
Log Message:
Reduce the difference between i386 and amd64 trap handler.
No functional changes intended.
To generate a diff of this commit:
cvs rdiff -u -r1.58 -r1.59 src/sys/arch/amd64/amd64/trap.c
cvs rdiff -u -r1.246 -r1.247 src/sys/arch/i386/i386/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/amd64/amd64/trap.c
diff -u src/sys/arch/amd64/amd64/trap.c:1.58 src/sys/arch/amd64/amd64/trap.c:1.59
--- src/sys/arch/amd64/amd64/trap.c:1.58 Wed Jul 29 17:14:38 2009
+++ src/sys/arch/amd64/amd64/trap.c Wed Jul 29 18:47:15 2009
@@ -1,4 +1,4 @@
-/* $NetBSD: trap.c,v 1.58 2009/07/29 17:14:38 rmind Exp $ */
+/* $NetBSD: trap.c,v 1.59 2009/07/29 18:47:15 rmind Exp $ */
/*-
* Copyright (c) 1998, 2000 The NetBSD Foundation, Inc.
@@ -68,7 +68,7 @@
*/
#include <sys/cdefs.h>
-__KERNEL_RCSID(0, "$NetBSD: trap.c,v 1.58 2009/07/29 17:14:38 rmind Exp $");
+__KERNEL_RCSID(0, "$NetBSD: trap.c,v 1.59 2009/07/29 18:47:15 rmind Exp $");
#include "opt_ddb.h"
#include "opt_kgdb.h"
@@ -81,12 +81,12 @@
#include <sys/acct.h>
#include <sys/kauth.h>
#include <sys/kernel.h>
+#include <sys/pool.h>
+#include <sys/ras.h>
#include <sys/signal.h>
#include <sys/syscall.h>
-#include <sys/ras.h>
-#include <sys/reboot.h>
-#include <sys/pool.h>
#include <sys/cpu.h>
+#include <sys/ucontext.h>
#include <sys/sa.h>
#include <sys/savar.h>
@@ -114,7 +114,7 @@
void trap(struct trapframe *);
-const char *trap_type[] = {
+const char * const trap_type[] = {
"privileged instruction fault", /* 0 T_PRIVINFLT */
"breakpoint trap", /* 1 T_BPTFLT */
"arithmetic trap", /* 2 T_ARITHTRAP */
@@ -133,11 +133,11 @@
"invalid TSS fault", /* 15 T_TSSFLT */
"segment not present fault", /* 16 T_SEGNPFLT */
"stack fault", /* 17 T_STKFLT */
- "machine check", /* 18 T_MCA */
+ "machine check fault", /* 18 T_MCA */
"SSE FP exception", /* 19 T_XMM */
"reserved trap", /* 20 T_RESERVED */
};
-int trap_types = sizeof trap_type / sizeof trap_type[0];
+int trap_types = __arraycount(trap_type);
#ifdef DEBUG
int trapdebug = 0;
@@ -177,20 +177,18 @@
}
/*
- * trap(frame):
- * Exception, fault, and trap interface to BSD kernel. This
- * common code is called from assembly language IDT gate entry
- * routines that prepare a suitable stack frame, and restore this
- * frame after the exception has been processed. Note that the
- * effect is as if the arguments were passed call by reference.
+ * trap(frame): exception, fault, and trap interface to BSD kernel.
+ *
+ * This common code is called from assembly language IDT gate entry routines
+ * that prepare a suitable stack frame, and restore this frame after the
+ * exception has been processed. Note that the effect is as if the arguments
+ * were passed call by reference.
*/
-/*ARGSUSED*/
void
trap(struct trapframe *frame)
{
struct lwp *l = curlwp;
struct proc *p;
- int type = (int)frame->tf_trapno;
struct pcb *pcb;
extern char fusuintrfailure[], kcopy_fault[],
resume_iret[];
@@ -199,11 +197,11 @@
extern char resume_pop_ds[], resume_pop_es[];
#endif
struct trapframe *vframe;
+ ksiginfo_t ksi;
void *resume;
void *onfault;
- int error;
+ int type, error;
uint64_t cr2;
- ksiginfo_t ksi;
bool pfail;
if (__predict_true(l != NULL)) {
@@ -216,18 +214,19 @@
pcb = NULL;
p = NULL;
}
+ type = frame->tf_trapno;
+
#ifdef DEBUG
if (trapdebug) {
printf("trap %d code %lx eip %lx cs %lx rflags %lx cr2 %lx "
"cpl %x\n",
type, frame->tf_err, frame->tf_rip, frame->tf_cs,
frame->tf_rflags, rcr2(), curcpu()->ci_ilevel);
- printf("curlwp %p\n", curlwp);
+ printf("curlwp %p%s", curlwp, curlwp ? " " : "\n");
if (curlwp)
printf("pid %d lid %d\n", l->l_proc->p_pid, l->l_lid);
}
#endif
-
if (type != T_NMI && !KERNELMODE(frame->tf_cs, frame->tf_rflags)) {
type |= T_USER;
l->l_md.md_regs = frame;
@@ -247,6 +246,10 @@
" %lx cpl %x rsp %lx\n",
type, frame->tf_err, (u_long)frame->tf_rip, frame->tf_cs,
frame->tf_rflags, rcr2(), curcpu()->ci_ilevel, frame->tf_rsp);
+#ifdef DDB
+ if (kdb_trap(type, 0, frame))
+ return;
+#endif
#ifdef KGDB
if (kgdb_trap(type, frame))
return;
@@ -261,10 +264,6 @@
}
}
#endif
-#ifdef DDB
- if (kdb_trap(type, 0, frame))
- return;
-#endif
panic("trap");
/*NOTREACHED*/
@@ -364,9 +363,7 @@
ksi.ksi_code = SEGV_ACCERR;
break;
default:
-#ifdef DIAGNOSTIC
- panic("unhandled type %x\n", type);
-#endif
+ KASSERT(0);
break;
}
goto trapsignal;
@@ -390,9 +387,7 @@
ksi.ksi_code = ILL_COPROC;
break;
default:
-#ifdef DIAGNOSTIC
- panic("unhandled type %x\n", type);
-#endif
+ KASSERT(0);
break;
}
goto trapsignal;
@@ -408,8 +403,9 @@
ADDUPROF(l);
}
/* Allow a forced task switch. */
- if (curcpu()->ci_want_resched)
+ if (curcpu()->ci_want_resched) {
preempt();
+ }
goto out;
#if 0 /* handled by fpudna() */
@@ -447,9 +443,11 @@
}
goto trapsignal;
- case T_PAGEFLT: /* allow page faults in kernel mode */
- if (l == NULL)
+ case T_PAGEFLT:
+ /* Allow page faults in kernel mode. */
+ if (__predict_false(l == NULL))
goto we_re_toast;
+
/*
* fusuintrfailure is used by [fs]uswintr() to prevent
* page faulting from inside the profiling interrupt.
@@ -482,8 +480,9 @@
}
faultcommon:
vm = p->p_vmspace;
- if (vm == NULL)
+ if (__predict_false(vm == NULL)) {
goto we_re_toast;
+ }
pcb->pcb_cr2 = cr2;
va = trunc_page((vaddr_t)cr2);
/*
@@ -511,7 +510,6 @@
goto we_re_toast;
}
#endif
-
/* Fault the original page in. */
onfault = pcb->pcb_onfault;
pcb->pcb_onfault = NULL;
@@ -573,12 +571,13 @@
}
KSI_INIT_TRAP(&ksi);
ksi.ksi_trap = type & ~T_USER;
- ksi.ksi_addr = (void *)rcr2();
+ ksi.ksi_addr = (void *)cr2;
if (error == EACCES) {
ksi.ksi_code = SEGV_ACCERR;
error = EFAULT;
- } else
+ } else {
ksi.ksi_code = SEGV_MAPERR;
+ }
if (type == T_PAGEFLT) {
onfault = onfault_handler(pcb, frame);
@@ -619,6 +618,9 @@
case T_BPTFLT|T_USER: /* bpt instruction fault */
case T_TRCTRAP|T_USER: /* trace trap */
+ /*
+ * Don't go single-stepping into a RAS.
+ */
if (p->p_raslist == NULL ||
(ras_lookup(p, (void *)frame->tf_rip) == (void *)-1)) {
KSI_INIT_TRAP(&ksi);
@@ -671,23 +673,29 @@
userret(l);
}
+/*
+ * startlwp: start of a new LWP.
+ */
void
startlwp(void *arg)
{
- int err;
ucontext_t *uc = arg;
- struct lwp *l = curlwp;
+ lwp_t *l = curlwp;
+ int error;
- err = cpu_setmcontext(l, &uc->uc_mcontext, uc->uc_flags);
+ error = cpu_setmcontext(l, &uc->uc_mcontext, uc->uc_flags);
+ KASSERT(error == 0);
pool_put(&lwp_uc_pool, uc);
userret(l);
}
+/*
+ * XXX_SA: This is a terrible name.
+ */
void
upcallret(struct lwp *l)
{
KERNEL_UNLOCK_LAST(l);
-
userret(l);
}
Index: src/sys/arch/i386/i386/trap.c
diff -u src/sys/arch/i386/i386/trap.c:1.246 src/sys/arch/i386/i386/trap.c:1.247
--- src/sys/arch/i386/i386/trap.c:1.246 Wed Jul 29 17:16:56 2009
+++ src/sys/arch/i386/i386/trap.c Wed Jul 29 18:47:15 2009
@@ -1,4 +1,4 @@
-/* $NetBSD: trap.c,v 1.246 2009/07/29 17:16:56 rmind Exp $ */
+/* $NetBSD: trap.c,v 1.247 2009/07/29 18:47:15 rmind Exp $ */
/*-
* Copyright (c) 1998, 2000, 2005, 2006, 2007, 2008 The NetBSD Foundation, Inc.
@@ -68,7 +68,7 @@
*/
#include <sys/cdefs.h>
-__KERNEL_RCSID(0, "$NetBSD: trap.c,v 1.246 2009/07/29 17:16:56 rmind Exp $");
+__KERNEL_RCSID(0, "$NetBSD: trap.c,v 1.247 2009/07/29 18:47:15 rmind Exp $");
#include "opt_ddb.h"
#include "opt_kgdb.h"
@@ -82,14 +82,14 @@
#include <sys/param.h>
#include <sys/systm.h>
#include <sys/proc.h>
-#include <sys/pool.h>
#include <sys/user.h>
#include <sys/acct.h>
+#include <sys/kauth.h>
#include <sys/kernel.h>
+#include <sys/pool.h>
#include <sys/ras.h>
#include <sys/signal.h>
#include <sys/syscall.h>
-#include <sys/kauth.h>
#include <sys/cpu.h>
#include <sys/ucontext.h>
#include <sys/sa.h>
@@ -224,7 +224,7 @@
case 0:
default:
return 0;
- }
+ }
}
static void *
@@ -253,26 +253,24 @@
}
/*
- * trap(frame):
- * Exception, fault, and trap interface to BSD kernel. This
- * common code is called from assembly language IDT gate entry
- * routines that prepare a suitable stack frame, and restore this
- * frame after the exception has been processed. Note that the
- * effect is as if the arguments were passed call by reference.
+ * trap(frame): exception, fault, and trap interface to BSD kernel.
+ *
+ * This common code is called from assembly language IDT gate entry routines
+ * that prepare a suitable stack frame, and restore this frame after the
+ * exception has been processed. Note that the effect is as if the arguments
+ * were passed call by reference.
*/
-/*ARGSUSED*/
void
trap(struct trapframe *frame)
{
struct lwp *l = curlwp;
struct proc *p;
- int type = frame->tf_trapno;
struct pcb *pcb;
extern char fusubail[], kcopy_fault[], trapreturn[], IDTVEC(osyscall)[];
struct trapframe *vframe;
ksiginfo_t ksi;
void *onfault;
- int error;
+ int type, error;
uint32_t cr2;
bool pfail;
@@ -286,17 +284,18 @@
pcb = NULL;
p = NULL;
}
+ type = frame->tf_trapno;
+
#ifdef DEBUG
if (trapdebug) {
printf("trap %d code %x eip %x cs %x eflags %x cr2 %lx cpl %x\n",
- frame->tf_trapno, frame->tf_err, frame->tf_eip, frame->tf_cs,
+ type, frame->tf_err, frame->tf_eip, frame->tf_cs,
frame->tf_eflags, rcr2(), curcpu()->ci_ilevel);
printf("curlwp %p%s", curlwp, curlwp ? " " : "\n");
if (curlwp)
printf("pid %d lid %d\n", l->l_proc->p_pid, l->l_lid);
}
#endif
-
if (type != T_NMI && !KVM86MODE &&
!KERNELMODE(frame->tf_cs, frame->tf_eflags)) {
type |= T_USER;
@@ -447,41 +446,45 @@
return;
case T_PROTFLT|T_USER: /* protection fault */
-#ifdef VM86
- if (frame->tf_eflags & PSL_VM) {
- vm86_gpfault(l, type & ~T_USER);
- goto out;
- }
-#endif
- /* If pmap_exec_fixup does something, let's retry the trap. */
- if (pmap_exec_fixup(&p->p_vmspace->vm_map, frame,
- &l->l_addr->u_pcb)) {
- goto out;
- }
- KSI_INIT_TRAP(&ksi);
- ksi.ksi_signo = SIGSEGV;
- ksi.ksi_addr = (void *)rcr2();
- ksi.ksi_code = SEGV_ACCERR;
- goto trapsignal;
-
case T_TSSFLT|T_USER:
case T_SEGNPFLT|T_USER:
case T_STKFLT|T_USER:
case T_ALIGNFLT|T_USER:
KSI_INIT_TRAP(&ksi);
- ksi.ksi_signo = SIGBUS;
+
ksi.ksi_addr = (void *)rcr2();
switch (type) {
case T_SEGNPFLT|T_USER:
case T_STKFLT|T_USER:
+ ksi.ksi_signo = SIGBUS;
ksi.ksi_code = BUS_ADRERR;
break;
case T_TSSFLT|T_USER:
+ ksi.ksi_signo = SIGBUS;
ksi.ksi_code = BUS_OBJERR;
break;
case T_ALIGNFLT|T_USER:
+ ksi.ksi_signo = SIGBUS;
ksi.ksi_code = BUS_ADRALN;
break;
+ case T_PROTFLT|T_USER:
+#ifdef VM86
+ if (frame->tf_eflags & PSL_VM) {
+ vm86_gpfault(l, type & ~T_USER);
+ goto out;
+ }
+#endif
+ /*
+ * If pmap_exec_fixup does something,
+ * let's retry the trap.
+ */
+ if (pmap_exec_fixup(&p->p_vmspace->vm_map, frame,
+ &l->l_addr->u_pcb)) {
+ goto out;
+ }
+ ksi.ksi_signo = SIGSEGV;
+ ksi.ksi_code = SEGV_ACCERR;
+ break;
default:
KASSERT(0);
break;
@@ -506,15 +509,17 @@
}
goto trapsignal;
- case T_ASTFLT|T_USER: /* Allow process switch */
+ case T_ASTFLT|T_USER:
+ /* Allow process switch. */
uvmexp.softs++;
if (l->l_pflag & LP_OWEUPC) {
l->l_pflag &= ~LP_OWEUPC;
ADDUPROF(l);
}
/* Allow a forced task switch. */
- if (curcpu()->ci_want_resched)
+ if (curcpu()->ci_want_resched) {
preempt();
+ }
goto out;
case T_DNA|T_USER: {
@@ -554,15 +559,17 @@
}
goto trapsignal;
- case T_PAGEFLT: /* allow page faults in kernel mode */
- if (l == 0)
+ case T_PAGEFLT:
+ /* Allow page faults in kernel mode. */
+ if (__predict_false(l == NULL))
goto we_re_toast;
/*
* fusubail is used by [fs]uswintr() to prevent page faulting
* from inside the profiling interrupt.
*/
- if ((onfault = pcb->pcb_onfault) == fusubail) {
+ onfault = pcb->pcb_onfault;
+ if (onfault == fusubail) {
goto copyefault;
}
if (cpu_intr_p() || (l->l_pflag & LP_INTR) != 0) {
@@ -584,12 +591,13 @@
l->l_savp->savp_faultaddr = (vaddr_t)cr2;
l->l_pflag |= LP_SA_PAGEFAULT;
}
- faultcommon:
+faultcommon:
vm = p->p_vmspace;
- if (vm == NULL)
+ if (__predict_false(vm == NULL)) {
goto we_re_toast;
+ }
pcb->pcb_cr2 = cr2;
- va = trunc_page((vaddr_t)pcb->pcb_cr2);
+ va = trunc_page((vaddr_t)cr2);
/*
* It is only a kernel address space fault iff:
* 1. (type & T_USER) == 0 and
@@ -613,7 +621,6 @@
goto we_re_toast;
}
#endif
-
/* Fault the original page in. */
onfault = pcb->pcb_onfault;
pcb->pcb_onfault = NULL;
@@ -782,32 +789,28 @@
userret(l);
}
-/*
- * XXX This is a terrible name.
+/*
+ * startlwp: start of a new LWP.
*/
void
-upcallret(struct lwp *l)
+startlwp(void *arg)
{
- KERNEL_UNLOCK_LAST(l);
+ ucontext_t *uc = arg;
+ lwp_t *l = curlwp;
+ int error;
+
+ error = cpu_setmcontext(l, &uc->uc_mcontext, uc->uc_flags);
+ KASSERT(error == 0);
+ pool_put(&lwp_uc_pool, uc);
userret(l);
}
-/*
- * Start a new LWP
+/*
+ * XXX_SA: This is a terrible name.
*/
void
-startlwp(void *arg)
+upcallret(struct lwp *l)
{
- int err;
- ucontext_t *uc = arg;
- struct lwp *l = curlwp;
-
- err = cpu_setmcontext(l, &uc->uc_mcontext, uc->uc_flags);
-#if DIAGNOSTIC
- if (err) {
- printf("Error %d from cpu_setmcontext.", err);
- }
-#endif
- pool_put(&lwp_uc_pool, uc);
+ KERNEL_UNLOCK_LAST(l);
userret(l);
}