📄 trap.c
字号:
/* * Copyright (c) 1992, 1993 * The Regents of the University of California. All rights reserved. * * This software was developed by the Computer Systems Engineering group * at Lawrence Berkeley Laboratory under DARPA contract BG 91-66 and * contributed to Berkeley. * * All advertising materials mentioning features or use of this software * must display the following acknowledgement: * This product includes software developed by the University of * California, Lawrence Berkeley Laboratory. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions * are met: * 1. Redistributions of source code must retain the above copyright * notice, this list of conditions and the following disclaimer. * 2. Redistributions in binary form must reproduce the above copyright * notice, this list of conditions and the following disclaimer in the * documentation and/or other materials provided with the distribution. * 3. All advertising materials mentioning features or use of this software * must display the following acknowledgement: * This product includes software developed by the University of * California, Berkeley and its contributors. * 4. Neither the name of the University nor the names of its contributors * may be used to endorse or promote products derived from this software * without specific prior written permission. * * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF * SUCH DAMAGE. * * @(#)trap.c 8.4 (Berkeley) 9/23/93 * * from: $Header: trap.c,v 1.34 93/05/28 04:34:50 torek Exp $ */#include <sys/param.h>#include <sys/systm.h>#include <sys/proc.h>#include <sys/user.h>#include <sys/kernel.h>#include <sys/malloc.h>#include <sys/resource.h>#include <sys/signal.h>#include <sys/wait.h>#include <sys/syscall.h>#include <sys/syslog.h>#ifdef KTRACE#include <sys/ktrace.h>#endif#include <vm/vm_kern.h>#include <machine/cpu.h>#include <machine/ctlreg.h>#include <machine/frame.h>#include <machine/trap.h>#define offsetof(s, f) ((int)&((s *)0)->f)extern int cold;int rwindow_debug = 0;/* * Initial FPU state is all registers == all 1s, everything else == all 0s. * This makes every floating point register a signalling NaN, with sign bit * set, no matter how it is interpreted. Appendix N of the Sparc V8 document * seems to imply that we should do this, and it does make sense. */struct fpstate initfpstate = { { ~0, ~0, ~0, ~0, ~0, ~0, ~0, ~0, ~0, ~0, ~0, ~0, ~0, ~0, ~0, ~0, ~0, ~0, ~0, ~0, ~0, ~0, ~0, ~0, ~0, ~0, ~0, ~0, ~0, ~0, ~0, ~0 }};/* * There are more than 100 trap types, but most are unused. * * Trap type 0 is taken over as an `Asynchronous System Trap'. * This is left-over Vax emulation crap that should be fixed. */static const char T[] = "trap";const char *trap_type[] = { /* non-user vectors */ "ast", /* 0 */ "text fault", /* 1 */ "illegal instruction", /* 2 */ "privileged instruction",/*3 */ "fp disabled", /* 4 */ "window overflow", /* 5 */ "window underflow", /* 6 */ "alignment fault", /* 7 */ "fp exception", /* 8 */ "data fault", /* 9 */ "tag overflow", /* 0a */ T, T, T, T, T, T, /* 0b..10 */ "level 1 int", /* 11 */ "level 2 int", /* 12 */ "level 3 int", /* 13 */ "level 4 int", /* 14 */ "level 5 int", /* 15 */ "level 6 int", /* 16 */ "level 7 int", /* 17 */ "level 8 int", /* 18 */ "level 9 int", /* 19 */ "level 10 int", /* 1a */ "level 11 int", /* 1b */ "level 12 int", /* 1c */ "level 13 int", /* 1d */ "level 14 int", /* 1e */ "level 15 int", /* 1f */ T, T, T, T, T, T, T, T, /* 20..27 */ T, T, T, T, T, T, T, T, /* 28..2f */ T, T, T, T, T, T, /* 30..35 */ "cp disabled", /* 36 */ T, /* 37 */ T, T, T, T, T, T, T, T, /* 38..3f */ "cp exception", /* 40 */ T, T, T, T, T, T, T, /* 41..47 */ T, T, T, T, T, T, T, T, /* 48..4f */ T, T, T, T, T, T, T, T, /* 50..57 */ T, T, T, T, T, T, T, T, /* 58..5f */ T, T, T, T, T, T, T, T, /* 60..67 */ T, T, T, T, T, T, T, T, /* 68..6f */ T, T, T, T, T, T, T, T, /* 70..77 */ T, T, T, T, T, T, T, T, /* 78..7f */ /* user (software trap) vectors */ "sun syscall", /* 80 */ "breakpoint", /* 81 */ "zero divide", /* 82 */ "flush windows", /* 83 */ "clean windows", /* 84 */ "range check", /* 85 */ "fix align", /* 86 */ "integer overflow", /* 87 */ "kgdb exec", /* 88 */ "syscall" /* 89 */};#define N_TRAP_TYPES (sizeof trap_type / sizeof *trap_type)/* * Define the code needed before returning to user mode, for * trap, mem_access_fault, and syscall. */static inline voiduserret(struct proc *p, int pc, u_quad_t oticks){ int sig; /* take pending signals */ while ((sig = CURSIG(p)) != 0) postsig(sig); p->p_priority = p->p_usrpri; if (want_ast) { want_ast = 0; if (p->p_flag & P_OWEUPC) { p->p_flag &= ~P_OWEUPC; ADDUPROF(p); } } if (want_resched) { /* * Since we are curproc, clock will normally just change * our priority without moving us from one queue to another * (since the running process is not on a queue.) * If that happened after we put ourselves on the run queue * but before we switched, we might not be on the queue * indicated by our priority. */ (void) splstatclock(); setrunqueue(p); p->p_stats->p_ru.ru_nivcsw++; mi_switch(); (void) spl0(); while ((sig = CURSIG(p)) != 0) postsig(sig); } /* * If profiling, charge recent system time to the trapped pc. */ if (p->p_flag & P_PROFIL) addupc_task(p, pc, (int)(p->p_sticks - oticks)); curpriority = p->p_priority;}/* * If someone stole the FPU while we were away, do not enable it * on return. This is not done in userret() above as it must follow * the ktrsysret() in syscall(). Actually, it is likely that the * ktrsysret should occur before the call to userret. */static inline void share_fpu(struct proc *p, struct trapframe *tf) { if ((tf->tf_psr & PSR_EF) != 0 && fpproc != p) tf->tf_psr &= ~PSR_EF;}/* * Called from locore.s trap handling, for non-MMU-related traps. * (MMU-related traps go through mem_access_fault, below.) */trap(type, psr, pc, tf) register unsigned type; register int psr, pc; register struct trapframe *tf;{ register struct proc *p; register struct pcb *pcb; register int n; u_quad_t sticks; /* This steps the PC over the trap. */#define ADVANCE (n = tf->tf_npc, tf->tf_pc = n, tf->tf_npc = n + 4) cnt.v_trap++; /* * Generally, kernel traps cause a panic. Any exceptions are * handled early here. */ if (psr & PSR_PS) { /* * Storing %fsr in cpu_attach will cause this trap * even though the fpu has been enabled, if and only * if there is no FPU. */ if (type == T_FPDISABLED && cold) { ADVANCE; return; } goto dopanic; } if ((p = curproc) == NULL) p = &proc0; sticks = p->p_sticks; pcb = &p->p_addr->u_pcb; p->p_md.md_tf = tf; /* for ptrace/signals */ switch (type) { default: if (type < 0x80) {dopanic: printf("trap type 0x%x: pc=%x npc=%x psr=%b\n", type, pc, tf->tf_npc, psr, PSR_BITS); panic(type < N_TRAP_TYPES ? trap_type[type] : T); /* NOTREACHED */ } /* the following message is gratuitous */ /* ... but leave it in until we find anything */ printf("%s[%d]: unimplemented software trap 0x%x\n", p->p_comm, p->p_pid, type); trapsignal(p, SIGILL, type); break; case T_AST: break; /* the work is all in userret() */ case T_ILLINST: trapsignal(p, SIGILL, 0); /* XXX code?? */ break; case T_PRIVINST: trapsignal(p, SIGILL, 0); /* XXX code?? */ break; case T_FPDISABLED: { register struct fpstate *fs = p->p_md.md_fpstate; if (fs == NULL) { fs = malloc(sizeof *fs, M_SUBPROC, M_WAITOK); *fs = initfpstate; p->p_md.md_fpstate = fs; } /* * If we have not found an FPU, we have to emulate it. */ if (!foundfpu) {#ifdef notyet fpu_emulate(p, tf, fs); break;#else trapsignal(p, SIGFPE, 0); /* XXX code?? */ break;#endif } /* * We may have more FPEs stored up and/or ops queued. * If they exist, handle them and get out. Otherwise, * resolve the FPU state, turn it on, and try again. */ if (fs->fs_qsize) { fpu_cleanup(p, fs); break; } if (fpproc != p) { /* we do not have it */ if (fpproc != NULL) /* someone else had it */ savefpstate(fpproc->p_md.md_fpstate); loadfpstate(fs); fpproc = p; /* now we do have it */ } tf->tf_psr |= PSR_EF; break; } case T_WINOF: if (rwindow_save(p)) sigexit(p, SIGILL); break;#define read_rw(src, dst) \ copyin((caddr_t)(src), (caddr_t)(dst), sizeof(struct rwindow)) case T_RWRET: /* * T_RWRET is a window load needed in order to rett. * It simply needs the window to which tf->tf_out[6] * (%sp) points. There are no user or saved windows now. * Copy the one from %sp into pcb->pcb_rw[0] and set * nsaved to -1. If we decide to deliver a signal on * our way out, we will clear nsaved. */if (pcb->pcb_uw || pcb->pcb_nsaved) panic("trap T_RWRET 1");if (rwindow_debug)printf("%s[%d]: rwindow: pcb<-stack: %x\n", p->p_comm, p->p_pid, tf->tf_out[6]); if (read_rw(tf->tf_out[6], &pcb->pcb_rw[0])) sigexit(p, SIGILL);if (pcb->pcb_nsaved) panic("trap T_RWRET 2"); pcb->pcb_nsaved = -1; /* mark success */ break; case T_WINUF: /* * T_WINUF is a real window underflow, from a restore * instruction. It needs to have the contents of two * windows---the one belonging to the restore instruction * itself, which is at its %sp, and the one belonging to * the window above, which is at its %fp or %i6---both * in the pcb. The restore's window may still be in * the cpu; we need to force it out to the stack. */if (rwindow_debug)printf("%s[%d]: rwindow: T_WINUF 0: pcb<-stack: %x\n",p->p_comm, p->p_pid, tf->tf_out[6]); write_user_windows(); if (rwindow_save(p) || read_rw(tf->tf_out[6], &pcb->pcb_rw[0])) sigexit(p, SIGILL);if (rwindow_debug)printf("%s[%d]: rwindow: T_WINUF 1: pcb<-stack: %x\n",p->p_comm, p->p_pid, pcb->pcb_rw[0].rw_in[6]); if (read_rw(pcb->pcb_rw[0].rw_in[6], &pcb->pcb_rw[1])) sigexit(p, SIGILL);if (pcb->pcb_nsaved) panic("trap T_WINUF"); pcb->pcb_nsaved = -1; /* mark success */ break; case T_ALIGN: trapsignal(p, SIGBUS, 0); /* XXX code?? */ break; case T_FPE: /* * Clean up after a floating point exception. * fpu_cleanup can (and usually does) modify the * state we save here, so we must `give up' the FPU * chip context. (The software and hardware states * will not match once fpu_cleanup does its job, so * we must not save again later.) */ if (p != fpproc) panic("fpe without being the FP user"); savefpstate(p->p_md.md_fpstate); fpproc = NULL; /* tf->tf_psr &= ~PSR_EF; */ /* share_fpu will do this */ fpu_cleanup(p, p->p_md.md_fpstate); /* fpu_cleanup posts signals if needed */#if 0 /* ??? really never??? */ ADVANCE;#endif break; case T_TAGOF: trapsignal(p, SIGEMT, 0); /* XXX code?? */ break; case T_CPDISABLED: uprintf("coprocessor instruction\n"); /* XXX */ trapsignal(p, SIGILL, 0); /* XXX code?? */ break;
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -