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 * 1249317Shibler * from: Utah $Hdr: trap.c 1.32 91/04/06$ 1341475Smckusick * 14*50753Skarels * @(#)trap.c 7.14.1.3 (Berkeley) 08/02/91 1541475Smckusick */ 1641475Smckusick 1748465Skarels #include "param.h" 1848465Skarels #include "systm.h" 1948465Skarels #include "proc.h" 2048465Skarels #include "seg.h" 2148465Skarels #include "acct.h" 2248465Skarels #include "kernel.h" 2348465Skarels #include "signalvar.h" 2448465Skarels #include "resourcevar.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" 3948465Skarels #include "vmmeter.h" 4045751Smckusick 4141475Smckusick #ifdef HPUXCOMPAT 4241475Smckusick #include "../hpux/hpux.h" 4341475Smckusick #endif 4441475Smckusick 4541475Smckusick struct sysent sysent[]; 4641475Smckusick int nsysent; 4741475Smckusick 4841475Smckusick char *trap_type[] = { 4941475Smckusick "Bus error", 5041475Smckusick "Address error", 5141475Smckusick "Illegal instruction", 5241475Smckusick "Zero divide", 5341475Smckusick "CHK instruction", 5441475Smckusick "TRAPV instruction", 5541475Smckusick "Privilege violation", 5641475Smckusick "Trace trap", 5741475Smckusick "MMU fault", 5841475Smckusick "SSIR trap", 5941475Smckusick "Format error", 6041475Smckusick "68881 exception", 6141475Smckusick "Coprocessor violation", 6241475Smckusick "Async system trap" 6341475Smckusick }; 6441475Smckusick #define TRAP_TYPES (sizeof trap_type / sizeof trap_type[0]) 6541475Smckusick 6649317Shibler /* 6749317Shibler * Size of various exception stack frames (minus the standard 8 bytes) 6849317Shibler */ 6949317Shibler short exframesize[] = { 7049317Shibler FMT0SIZE, /* type 0 - normal (68020/030/040) */ 7149317Shibler FMT1SIZE, /* type 1 - throwaway (68020/030/040) */ 7249317Shibler FMT2SIZE, /* type 2 - normal 6-word (68020/030/040) */ 7349317Shibler -1, /* type 3 - FP post-instruction (68040) */ 7449317Shibler -1, -1, -1, /* type 4-6 - undefined */ 7549317Shibler -1, /* type 7 - access error (68040) */ 7649317Shibler 58, /* type 8 - bus fault (68010) */ 7749317Shibler FMT9SIZE, /* type 9 - coprocessor mid-instruction (68020/030) */ 7849317Shibler FMTASIZE, /* type A - short bus fault (68020/030) */ 7949317Shibler FMTBSIZE, /* type B - long bus fault (68020/030) */ 8049317Shibler -1, -1, -1, -1 /* type C-F - undefined */ 8149317Shibler }; 8249317Shibler 8341475Smckusick #ifdef DEBUG 8441475Smckusick int mmudebug = 0; 8541475Smckusick #endif 8641475Smckusick 8741475Smckusick /* 8849531Skarels * Trap is called from locore to handle most types of processor traps, 8949531Skarels * including events such as simulated software interrupts/AST's. 9049531Skarels * System calls are broken out for efficiency. 9141475Smckusick */ 9241475Smckusick /*ARGSUSED*/ 9341475Smckusick trap(type, code, v, frame) 9441475Smckusick int type; 9541475Smckusick unsigned code; 9641475Smckusick register unsigned v; 9741475Smckusick struct frame frame; 9841475Smckusick { 9941475Smckusick register int i; 10041475Smckusick unsigned ucode = 0; 10148465Skarels register struct proc *p = curproc; 10241475Smckusick struct timeval syst; 10341475Smckusick unsigned ncode; 104*50753Skarels int s; 10541475Smckusick 10641475Smckusick cnt.v_trap++; 10748465Skarels syst = p->p_stime; 10841475Smckusick if (USERMODE(frame.f_sr)) { 10949531Skarels type |= T_USER; 11048465Skarels p->p_regs = frame.f_regs; 11141475Smckusick } 11241475Smckusick switch (type) { 11341475Smckusick 11441475Smckusick default: 11541475Smckusick dopanic: 11641475Smckusick printf("trap type %d, code = %x, v = %x\n", type, code, v); 11741475Smckusick regdump(frame.f_regs, 128); 11849531Skarels type &= ~T_USER; 11941475Smckusick if ((unsigned)type < TRAP_TYPES) 12041475Smckusick panic(trap_type[type]); 12141475Smckusick panic("trap"); 12241475Smckusick 12341475Smckusick case T_BUSERR: /* kernel bus error */ 12449125Skarels if (!p->p_addr->u_pcb.pcb_onfault) 12541475Smckusick goto dopanic; 12641475Smckusick /* 12741475Smckusick * If we have arranged to catch this fault in any of the 12841475Smckusick * copy to/from user space routines, set PC to return to 12941475Smckusick * indicated location and set flag informing buserror code 13041475Smckusick * that it may need to clean up stack frame. 13141475Smckusick */ 13241475Smckusick copyfault: 13349317Shibler frame.f_stackadj = exframesize[frame.f_format]; 13449317Shibler frame.f_format = frame.f_vector = 0; 13549125Skarels frame.f_pc = (int) p->p_addr->u_pcb.pcb_onfault; 13641475Smckusick return; 13741475Smckusick 13849531Skarels case T_BUSERR|T_USER: /* bus error */ 13949531Skarels case T_ADDRERR|T_USER: /* address error */ 14041475Smckusick i = SIGBUS; 14141475Smckusick break; 14241475Smckusick 14341475Smckusick #ifdef FPCOPROC 14441475Smckusick case T_COPERR: /* kernel coprocessor violation */ 14541475Smckusick #endif 14641475Smckusick case T_FMTERR: /* kernel format error */ 14741475Smckusick /* 14841475Smckusick * The user has most likely trashed the RTE or FP state info 14941475Smckusick * in the stack frame of a signal handler. 15041475Smckusick */ 15149531Skarels type |= T_USER; 15248465Skarels printf("pid %d: kernel %s exception\n", p->p_pid, 15341475Smckusick type==T_COPERR ? "coprocessor" : "format"); 15448465Skarels p->p_sigacts->ps_sigact[SIGILL] = SIG_DFL; 15541475Smckusick i = sigmask(SIGILL); 15641475Smckusick p->p_sigignore &= ~i; 15741475Smckusick p->p_sigcatch &= ~i; 15841475Smckusick p->p_sigmask &= ~i; 15942370Skarels i = SIGILL; 16041475Smckusick ucode = frame.f_format; /* XXX was ILL_RESAD_FAULT */ 16142370Skarels break; 16241475Smckusick 16341475Smckusick #ifdef FPCOPROC 16449531Skarels case T_COPERR|T_USER: /* user coprocessor violation */ 16541475Smckusick /* What is a proper response here? */ 16641475Smckusick ucode = 0; 16741475Smckusick i = SIGFPE; 16841475Smckusick break; 16941475Smckusick 17049531Skarels case T_FPERR|T_USER: /* 68881 exceptions */ 17141475Smckusick /* 17241475Smckusick * We pass along the 68881 status register which locore stashed 17341475Smckusick * in code for us. Note that there is a possibility that the 17441475Smckusick * bit pattern of this register will conflict with one of the 17541475Smckusick * FPE_* codes defined in signal.h. Fortunately for us, the 17641475Smckusick * only such codes we use are all in the range 1-7 and the low 17741475Smckusick * 3 bits of the status register are defined as 0 so there is 17841475Smckusick * no clash. 17941475Smckusick */ 18041475Smckusick ucode = code; 18141475Smckusick i = SIGFPE; 18241475Smckusick break; 18341475Smckusick #endif 18441475Smckusick 18549531Skarels case T_ILLINST|T_USER: /* illegal instruction fault */ 18641475Smckusick #ifdef HPUXCOMPAT 18748465Skarels if (p->p_flag & SHPUX) { 18841475Smckusick ucode = HPUX_ILL_ILLINST_TRAP; 18941475Smckusick i = SIGILL; 19041475Smckusick break; 19141475Smckusick } 19241475Smckusick /* fall through */ 19341475Smckusick #endif 19449531Skarels case T_PRIVINST|T_USER: /* privileged instruction fault */ 19541475Smckusick #ifdef HPUXCOMPAT 19648465Skarels if (p->p_flag & SHPUX) 19741475Smckusick ucode = HPUX_ILL_PRIV_TRAP; 19841475Smckusick else 19941475Smckusick #endif 20041475Smckusick ucode = frame.f_format; /* XXX was ILL_PRIVIN_FAULT */ 20141475Smckusick i = SIGILL; 20241475Smckusick break; 20341475Smckusick 20449531Skarels case T_ZERODIV|T_USER: /* Divide by zero */ 20541475Smckusick #ifdef HPUXCOMPAT 20648465Skarels if (p->p_flag & SHPUX) 20741475Smckusick ucode = HPUX_FPE_INTDIV_TRAP; 20841475Smckusick else 20941475Smckusick #endif 21041475Smckusick ucode = frame.f_format; /* XXX was FPE_INTDIV_TRAP */ 21141475Smckusick i = SIGFPE; 21241475Smckusick break; 21341475Smckusick 21449531Skarels case T_CHKINST|T_USER: /* CHK instruction trap */ 21541475Smckusick #ifdef HPUXCOMPAT 21648465Skarels if (p->p_flag & SHPUX) { 21741475Smckusick /* handled differently under hp-ux */ 21841475Smckusick i = SIGILL; 21941475Smckusick ucode = HPUX_ILL_CHK_TRAP; 22041475Smckusick break; 22141475Smckusick } 22241475Smckusick #endif 22341475Smckusick ucode = frame.f_format; /* XXX was FPE_SUBRNG_TRAP */ 22441475Smckusick i = SIGFPE; 22541475Smckusick break; 22641475Smckusick 22749531Skarels case T_TRAPVINST|T_USER: /* TRAPV instruction trap */ 22841475Smckusick #ifdef HPUXCOMPAT 22948465Skarels if (p->p_flag & SHPUX) { 23041475Smckusick /* handled differently under hp-ux */ 23141475Smckusick i = SIGILL; 23241475Smckusick ucode = HPUX_ILL_TRAPV_TRAP; 23341475Smckusick break; 23441475Smckusick } 23541475Smckusick #endif 23641475Smckusick ucode = frame.f_format; /* XXX was FPE_INTOVF_TRAP */ 23741475Smckusick i = SIGFPE; 23841475Smckusick break; 23941475Smckusick 24041475Smckusick /* 24141475Smckusick * XXX: Trace traps are a nightmare. 24241475Smckusick * 24341475Smckusick * HP-UX uses trap #1 for breakpoints, 24441475Smckusick * HPBSD uses trap #2, 24541475Smckusick * SUN 3.x uses trap #15, 24648465Skarels * KGDB uses trap #15 (for kernel breakpoints; handled elsewhere). 24741475Smckusick * 24841475Smckusick * HPBSD and HP-UX traps both get mapped by locore.s into T_TRACE. 24941475Smckusick * SUN 3.x traps get passed through as T_TRAP15 and are not really 25048465Skarels * supported yet. 25141475Smckusick */ 25241475Smckusick case T_TRACE: /* kernel trace trap */ 25348465Skarels case T_TRAP15: /* SUN trace trap */ 25441475Smckusick frame.f_sr &= ~PSL_T; 25541475Smckusick i = SIGTRAP; 25641475Smckusick break; 25741475Smckusick 25849531Skarels case T_TRACE|T_USER: /* user trace trap */ 25949531Skarels case T_TRAP15|T_USER: /* SUN user trace trap */ 26041475Smckusick frame.f_sr &= ~PSL_T; 26141475Smckusick i = SIGTRAP; 26241475Smckusick break; 26341475Smckusick 26443413Shibler case T_ASTFLT: /* system async trap, cannot happen */ 26541475Smckusick goto dopanic; 26641475Smckusick 26749531Skarels case T_ASTFLT|T_USER: /* user async trap */ 26849125Skarels astpending = 0; 26941475Smckusick /* 27041475Smckusick * We check for software interrupts first. This is because 27141475Smckusick * they are at a higher level than ASTs, and on a VAX would 27241475Smckusick * interrupt the AST. We assume that if we are processing 27341475Smckusick * an AST that we must be at IPL0 so we don't bother to 27441475Smckusick * check. Note that we ensure that we are at least at SIR 27541475Smckusick * IPL while processing the SIR. 27641475Smckusick */ 27741475Smckusick spl1(); 27841475Smckusick /* fall into... */ 27941475Smckusick 28041475Smckusick case T_SSIR: /* software interrupt */ 28149531Skarels case T_SSIR|T_USER: 28241475Smckusick if (ssir & SIR_NET) { 28341475Smckusick siroff(SIR_NET); 28441475Smckusick cnt.v_soft++; 28541475Smckusick netintr(); 28641475Smckusick } 28741475Smckusick if (ssir & SIR_CLOCK) { 28841475Smckusick siroff(SIR_CLOCK); 28941475Smckusick cnt.v_soft++; 29041475Smckusick softclock((caddr_t)frame.f_pc, (int)frame.f_sr); 29141475Smckusick } 29241475Smckusick /* 29341475Smckusick * If this was not an AST trap, we are all done. 29441475Smckusick */ 295*50753Skarels if (type != (T_ASTFLT|T_USER)) { 29641475Smckusick cnt.v_trap--; 29741475Smckusick return; 29841475Smckusick } 29941475Smckusick spl0(); 30041475Smckusick #ifndef PROFTIMER 30148465Skarels if ((p->p_flag&SOWEUPC) && p->p_stats->p_prof.pr_scale) { 30248465Skarels addupc(frame.f_pc, &p->p_stats->p_prof, 1); 30348465Skarels p->p_flag &= ~SOWEUPC; 30441475Smckusick } 30541475Smckusick #endif 30641475Smckusick goto out; 30741475Smckusick 30841475Smckusick case T_MMUFLT: /* kernel mode page fault */ 30941475Smckusick /* fall into ... */ 31041475Smckusick 31149531Skarels case T_MMUFLT|T_USER: /* page fault */ 31245751Smckusick { 31345751Smckusick register vm_offset_t va; 31448465Skarels register struct vmspace *vm = p->p_vmspace; 31545751Smckusick register vm_map_t map; 31645751Smckusick int rv; 31745751Smckusick vm_prot_t ftype; 31845751Smckusick extern vm_map_t kernel_map; 31945751Smckusick 32041475Smckusick /* 32145751Smckusick * It is only a kernel address space fault iff: 32249531Skarels * 1. (type & T_USER) == 0 and 32345751Smckusick * 2. pcb_onfault not set or 32445751Smckusick * 3. pcb_onfault set but supervisor space data fault 32545751Smckusick * The last can occur during an exec() copyin where the 32645751Smckusick * argument space is lazy-allocated. 32741475Smckusick */ 32845751Smckusick if (type == T_MMUFLT && 32949125Skarels (!p->p_addr->u_pcb.pcb_onfault || 33045751Smckusick (code & (SSW_DF|FC_SUPERD)) == (SSW_DF|FC_SUPERD))) 33145751Smckusick map = kernel_map; 33245751Smckusick else 33348465Skarels map = &vm->vm_map; 33445751Smckusick if ((code & (SSW_DF|SSW_RW)) == SSW_DF) /* what about RMW? */ 33545751Smckusick ftype = VM_PROT_READ | VM_PROT_WRITE; 33645751Smckusick else 33745751Smckusick ftype = VM_PROT_READ; 33845751Smckusick va = trunc_page((vm_offset_t)v); 33941475Smckusick #ifdef DEBUG 34045751Smckusick if (map == kernel_map && va == 0) { 34145751Smckusick printf("trap: bad kernel access at %x\n", v); 34241475Smckusick goto dopanic; 34341475Smckusick } 34441475Smckusick #endif 34549317Shibler rv = vm_fault(map, va, ftype, FALSE); 34641475Smckusick /* 34749317Shibler * If this was a stack access we keep track of the maximum 34849317Shibler * accessed stack size. Also, if vm_fault gets a protection 34949317Shibler * failure it is due to accessing the stack region outside 35049317Shibler * the current limit and we need to reflect that as an access 35149317Shibler * error. 35241475Smckusick */ 35348465Skarels if ((caddr_t)va >= vm->vm_maxsaddr && map != kernel_map) { 35449317Shibler if (rv == KERN_SUCCESS) { 35549317Shibler unsigned nss; 35649317Shibler 35749317Shibler nss = clrnd(btoc(USRSTACK-(unsigned)va)); 35849317Shibler if (nss > vm->vm_ssize) 35949317Shibler vm->vm_ssize = nss; 36049317Shibler } else if (rv == KERN_PROTECTION_FAILURE) 36149317Shibler rv = KERN_INVALID_ADDRESS; 36241475Smckusick } 36345751Smckusick if (rv == KERN_SUCCESS) { 36441475Smckusick if (type == T_MMUFLT) 36541475Smckusick return; 36641475Smckusick goto out; 36741475Smckusick } 36845751Smckusick if (type == T_MMUFLT) { 36949125Skarels if (p->p_addr->u_pcb.pcb_onfault) 37045751Smckusick goto copyfault; 37145751Smckusick printf("vm_fault(%x, %x, %x, 0) -> %x\n", 37245751Smckusick map, va, ftype, rv); 37345751Smckusick printf(" type %x, code [mmu,,ssw]: %x\n", 37445751Smckusick type, code); 37545751Smckusick goto dopanic; 37645751Smckusick } 37748465Skarels ucode = v; 37845751Smckusick i = (rv == KERN_PROTECTION_FAILURE) ? SIGBUS : SIGSEGV; 37945751Smckusick break; 38045751Smckusick } 38141475Smckusick } 38248465Skarels trapsignal(p, i, ucode); 38349531Skarels if ((type & T_USER) == 0) 38441475Smckusick return; 38541475Smckusick out: 38648465Skarels while (i = CURSIG(p)) 38742370Skarels psig(i); 38841475Smckusick p->p_pri = p->p_usrpri; 38948465Skarels if (want_resched) { 39041475Smckusick /* 39148465Skarels * Since we are curproc, clock will normally just change 39241475Smckusick * our priority without moving us from one queue to another 39341475Smckusick * (since the running process is not on a queue.) 39441475Smckusick * If that happened after we setrq ourselves but before we 39541475Smckusick * swtch()'ed, we might not be on the queue indicated by 39641475Smckusick * our priority. 39741475Smckusick */ 398*50753Skarels s = splclock(); 39941475Smckusick setrq(p); 40048465Skarels p->p_stats->p_ru.ru_nivcsw++; 40141475Smckusick swtch(); 402*50753Skarels splx(s); 40348465Skarels while (i = CURSIG(p)) 40442370Skarels psig(i); 40541475Smckusick } 40648465Skarels if (p->p_stats->p_prof.pr_scale) { 40741475Smckusick int ticks; 40848465Skarels struct timeval *tv = &p->p_stime; 40941475Smckusick 41041475Smckusick ticks = ((tv->tv_sec - syst.tv_sec) * 1000 + 41141475Smckusick (tv->tv_usec - syst.tv_usec) / 1000) / (tick / 1000); 41241475Smckusick if (ticks) { 41341475Smckusick #ifdef PROFTIMER 41441475Smckusick extern int profscale; 41548465Skarels addupc(frame.f_pc, &p->p_stats->p_prof, 41648465Skarels ticks * profscale); 41741475Smckusick #else 41848465Skarels addupc(frame.f_pc, &p->p_stats->p_prof, ticks); 41941475Smckusick #endif 42041475Smckusick } 42141475Smckusick } 42241475Smckusick curpri = p->p_pri; 42341475Smckusick } 42441475Smckusick 42541475Smckusick /* 42649531Skarels * Proces a system call. 42741475Smckusick */ 42841475Smckusick syscall(code, frame) 42941475Smckusick volatile int code; 43041475Smckusick struct frame frame; 43141475Smckusick { 43241475Smckusick register caddr_t params; 43341475Smckusick register int i; 43441475Smckusick register struct sysent *callp; 43548465Skarels register struct proc *p = curproc; 436*50753Skarels int error, opc, numsys, s; 43744018Skarels struct args { 43844018Skarels int i[8]; 43944018Skarels } args; 44044018Skarels int rval[2]; 44141475Smckusick struct timeval syst; 44241475Smckusick struct sysent *systab; 44341475Smckusick #ifdef HPUXCOMPAT 44441475Smckusick extern struct sysent hpuxsysent[]; 44541475Smckusick extern int hpuxnsysent, notimp(); 44641475Smckusick #endif 44741475Smckusick 44841475Smckusick cnt.v_syscall++; 44948465Skarels syst = p->p_stime; 45041475Smckusick if (!USERMODE(frame.f_sr)) 45141475Smckusick panic("syscall"); 45248465Skarels p->p_regs = frame.f_regs; 45341475Smckusick opc = frame.f_pc - 2; 45441475Smckusick systab = sysent; 45541475Smckusick numsys = nsysent; 45641475Smckusick #ifdef HPUXCOMPAT 45742370Skarels if (p->p_flag & SHPUX) { 45841475Smckusick systab = hpuxsysent; 45941475Smckusick numsys = hpuxnsysent; 46041475Smckusick } 46141475Smckusick #endif 46249531Skarels params = (caddr_t)frame.f_regs[SP] + sizeof(int); 46342370Skarels if (code == 0) { /* indir */ 46442370Skarels code = fuword(params); 46549531Skarels params += sizeof(int); 46642370Skarels } 46742370Skarels if (code >= numsys) 46842370Skarels callp = &systab[0]; /* indir (illegal) */ 46942370Skarels else 47042370Skarels callp = &systab[code]; 47141475Smckusick if ((i = callp->sy_narg * sizeof (int)) && 47244018Skarels (error = copyin(params, (caddr_t)&args, (u_int)i))) { 47341475Smckusick #ifdef HPUXCOMPAT 47441475Smckusick if (p->p_flag & SHPUX) 47542370Skarels error = bsdtohpuxerrno(error); 47641475Smckusick #endif 47749362Skarels frame.f_regs[D0] = error; 47841475Smckusick frame.f_sr |= PSL_C; /* carry bit */ 47941475Smckusick #ifdef KTRACE 48043641Skarels if (KTRPOINT(p, KTR_SYSCALL)) 48144018Skarels ktrsyscall(p->p_tracep, code, callp->sy_narg, args.i); 48241475Smckusick #endif 48341475Smckusick goto done; 48441475Smckusick } 48541475Smckusick #ifdef KTRACE 48643641Skarels if (KTRPOINT(p, KTR_SYSCALL)) 48744018Skarels ktrsyscall(p->p_tracep, code, callp->sy_narg, args.i); 48841475Smckusick #endif 48943641Skarels rval[0] = 0; 49043641Skarels rval[1] = frame.f_regs[D1]; 49141475Smckusick #ifdef HPUXCOMPAT 49242370Skarels /* debug kludge */ 49342370Skarels if (callp->sy_call == notimp) 49448465Skarels error = notimp(p, args.i, rval, code, callp->sy_narg); 49542370Skarels else 49641475Smckusick #endif 49748465Skarels error = (*callp->sy_call)(p, &args, rval); 49849817Smckusick #ifdef DIAGNOSTIC 49949817Smckusick if (curproc->p_spare[0]) 50049817Smckusick panic("syscall: M_NAMEI"); 50149817Smckusick if (curproc->p_spare[1]) 50249817Smckusick panic("syscall: STARTSAVE"); 50349911Smckusick if (curproc->p_spare[2]) 50449911Smckusick panic("syscall: LOCK COUNT"); 50549817Smckusick #endif 50642370Skarels if (error == ERESTART) 50742370Skarels frame.f_pc = opc; 50842370Skarels else if (error != EJUSTRETURN) { 50942370Skarels if (error) { 51041475Smckusick #ifdef HPUXCOMPAT 51142370Skarels if (p->p_flag & SHPUX) 51242370Skarels error = bsdtohpuxerrno(error); 51341475Smckusick #endif 51449362Skarels frame.f_regs[D0] = error; 51542370Skarels frame.f_sr |= PSL_C; /* carry bit */ 51641475Smckusick } else { 51743641Skarels frame.f_regs[D0] = rval[0]; 51843641Skarels frame.f_regs[D1] = rval[1]; 51941475Smckusick frame.f_sr &= ~PSL_C; 52041475Smckusick } 52142370Skarels } 52242370Skarels /* else if (error == EJUSTRETURN) */ 52341475Smckusick /* nothing to do */ 52442370Skarels 52541475Smckusick done: 52641475Smckusick /* 52742370Skarels * Reinitialize proc pointer `p' as it may be different 52842370Skarels * if this is a child returning from fork syscall. 52942370Skarels */ 53048465Skarels p = curproc; 53149317Shibler while (i = CURSIG(p)) 53249317Shibler psig(i); 53341475Smckusick p->p_pri = p->p_usrpri; 53448465Skarels if (want_resched) { 53541475Smckusick /* 53648465Skarels * Since we are curproc, clock will normally just change 53741475Smckusick * our priority without moving us from one queue to another 53841475Smckusick * (since the running process is not on a queue.) 53941475Smckusick * If that happened after we setrq ourselves but before we 54041475Smckusick * swtch()'ed, we might not be on the queue indicated by 54141475Smckusick * our priority. 54241475Smckusick */ 543*50753Skarels s = splclock(); 54441475Smckusick setrq(p); 54548465Skarels p->p_stats->p_ru.ru_nivcsw++; 54641475Smckusick swtch(); 547*50753Skarels splx(s); 54849317Shibler while (i = CURSIG(p)) 54949317Shibler psig(i); 55041475Smckusick } 55148465Skarels if (p->p_stats->p_prof.pr_scale) { 55241475Smckusick int ticks; 55348465Skarels struct timeval *tv = &p->p_stime; 55441475Smckusick 55541475Smckusick ticks = ((tv->tv_sec - syst.tv_sec) * 1000 + 55641475Smckusick (tv->tv_usec - syst.tv_usec) / 1000) / (tick / 1000); 55741475Smckusick if (ticks) { 55841475Smckusick #ifdef PROFTIMER 55941475Smckusick extern int profscale; 56048465Skarels addupc(frame.f_pc, &p->p_stats->p_prof, 56148465Skarels ticks * profscale); 56241475Smckusick #else 56348465Skarels addupc(frame.f_pc, &p->p_stats->p_prof, ticks); 56441475Smckusick #endif 56541475Smckusick } 56641475Smckusick } 56741475Smckusick curpri = p->p_pri; 56841475Smckusick #ifdef KTRACE 56943641Skarels if (KTRPOINT(p, KTR_SYSRET)) 57043641Skarels ktrsysret(p->p_tracep, code, error, rval[0]); 57141475Smckusick #endif 57241475Smckusick } 573