141475Smckusick /* 241475Smckusick * Copyright (c) 1988 University of Utah. 341475Smckusick * Copyright (c) 1982, 1986, 1990 The Regents of the University of California. 441475Smckusick * All rights reserved. 541475Smckusick * 641475Smckusick * This code is derived from software contributed to Berkeley by 741475Smckusick * the Systems Programming Group of the University of Utah Computer 841475Smckusick * Science Department. 941475Smckusick * 1041475Smckusick * %sccs.include.redist.c% 1141475Smckusick * 1253933Shibler * from: Utah $Hdr: trap.c 1.35 91/12/26$ 1341475Smckusick * 14*56318Shibler * @(#)trap.c 7.24 (Berkeley) 09/21/92 1541475Smckusick */ 1641475Smckusick 1748465Skarels #include "param.h" 1848465Skarels #include "systm.h" 1948465Skarels #include "proc.h" 2048465Skarels #include "acct.h" 2148465Skarels #include "kernel.h" 2248465Skarels #include "signalvar.h" 2348465Skarels #include "resourcevar.h" 2454801Storek #include "syscall.h" 2548465Skarels #include "syslog.h" 2648465Skarels #include "user.h" 2748465Skarels #ifdef KTRACE 2848465Skarels #include "ktrace.h" 2948465Skarels #endif 3048465Skarels 3149125Skarels #include "../include/psl.h" 3248465Skarels #include "../include/trap.h" 3345788Sbostic #include "../include/cpu.h" 3445788Sbostic #include "../include/reg.h" 3545788Sbostic #include "../include/mtpr.h" 3641475Smckusick 3748465Skarels #include "vm/vm.h" 3845788Sbostic #include "vm/pmap.h" 3945751Smckusick 4041475Smckusick #ifdef HPUXCOMPAT 4153933Shibler #include "hp/hpux/hpux.h" 4241475Smckusick #endif 4341475Smckusick 4441475Smckusick struct sysent sysent[]; 4541475Smckusick int nsysent; 4641475Smckusick 4741475Smckusick char *trap_type[] = { 4841475Smckusick "Bus error", 4941475Smckusick "Address error", 5041475Smckusick "Illegal instruction", 5141475Smckusick "Zero divide", 5241475Smckusick "CHK instruction", 5341475Smckusick "TRAPV instruction", 5441475Smckusick "Privilege violation", 5541475Smckusick "Trace trap", 5641475Smckusick "MMU fault", 5741475Smckusick "SSIR trap", 5841475Smckusick "Format error", 5941475Smckusick "68881 exception", 6041475Smckusick "Coprocessor violation", 6141475Smckusick "Async system trap" 6241475Smckusick }; 6341475Smckusick #define TRAP_TYPES (sizeof trap_type / sizeof trap_type[0]) 6441475Smckusick 6549317Shibler /* 6649317Shibler * Size of various exception stack frames (minus the standard 8 bytes) 6749317Shibler */ 6849317Shibler short exframesize[] = { 6949317Shibler FMT0SIZE, /* type 0 - normal (68020/030/040) */ 7049317Shibler FMT1SIZE, /* type 1 - throwaway (68020/030/040) */ 7149317Shibler FMT2SIZE, /* type 2 - normal 6-word (68020/030/040) */ 7253933Shibler FMT3SIZE, /* type 3 - FP post-instruction (68040) */ 7349317Shibler -1, -1, -1, /* type 4-6 - undefined */ 7453933Shibler FMT7SIZE, /* type 7 - access error (68040) */ 7549317Shibler 58, /* type 8 - bus fault (68010) */ 7649317Shibler FMT9SIZE, /* type 9 - coprocessor mid-instruction (68020/030) */ 7749317Shibler FMTASIZE, /* type A - short bus fault (68020/030) */ 7849317Shibler FMTBSIZE, /* type B - long bus fault (68020/030) */ 7949317Shibler -1, -1, -1, -1 /* type C-F - undefined */ 8049317Shibler }; 8149317Shibler 8254801Storek #ifdef HP380 8353933Shibler #define KDFAULT(c) (mmutype == MMU_68040 ? \ 8453933Shibler ((c) & SSW4_TMMASK) == SSW4_TMKD : \ 8553933Shibler ((c) & (SSW_DF|FC_SUPERD)) == (SSW_DF|FC_SUPERD)) 8653933Shibler #define WRFAULT(c) (mmutype == MMU_68040 ? \ 8753933Shibler ((c) & SSW4_RW) == 0 : \ 8853933Shibler ((c) & (SSW_DF|SSW_RW)) == SSW_DF) 8953933Shibler #else 9053933Shibler #define KDFAULT(c) (((c) & (SSW_DF|SSW_FCMASK)) == (SSW_DF|FC_SUPERD)) 9153933Shibler #define WRFAULT(c) (((c) & (SSW_DF|SSW_RW)) == SSW_DF) 9253933Shibler #endif 9353933Shibler 9441475Smckusick #ifdef DEBUG 9541475Smckusick int mmudebug = 0; 9653933Shibler int mmupid = -1; 9753933Shibler #define MDB_FOLLOW 1 9853933Shibler #define MDB_WBFOLLOW 2 9953933Shibler #define MDB_WBFAILED 4 10053933Shibler #define MDB_ISPID(p) (p) == mmupid 10141475Smckusick #endif 10241475Smckusick 10341475Smckusick /* 10454801Storek * trap and syscall both need the following work done before returning 10554801Storek * to user mode. 10654801Storek */ 10754801Storek static inline void 10854801Storek userret(p, fp, oticks, faultaddr, fromtrap) 10954801Storek register struct proc *p; 11054801Storek register struct frame *fp; 11154801Storek u_quad_t oticks; 11254801Storek u_int faultaddr; 11354801Storek int fromtrap; 11454801Storek { 11554801Storek int sig, s; 11654801Storek #ifdef HP380 11754801Storek int beenhere = 0; 11854801Storek 11954801Storek again: 12054801Storek #endif 12154801Storek /* take pending signals */ 12254801Storek while ((sig = CURSIG(p)) != 0) 12354801Storek psig(sig); 12454801Storek p->p_pri = p->p_usrpri; 12554801Storek if (want_resched) { 12654801Storek /* 12754801Storek * Since we are curproc, clock will normally just change 12854801Storek * our priority without moving us from one queue to another 12954801Storek * (since the running process is not on a queue.) 13054801Storek * If that happened after we setrq ourselves but before we 13154801Storek * swtch()'ed, we might not be on the queue indicated by 13254801Storek * our priority. 13354801Storek */ 13454801Storek s = splstatclock(); 13554801Storek setrq(p); 13654801Storek p->p_stats->p_ru.ru_nivcsw++; 13754801Storek swtch(); 13854801Storek splx(s); 13954801Storek while ((sig = CURSIG(p)) != 0) 14054801Storek psig(sig); 14154801Storek } 14254801Storek 14354801Storek /* 14454801Storek * If profiling, charge system time to the trapped pc. 14554801Storek */ 146*56318Shibler if (p->p_flag & SPROFIL) { 147*56318Shibler extern int psratio; 148*56318Shibler 149*56318Shibler addupc_task(p, fp->f_pc, 150*56318Shibler (int)(p->p_sticks - oticks) * psratio); 151*56318Shibler } 15254801Storek #ifdef HP380 15354801Storek /* 15454801Storek * Deal with user mode writebacks (from trap, or from sigreturn). 15554801Storek * If any writeback fails, go back and attempt signal delivery. 15654801Storek * unless we have already been here and attempted the writeback 15754801Storek * (e.g. bad address with user ignoring SIGSEGV). In that case 15854801Storek * we just return to the user without sucessfully completing 15954801Storek * the writebacks. Maybe we should just drop the sucker? 16054801Storek */ 16154801Storek if (mmutype == MMU_68040 && fp->f_format == FMT7) { 16254801Storek if (beenhere) { 16354801Storek #ifdef DEBUG 16454801Storek if (mmudebug & MDB_WBFAILED) 16554801Storek printf(fromtrap ? 16654801Storek "pid %d(%s): writeback aborted, pc=%x, fa=%x\n" : 16754801Storek "pid %d(%s): writeback aborted in sigreturn, pc=%x\n", 16854801Storek p->p_pid, p->p_comm, fp->f_pc, faultaddr); 16954801Storek #endif 17054801Storek } else if (sig = writeback(fp, fromtrap)) { 17154801Storek beenhere = 1; 17254801Storek oticks = p->p_sticks; 17354801Storek trapsignal(p, sig, faultaddr); 17454801Storek goto again; 17554801Storek } 17654801Storek } 17754801Storek #endif 17854801Storek curpri = p->p_pri; 17954801Storek } 18054801Storek 18154801Storek /* 18249531Skarels * Trap is called from locore to handle most types of processor traps, 18349531Skarels * including events such as simulated software interrupts/AST's. 18449531Skarels * System calls are broken out for efficiency. 18541475Smckusick */ 18641475Smckusick /*ARGSUSED*/ 18741475Smckusick trap(type, code, v, frame) 18841475Smckusick int type; 18941475Smckusick unsigned code; 19041475Smckusick register unsigned v; 19141475Smckusick struct frame frame; 19241475Smckusick { 19341475Smckusick register int i; 19454801Storek unsigned ucode; 19554801Storek register struct proc *p; 19654801Storek u_quad_t sticks; 19741475Smckusick unsigned ncode; 19854574Storek extern char fswintr[]; 19941475Smckusick 20041475Smckusick cnt.v_trap++; 20154801Storek p = curproc; 20254801Storek ucode = 0; 20341475Smckusick if (USERMODE(frame.f_sr)) { 20449531Skarels type |= T_USER; 20554801Storek sticks = p->p_sticks; 20652380Smckusick p->p_md.md_regs = frame.f_regs; 20741475Smckusick } 20841475Smckusick switch (type) { 20941475Smckusick 21041475Smckusick default: 21141475Smckusick dopanic: 21241475Smckusick printf("trap type %d, code = %x, v = %x\n", type, code, v); 21341475Smckusick regdump(frame.f_regs, 128); 21449531Skarels type &= ~T_USER; 21541475Smckusick if ((unsigned)type < TRAP_TYPES) 21641475Smckusick panic(trap_type[type]); 21741475Smckusick panic("trap"); 21841475Smckusick 21941475Smckusick case T_BUSERR: /* kernel bus error */ 22049125Skarels if (!p->p_addr->u_pcb.pcb_onfault) 22141475Smckusick goto dopanic; 22241475Smckusick /* 22341475Smckusick * If we have arranged to catch this fault in any of the 22441475Smckusick * copy to/from user space routines, set PC to return to 22541475Smckusick * indicated location and set flag informing buserror code 22641475Smckusick * that it may need to clean up stack frame. 22741475Smckusick */ 22841475Smckusick copyfault: 22949317Shibler frame.f_stackadj = exframesize[frame.f_format]; 23049317Shibler frame.f_format = frame.f_vector = 0; 23149125Skarels frame.f_pc = (int) p->p_addr->u_pcb.pcb_onfault; 23241475Smckusick return; 23341475Smckusick 23449531Skarels case T_BUSERR|T_USER: /* bus error */ 23549531Skarels case T_ADDRERR|T_USER: /* address error */ 23653933Shibler ucode = v; 23741475Smckusick i = SIGBUS; 23841475Smckusick break; 23941475Smckusick 24041475Smckusick #ifdef FPCOPROC 24141475Smckusick case T_COPERR: /* kernel coprocessor violation */ 24241475Smckusick #endif 24353933Shibler case T_FMTERR|T_USER: /* do all RTE errors come in as T_USER? */ 24453933Shibler case T_FMTERR: /* ...just in case... */ 24541475Smckusick /* 24641475Smckusick * The user has most likely trashed the RTE or FP state info 24741475Smckusick * in the stack frame of a signal handler. 24841475Smckusick */ 24949531Skarels type |= T_USER; 25048465Skarels printf("pid %d: kernel %s exception\n", p->p_pid, 25141475Smckusick type==T_COPERR ? "coprocessor" : "format"); 25248465Skarels p->p_sigacts->ps_sigact[SIGILL] = SIG_DFL; 25341475Smckusick i = sigmask(SIGILL); 25441475Smckusick p->p_sigignore &= ~i; 25541475Smckusick p->p_sigcatch &= ~i; 25641475Smckusick p->p_sigmask &= ~i; 25742370Skarels i = SIGILL; 25841475Smckusick ucode = frame.f_format; /* XXX was ILL_RESAD_FAULT */ 25942370Skarels break; 26041475Smckusick 26141475Smckusick #ifdef FPCOPROC 26249531Skarels case T_COPERR|T_USER: /* user coprocessor violation */ 26341475Smckusick /* What is a proper response here? */ 26441475Smckusick ucode = 0; 26541475Smckusick i = SIGFPE; 26641475Smckusick break; 26741475Smckusick 26849531Skarels case T_FPERR|T_USER: /* 68881 exceptions */ 26941475Smckusick /* 27041475Smckusick * We pass along the 68881 status register which locore stashed 27141475Smckusick * in code for us. Note that there is a possibility that the 27241475Smckusick * bit pattern of this register will conflict with one of the 27341475Smckusick * FPE_* codes defined in signal.h. Fortunately for us, the 27441475Smckusick * only such codes we use are all in the range 1-7 and the low 27541475Smckusick * 3 bits of the status register are defined as 0 so there is 27641475Smckusick * no clash. 27741475Smckusick */ 27841475Smckusick ucode = code; 27941475Smckusick i = SIGFPE; 28041475Smckusick break; 28141475Smckusick #endif 28241475Smckusick 28354801Storek #ifdef HP380 28453933Shibler case T_FPEMULI|T_USER: /* unimplemented FP instuction */ 28553933Shibler case T_FPEMULD|T_USER: /* unimplemented FP data type */ 28653933Shibler /* XXX need to FSAVE */ 28753933Shibler printf("pid %d(%s): unimplemented FP %s at %x (EA %x)\n", 28853933Shibler p->p_pid, p->p_comm, 28953933Shibler frame.f_format == 2 ? "instruction" : "data type", 29053933Shibler frame.f_pc, frame.f_fmt2.f_iaddr); 29153933Shibler /* XXX need to FRESTORE */ 29253933Shibler i = SIGFPE; 29353933Shibler break; 29453933Shibler #endif 29553933Shibler 29649531Skarels case T_ILLINST|T_USER: /* illegal instruction fault */ 29741475Smckusick #ifdef HPUXCOMPAT 29848465Skarels if (p->p_flag & SHPUX) { 29941475Smckusick ucode = HPUX_ILL_ILLINST_TRAP; 30041475Smckusick i = SIGILL; 30141475Smckusick break; 30241475Smckusick } 30341475Smckusick /* fall through */ 30441475Smckusick #endif 30549531Skarels case T_PRIVINST|T_USER: /* privileged instruction fault */ 30641475Smckusick #ifdef HPUXCOMPAT 30748465Skarels if (p->p_flag & SHPUX) 30841475Smckusick ucode = HPUX_ILL_PRIV_TRAP; 30941475Smckusick else 31041475Smckusick #endif 31141475Smckusick ucode = frame.f_format; /* XXX was ILL_PRIVIN_FAULT */ 31241475Smckusick i = SIGILL; 31341475Smckusick break; 31441475Smckusick 31549531Skarels case T_ZERODIV|T_USER: /* Divide by zero */ 31641475Smckusick #ifdef HPUXCOMPAT 31748465Skarels if (p->p_flag & SHPUX) 31841475Smckusick ucode = HPUX_FPE_INTDIV_TRAP; 31941475Smckusick else 32041475Smckusick #endif 32141475Smckusick ucode = frame.f_format; /* XXX was FPE_INTDIV_TRAP */ 32241475Smckusick i = SIGFPE; 32341475Smckusick break; 32441475Smckusick 32549531Skarels case T_CHKINST|T_USER: /* CHK instruction trap */ 32641475Smckusick #ifdef HPUXCOMPAT 32748465Skarels if (p->p_flag & SHPUX) { 32841475Smckusick /* handled differently under hp-ux */ 32941475Smckusick i = SIGILL; 33041475Smckusick ucode = HPUX_ILL_CHK_TRAP; 33141475Smckusick break; 33241475Smckusick } 33341475Smckusick #endif 33441475Smckusick ucode = frame.f_format; /* XXX was FPE_SUBRNG_TRAP */ 33541475Smckusick i = SIGFPE; 33641475Smckusick break; 33741475Smckusick 33849531Skarels case T_TRAPVINST|T_USER: /* TRAPV instruction trap */ 33941475Smckusick #ifdef HPUXCOMPAT 34048465Skarels if (p->p_flag & SHPUX) { 34141475Smckusick /* handled differently under hp-ux */ 34241475Smckusick i = SIGILL; 34341475Smckusick ucode = HPUX_ILL_TRAPV_TRAP; 34441475Smckusick break; 34541475Smckusick } 34641475Smckusick #endif 34741475Smckusick ucode = frame.f_format; /* XXX was FPE_INTOVF_TRAP */ 34841475Smckusick i = SIGFPE; 34941475Smckusick break; 35041475Smckusick 35141475Smckusick /* 35241475Smckusick * XXX: Trace traps are a nightmare. 35341475Smckusick * 35441475Smckusick * HP-UX uses trap #1 for breakpoints, 35541475Smckusick * HPBSD uses trap #2, 35641475Smckusick * SUN 3.x uses trap #15, 35748465Skarels * KGDB uses trap #15 (for kernel breakpoints; handled elsewhere). 35841475Smckusick * 35941475Smckusick * HPBSD and HP-UX traps both get mapped by locore.s into T_TRACE. 36041475Smckusick * SUN 3.x traps get passed through as T_TRAP15 and are not really 36148465Skarels * supported yet. 36241475Smckusick */ 36341475Smckusick case T_TRACE: /* kernel trace trap */ 36448465Skarels case T_TRAP15: /* SUN trace trap */ 36541475Smckusick frame.f_sr &= ~PSL_T; 36641475Smckusick i = SIGTRAP; 36741475Smckusick break; 36841475Smckusick 36949531Skarels case T_TRACE|T_USER: /* user trace trap */ 37049531Skarels case T_TRAP15|T_USER: /* SUN user trace trap */ 37141475Smckusick frame.f_sr &= ~PSL_T; 37241475Smckusick i = SIGTRAP; 37341475Smckusick break; 37441475Smckusick 37543413Shibler case T_ASTFLT: /* system async trap, cannot happen */ 37641475Smckusick goto dopanic; 37741475Smckusick 37849531Skarels case T_ASTFLT|T_USER: /* user async trap */ 37949125Skarels astpending = 0; 38041475Smckusick /* 38141475Smckusick * We check for software interrupts first. This is because 38241475Smckusick * they are at a higher level than ASTs, and on a VAX would 38341475Smckusick * interrupt the AST. We assume that if we are processing 38441475Smckusick * an AST that we must be at IPL0 so we don't bother to 38541475Smckusick * check. Note that we ensure that we are at least at SIR 38641475Smckusick * IPL while processing the SIR. 38741475Smckusick */ 38841475Smckusick spl1(); 38941475Smckusick /* fall into... */ 39041475Smckusick 39141475Smckusick case T_SSIR: /* software interrupt */ 39249531Skarels case T_SSIR|T_USER: 39341475Smckusick if (ssir & SIR_NET) { 39441475Smckusick siroff(SIR_NET); 39541475Smckusick cnt.v_soft++; 39641475Smckusick netintr(); 39741475Smckusick } 39841475Smckusick if (ssir & SIR_CLOCK) { 39941475Smckusick siroff(SIR_CLOCK); 40041475Smckusick cnt.v_soft++; 40154801Storek softclock(); 40241475Smckusick } 40341475Smckusick /* 40441475Smckusick * If this was not an AST trap, we are all done. 40541475Smckusick */ 40650753Skarels if (type != (T_ASTFLT|T_USER)) { 40741475Smckusick cnt.v_trap--; 40841475Smckusick return; 40941475Smckusick } 41041475Smckusick spl0(); 41154801Storek if (p->p_flag & SOWEUPC) { 41248465Skarels p->p_flag &= ~SOWEUPC; 41354801Storek ADDUPROF(p); 41441475Smckusick } 41541475Smckusick goto out; 41641475Smckusick 41741475Smckusick case T_MMUFLT: /* kernel mode page fault */ 41854574Storek /* 41954574Storek * If we were doing profiling ticks or other user mode 42054574Storek * stuff from interrupt code, Just Say No. 42154574Storek */ 42254574Storek if (p->p_addr->u_pcb.pcb_onfault == fswintr) 42354574Storek goto copyfault; 42441475Smckusick /* fall into ... */ 42541475Smckusick 42649531Skarels case T_MMUFLT|T_USER: /* page fault */ 42745751Smckusick { 42845751Smckusick register vm_offset_t va; 42948465Skarels register struct vmspace *vm = p->p_vmspace; 43045751Smckusick register vm_map_t map; 43145751Smckusick int rv; 43245751Smckusick vm_prot_t ftype; 43345751Smckusick extern vm_map_t kernel_map; 43445751Smckusick 43553933Shibler #ifdef DEBUG 43653933Shibler if ((mmudebug & MDB_WBFOLLOW) || MDB_ISPID(p->p_pid)) 43753933Shibler printf("trap: T_MMUFLT pid=%d, code=%x, v=%x, pc=%x, sr=%x\n", 43853933Shibler p->p_pid, code, v, frame.f_pc, frame.f_sr); 43953933Shibler #endif 44041475Smckusick /* 44145751Smckusick * It is only a kernel address space fault iff: 44249531Skarels * 1. (type & T_USER) == 0 and 44345751Smckusick * 2. pcb_onfault not set or 44445751Smckusick * 3. pcb_onfault set but supervisor space data fault 44545751Smckusick * The last can occur during an exec() copyin where the 44645751Smckusick * argument space is lazy-allocated. 44741475Smckusick */ 44845751Smckusick if (type == T_MMUFLT && 44953933Shibler (!p->p_addr->u_pcb.pcb_onfault || KDFAULT(code))) 45045751Smckusick map = kernel_map; 45145751Smckusick else 45248465Skarels map = &vm->vm_map; 45353933Shibler if (WRFAULT(code)) 45445751Smckusick ftype = VM_PROT_READ | VM_PROT_WRITE; 45545751Smckusick else 45645751Smckusick ftype = VM_PROT_READ; 45745751Smckusick va = trunc_page((vm_offset_t)v); 45841475Smckusick #ifdef DEBUG 45945751Smckusick if (map == kernel_map && va == 0) { 46045751Smckusick printf("trap: bad kernel access at %x\n", v); 46141475Smckusick goto dopanic; 46241475Smckusick } 46341475Smckusick #endif 46449317Shibler rv = vm_fault(map, va, ftype, FALSE); 46553933Shibler #ifdef DEBUG 46653933Shibler if (rv && MDB_ISPID(p->p_pid)) 46753933Shibler printf("vm_fault(%x, %x, %x, 0) -> %x\n", 46853933Shibler map, va, ftype, rv); 46953933Shibler #endif 47041475Smckusick /* 47149317Shibler * If this was a stack access we keep track of the maximum 47249317Shibler * accessed stack size. Also, if vm_fault gets a protection 47349317Shibler * failure it is due to accessing the stack region outside 47449317Shibler * the current limit and we need to reflect that as an access 47549317Shibler * error. 47641475Smckusick */ 47748465Skarels if ((caddr_t)va >= vm->vm_maxsaddr && map != kernel_map) { 47849317Shibler if (rv == KERN_SUCCESS) { 47949317Shibler unsigned nss; 48049317Shibler 48149317Shibler nss = clrnd(btoc(USRSTACK-(unsigned)va)); 48249317Shibler if (nss > vm->vm_ssize) 48349317Shibler vm->vm_ssize = nss; 48449317Shibler } else if (rv == KERN_PROTECTION_FAILURE) 48549317Shibler rv = KERN_INVALID_ADDRESS; 48641475Smckusick } 48745751Smckusick if (rv == KERN_SUCCESS) { 48853933Shibler if (type == T_MMUFLT) { 48954801Storek #ifdef HP380 49053933Shibler if (mmutype == MMU_68040) 49153933Shibler (void) writeback(&frame, 1); 49253933Shibler #endif 49341475Smckusick return; 49453933Shibler } 49541475Smckusick goto out; 49641475Smckusick } 49745751Smckusick if (type == T_MMUFLT) { 49849125Skarels if (p->p_addr->u_pcb.pcb_onfault) 49945751Smckusick goto copyfault; 50045751Smckusick printf("vm_fault(%x, %x, %x, 0) -> %x\n", 50145751Smckusick map, va, ftype, rv); 50245751Smckusick printf(" type %x, code [mmu,,ssw]: %x\n", 50345751Smckusick type, code); 50445751Smckusick goto dopanic; 50545751Smckusick } 50648465Skarels ucode = v; 50745751Smckusick i = (rv == KERN_PROTECTION_FAILURE) ? SIGBUS : SIGSEGV; 50845751Smckusick break; 50945751Smckusick } 51041475Smckusick } 51148465Skarels trapsignal(p, i, ucode); 51249531Skarels if ((type & T_USER) == 0) 51341475Smckusick return; 51441475Smckusick out: 51554801Storek userret(p, &frame, sticks, v, 1); 51641475Smckusick } 51741475Smckusick 51854801Storek #ifdef HP380 51953933Shibler #ifdef DEBUG 52053933Shibler struct writebackstats { 52153933Shibler int calls; 52253933Shibler int cpushes; 52353933Shibler int move16s; 52453933Shibler int wb1s, wb2s, wb3s; 52553933Shibler int wbsize[4]; 52653933Shibler } wbstats; 52753933Shibler 52853933Shibler char *f7sz[] = { "longword", "byte", "word", "line" }; 52953933Shibler char *f7tt[] = { "normal", "MOVE16", "AFC", "ACK" }; 53053933Shibler char *f7tm[] = { "d-push", "u-data", "u-code", "M-data", 53153933Shibler "M-code", "k-data", "k-code", "RES" }; 53253933Shibler char wberrstr[] = 53353933Shibler "WARNING: pid %d(%s) writeback [%s] failed, pc=%x fa=%x wba=%x wbd=%x\n"; 53453933Shibler #endif 53553933Shibler 53653933Shibler writeback(fp, docachepush) 53753933Shibler struct frame *fp; 53853933Shibler int docachepush; 53953933Shibler { 54053933Shibler register struct fmt7 *f = &fp->f_fmt7; 54153933Shibler register struct proc *p = curproc; 54253933Shibler int err = 0; 54353933Shibler u_int fa; 54453933Shibler caddr_t oonfault = p->p_addr->u_pcb.pcb_onfault; 54553933Shibler 54653933Shibler #ifdef DEBUG 54753933Shibler if ((mmudebug & MDB_WBFOLLOW) || MDB_ISPID(p->p_pid)) { 54853933Shibler printf(" pid=%d, fa=%x,", p->p_pid, f->f_fa); 54953933Shibler dumpssw(f->f_ssw); 55053933Shibler } 55153933Shibler wbstats.calls++; 55253933Shibler #endif 55353933Shibler /* 55453933Shibler * Deal with special cases first. 55553933Shibler */ 55653933Shibler if ((f->f_ssw & SSW4_TMMASK) == SSW4_TMDCP) { 55753933Shibler /* 55853933Shibler * Dcache push fault. 55953933Shibler * Line-align the address and write out the push data to 56053933Shibler * the indicated physical address. 56153933Shibler */ 56253933Shibler #ifdef DEBUG 56353933Shibler if ((mmudebug & MDB_WBFOLLOW) || MDB_ISPID(p->p_pid)) { 56453933Shibler printf(" pushing %s to PA %x, data %x", 56553933Shibler f7sz[(f->f_ssw & SSW4_SZMASK) >> 5], 56653933Shibler f->f_fa, f->f_pd0); 56753933Shibler if ((f->f_ssw & SSW4_SZMASK) == SSW4_SZLN) 56853933Shibler printf("/%x/%x/%x", 56953933Shibler f->f_pd1, f->f_pd2, f->f_pd3); 57053933Shibler printf("\n"); 57153933Shibler } 57253933Shibler if (f->f_wb1s & SSW4_WBSV) 57353933Shibler panic("writeback: cache push with WB1S valid"); 57453933Shibler wbstats.cpushes++; 57553933Shibler #endif 57653933Shibler /* 57753933Shibler * XXX there are security problems if we attempt to do a 57853933Shibler * cache push after a signal handler has been called. 57953933Shibler */ 58053933Shibler if (docachepush) { 58153933Shibler pmap_enter(kernel_pmap, (vm_offset_t)vmmap, 58253933Shibler trunc_page(f->f_fa), VM_PROT_WRITE, TRUE); 58353933Shibler fa = (u_int)&vmmap[(f->f_fa & PGOFSET) & ~0xF]; 58453933Shibler bcopy((caddr_t)&f->f_pd0, (caddr_t)fa, 16); 58553933Shibler DCFL(pmap_extract(kernel_pmap, (vm_offset_t)fa)); 58653933Shibler pmap_remove(kernel_pmap, (vm_offset_t)vmmap, 58753933Shibler (vm_offset_t)&vmmap[NBPG]); 58853933Shibler } else 58953933Shibler printf("WARNING: pid %d(%s) uid %d: CPUSH not done\n", 59053933Shibler p->p_pid, p->p_comm, p->p_ucred->cr_uid); 59153933Shibler } else if ((f->f_ssw & (SSW4_RW|SSW4_TTMASK)) == SSW4_TTM16) { 59253933Shibler /* 59353933Shibler * MOVE16 fault. 59453933Shibler * Line-align the address and write out the push data to 59553933Shibler * the indicated virtual address. 59653933Shibler */ 59753933Shibler #ifdef DEBUG 59853933Shibler if ((mmudebug & MDB_WBFOLLOW) || MDB_ISPID(p->p_pid)) 59953933Shibler printf(" MOVE16 to VA %x(%x), data %x/%x/%x/%x\n", 60053933Shibler f->f_fa, f->f_fa & ~0xF, f->f_pd0, f->f_pd1, 60153933Shibler f->f_pd2, f->f_pd3); 60253933Shibler if (f->f_wb1s & SSW4_WBSV) 60353933Shibler panic("writeback: MOVE16 with WB1S valid"); 60453933Shibler wbstats.move16s++; 60553933Shibler #endif 60653933Shibler if (KDFAULT(f->f_wb1s)) 60753933Shibler bcopy((caddr_t)&f->f_pd0, (caddr_t)(f->f_fa & ~0xF), 16); 60853933Shibler else 60953933Shibler err = suline((caddr_t)(f->f_fa & ~0xF), (caddr_t)&f->f_pd0); 61053933Shibler if (err) { 61153933Shibler fa = f->f_fa & ~0xF; 61253933Shibler #ifdef DEBUG 61353933Shibler if (mmudebug & MDB_WBFAILED) 61453933Shibler printf(wberrstr, p->p_pid, p->p_comm, 61553933Shibler "MOVE16", fp->f_pc, f->f_fa, 61653933Shibler f->f_fa & ~0xF, f->f_pd0); 61753933Shibler #endif 61853933Shibler } 61953933Shibler } else if (f->f_wb1s & SSW4_WBSV) { 62053933Shibler /* 62153933Shibler * Writeback #1. 62253933Shibler * Position the "memory-aligned" data and write it out. 62353933Shibler */ 62453933Shibler register u_int wb1d = f->f_wb1d; 62553933Shibler register int off; 62653933Shibler 62753933Shibler #ifdef DEBUG 62853933Shibler if ((mmudebug & MDB_WBFOLLOW) || MDB_ISPID(p->p_pid)) 62953933Shibler dumpwb(1, f->f_wb1s, f->f_wb1a, f->f_wb1d); 63053933Shibler wbstats.wb1s++; 63153933Shibler wbstats.wbsize[(f->f_wb2s&SSW4_SZMASK)>>5]++; 63253933Shibler #endif 63353933Shibler off = (f->f_wb1a & 3) * 8; 63453933Shibler switch (f->f_wb1s & SSW4_SZMASK) { 63553933Shibler case SSW4_SZLW: 63653933Shibler if (off) 63753933Shibler wb1d = (wb1d >> (32 - off)) | (wb1d << off); 63853933Shibler if (KDFAULT(f->f_wb1s)) 63953933Shibler *(long *)f->f_wb1a = wb1d; 64053933Shibler else 64153933Shibler err = suword((caddr_t)f->f_wb1a, wb1d); 64253933Shibler break; 64353933Shibler case SSW4_SZB: 64453933Shibler off = 24 - off; 64553933Shibler if (off) 64653933Shibler wb1d >>= off; 64753933Shibler if (KDFAULT(f->f_wb1s)) 64853933Shibler *(char *)f->f_wb1a = wb1d; 64953933Shibler else 65053933Shibler err = subyte((caddr_t)f->f_wb1a, wb1d); 65153933Shibler break; 65253933Shibler case SSW4_SZW: 65353933Shibler off = (off + 16) % 32; 65453933Shibler if (off) 65553933Shibler wb1d = (wb1d >> (32 - off)) | (wb1d << off); 65653933Shibler if (KDFAULT(f->f_wb1s)) 65753933Shibler *(short *)f->f_wb1a = wb1d; 65853933Shibler else 65953933Shibler err = susword((caddr_t)f->f_wb1a, wb1d); 66053933Shibler break; 66153933Shibler } 66253933Shibler if (err) { 66353933Shibler fa = f->f_wb1a; 66453933Shibler #ifdef DEBUG 66553933Shibler if (mmudebug & MDB_WBFAILED) 66653933Shibler printf(wberrstr, p->p_pid, p->p_comm, 66753933Shibler "#1", fp->f_pc, f->f_fa, 66853933Shibler f->f_wb1a, f->f_wb1d); 66953933Shibler #endif 67053933Shibler } 67153933Shibler } 67253933Shibler /* 67353933Shibler * Deal with the "normal" writebacks. 67453933Shibler * 67553933Shibler * XXX writeback2 is known to reflect a LINE size writeback after 67653933Shibler * a MOVE16 was already dealt with above. Ignore it. 67753933Shibler */ 67853933Shibler if (err == 0 && (f->f_wb2s & SSW4_WBSV) && 67953933Shibler (f->f_wb2s & SSW4_SZMASK) != SSW4_SZLN) { 68053933Shibler #ifdef DEBUG 68153933Shibler if ((mmudebug & MDB_WBFOLLOW) || MDB_ISPID(p->p_pid)) 68253933Shibler dumpwb(2, f->f_wb2s, f->f_wb2a, f->f_wb2d); 68353933Shibler wbstats.wb2s++; 68453933Shibler wbstats.wbsize[(f->f_wb2s&SSW4_SZMASK)>>5]++; 68553933Shibler #endif 68653933Shibler switch (f->f_wb2s & SSW4_SZMASK) { 68753933Shibler case SSW4_SZLW: 68853933Shibler if (KDFAULT(f->f_wb2s)) 68953933Shibler *(long *)f->f_wb2a = f->f_wb2d; 69053933Shibler else 69153933Shibler err = suword((caddr_t)f->f_wb2a, f->f_wb2d); 69253933Shibler break; 69353933Shibler case SSW4_SZB: 69453933Shibler if (KDFAULT(f->f_wb2s)) 69553933Shibler *(char *)f->f_wb2a = f->f_wb2d; 69653933Shibler else 69753933Shibler err = subyte((caddr_t)f->f_wb2a, f->f_wb2d); 69853933Shibler break; 69953933Shibler case SSW4_SZW: 70053933Shibler if (KDFAULT(f->f_wb2s)) 70153933Shibler *(short *)f->f_wb2a = f->f_wb2d; 70253933Shibler else 70353933Shibler err = susword((caddr_t)f->f_wb2a, f->f_wb2d); 70453933Shibler break; 70553933Shibler } 70653933Shibler if (err) { 70753933Shibler fa = f->f_wb2a; 70853933Shibler #ifdef DEBUG 70953933Shibler if (mmudebug & MDB_WBFAILED) { 71053933Shibler printf(wberrstr, p->p_pid, p->p_comm, 71153933Shibler "#2", fp->f_pc, f->f_fa, 71253933Shibler f->f_wb2a, f->f_wb2d); 71353933Shibler dumpssw(f->f_ssw); 71453933Shibler dumpwb(2, f->f_wb2s, f->f_wb2a, f->f_wb2d); 71553933Shibler } 71653933Shibler #endif 71753933Shibler } 71853933Shibler } 71953933Shibler if (err == 0 && (f->f_wb3s & SSW4_WBSV)) { 72053933Shibler #ifdef DEBUG 72153933Shibler if ((mmudebug & MDB_WBFOLLOW) || MDB_ISPID(p->p_pid)) 72253933Shibler dumpwb(3, f->f_wb3s, f->f_wb3a, f->f_wb3d); 72353933Shibler wbstats.wb3s++; 72453933Shibler wbstats.wbsize[(f->f_wb3s&SSW4_SZMASK)>>5]++; 72553933Shibler #endif 72653933Shibler switch (f->f_wb3s & SSW4_SZMASK) { 72753933Shibler case SSW4_SZLW: 72853933Shibler if (KDFAULT(f->f_wb3s)) 72953933Shibler *(long *)f->f_wb3a = f->f_wb3d; 73053933Shibler else 73153933Shibler err = suword((caddr_t)f->f_wb3a, f->f_wb3d); 73253933Shibler break; 73353933Shibler case SSW4_SZB: 73453933Shibler if (KDFAULT(f->f_wb3s)) 73553933Shibler *(char *)f->f_wb3a = f->f_wb3d; 73653933Shibler else 73753933Shibler err = subyte((caddr_t)f->f_wb3a, f->f_wb3d); 73853933Shibler break; 73953933Shibler case SSW4_SZW: 74053933Shibler if (KDFAULT(f->f_wb3s)) 74153933Shibler *(short *)f->f_wb3a = f->f_wb3d; 74253933Shibler else 74353933Shibler err = susword((caddr_t)f->f_wb3a, f->f_wb3d); 74453933Shibler break; 74553933Shibler #ifdef DEBUG 74653933Shibler case SSW4_SZLN: 74753933Shibler panic("writeback: wb3s indicates LINE write"); 74853933Shibler #endif 74953933Shibler } 75053933Shibler if (err) { 75153933Shibler fa = f->f_wb3a; 75253933Shibler #ifdef DEBUG 75353933Shibler if (mmudebug & MDB_WBFAILED) 75453933Shibler printf(wberrstr, p->p_pid, p->p_comm, 75553933Shibler "#3", fp->f_pc, f->f_fa, 75653933Shibler f->f_wb3a, f->f_wb3d); 75753933Shibler #endif 75853933Shibler } 75953933Shibler } 76053933Shibler p->p_addr->u_pcb.pcb_onfault = oonfault; 76153933Shibler /* 76253933Shibler * Determine the cause of the failure if any translating to 76353933Shibler * a signal. If the corresponding VA is valid and RO it is 76453933Shibler * a protection fault (SIGBUS) otherwise consider it an 76553933Shibler * illegal reference (SIGSEGV). 76653933Shibler */ 76753933Shibler if (err) { 76853933Shibler if (vm_map_check_protection(&p->p_vmspace->vm_map, 76953933Shibler trunc_page(fa), round_page(fa), 77053933Shibler VM_PROT_READ) && 77153933Shibler !vm_map_check_protection(&p->p_vmspace->vm_map, 77253933Shibler trunc_page(fa), round_page(fa), 77353933Shibler VM_PROT_WRITE)) 77453933Shibler err = SIGBUS; 77553933Shibler else 77653933Shibler err = SIGSEGV; 77753933Shibler } 77853933Shibler return(err); 77953933Shibler } 78053933Shibler 78153933Shibler #ifdef DEBUG 78253933Shibler dumpssw(ssw) 78353933Shibler register u_short ssw; 78453933Shibler { 78553933Shibler printf(" SSW: %x: ", ssw); 78653933Shibler if (ssw & SSW4_CP) 78753933Shibler printf("CP,"); 78853933Shibler if (ssw & SSW4_CU) 78953933Shibler printf("CU,"); 79053933Shibler if (ssw & SSW4_CT) 79153933Shibler printf("CT,"); 79253933Shibler if (ssw & SSW4_CM) 79353933Shibler printf("CM,"); 79453933Shibler if (ssw & SSW4_MA) 79553933Shibler printf("MA,"); 79653933Shibler if (ssw & SSW4_ATC) 79753933Shibler printf("ATC,"); 79853933Shibler if (ssw & SSW4_LK) 79953933Shibler printf("LK,"); 80053933Shibler if (ssw & SSW4_RW) 80153933Shibler printf("RW,"); 80253933Shibler printf(" SZ=%s, TT=%s, TM=%s\n", 80353933Shibler f7sz[(ssw & SSW4_SZMASK) >> 5], 80453933Shibler f7tt[(ssw & SSW4_TTMASK) >> 3], 80553933Shibler f7tm[ssw & SSW4_TMMASK]); 80653933Shibler } 80753933Shibler 80853933Shibler dumpwb(num, s, a, d) 80953933Shibler int num; 81053933Shibler u_short s; 81153933Shibler u_int a, d; 81253933Shibler { 81353933Shibler register struct proc *p = curproc; 81453933Shibler vm_offset_t pa; 81553933Shibler 81653933Shibler printf(" writeback #%d: VA %x, data %x, SZ=%s, TT=%s, TM=%s\n", 81753933Shibler num, a, d, f7sz[(s & SSW4_SZMASK) >> 5], 81853933Shibler f7tt[(s & SSW4_TTMASK) >> 3], f7tm[s & SSW4_TMMASK]); 81953933Shibler printf(" PA "); 82053933Shibler pa = pmap_extract(&p->p_vmspace->vm_pmap, (vm_offset_t)a); 82153933Shibler if (pa == 0) 82253933Shibler printf("<invalid address>"); 82353933Shibler else 82453933Shibler printf("%x, current value %x", pa, fuword((caddr_t)a)); 82553933Shibler printf("\n"); 82653933Shibler } 82753933Shibler 82853933Shibler #ifdef HPFPLIB 82953933Shibler fppanic(frame) 83053933Shibler struct fppanicframe { 83153933Shibler int fpsaveframe; 83253933Shibler int regs[16]; 83353933Shibler int fpregs[8*3]; 83453933Shibler int fpcregs[3]; 83553933Shibler int hole[5]; 83653933Shibler int oa6; 83753933Shibler short sr; 83853933Shibler int pc; 83953933Shibler short vector; 84053933Shibler } frame; 84153933Shibler { 84253933Shibler printf("FP exception: pid %d(%s): no busy frame, ft=%x pc=%x vec=%x\n", 84353933Shibler curproc->p_pid, curproc->p_comm, 84453933Shibler frame.fpsaveframe, frame.pc, frame.vector); 84553933Shibler panic("bad FP exception"); 84653933Shibler } 84753933Shibler #endif 84853933Shibler #endif 84953933Shibler #endif 85053933Shibler 85141475Smckusick /* 85249531Skarels * Proces a system call. 85341475Smckusick */ 85441475Smckusick syscall(code, frame) 85554801Storek u_int code; 85641475Smckusick struct frame frame; 85741475Smckusick { 85841475Smckusick register caddr_t params; 85941475Smckusick register struct sysent *callp; 86054801Storek register struct proc *p; 86150753Skarels int error, opc, numsys, s; 86254801Storek u_int argsize; 86344018Skarels struct args { 86444018Skarels int i[8]; 86544018Skarels } args; 86644018Skarels int rval[2]; 86754801Storek u_quad_t sticks; 86841475Smckusick #ifdef HPUXCOMPAT 86941475Smckusick extern struct sysent hpuxsysent[]; 87041475Smckusick extern int hpuxnsysent, notimp(); 87141475Smckusick #endif 87241475Smckusick 87341475Smckusick cnt.v_syscall++; 87441475Smckusick if (!USERMODE(frame.f_sr)) 87541475Smckusick panic("syscall"); 87654801Storek p = curproc; 87754801Storek sticks = p->p_sticks; 87852380Smckusick p->p_md.md_regs = frame.f_regs; 87941475Smckusick opc = frame.f_pc - 2; 88041475Smckusick #ifdef HPUXCOMPAT 88154801Storek if (p->p_flag & SHPUX) 88254801Storek callp = hpuxsysent, numsys = hpuxnsysent; 88354801Storek else 88441475Smckusick #endif 88554801Storek callp = sysent, numsys = nsysent; 88649531Skarels params = (caddr_t)frame.f_regs[SP] + sizeof(int); 88754801Storek switch (code) { 88854801Storek 88954801Storek case SYS_indir: 89054801Storek /* 89154801Storek * Code is first argument, followed by actual args. 89254801Storek */ 89342370Skarels code = fuword(params); 89449531Skarels params += sizeof(int); 89554801Storek break; 89654801Storek 89754801Storek case SYS___indir: 89854801Storek /* 89954801Storek * Like indir, but code is a quad, so as to maintain 90054801Storek * quad alignment for the rest of the arguments. 90154801Storek */ 90241475Smckusick #ifdef HPUXCOMPAT 90341475Smckusick if (p->p_flag & SHPUX) 90454801Storek break; 90541475Smckusick #endif 90654865Smckusick code = fuword(params + _QUAD_LOWWORD * sizeof(int)); 90754865Smckusick params += sizeof(quad_t); 90854801Storek break; 90954801Storek 91054865Smckusick default: 91154865Smckusick /* nothing to do by default */ 91254865Smckusick break; 91354801Storek } 91454801Storek if (code < numsys) 91554801Storek callp += code; 91654801Storek else 91754801Storek callp += SYS_indir; /* => nosys */ 91854801Storek argsize = callp->sy_narg * sizeof(int); 91954801Storek if (argsize && (error = copyin(params, (caddr_t)&args, argsize))) { 92041475Smckusick #ifdef KTRACE 92143641Skarels if (KTRPOINT(p, KTR_SYSCALL)) 92244018Skarels ktrsyscall(p->p_tracep, code, callp->sy_narg, args.i); 92341475Smckusick #endif 92454801Storek goto bad; 92541475Smckusick } 92641475Smckusick #ifdef KTRACE 92743641Skarels if (KTRPOINT(p, KTR_SYSCALL)) 92844018Skarels ktrsyscall(p->p_tracep, code, callp->sy_narg, args.i); 92941475Smckusick #endif 93043641Skarels rval[0] = 0; 93143641Skarels rval[1] = frame.f_regs[D1]; 93241475Smckusick #ifdef HPUXCOMPAT 93342370Skarels /* debug kludge */ 93442370Skarels if (callp->sy_call == notimp) 93548465Skarels error = notimp(p, args.i, rval, code, callp->sy_narg); 93642370Skarels else 93741475Smckusick #endif 93854801Storek error = (*callp->sy_call)(p, &args, rval); 93954801Storek switch (error) { 94042370Skarels 94154801Storek case 0: 94241475Smckusick /* 94354801Storek * Reinitialize proc pointer `p' as it may be different 94454801Storek * if this is a child returning from fork syscall. 94541475Smckusick */ 94654801Storek p = curproc; 94754801Storek frame.f_regs[D0] = rval[0]; 94854801Storek frame.f_regs[D1] = rval[1]; 94954801Storek frame.f_sr &= ~PSL_C; 95054801Storek break; 95141475Smckusick 95254801Storek case ERESTART: 95354801Storek frame.f_pc = opc; 95454801Storek break; 95554801Storek 95654801Storek case EJUSTRETURN: 95754801Storek break; /* nothing to do */ 95854801Storek 95954801Storek default: 96054801Storek bad: 96154801Storek #ifdef HPUXCOMPAT 96254801Storek if (p->p_flag & SHPUX) 96354801Storek error = bsdtohpuxerrno(error); 96441475Smckusick #endif 96554801Storek frame.f_regs[D0] = error; 96654801Storek frame.f_sr |= PSL_C; 96754801Storek break; 96841475Smckusick } 96954801Storek 97054801Storek userret(p, &frame, sticks, (u_int)0, 0); 97141475Smckusick #ifdef KTRACE 97243641Skarels if (KTRPOINT(p, KTR_SYSRET)) 97343641Skarels ktrsysret(p->p_tracep, code, error, rval[0]); 97441475Smckusick #endif 97541475Smckusick } 976