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); }