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*54865Smckusick * @(#)trap.c 7.23 (Berkeley) 07/09/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 */ 14654801Storek if (p->p_flag & SPROFIL) 14754801Storek addupc_intr(p, fp->f_pc, (int)(p->p_sticks - oticks)); 14854801Storek #ifdef HP380 14954801Storek /* 15054801Storek * Deal with user mode writebacks (from trap, or from sigreturn). 15154801Storek * If any writeback fails, go back and attempt signal delivery. 15254801Storek * unless we have already been here and attempted the writeback 15354801Storek * (e.g. bad address with user ignoring SIGSEGV). In that case 15454801Storek * we just return to the user without sucessfully completing 15554801Storek * the writebacks. Maybe we should just drop the sucker? 15654801Storek */ 15754801Storek if (mmutype == MMU_68040 && fp->f_format == FMT7) { 15854801Storek if (beenhere) { 15954801Storek #ifdef DEBUG 16054801Storek if (mmudebug & MDB_WBFAILED) 16154801Storek printf(fromtrap ? 16254801Storek "pid %d(%s): writeback aborted, pc=%x, fa=%x\n" : 16354801Storek "pid %d(%s): writeback aborted in sigreturn, pc=%x\n", 16454801Storek p->p_pid, p->p_comm, fp->f_pc, faultaddr); 16554801Storek #endif 16654801Storek } else if (sig = writeback(fp, fromtrap)) { 16754801Storek beenhere = 1; 16854801Storek oticks = p->p_sticks; 16954801Storek trapsignal(p, sig, faultaddr); 17054801Storek goto again; 17154801Storek } 17254801Storek } 17354801Storek #endif 17454801Storek curpri = p->p_pri; 17554801Storek } 17654801Storek 17754801Storek /* 17849531Skarels * Trap is called from locore to handle most types of processor traps, 17949531Skarels * including events such as simulated software interrupts/AST's. 18049531Skarels * System calls are broken out for efficiency. 18141475Smckusick */ 18241475Smckusick /*ARGSUSED*/ 18341475Smckusick trap(type, code, v, frame) 18441475Smckusick int type; 18541475Smckusick unsigned code; 18641475Smckusick register unsigned v; 18741475Smckusick struct frame frame; 18841475Smckusick { 18941475Smckusick register int i; 19054801Storek unsigned ucode; 19154801Storek register struct proc *p; 19254801Storek u_quad_t sticks; 19341475Smckusick unsigned ncode; 19454574Storek extern char fswintr[]; 19541475Smckusick 19641475Smckusick cnt.v_trap++; 19754801Storek p = curproc; 19854801Storek ucode = 0; 19941475Smckusick if (USERMODE(frame.f_sr)) { 20049531Skarels type |= T_USER; 20154801Storek sticks = p->p_sticks; 20252380Smckusick p->p_md.md_regs = frame.f_regs; 20341475Smckusick } 20441475Smckusick switch (type) { 20541475Smckusick 20641475Smckusick default: 20741475Smckusick dopanic: 20841475Smckusick printf("trap type %d, code = %x, v = %x\n", type, code, v); 20941475Smckusick regdump(frame.f_regs, 128); 21049531Skarels type &= ~T_USER; 21141475Smckusick if ((unsigned)type < TRAP_TYPES) 21241475Smckusick panic(trap_type[type]); 21341475Smckusick panic("trap"); 21441475Smckusick 21541475Smckusick case T_BUSERR: /* kernel bus error */ 21649125Skarels if (!p->p_addr->u_pcb.pcb_onfault) 21741475Smckusick goto dopanic; 21841475Smckusick /* 21941475Smckusick * If we have arranged to catch this fault in any of the 22041475Smckusick * copy to/from user space routines, set PC to return to 22141475Smckusick * indicated location and set flag informing buserror code 22241475Smckusick * that it may need to clean up stack frame. 22341475Smckusick */ 22441475Smckusick copyfault: 22549317Shibler frame.f_stackadj = exframesize[frame.f_format]; 22649317Shibler frame.f_format = frame.f_vector = 0; 22749125Skarels frame.f_pc = (int) p->p_addr->u_pcb.pcb_onfault; 22841475Smckusick return; 22941475Smckusick 23049531Skarels case T_BUSERR|T_USER: /* bus error */ 23149531Skarels case T_ADDRERR|T_USER: /* address error */ 23253933Shibler ucode = v; 23341475Smckusick i = SIGBUS; 23441475Smckusick break; 23541475Smckusick 23641475Smckusick #ifdef FPCOPROC 23741475Smckusick case T_COPERR: /* kernel coprocessor violation */ 23841475Smckusick #endif 23953933Shibler case T_FMTERR|T_USER: /* do all RTE errors come in as T_USER? */ 24053933Shibler case T_FMTERR: /* ...just in case... */ 24141475Smckusick /* 24241475Smckusick * The user has most likely trashed the RTE or FP state info 24341475Smckusick * in the stack frame of a signal handler. 24441475Smckusick */ 24549531Skarels type |= T_USER; 24648465Skarels printf("pid %d: kernel %s exception\n", p->p_pid, 24741475Smckusick type==T_COPERR ? "coprocessor" : "format"); 24848465Skarels p->p_sigacts->ps_sigact[SIGILL] = SIG_DFL; 24941475Smckusick i = sigmask(SIGILL); 25041475Smckusick p->p_sigignore &= ~i; 25141475Smckusick p->p_sigcatch &= ~i; 25241475Smckusick p->p_sigmask &= ~i; 25342370Skarels i = SIGILL; 25441475Smckusick ucode = frame.f_format; /* XXX was ILL_RESAD_FAULT */ 25542370Skarels break; 25641475Smckusick 25741475Smckusick #ifdef FPCOPROC 25849531Skarels case T_COPERR|T_USER: /* user coprocessor violation */ 25941475Smckusick /* What is a proper response here? */ 26041475Smckusick ucode = 0; 26141475Smckusick i = SIGFPE; 26241475Smckusick break; 26341475Smckusick 26449531Skarels case T_FPERR|T_USER: /* 68881 exceptions */ 26541475Smckusick /* 26641475Smckusick * We pass along the 68881 status register which locore stashed 26741475Smckusick * in code for us. Note that there is a possibility that the 26841475Smckusick * bit pattern of this register will conflict with one of the 26941475Smckusick * FPE_* codes defined in signal.h. Fortunately for us, the 27041475Smckusick * only such codes we use are all in the range 1-7 and the low 27141475Smckusick * 3 bits of the status register are defined as 0 so there is 27241475Smckusick * no clash. 27341475Smckusick */ 27441475Smckusick ucode = code; 27541475Smckusick i = SIGFPE; 27641475Smckusick break; 27741475Smckusick #endif 27841475Smckusick 27954801Storek #ifdef HP380 28053933Shibler case T_FPEMULI|T_USER: /* unimplemented FP instuction */ 28153933Shibler case T_FPEMULD|T_USER: /* unimplemented FP data type */ 28253933Shibler /* XXX need to FSAVE */ 28353933Shibler printf("pid %d(%s): unimplemented FP %s at %x (EA %x)\n", 28453933Shibler p->p_pid, p->p_comm, 28553933Shibler frame.f_format == 2 ? "instruction" : "data type", 28653933Shibler frame.f_pc, frame.f_fmt2.f_iaddr); 28753933Shibler /* XXX need to FRESTORE */ 28853933Shibler i = SIGFPE; 28953933Shibler break; 29053933Shibler #endif 29153933Shibler 29249531Skarels case T_ILLINST|T_USER: /* illegal instruction fault */ 29341475Smckusick #ifdef HPUXCOMPAT 29448465Skarels if (p->p_flag & SHPUX) { 29541475Smckusick ucode = HPUX_ILL_ILLINST_TRAP; 29641475Smckusick i = SIGILL; 29741475Smckusick break; 29841475Smckusick } 29941475Smckusick /* fall through */ 30041475Smckusick #endif 30149531Skarels case T_PRIVINST|T_USER: /* privileged instruction fault */ 30241475Smckusick #ifdef HPUXCOMPAT 30348465Skarels if (p->p_flag & SHPUX) 30441475Smckusick ucode = HPUX_ILL_PRIV_TRAP; 30541475Smckusick else 30641475Smckusick #endif 30741475Smckusick ucode = frame.f_format; /* XXX was ILL_PRIVIN_FAULT */ 30841475Smckusick i = SIGILL; 30941475Smckusick break; 31041475Smckusick 31149531Skarels case T_ZERODIV|T_USER: /* Divide by zero */ 31241475Smckusick #ifdef HPUXCOMPAT 31348465Skarels if (p->p_flag & SHPUX) 31441475Smckusick ucode = HPUX_FPE_INTDIV_TRAP; 31541475Smckusick else 31641475Smckusick #endif 31741475Smckusick ucode = frame.f_format; /* XXX was FPE_INTDIV_TRAP */ 31841475Smckusick i = SIGFPE; 31941475Smckusick break; 32041475Smckusick 32149531Skarels case T_CHKINST|T_USER: /* CHK instruction trap */ 32241475Smckusick #ifdef HPUXCOMPAT 32348465Skarels if (p->p_flag & SHPUX) { 32441475Smckusick /* handled differently under hp-ux */ 32541475Smckusick i = SIGILL; 32641475Smckusick ucode = HPUX_ILL_CHK_TRAP; 32741475Smckusick break; 32841475Smckusick } 32941475Smckusick #endif 33041475Smckusick ucode = frame.f_format; /* XXX was FPE_SUBRNG_TRAP */ 33141475Smckusick i = SIGFPE; 33241475Smckusick break; 33341475Smckusick 33449531Skarels case T_TRAPVINST|T_USER: /* TRAPV instruction trap */ 33541475Smckusick #ifdef HPUXCOMPAT 33648465Skarels if (p->p_flag & SHPUX) { 33741475Smckusick /* handled differently under hp-ux */ 33841475Smckusick i = SIGILL; 33941475Smckusick ucode = HPUX_ILL_TRAPV_TRAP; 34041475Smckusick break; 34141475Smckusick } 34241475Smckusick #endif 34341475Smckusick ucode = frame.f_format; /* XXX was FPE_INTOVF_TRAP */ 34441475Smckusick i = SIGFPE; 34541475Smckusick break; 34641475Smckusick 34741475Smckusick /* 34841475Smckusick * XXX: Trace traps are a nightmare. 34941475Smckusick * 35041475Smckusick * HP-UX uses trap #1 for breakpoints, 35141475Smckusick * HPBSD uses trap #2, 35241475Smckusick * SUN 3.x uses trap #15, 35348465Skarels * KGDB uses trap #15 (for kernel breakpoints; handled elsewhere). 35441475Smckusick * 35541475Smckusick * HPBSD and HP-UX traps both get mapped by locore.s into T_TRACE. 35641475Smckusick * SUN 3.x traps get passed through as T_TRAP15 and are not really 35748465Skarels * supported yet. 35841475Smckusick */ 35941475Smckusick case T_TRACE: /* kernel trace trap */ 36048465Skarels case T_TRAP15: /* SUN trace trap */ 36141475Smckusick frame.f_sr &= ~PSL_T; 36241475Smckusick i = SIGTRAP; 36341475Smckusick break; 36441475Smckusick 36549531Skarels case T_TRACE|T_USER: /* user trace trap */ 36649531Skarels case T_TRAP15|T_USER: /* SUN user trace trap */ 36741475Smckusick frame.f_sr &= ~PSL_T; 36841475Smckusick i = SIGTRAP; 36941475Smckusick break; 37041475Smckusick 37143413Shibler case T_ASTFLT: /* system async trap, cannot happen */ 37241475Smckusick goto dopanic; 37341475Smckusick 37449531Skarels case T_ASTFLT|T_USER: /* user async trap */ 37549125Skarels astpending = 0; 37641475Smckusick /* 37741475Smckusick * We check for software interrupts first. This is because 37841475Smckusick * they are at a higher level than ASTs, and on a VAX would 37941475Smckusick * interrupt the AST. We assume that if we are processing 38041475Smckusick * an AST that we must be at IPL0 so we don't bother to 38141475Smckusick * check. Note that we ensure that we are at least at SIR 38241475Smckusick * IPL while processing the SIR. 38341475Smckusick */ 38441475Smckusick spl1(); 38541475Smckusick /* fall into... */ 38641475Smckusick 38741475Smckusick case T_SSIR: /* software interrupt */ 38849531Skarels case T_SSIR|T_USER: 38941475Smckusick if (ssir & SIR_NET) { 39041475Smckusick siroff(SIR_NET); 39141475Smckusick cnt.v_soft++; 39241475Smckusick netintr(); 39341475Smckusick } 39441475Smckusick if (ssir & SIR_CLOCK) { 39541475Smckusick siroff(SIR_CLOCK); 39641475Smckusick cnt.v_soft++; 39754801Storek softclock(); 39841475Smckusick } 39941475Smckusick /* 40041475Smckusick * If this was not an AST trap, we are all done. 40141475Smckusick */ 40250753Skarels if (type != (T_ASTFLT|T_USER)) { 40341475Smckusick cnt.v_trap--; 40441475Smckusick return; 40541475Smckusick } 40641475Smckusick spl0(); 40754801Storek if (p->p_flag & SOWEUPC) { 40848465Skarels p->p_flag &= ~SOWEUPC; 40954801Storek ADDUPROF(p); 41041475Smckusick } 41141475Smckusick goto out; 41241475Smckusick 41341475Smckusick case T_MMUFLT: /* kernel mode page fault */ 41454574Storek /* 41554574Storek * If we were doing profiling ticks or other user mode 41654574Storek * stuff from interrupt code, Just Say No. 41754574Storek */ 41854574Storek if (p->p_addr->u_pcb.pcb_onfault == fswintr) 41954574Storek goto copyfault; 42041475Smckusick /* fall into ... */ 42141475Smckusick 42249531Skarels case T_MMUFLT|T_USER: /* page fault */ 42345751Smckusick { 42445751Smckusick register vm_offset_t va; 42548465Skarels register struct vmspace *vm = p->p_vmspace; 42645751Smckusick register vm_map_t map; 42745751Smckusick int rv; 42845751Smckusick vm_prot_t ftype; 42945751Smckusick extern vm_map_t kernel_map; 43045751Smckusick 43153933Shibler #ifdef DEBUG 43253933Shibler if ((mmudebug & MDB_WBFOLLOW) || MDB_ISPID(p->p_pid)) 43353933Shibler printf("trap: T_MMUFLT pid=%d, code=%x, v=%x, pc=%x, sr=%x\n", 43453933Shibler p->p_pid, code, v, frame.f_pc, frame.f_sr); 43553933Shibler #endif 43641475Smckusick /* 43745751Smckusick * It is only a kernel address space fault iff: 43849531Skarels * 1. (type & T_USER) == 0 and 43945751Smckusick * 2. pcb_onfault not set or 44045751Smckusick * 3. pcb_onfault set but supervisor space data fault 44145751Smckusick * The last can occur during an exec() copyin where the 44245751Smckusick * argument space is lazy-allocated. 44341475Smckusick */ 44445751Smckusick if (type == T_MMUFLT && 44553933Shibler (!p->p_addr->u_pcb.pcb_onfault || KDFAULT(code))) 44645751Smckusick map = kernel_map; 44745751Smckusick else 44848465Skarels map = &vm->vm_map; 44953933Shibler if (WRFAULT(code)) 45045751Smckusick ftype = VM_PROT_READ | VM_PROT_WRITE; 45145751Smckusick else 45245751Smckusick ftype = VM_PROT_READ; 45345751Smckusick va = trunc_page((vm_offset_t)v); 45441475Smckusick #ifdef DEBUG 45545751Smckusick if (map == kernel_map && va == 0) { 45645751Smckusick printf("trap: bad kernel access at %x\n", v); 45741475Smckusick goto dopanic; 45841475Smckusick } 45941475Smckusick #endif 46049317Shibler rv = vm_fault(map, va, ftype, FALSE); 46153933Shibler #ifdef DEBUG 46253933Shibler if (rv && MDB_ISPID(p->p_pid)) 46353933Shibler printf("vm_fault(%x, %x, %x, 0) -> %x\n", 46453933Shibler map, va, ftype, rv); 46553933Shibler #endif 46641475Smckusick /* 46749317Shibler * If this was a stack access we keep track of the maximum 46849317Shibler * accessed stack size. Also, if vm_fault gets a protection 46949317Shibler * failure it is due to accessing the stack region outside 47049317Shibler * the current limit and we need to reflect that as an access 47149317Shibler * error. 47241475Smckusick */ 47348465Skarels if ((caddr_t)va >= vm->vm_maxsaddr && map != kernel_map) { 47449317Shibler if (rv == KERN_SUCCESS) { 47549317Shibler unsigned nss; 47649317Shibler 47749317Shibler nss = clrnd(btoc(USRSTACK-(unsigned)va)); 47849317Shibler if (nss > vm->vm_ssize) 47949317Shibler vm->vm_ssize = nss; 48049317Shibler } else if (rv == KERN_PROTECTION_FAILURE) 48149317Shibler rv = KERN_INVALID_ADDRESS; 48241475Smckusick } 48345751Smckusick if (rv == KERN_SUCCESS) { 48453933Shibler if (type == T_MMUFLT) { 48554801Storek #ifdef HP380 48653933Shibler if (mmutype == MMU_68040) 48753933Shibler (void) writeback(&frame, 1); 48853933Shibler #endif 48941475Smckusick return; 49053933Shibler } 49141475Smckusick goto out; 49241475Smckusick } 49345751Smckusick if (type == T_MMUFLT) { 49449125Skarels if (p->p_addr->u_pcb.pcb_onfault) 49545751Smckusick goto copyfault; 49645751Smckusick printf("vm_fault(%x, %x, %x, 0) -> %x\n", 49745751Smckusick map, va, ftype, rv); 49845751Smckusick printf(" type %x, code [mmu,,ssw]: %x\n", 49945751Smckusick type, code); 50045751Smckusick goto dopanic; 50145751Smckusick } 50248465Skarels ucode = v; 50345751Smckusick i = (rv == KERN_PROTECTION_FAILURE) ? SIGBUS : SIGSEGV; 50445751Smckusick break; 50545751Smckusick } 50641475Smckusick } 50748465Skarels trapsignal(p, i, ucode); 50849531Skarels if ((type & T_USER) == 0) 50941475Smckusick return; 51041475Smckusick out: 51154801Storek userret(p, &frame, sticks, v, 1); 51241475Smckusick } 51341475Smckusick 51454801Storek #ifdef HP380 51553933Shibler #ifdef DEBUG 51653933Shibler struct writebackstats { 51753933Shibler int calls; 51853933Shibler int cpushes; 51953933Shibler int move16s; 52053933Shibler int wb1s, wb2s, wb3s; 52153933Shibler int wbsize[4]; 52253933Shibler } wbstats; 52353933Shibler 52453933Shibler char *f7sz[] = { "longword", "byte", "word", "line" }; 52553933Shibler char *f7tt[] = { "normal", "MOVE16", "AFC", "ACK" }; 52653933Shibler char *f7tm[] = { "d-push", "u-data", "u-code", "M-data", 52753933Shibler "M-code", "k-data", "k-code", "RES" }; 52853933Shibler char wberrstr[] = 52953933Shibler "WARNING: pid %d(%s) writeback [%s] failed, pc=%x fa=%x wba=%x wbd=%x\n"; 53053933Shibler #endif 53153933Shibler 53253933Shibler writeback(fp, docachepush) 53353933Shibler struct frame *fp; 53453933Shibler int docachepush; 53553933Shibler { 53653933Shibler register struct fmt7 *f = &fp->f_fmt7; 53753933Shibler register struct proc *p = curproc; 53853933Shibler int err = 0; 53953933Shibler u_int fa; 54053933Shibler caddr_t oonfault = p->p_addr->u_pcb.pcb_onfault; 54153933Shibler 54253933Shibler #ifdef DEBUG 54353933Shibler if ((mmudebug & MDB_WBFOLLOW) || MDB_ISPID(p->p_pid)) { 54453933Shibler printf(" pid=%d, fa=%x,", p->p_pid, f->f_fa); 54553933Shibler dumpssw(f->f_ssw); 54653933Shibler } 54753933Shibler wbstats.calls++; 54853933Shibler #endif 54953933Shibler /* 55053933Shibler * Deal with special cases first. 55153933Shibler */ 55253933Shibler if ((f->f_ssw & SSW4_TMMASK) == SSW4_TMDCP) { 55353933Shibler /* 55453933Shibler * Dcache push fault. 55553933Shibler * Line-align the address and write out the push data to 55653933Shibler * the indicated physical address. 55753933Shibler */ 55853933Shibler #ifdef DEBUG 55953933Shibler if ((mmudebug & MDB_WBFOLLOW) || MDB_ISPID(p->p_pid)) { 56053933Shibler printf(" pushing %s to PA %x, data %x", 56153933Shibler f7sz[(f->f_ssw & SSW4_SZMASK) >> 5], 56253933Shibler f->f_fa, f->f_pd0); 56353933Shibler if ((f->f_ssw & SSW4_SZMASK) == SSW4_SZLN) 56453933Shibler printf("/%x/%x/%x", 56553933Shibler f->f_pd1, f->f_pd2, f->f_pd3); 56653933Shibler printf("\n"); 56753933Shibler } 56853933Shibler if (f->f_wb1s & SSW4_WBSV) 56953933Shibler panic("writeback: cache push with WB1S valid"); 57053933Shibler wbstats.cpushes++; 57153933Shibler #endif 57253933Shibler /* 57353933Shibler * XXX there are security problems if we attempt to do a 57453933Shibler * cache push after a signal handler has been called. 57553933Shibler */ 57653933Shibler if (docachepush) { 57753933Shibler pmap_enter(kernel_pmap, (vm_offset_t)vmmap, 57853933Shibler trunc_page(f->f_fa), VM_PROT_WRITE, TRUE); 57953933Shibler fa = (u_int)&vmmap[(f->f_fa & PGOFSET) & ~0xF]; 58053933Shibler bcopy((caddr_t)&f->f_pd0, (caddr_t)fa, 16); 58153933Shibler DCFL(pmap_extract(kernel_pmap, (vm_offset_t)fa)); 58253933Shibler pmap_remove(kernel_pmap, (vm_offset_t)vmmap, 58353933Shibler (vm_offset_t)&vmmap[NBPG]); 58453933Shibler } else 58553933Shibler printf("WARNING: pid %d(%s) uid %d: CPUSH not done\n", 58653933Shibler p->p_pid, p->p_comm, p->p_ucred->cr_uid); 58753933Shibler } else if ((f->f_ssw & (SSW4_RW|SSW4_TTMASK)) == SSW4_TTM16) { 58853933Shibler /* 58953933Shibler * MOVE16 fault. 59053933Shibler * Line-align the address and write out the push data to 59153933Shibler * the indicated virtual address. 59253933Shibler */ 59353933Shibler #ifdef DEBUG 59453933Shibler if ((mmudebug & MDB_WBFOLLOW) || MDB_ISPID(p->p_pid)) 59553933Shibler printf(" MOVE16 to VA %x(%x), data %x/%x/%x/%x\n", 59653933Shibler f->f_fa, f->f_fa & ~0xF, f->f_pd0, f->f_pd1, 59753933Shibler f->f_pd2, f->f_pd3); 59853933Shibler if (f->f_wb1s & SSW4_WBSV) 59953933Shibler panic("writeback: MOVE16 with WB1S valid"); 60053933Shibler wbstats.move16s++; 60153933Shibler #endif 60253933Shibler if (KDFAULT(f->f_wb1s)) 60353933Shibler bcopy((caddr_t)&f->f_pd0, (caddr_t)(f->f_fa & ~0xF), 16); 60453933Shibler else 60553933Shibler err = suline((caddr_t)(f->f_fa & ~0xF), (caddr_t)&f->f_pd0); 60653933Shibler if (err) { 60753933Shibler fa = f->f_fa & ~0xF; 60853933Shibler #ifdef DEBUG 60953933Shibler if (mmudebug & MDB_WBFAILED) 61053933Shibler printf(wberrstr, p->p_pid, p->p_comm, 61153933Shibler "MOVE16", fp->f_pc, f->f_fa, 61253933Shibler f->f_fa & ~0xF, f->f_pd0); 61353933Shibler #endif 61453933Shibler } 61553933Shibler } else if (f->f_wb1s & SSW4_WBSV) { 61653933Shibler /* 61753933Shibler * Writeback #1. 61853933Shibler * Position the "memory-aligned" data and write it out. 61953933Shibler */ 62053933Shibler register u_int wb1d = f->f_wb1d; 62153933Shibler register int off; 62253933Shibler 62353933Shibler #ifdef DEBUG 62453933Shibler if ((mmudebug & MDB_WBFOLLOW) || MDB_ISPID(p->p_pid)) 62553933Shibler dumpwb(1, f->f_wb1s, f->f_wb1a, f->f_wb1d); 62653933Shibler wbstats.wb1s++; 62753933Shibler wbstats.wbsize[(f->f_wb2s&SSW4_SZMASK)>>5]++; 62853933Shibler #endif 62953933Shibler off = (f->f_wb1a & 3) * 8; 63053933Shibler switch (f->f_wb1s & SSW4_SZMASK) { 63153933Shibler case SSW4_SZLW: 63253933Shibler if (off) 63353933Shibler wb1d = (wb1d >> (32 - off)) | (wb1d << off); 63453933Shibler if (KDFAULT(f->f_wb1s)) 63553933Shibler *(long *)f->f_wb1a = wb1d; 63653933Shibler else 63753933Shibler err = suword((caddr_t)f->f_wb1a, wb1d); 63853933Shibler break; 63953933Shibler case SSW4_SZB: 64053933Shibler off = 24 - off; 64153933Shibler if (off) 64253933Shibler wb1d >>= off; 64353933Shibler if (KDFAULT(f->f_wb1s)) 64453933Shibler *(char *)f->f_wb1a = wb1d; 64553933Shibler else 64653933Shibler err = subyte((caddr_t)f->f_wb1a, wb1d); 64753933Shibler break; 64853933Shibler case SSW4_SZW: 64953933Shibler off = (off + 16) % 32; 65053933Shibler if (off) 65153933Shibler wb1d = (wb1d >> (32 - off)) | (wb1d << off); 65253933Shibler if (KDFAULT(f->f_wb1s)) 65353933Shibler *(short *)f->f_wb1a = wb1d; 65453933Shibler else 65553933Shibler err = susword((caddr_t)f->f_wb1a, wb1d); 65653933Shibler break; 65753933Shibler } 65853933Shibler if (err) { 65953933Shibler fa = f->f_wb1a; 66053933Shibler #ifdef DEBUG 66153933Shibler if (mmudebug & MDB_WBFAILED) 66253933Shibler printf(wberrstr, p->p_pid, p->p_comm, 66353933Shibler "#1", fp->f_pc, f->f_fa, 66453933Shibler f->f_wb1a, f->f_wb1d); 66553933Shibler #endif 66653933Shibler } 66753933Shibler } 66853933Shibler /* 66953933Shibler * Deal with the "normal" writebacks. 67053933Shibler * 67153933Shibler * XXX writeback2 is known to reflect a LINE size writeback after 67253933Shibler * a MOVE16 was already dealt with above. Ignore it. 67353933Shibler */ 67453933Shibler if (err == 0 && (f->f_wb2s & SSW4_WBSV) && 67553933Shibler (f->f_wb2s & SSW4_SZMASK) != SSW4_SZLN) { 67653933Shibler #ifdef DEBUG 67753933Shibler if ((mmudebug & MDB_WBFOLLOW) || MDB_ISPID(p->p_pid)) 67853933Shibler dumpwb(2, f->f_wb2s, f->f_wb2a, f->f_wb2d); 67953933Shibler wbstats.wb2s++; 68053933Shibler wbstats.wbsize[(f->f_wb2s&SSW4_SZMASK)>>5]++; 68153933Shibler #endif 68253933Shibler switch (f->f_wb2s & SSW4_SZMASK) { 68353933Shibler case SSW4_SZLW: 68453933Shibler if (KDFAULT(f->f_wb2s)) 68553933Shibler *(long *)f->f_wb2a = f->f_wb2d; 68653933Shibler else 68753933Shibler err = suword((caddr_t)f->f_wb2a, f->f_wb2d); 68853933Shibler break; 68953933Shibler case SSW4_SZB: 69053933Shibler if (KDFAULT(f->f_wb2s)) 69153933Shibler *(char *)f->f_wb2a = f->f_wb2d; 69253933Shibler else 69353933Shibler err = subyte((caddr_t)f->f_wb2a, f->f_wb2d); 69453933Shibler break; 69553933Shibler case SSW4_SZW: 69653933Shibler if (KDFAULT(f->f_wb2s)) 69753933Shibler *(short *)f->f_wb2a = f->f_wb2d; 69853933Shibler else 69953933Shibler err = susword((caddr_t)f->f_wb2a, f->f_wb2d); 70053933Shibler break; 70153933Shibler } 70253933Shibler if (err) { 70353933Shibler fa = f->f_wb2a; 70453933Shibler #ifdef DEBUG 70553933Shibler if (mmudebug & MDB_WBFAILED) { 70653933Shibler printf(wberrstr, p->p_pid, p->p_comm, 70753933Shibler "#2", fp->f_pc, f->f_fa, 70853933Shibler f->f_wb2a, f->f_wb2d); 70953933Shibler dumpssw(f->f_ssw); 71053933Shibler dumpwb(2, f->f_wb2s, f->f_wb2a, f->f_wb2d); 71153933Shibler } 71253933Shibler #endif 71353933Shibler } 71453933Shibler } 71553933Shibler if (err == 0 && (f->f_wb3s & SSW4_WBSV)) { 71653933Shibler #ifdef DEBUG 71753933Shibler if ((mmudebug & MDB_WBFOLLOW) || MDB_ISPID(p->p_pid)) 71853933Shibler dumpwb(3, f->f_wb3s, f->f_wb3a, f->f_wb3d); 71953933Shibler wbstats.wb3s++; 72053933Shibler wbstats.wbsize[(f->f_wb3s&SSW4_SZMASK)>>5]++; 72153933Shibler #endif 72253933Shibler switch (f->f_wb3s & SSW4_SZMASK) { 72353933Shibler case SSW4_SZLW: 72453933Shibler if (KDFAULT(f->f_wb3s)) 72553933Shibler *(long *)f->f_wb3a = f->f_wb3d; 72653933Shibler else 72753933Shibler err = suword((caddr_t)f->f_wb3a, f->f_wb3d); 72853933Shibler break; 72953933Shibler case SSW4_SZB: 73053933Shibler if (KDFAULT(f->f_wb3s)) 73153933Shibler *(char *)f->f_wb3a = f->f_wb3d; 73253933Shibler else 73353933Shibler err = subyte((caddr_t)f->f_wb3a, f->f_wb3d); 73453933Shibler break; 73553933Shibler case SSW4_SZW: 73653933Shibler if (KDFAULT(f->f_wb3s)) 73753933Shibler *(short *)f->f_wb3a = f->f_wb3d; 73853933Shibler else 73953933Shibler err = susword((caddr_t)f->f_wb3a, f->f_wb3d); 74053933Shibler break; 74153933Shibler #ifdef DEBUG 74253933Shibler case SSW4_SZLN: 74353933Shibler panic("writeback: wb3s indicates LINE write"); 74453933Shibler #endif 74553933Shibler } 74653933Shibler if (err) { 74753933Shibler fa = f->f_wb3a; 74853933Shibler #ifdef DEBUG 74953933Shibler if (mmudebug & MDB_WBFAILED) 75053933Shibler printf(wberrstr, p->p_pid, p->p_comm, 75153933Shibler "#3", fp->f_pc, f->f_fa, 75253933Shibler f->f_wb3a, f->f_wb3d); 75353933Shibler #endif 75453933Shibler } 75553933Shibler } 75653933Shibler p->p_addr->u_pcb.pcb_onfault = oonfault; 75753933Shibler /* 75853933Shibler * Determine the cause of the failure if any translating to 75953933Shibler * a signal. If the corresponding VA is valid and RO it is 76053933Shibler * a protection fault (SIGBUS) otherwise consider it an 76153933Shibler * illegal reference (SIGSEGV). 76253933Shibler */ 76353933Shibler if (err) { 76453933Shibler if (vm_map_check_protection(&p->p_vmspace->vm_map, 76553933Shibler trunc_page(fa), round_page(fa), 76653933Shibler VM_PROT_READ) && 76753933Shibler !vm_map_check_protection(&p->p_vmspace->vm_map, 76853933Shibler trunc_page(fa), round_page(fa), 76953933Shibler VM_PROT_WRITE)) 77053933Shibler err = SIGBUS; 77153933Shibler else 77253933Shibler err = SIGSEGV; 77353933Shibler } 77453933Shibler return(err); 77553933Shibler } 77653933Shibler 77753933Shibler #ifdef DEBUG 77853933Shibler dumpssw(ssw) 77953933Shibler register u_short ssw; 78053933Shibler { 78153933Shibler printf(" SSW: %x: ", ssw); 78253933Shibler if (ssw & SSW4_CP) 78353933Shibler printf("CP,"); 78453933Shibler if (ssw & SSW4_CU) 78553933Shibler printf("CU,"); 78653933Shibler if (ssw & SSW4_CT) 78753933Shibler printf("CT,"); 78853933Shibler if (ssw & SSW4_CM) 78953933Shibler printf("CM,"); 79053933Shibler if (ssw & SSW4_MA) 79153933Shibler printf("MA,"); 79253933Shibler if (ssw & SSW4_ATC) 79353933Shibler printf("ATC,"); 79453933Shibler if (ssw & SSW4_LK) 79553933Shibler printf("LK,"); 79653933Shibler if (ssw & SSW4_RW) 79753933Shibler printf("RW,"); 79853933Shibler printf(" SZ=%s, TT=%s, TM=%s\n", 79953933Shibler f7sz[(ssw & SSW4_SZMASK) >> 5], 80053933Shibler f7tt[(ssw & SSW4_TTMASK) >> 3], 80153933Shibler f7tm[ssw & SSW4_TMMASK]); 80253933Shibler } 80353933Shibler 80453933Shibler dumpwb(num, s, a, d) 80553933Shibler int num; 80653933Shibler u_short s; 80753933Shibler u_int a, d; 80853933Shibler { 80953933Shibler register struct proc *p = curproc; 81053933Shibler vm_offset_t pa; 81153933Shibler 81253933Shibler printf(" writeback #%d: VA %x, data %x, SZ=%s, TT=%s, TM=%s\n", 81353933Shibler num, a, d, f7sz[(s & SSW4_SZMASK) >> 5], 81453933Shibler f7tt[(s & SSW4_TTMASK) >> 3], f7tm[s & SSW4_TMMASK]); 81553933Shibler printf(" PA "); 81653933Shibler pa = pmap_extract(&p->p_vmspace->vm_pmap, (vm_offset_t)a); 81753933Shibler if (pa == 0) 81853933Shibler printf("<invalid address>"); 81953933Shibler else 82053933Shibler printf("%x, current value %x", pa, fuword((caddr_t)a)); 82153933Shibler printf("\n"); 82253933Shibler } 82353933Shibler 82453933Shibler #ifdef HPFPLIB 82553933Shibler fppanic(frame) 82653933Shibler struct fppanicframe { 82753933Shibler int fpsaveframe; 82853933Shibler int regs[16]; 82953933Shibler int fpregs[8*3]; 83053933Shibler int fpcregs[3]; 83153933Shibler int hole[5]; 83253933Shibler int oa6; 83353933Shibler short sr; 83453933Shibler int pc; 83553933Shibler short vector; 83653933Shibler } frame; 83753933Shibler { 83853933Shibler printf("FP exception: pid %d(%s): no busy frame, ft=%x pc=%x vec=%x\n", 83953933Shibler curproc->p_pid, curproc->p_comm, 84053933Shibler frame.fpsaveframe, frame.pc, frame.vector); 84153933Shibler panic("bad FP exception"); 84253933Shibler } 84353933Shibler #endif 84453933Shibler #endif 84553933Shibler #endif 84653933Shibler 84741475Smckusick /* 84849531Skarels * Proces a system call. 84941475Smckusick */ 85041475Smckusick syscall(code, frame) 85154801Storek u_int code; 85241475Smckusick struct frame frame; 85341475Smckusick { 85441475Smckusick register caddr_t params; 85541475Smckusick register struct sysent *callp; 85654801Storek register struct proc *p; 85750753Skarels int error, opc, numsys, s; 85854801Storek u_int argsize; 85944018Skarels struct args { 86044018Skarels int i[8]; 86144018Skarels } args; 86244018Skarels int rval[2]; 86354801Storek u_quad_t sticks; 86441475Smckusick #ifdef HPUXCOMPAT 86541475Smckusick extern struct sysent hpuxsysent[]; 86641475Smckusick extern int hpuxnsysent, notimp(); 86741475Smckusick #endif 86841475Smckusick 86941475Smckusick cnt.v_syscall++; 87041475Smckusick if (!USERMODE(frame.f_sr)) 87141475Smckusick panic("syscall"); 87254801Storek p = curproc; 87354801Storek sticks = p->p_sticks; 87452380Smckusick p->p_md.md_regs = frame.f_regs; 87541475Smckusick opc = frame.f_pc - 2; 87641475Smckusick #ifdef HPUXCOMPAT 87754801Storek if (p->p_flag & SHPUX) 87854801Storek callp = hpuxsysent, numsys = hpuxnsysent; 87954801Storek else 88041475Smckusick #endif 88154801Storek callp = sysent, numsys = nsysent; 88249531Skarels params = (caddr_t)frame.f_regs[SP] + sizeof(int); 88354801Storek switch (code) { 88454801Storek 88554801Storek case SYS_indir: 88654801Storek /* 88754801Storek * Code is first argument, followed by actual args. 88854801Storek */ 88942370Skarels code = fuword(params); 89049531Skarels params += sizeof(int); 89154801Storek break; 89254801Storek 89354801Storek case SYS___indir: 89454801Storek /* 89554801Storek * Like indir, but code is a quad, so as to maintain 89654801Storek * quad alignment for the rest of the arguments. 89754801Storek */ 89841475Smckusick #ifdef HPUXCOMPAT 89941475Smckusick if (p->p_flag & SHPUX) 90054801Storek break; 90141475Smckusick #endif 902*54865Smckusick code = fuword(params + _QUAD_LOWWORD * sizeof(int)); 903*54865Smckusick params += sizeof(quad_t); 90454801Storek break; 90554801Storek 906*54865Smckusick default: 907*54865Smckusick /* nothing to do by default */ 908*54865Smckusick break; 90954801Storek } 91054801Storek if (code < numsys) 91154801Storek callp += code; 91254801Storek else 91354801Storek callp += SYS_indir; /* => nosys */ 91454801Storek argsize = callp->sy_narg * sizeof(int); 91554801Storek if (argsize && (error = copyin(params, (caddr_t)&args, argsize))) { 91641475Smckusick #ifdef KTRACE 91743641Skarels if (KTRPOINT(p, KTR_SYSCALL)) 91844018Skarels ktrsyscall(p->p_tracep, code, callp->sy_narg, args.i); 91941475Smckusick #endif 92054801Storek goto bad; 92141475Smckusick } 92241475Smckusick #ifdef KTRACE 92343641Skarels if (KTRPOINT(p, KTR_SYSCALL)) 92444018Skarels ktrsyscall(p->p_tracep, code, callp->sy_narg, args.i); 92541475Smckusick #endif 92643641Skarels rval[0] = 0; 92743641Skarels rval[1] = frame.f_regs[D1]; 92841475Smckusick #ifdef HPUXCOMPAT 92942370Skarels /* debug kludge */ 93042370Skarels if (callp->sy_call == notimp) 93148465Skarels error = notimp(p, args.i, rval, code, callp->sy_narg); 93242370Skarels else 93341475Smckusick #endif 93454801Storek error = (*callp->sy_call)(p, &args, rval); 93554801Storek switch (error) { 93642370Skarels 93754801Storek case 0: 93841475Smckusick /* 93954801Storek * Reinitialize proc pointer `p' as it may be different 94054801Storek * if this is a child returning from fork syscall. 94141475Smckusick */ 94254801Storek p = curproc; 94354801Storek frame.f_regs[D0] = rval[0]; 94454801Storek frame.f_regs[D1] = rval[1]; 94554801Storek frame.f_sr &= ~PSL_C; 94654801Storek break; 94741475Smckusick 94854801Storek case ERESTART: 94954801Storek frame.f_pc = opc; 95054801Storek break; 95154801Storek 95254801Storek case EJUSTRETURN: 95354801Storek break; /* nothing to do */ 95454801Storek 95554801Storek default: 95654801Storek bad: 95754801Storek #ifdef HPUXCOMPAT 95854801Storek if (p->p_flag & SHPUX) 95954801Storek error = bsdtohpuxerrno(error); 96041475Smckusick #endif 96154801Storek frame.f_regs[D0] = error; 96254801Storek frame.f_sr |= PSL_C; 96354801Storek break; 96441475Smckusick } 96554801Storek 96654801Storek userret(p, &frame, sticks, (u_int)0, 0); 96741475Smckusick #ifdef KTRACE 96843641Skarels if (KTRPOINT(p, KTR_SYSRET)) 96943641Skarels ktrsysret(p->p_tracep, code, error, rval[0]); 97041475Smckusick #endif 97141475Smckusick } 972