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*49817Smckusick * @(#)trap.c 7.14.1.1 (Berkeley) 05/19/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; 10441475Smckusick 10541475Smckusick cnt.v_trap++; 10648465Skarels syst = p->p_stime; 10741475Smckusick if (USERMODE(frame.f_sr)) { 10849531Skarels type |= T_USER; 10948465Skarels p->p_regs = frame.f_regs; 11041475Smckusick } 11141475Smckusick switch (type) { 11241475Smckusick 11341475Smckusick default: 11441475Smckusick dopanic: 11541475Smckusick printf("trap type %d, code = %x, v = %x\n", type, code, v); 11641475Smckusick regdump(frame.f_regs, 128); 11749531Skarels type &= ~T_USER; 11841475Smckusick if ((unsigned)type < TRAP_TYPES) 11941475Smckusick panic(trap_type[type]); 12041475Smckusick panic("trap"); 12141475Smckusick 12241475Smckusick case T_BUSERR: /* kernel bus error */ 12349125Skarels if (!p->p_addr->u_pcb.pcb_onfault) 12441475Smckusick goto dopanic; 12541475Smckusick /* 12641475Smckusick * If we have arranged to catch this fault in any of the 12741475Smckusick * copy to/from user space routines, set PC to return to 12841475Smckusick * indicated location and set flag informing buserror code 12941475Smckusick * that it may need to clean up stack frame. 13041475Smckusick */ 13141475Smckusick copyfault: 13249317Shibler frame.f_stackadj = exframesize[frame.f_format]; 13349317Shibler frame.f_format = frame.f_vector = 0; 13449125Skarels frame.f_pc = (int) p->p_addr->u_pcb.pcb_onfault; 13541475Smckusick return; 13641475Smckusick 13749531Skarels case T_BUSERR|T_USER: /* bus error */ 13849531Skarels case T_ADDRERR|T_USER: /* address error */ 13941475Smckusick i = SIGBUS; 14041475Smckusick break; 14141475Smckusick 14241475Smckusick #ifdef FPCOPROC 14341475Smckusick case T_COPERR: /* kernel coprocessor violation */ 14441475Smckusick #endif 14541475Smckusick case T_FMTERR: /* kernel format error */ 14641475Smckusick /* 14741475Smckusick * The user has most likely trashed the RTE or FP state info 14841475Smckusick * in the stack frame of a signal handler. 14941475Smckusick */ 15049531Skarels type |= T_USER; 15148465Skarels printf("pid %d: kernel %s exception\n", p->p_pid, 15241475Smckusick type==T_COPERR ? "coprocessor" : "format"); 15348465Skarels p->p_sigacts->ps_sigact[SIGILL] = SIG_DFL; 15441475Smckusick i = sigmask(SIGILL); 15541475Smckusick p->p_sigignore &= ~i; 15641475Smckusick p->p_sigcatch &= ~i; 15741475Smckusick p->p_sigmask &= ~i; 15842370Skarels i = SIGILL; 15941475Smckusick ucode = frame.f_format; /* XXX was ILL_RESAD_FAULT */ 16042370Skarels break; 16141475Smckusick 16241475Smckusick #ifdef FPCOPROC 16349531Skarels case T_COPERR|T_USER: /* user coprocessor violation */ 16441475Smckusick /* What is a proper response here? */ 16541475Smckusick ucode = 0; 16641475Smckusick i = SIGFPE; 16741475Smckusick break; 16841475Smckusick 16949531Skarels case T_FPERR|T_USER: /* 68881 exceptions */ 17041475Smckusick /* 17141475Smckusick * We pass along the 68881 status register which locore stashed 17241475Smckusick * in code for us. Note that there is a possibility that the 17341475Smckusick * bit pattern of this register will conflict with one of the 17441475Smckusick * FPE_* codes defined in signal.h. Fortunately for us, the 17541475Smckusick * only such codes we use are all in the range 1-7 and the low 17641475Smckusick * 3 bits of the status register are defined as 0 so there is 17741475Smckusick * no clash. 17841475Smckusick */ 17941475Smckusick ucode = code; 18041475Smckusick i = SIGFPE; 18141475Smckusick break; 18241475Smckusick #endif 18341475Smckusick 18449531Skarels case T_ILLINST|T_USER: /* illegal instruction fault */ 18541475Smckusick #ifdef HPUXCOMPAT 18648465Skarels if (p->p_flag & SHPUX) { 18741475Smckusick ucode = HPUX_ILL_ILLINST_TRAP; 18841475Smckusick i = SIGILL; 18941475Smckusick break; 19041475Smckusick } 19141475Smckusick /* fall through */ 19241475Smckusick #endif 19349531Skarels case T_PRIVINST|T_USER: /* privileged instruction fault */ 19441475Smckusick #ifdef HPUXCOMPAT 19548465Skarels if (p->p_flag & SHPUX) 19641475Smckusick ucode = HPUX_ILL_PRIV_TRAP; 19741475Smckusick else 19841475Smckusick #endif 19941475Smckusick ucode = frame.f_format; /* XXX was ILL_PRIVIN_FAULT */ 20041475Smckusick i = SIGILL; 20141475Smckusick break; 20241475Smckusick 20349531Skarels case T_ZERODIV|T_USER: /* Divide by zero */ 20441475Smckusick #ifdef HPUXCOMPAT 20548465Skarels if (p->p_flag & SHPUX) 20641475Smckusick ucode = HPUX_FPE_INTDIV_TRAP; 20741475Smckusick else 20841475Smckusick #endif 20941475Smckusick ucode = frame.f_format; /* XXX was FPE_INTDIV_TRAP */ 21041475Smckusick i = SIGFPE; 21141475Smckusick break; 21241475Smckusick 21349531Skarels case T_CHKINST|T_USER: /* CHK instruction trap */ 21441475Smckusick #ifdef HPUXCOMPAT 21548465Skarels if (p->p_flag & SHPUX) { 21641475Smckusick /* handled differently under hp-ux */ 21741475Smckusick i = SIGILL; 21841475Smckusick ucode = HPUX_ILL_CHK_TRAP; 21941475Smckusick break; 22041475Smckusick } 22141475Smckusick #endif 22241475Smckusick ucode = frame.f_format; /* XXX was FPE_SUBRNG_TRAP */ 22341475Smckusick i = SIGFPE; 22441475Smckusick break; 22541475Smckusick 22649531Skarels case T_TRAPVINST|T_USER: /* TRAPV instruction trap */ 22741475Smckusick #ifdef HPUXCOMPAT 22848465Skarels if (p->p_flag & SHPUX) { 22941475Smckusick /* handled differently under hp-ux */ 23041475Smckusick i = SIGILL; 23141475Smckusick ucode = HPUX_ILL_TRAPV_TRAP; 23241475Smckusick break; 23341475Smckusick } 23441475Smckusick #endif 23541475Smckusick ucode = frame.f_format; /* XXX was FPE_INTOVF_TRAP */ 23641475Smckusick i = SIGFPE; 23741475Smckusick break; 23841475Smckusick 23941475Smckusick /* 24041475Smckusick * XXX: Trace traps are a nightmare. 24141475Smckusick * 24241475Smckusick * HP-UX uses trap #1 for breakpoints, 24341475Smckusick * HPBSD uses trap #2, 24441475Smckusick * SUN 3.x uses trap #15, 24548465Skarels * KGDB uses trap #15 (for kernel breakpoints; handled elsewhere). 24641475Smckusick * 24741475Smckusick * HPBSD and HP-UX traps both get mapped by locore.s into T_TRACE. 24841475Smckusick * SUN 3.x traps get passed through as T_TRAP15 and are not really 24948465Skarels * supported yet. 25041475Smckusick */ 25141475Smckusick case T_TRACE: /* kernel trace trap */ 25248465Skarels case T_TRAP15: /* SUN trace trap */ 25341475Smckusick frame.f_sr &= ~PSL_T; 25441475Smckusick i = SIGTRAP; 25541475Smckusick break; 25641475Smckusick 25749531Skarels case T_TRACE|T_USER: /* user trace trap */ 25849531Skarels case T_TRAP15|T_USER: /* SUN user trace trap */ 25941475Smckusick frame.f_sr &= ~PSL_T; 26041475Smckusick i = SIGTRAP; 26141475Smckusick break; 26241475Smckusick 26343413Shibler case T_ASTFLT: /* system async trap, cannot happen */ 26441475Smckusick goto dopanic; 26541475Smckusick 26649531Skarels case T_ASTFLT|T_USER: /* user async trap */ 26749125Skarels astpending = 0; 26841475Smckusick /* 26941475Smckusick * We check for software interrupts first. This is because 27041475Smckusick * they are at a higher level than ASTs, and on a VAX would 27141475Smckusick * interrupt the AST. We assume that if we are processing 27241475Smckusick * an AST that we must be at IPL0 so we don't bother to 27341475Smckusick * check. Note that we ensure that we are at least at SIR 27441475Smckusick * IPL while processing the SIR. 27541475Smckusick */ 27641475Smckusick spl1(); 27741475Smckusick /* fall into... */ 27841475Smckusick 27941475Smckusick case T_SSIR: /* software interrupt */ 28049531Skarels case T_SSIR|T_USER: 28141475Smckusick if (ssir & SIR_NET) { 28241475Smckusick siroff(SIR_NET); 28341475Smckusick cnt.v_soft++; 28441475Smckusick netintr(); 28541475Smckusick } 28641475Smckusick if (ssir & SIR_CLOCK) { 28741475Smckusick siroff(SIR_CLOCK); 28841475Smckusick cnt.v_soft++; 28941475Smckusick softclock((caddr_t)frame.f_pc, (int)frame.f_sr); 29041475Smckusick } 29141475Smckusick /* 29241475Smckusick * If this was not an AST trap, we are all done. 29341475Smckusick */ 29449531Skarels if (type != T_ASTFLT|T_USER) { 29541475Smckusick cnt.v_trap--; 29641475Smckusick return; 29741475Smckusick } 29841475Smckusick spl0(); 29941475Smckusick #ifndef PROFTIMER 30048465Skarels if ((p->p_flag&SOWEUPC) && p->p_stats->p_prof.pr_scale) { 30148465Skarels addupc(frame.f_pc, &p->p_stats->p_prof, 1); 30248465Skarels p->p_flag &= ~SOWEUPC; 30341475Smckusick } 30441475Smckusick #endif 30541475Smckusick goto out; 30641475Smckusick 30741475Smckusick case T_MMUFLT: /* kernel mode page fault */ 30841475Smckusick /* fall into ... */ 30941475Smckusick 31049531Skarels case T_MMUFLT|T_USER: /* page fault */ 31145751Smckusick { 31245751Smckusick register vm_offset_t va; 31348465Skarels register struct vmspace *vm = p->p_vmspace; 31445751Smckusick register vm_map_t map; 31545751Smckusick int rv; 31645751Smckusick vm_prot_t ftype; 31745751Smckusick extern vm_map_t kernel_map; 31845751Smckusick 31941475Smckusick /* 32045751Smckusick * It is only a kernel address space fault iff: 32149531Skarels * 1. (type & T_USER) == 0 and 32245751Smckusick * 2. pcb_onfault not set or 32345751Smckusick * 3. pcb_onfault set but supervisor space data fault 32445751Smckusick * The last can occur during an exec() copyin where the 32545751Smckusick * argument space is lazy-allocated. 32641475Smckusick */ 32745751Smckusick if (type == T_MMUFLT && 32849125Skarels (!p->p_addr->u_pcb.pcb_onfault || 32945751Smckusick (code & (SSW_DF|FC_SUPERD)) == (SSW_DF|FC_SUPERD))) 33045751Smckusick map = kernel_map; 33145751Smckusick else 33248465Skarels map = &vm->vm_map; 33345751Smckusick if ((code & (SSW_DF|SSW_RW)) == SSW_DF) /* what about RMW? */ 33445751Smckusick ftype = VM_PROT_READ | VM_PROT_WRITE; 33545751Smckusick else 33645751Smckusick ftype = VM_PROT_READ; 33745751Smckusick va = trunc_page((vm_offset_t)v); 33841475Smckusick #ifdef DEBUG 33945751Smckusick if (map == kernel_map && va == 0) { 34045751Smckusick printf("trap: bad kernel access at %x\n", v); 34141475Smckusick goto dopanic; 34241475Smckusick } 34341475Smckusick #endif 34449317Shibler rv = vm_fault(map, va, ftype, FALSE); 34541475Smckusick /* 34649317Shibler * If this was a stack access we keep track of the maximum 34749317Shibler * accessed stack size. Also, if vm_fault gets a protection 34849317Shibler * failure it is due to accessing the stack region outside 34949317Shibler * the current limit and we need to reflect that as an access 35049317Shibler * error. 35141475Smckusick */ 35248465Skarels if ((caddr_t)va >= vm->vm_maxsaddr && map != kernel_map) { 35349317Shibler if (rv == KERN_SUCCESS) { 35449317Shibler unsigned nss; 35549317Shibler 35649317Shibler nss = clrnd(btoc(USRSTACK-(unsigned)va)); 35749317Shibler if (nss > vm->vm_ssize) 35849317Shibler vm->vm_ssize = nss; 35949317Shibler } else if (rv == KERN_PROTECTION_FAILURE) 36049317Shibler rv = KERN_INVALID_ADDRESS; 36141475Smckusick } 36245751Smckusick if (rv == KERN_SUCCESS) { 36341475Smckusick if (type == T_MMUFLT) 36441475Smckusick return; 36541475Smckusick goto out; 36641475Smckusick } 36745751Smckusick if (type == T_MMUFLT) { 36849125Skarels if (p->p_addr->u_pcb.pcb_onfault) 36945751Smckusick goto copyfault; 37045751Smckusick printf("vm_fault(%x, %x, %x, 0) -> %x\n", 37145751Smckusick map, va, ftype, rv); 37245751Smckusick printf(" type %x, code [mmu,,ssw]: %x\n", 37345751Smckusick type, code); 37445751Smckusick goto dopanic; 37545751Smckusick } 37648465Skarels ucode = v; 37745751Smckusick i = (rv == KERN_PROTECTION_FAILURE) ? SIGBUS : SIGSEGV; 37845751Smckusick break; 37945751Smckusick } 38041475Smckusick } 38148465Skarels trapsignal(p, i, ucode); 38249531Skarels if ((type & T_USER) == 0) 38341475Smckusick return; 38441475Smckusick out: 38548465Skarels while (i = CURSIG(p)) 38642370Skarels psig(i); 38741475Smckusick p->p_pri = p->p_usrpri; 38848465Skarels if (want_resched) { 38941475Smckusick /* 39048465Skarels * Since we are curproc, clock will normally just change 39141475Smckusick * our priority without moving us from one queue to another 39241475Smckusick * (since the running process is not on a queue.) 39341475Smckusick * If that happened after we setrq ourselves but before we 39441475Smckusick * swtch()'ed, we might not be on the queue indicated by 39541475Smckusick * our priority. 39641475Smckusick */ 39741475Smckusick (void) splclock(); 39841475Smckusick setrq(p); 39948465Skarels p->p_stats->p_ru.ru_nivcsw++; 40041475Smckusick swtch(); 40148465Skarels while (i = CURSIG(p)) 40242370Skarels psig(i); 40341475Smckusick } 40448465Skarels if (p->p_stats->p_prof.pr_scale) { 40541475Smckusick int ticks; 40648465Skarels struct timeval *tv = &p->p_stime; 40741475Smckusick 40841475Smckusick ticks = ((tv->tv_sec - syst.tv_sec) * 1000 + 40941475Smckusick (tv->tv_usec - syst.tv_usec) / 1000) / (tick / 1000); 41041475Smckusick if (ticks) { 41141475Smckusick #ifdef PROFTIMER 41241475Smckusick extern int profscale; 41348465Skarels addupc(frame.f_pc, &p->p_stats->p_prof, 41448465Skarels ticks * profscale); 41541475Smckusick #else 41648465Skarels addupc(frame.f_pc, &p->p_stats->p_prof, ticks); 41741475Smckusick #endif 41841475Smckusick } 41941475Smckusick } 42041475Smckusick curpri = p->p_pri; 42141475Smckusick } 42241475Smckusick 42341475Smckusick /* 42449531Skarels * Proces a system call. 42541475Smckusick */ 42641475Smckusick syscall(code, frame) 42741475Smckusick volatile int code; 42841475Smckusick struct frame frame; 42941475Smckusick { 43041475Smckusick register caddr_t params; 43141475Smckusick register int i; 43241475Smckusick register struct sysent *callp; 43348465Skarels register struct proc *p = curproc; 43442370Skarels int error, opc, numsys; 43544018Skarels struct args { 43644018Skarels int i[8]; 43744018Skarels } args; 43844018Skarels int rval[2]; 43941475Smckusick struct timeval syst; 44041475Smckusick struct sysent *systab; 44141475Smckusick #ifdef HPUXCOMPAT 44241475Smckusick extern struct sysent hpuxsysent[]; 44341475Smckusick extern int hpuxnsysent, notimp(); 44441475Smckusick #endif 44541475Smckusick 44641475Smckusick cnt.v_syscall++; 44748465Skarels syst = p->p_stime; 44841475Smckusick if (!USERMODE(frame.f_sr)) 44941475Smckusick panic("syscall"); 45048465Skarels p->p_regs = frame.f_regs; 45141475Smckusick opc = frame.f_pc - 2; 45241475Smckusick systab = sysent; 45341475Smckusick numsys = nsysent; 45441475Smckusick #ifdef HPUXCOMPAT 45542370Skarels if (p->p_flag & SHPUX) { 45641475Smckusick systab = hpuxsysent; 45741475Smckusick numsys = hpuxnsysent; 45841475Smckusick } 45941475Smckusick #endif 46049531Skarels params = (caddr_t)frame.f_regs[SP] + sizeof(int); 46142370Skarels if (code == 0) { /* indir */ 46242370Skarels code = fuword(params); 46349531Skarels params += sizeof(int); 46442370Skarels } 46542370Skarels if (code >= numsys) 46642370Skarels callp = &systab[0]; /* indir (illegal) */ 46742370Skarels else 46842370Skarels callp = &systab[code]; 46941475Smckusick if ((i = callp->sy_narg * sizeof (int)) && 47044018Skarels (error = copyin(params, (caddr_t)&args, (u_int)i))) { 47141475Smckusick #ifdef HPUXCOMPAT 47241475Smckusick if (p->p_flag & SHPUX) 47342370Skarels error = bsdtohpuxerrno(error); 47441475Smckusick #endif 47549362Skarels frame.f_regs[D0] = error; 47641475Smckusick frame.f_sr |= PSL_C; /* carry bit */ 47741475Smckusick #ifdef KTRACE 47843641Skarels if (KTRPOINT(p, KTR_SYSCALL)) 47944018Skarels ktrsyscall(p->p_tracep, code, callp->sy_narg, args.i); 48041475Smckusick #endif 48141475Smckusick goto done; 48241475Smckusick } 48341475Smckusick #ifdef KTRACE 48443641Skarels if (KTRPOINT(p, KTR_SYSCALL)) 48544018Skarels ktrsyscall(p->p_tracep, code, callp->sy_narg, args.i); 48641475Smckusick #endif 48743641Skarels rval[0] = 0; 48843641Skarels rval[1] = frame.f_regs[D1]; 48941475Smckusick #ifdef HPUXCOMPAT 49042370Skarels /* debug kludge */ 49142370Skarels if (callp->sy_call == notimp) 49248465Skarels error = notimp(p, args.i, rval, code, callp->sy_narg); 49342370Skarels else 49441475Smckusick #endif 49548465Skarels error = (*callp->sy_call)(p, &args, rval); 496*49817Smckusick #ifdef DIAGNOSTIC 497*49817Smckusick if (curproc->p_spare[0]) 498*49817Smckusick panic("syscall: M_NAMEI"); 499*49817Smckusick if (curproc->p_spare[1]) 500*49817Smckusick panic("syscall: STARTSAVE"); 501*49817Smckusick #endif 50242370Skarels if (error == ERESTART) 50342370Skarels frame.f_pc = opc; 50442370Skarels else if (error != EJUSTRETURN) { 50542370Skarels if (error) { 50641475Smckusick #ifdef HPUXCOMPAT 50742370Skarels if (p->p_flag & SHPUX) 50842370Skarels error = bsdtohpuxerrno(error); 50941475Smckusick #endif 51049362Skarels frame.f_regs[D0] = error; 51142370Skarels frame.f_sr |= PSL_C; /* carry bit */ 51241475Smckusick } else { 51343641Skarels frame.f_regs[D0] = rval[0]; 51443641Skarels frame.f_regs[D1] = rval[1]; 51541475Smckusick frame.f_sr &= ~PSL_C; 51641475Smckusick } 51742370Skarels } 51842370Skarels /* else if (error == EJUSTRETURN) */ 51941475Smckusick /* nothing to do */ 52042370Skarels 52141475Smckusick done: 52241475Smckusick /* 52342370Skarels * Reinitialize proc pointer `p' as it may be different 52442370Skarels * if this is a child returning from fork syscall. 52542370Skarels */ 52648465Skarels p = curproc; 52749317Shibler while (i = CURSIG(p)) 52849317Shibler psig(i); 52941475Smckusick p->p_pri = p->p_usrpri; 53048465Skarels if (want_resched) { 53141475Smckusick /* 53248465Skarels * Since we are curproc, clock will normally just change 53341475Smckusick * our priority without moving us from one queue to another 53441475Smckusick * (since the running process is not on a queue.) 53541475Smckusick * If that happened after we setrq ourselves but before we 53641475Smckusick * swtch()'ed, we might not be on the queue indicated by 53741475Smckusick * our priority. 53841475Smckusick */ 53941475Smckusick (void) splclock(); 54041475Smckusick setrq(p); 54148465Skarels p->p_stats->p_ru.ru_nivcsw++; 54241475Smckusick swtch(); 54349317Shibler while (i = CURSIG(p)) 54449317Shibler psig(i); 54541475Smckusick } 54648465Skarels if (p->p_stats->p_prof.pr_scale) { 54741475Smckusick int ticks; 54848465Skarels struct timeval *tv = &p->p_stime; 54941475Smckusick 55041475Smckusick ticks = ((tv->tv_sec - syst.tv_sec) * 1000 + 55141475Smckusick (tv->tv_usec - syst.tv_usec) / 1000) / (tick / 1000); 55241475Smckusick if (ticks) { 55341475Smckusick #ifdef PROFTIMER 55441475Smckusick extern int profscale; 55548465Skarels addupc(frame.f_pc, &p->p_stats->p_prof, 55648465Skarels ticks * profscale); 55741475Smckusick #else 55848465Skarels addupc(frame.f_pc, &p->p_stats->p_prof, ticks); 55941475Smckusick #endif 56041475Smckusick } 56141475Smckusick } 56241475Smckusick curpri = p->p_pri; 56341475Smckusick #ifdef KTRACE 56443641Skarels if (KTRPOINT(p, KTR_SYSRET)) 56543641Skarels ktrsysret(p->p_tracep, code, error, rval[0]); 56641475Smckusick #endif 56741475Smckusick } 568