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 * 1241475Smckusick * from: Utah $Hdr: trap.c 1.28 89/09/25$ 1341475Smckusick * 14*44018Skarels * @(#)trap.c 7.7 (Berkeley) 06/25/90 1541475Smckusick */ 1641475Smckusick 1741475Smckusick #include "cpu.h" 1841475Smckusick #include "psl.h" 1941475Smckusick #include "reg.h" 2041475Smckusick #include "pte.h" 2141475Smckusick #include "mtpr.h" 2241475Smckusick 2341475Smckusick #include "param.h" 2441475Smckusick #include "systm.h" 2541475Smckusick #include "user.h" 2641475Smckusick #include "proc.h" 2741475Smckusick #include "seg.h" 2841475Smckusick #include "trap.h" 2941475Smckusick #include "acct.h" 3041475Smckusick #include "kernel.h" 3141475Smckusick #include "vm.h" 3241475Smckusick #include "cmap.h" 3341475Smckusick #include "syslog.h" 3441475Smckusick #ifdef KTRACE 3541475Smckusick #include "ktrace.h" 3641475Smckusick #endif 3741475Smckusick 3841475Smckusick #ifdef HPUXCOMPAT 3941475Smckusick #include "../hpux/hpux.h" 4041475Smckusick #endif 4141475Smckusick 4241475Smckusick #define USER 040 /* user-mode flag added to type */ 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 6541475Smckusick #ifdef DEBUG 6641475Smckusick int mmudebug = 0; 6741475Smckusick #endif 6841475Smckusick 6941475Smckusick /* 7041475Smckusick * Called from the trap handler when a processor trap occurs. 7141475Smckusick */ 7241475Smckusick /*ARGSUSED*/ 7341475Smckusick trap(type, code, v, frame) 7441475Smckusick int type; 7541475Smckusick unsigned code; 7641475Smckusick register unsigned v; 7741475Smckusick struct frame frame; 7841475Smckusick { 7941475Smckusick register int i; 8041475Smckusick unsigned ucode = 0; 8141475Smckusick register struct proc *p = u.u_procp; 8241475Smckusick struct timeval syst; 8341475Smckusick unsigned ncode; 8441475Smckusick 8541475Smckusick cnt.v_trap++; 8641475Smckusick syst = u.u_ru.ru_stime; 8741475Smckusick if (USERMODE(frame.f_sr)) { 8841475Smckusick type |= USER; 8941475Smckusick u.u_ar0 = frame.f_regs; 9041475Smckusick } 9141475Smckusick switch (type) { 9241475Smckusick 9341475Smckusick default: 9441475Smckusick dopanic: 9541475Smckusick #ifdef KGDB 9641475Smckusick if (!panicstr && kgdb_trap(type, code, v, &frame)) 9741475Smckusick return; 9841475Smckusick #endif 9941475Smckusick printf("trap type %d, code = %x, v = %x\n", type, code, v); 10041475Smckusick regdump(frame.f_regs, 128); 10141475Smckusick type &= ~USER; 10241475Smckusick if ((unsigned)type < TRAP_TYPES) 10341475Smckusick panic(trap_type[type]); 10441475Smckusick panic("trap"); 10541475Smckusick 10641475Smckusick case T_BUSERR: /* kernel bus error */ 10741475Smckusick if (!u.u_pcb.pcb_onfault) 10841475Smckusick goto dopanic; 10941475Smckusick /* 11041475Smckusick * If we have arranged to catch this fault in any of the 11141475Smckusick * copy to/from user space routines, set PC to return to 11241475Smckusick * indicated location and set flag informing buserror code 11341475Smckusick * that it may need to clean up stack frame. 11441475Smckusick */ 11541475Smckusick copyfault: 11641475Smckusick frame.f_pc = (int) u.u_pcb.pcb_onfault; 11741475Smckusick frame.f_stackadj = -1; 11841475Smckusick return; 11941475Smckusick 12041475Smckusick case T_BUSERR+USER: /* bus error */ 12141475Smckusick case T_ADDRERR+USER: /* address error */ 12241475Smckusick i = SIGBUS; 12341475Smckusick break; 12441475Smckusick 12541475Smckusick #ifdef FPCOPROC 12641475Smckusick case T_COPERR: /* kernel coprocessor violation */ 12741475Smckusick #endif 12841475Smckusick case T_FMTERR: /* kernel format error */ 12941475Smckusick /* 13041475Smckusick * The user has most likely trashed the RTE or FP state info 13141475Smckusick * in the stack frame of a signal handler. 13241475Smckusick */ 13342370Skarels type |= USER; 13441475Smckusick printf("pid %d: kernel %s exception\n", u.u_procp->p_pid, 13541475Smckusick type==T_COPERR ? "coprocessor" : "format"); 13641475Smckusick u.u_signal[SIGILL] = SIG_DFL; 13741475Smckusick i = sigmask(SIGILL); 13841475Smckusick p->p_sigignore &= ~i; 13941475Smckusick p->p_sigcatch &= ~i; 14041475Smckusick p->p_sigmask &= ~i; 14142370Skarels i = SIGILL; 14241475Smckusick ucode = frame.f_format; /* XXX was ILL_RESAD_FAULT */ 14342370Skarels break; 14441475Smckusick 14541475Smckusick #ifdef FPCOPROC 14641475Smckusick case T_COPERR+USER: /* user coprocessor violation */ 14741475Smckusick /* What is a proper response here? */ 14841475Smckusick ucode = 0; 14941475Smckusick i = SIGFPE; 15041475Smckusick break; 15141475Smckusick 15241475Smckusick case T_FPERR+USER: /* 68881 exceptions */ 15341475Smckusick /* 15441475Smckusick * We pass along the 68881 status register which locore stashed 15541475Smckusick * in code for us. Note that there is a possibility that the 15641475Smckusick * bit pattern of this register will conflict with one of the 15741475Smckusick * FPE_* codes defined in signal.h. Fortunately for us, the 15841475Smckusick * only such codes we use are all in the range 1-7 and the low 15941475Smckusick * 3 bits of the status register are defined as 0 so there is 16041475Smckusick * no clash. 16141475Smckusick */ 16241475Smckusick ucode = code; 16341475Smckusick i = SIGFPE; 16441475Smckusick break; 16541475Smckusick #endif 16641475Smckusick 16741475Smckusick case T_ILLINST+USER: /* illegal instruction fault */ 16841475Smckusick #ifdef HPUXCOMPAT 16941475Smckusick if (u.u_procp->p_flag & SHPUX) { 17041475Smckusick ucode = HPUX_ILL_ILLINST_TRAP; 17141475Smckusick i = SIGILL; 17241475Smckusick break; 17341475Smckusick } 17441475Smckusick /* fall through */ 17541475Smckusick #endif 17641475Smckusick case T_PRIVINST+USER: /* privileged instruction fault */ 17741475Smckusick #ifdef HPUXCOMPAT 17841475Smckusick if (u.u_procp->p_flag & SHPUX) 17941475Smckusick ucode = HPUX_ILL_PRIV_TRAP; 18041475Smckusick else 18141475Smckusick #endif 18241475Smckusick ucode = frame.f_format; /* XXX was ILL_PRIVIN_FAULT */ 18341475Smckusick i = SIGILL; 18441475Smckusick break; 18541475Smckusick 18641475Smckusick case T_ZERODIV+USER: /* Divide by zero */ 18741475Smckusick #ifdef HPUXCOMPAT 18841475Smckusick if (u.u_procp->p_flag & SHPUX) 18941475Smckusick ucode = HPUX_FPE_INTDIV_TRAP; 19041475Smckusick else 19141475Smckusick #endif 19241475Smckusick ucode = frame.f_format; /* XXX was FPE_INTDIV_TRAP */ 19341475Smckusick i = SIGFPE; 19441475Smckusick break; 19541475Smckusick 19641475Smckusick case T_CHKINST+USER: /* CHK instruction trap */ 19741475Smckusick #ifdef HPUXCOMPAT 19841475Smckusick if (u.u_procp->p_flag & SHPUX) { 19941475Smckusick /* handled differently under hp-ux */ 20041475Smckusick i = SIGILL; 20141475Smckusick ucode = HPUX_ILL_CHK_TRAP; 20241475Smckusick break; 20341475Smckusick } 20441475Smckusick #endif 20541475Smckusick ucode = frame.f_format; /* XXX was FPE_SUBRNG_TRAP */ 20641475Smckusick i = SIGFPE; 20741475Smckusick break; 20841475Smckusick 20941475Smckusick case T_TRAPVINST+USER: /* TRAPV instruction trap */ 21041475Smckusick #ifdef HPUXCOMPAT 21141475Smckusick if (u.u_procp->p_flag & SHPUX) { 21241475Smckusick /* handled differently under hp-ux */ 21341475Smckusick i = SIGILL; 21441475Smckusick ucode = HPUX_ILL_TRAPV_TRAP; 21541475Smckusick break; 21641475Smckusick } 21741475Smckusick #endif 21841475Smckusick ucode = frame.f_format; /* XXX was FPE_INTOVF_TRAP */ 21941475Smckusick i = SIGFPE; 22041475Smckusick break; 22141475Smckusick 22241475Smckusick /* 22341475Smckusick * XXX: Trace traps are a nightmare. 22441475Smckusick * 22541475Smckusick * HP-UX uses trap #1 for breakpoints, 22641475Smckusick * HPBSD uses trap #2, 22741475Smckusick * SUN 3.x uses trap #15, 22841475Smckusick * KGDB uses trap #15 (for kernel breakpoints). 22941475Smckusick * 23041475Smckusick * HPBSD and HP-UX traps both get mapped by locore.s into T_TRACE. 23141475Smckusick * SUN 3.x traps get passed through as T_TRAP15 and are not really 23241475Smckusick * supported yet. KGDB traps are also passed through as T_TRAP15 23341475Smckusick * and are not used yet. 23441475Smckusick */ 23541475Smckusick case T_TRACE: /* kernel trace trap */ 23641475Smckusick case T_TRAP15: /* SUN (or KGDB) kernel trace trap */ 23741475Smckusick #ifdef KGDB 23841475Smckusick if (kgdb_trap(type, code, v, &frame)) 23941475Smckusick return; 24041475Smckusick #endif 24141475Smckusick frame.f_sr &= ~PSL_T; 24241475Smckusick i = SIGTRAP; 24341475Smckusick break; 24441475Smckusick 24541475Smckusick case T_TRACE+USER: /* user trace trap */ 24641475Smckusick case T_TRAP15+USER: /* SUN user trace trap */ 24741475Smckusick frame.f_sr &= ~PSL_T; 24841475Smckusick i = SIGTRAP; 24941475Smckusick break; 25041475Smckusick 25143413Shibler case T_ASTFLT: /* system async trap, cannot happen */ 25241475Smckusick goto dopanic; 25341475Smckusick 25443413Shibler case T_ASTFLT+USER: /* user async trap */ 25541475Smckusick astoff(); 25641475Smckusick /* 25741475Smckusick * We check for software interrupts first. This is because 25841475Smckusick * they are at a higher level than ASTs, and on a VAX would 25941475Smckusick * interrupt the AST. We assume that if we are processing 26041475Smckusick * an AST that we must be at IPL0 so we don't bother to 26141475Smckusick * check. Note that we ensure that we are at least at SIR 26241475Smckusick * IPL while processing the SIR. 26341475Smckusick */ 26441475Smckusick spl1(); 26541475Smckusick /* fall into... */ 26641475Smckusick 26741475Smckusick case T_SSIR: /* software interrupt */ 26841475Smckusick case T_SSIR+USER: 26941475Smckusick if (ssir & SIR_NET) { 27041475Smckusick siroff(SIR_NET); 27141475Smckusick cnt.v_soft++; 27241475Smckusick netintr(); 27341475Smckusick } 27441475Smckusick if (ssir & SIR_CLOCK) { 27541475Smckusick siroff(SIR_CLOCK); 27641475Smckusick cnt.v_soft++; 27741475Smckusick softclock((caddr_t)frame.f_pc, (int)frame.f_sr); 27841475Smckusick } 27941475Smckusick /* 28041475Smckusick * If this was not an AST trap, we are all done. 28141475Smckusick */ 28243413Shibler if (type != T_ASTFLT+USER) { 28341475Smckusick cnt.v_trap--; 28441475Smckusick return; 28541475Smckusick } 28641475Smckusick spl0(); 28741475Smckusick #ifndef PROFTIMER 28841475Smckusick if ((u.u_procp->p_flag&SOWEUPC) && u.u_prof.pr_scale) { 28941475Smckusick addupc(frame.f_pc, &u.u_prof, 1); 29041475Smckusick u.u_procp->p_flag &= ~SOWEUPC; 29141475Smckusick } 29241475Smckusick #endif 29341475Smckusick goto out; 29441475Smckusick 29541475Smckusick case T_MMUFLT: /* kernel mode page fault */ 29641475Smckusick /* 29741475Smckusick * Could be caused by a page fault in one of the copy to/from 29841475Smckusick * user space routines. If so, we will have a catch address. 29941475Smckusick */ 30041475Smckusick if (!u.u_pcb.pcb_onfault) 30141475Smckusick goto dopanic; 30241475Smckusick /* fall into ... */ 30341475Smckusick 30441475Smckusick case T_MMUFLT+USER: /* page fault */ 30541475Smckusick /* 30641475Smckusick printf("trap: T_MMUFLT pid %d, code %x, v %x, pc %x, ps %x\n", 30741475Smckusick p->p_pid, code, v, frame.f_pc, frame.f_sr); 30841475Smckusick */ 30941475Smckusick if (v >= USRSTACK) { 31041475Smckusick if (type == T_MMUFLT) 31141475Smckusick goto copyfault; 31241475Smckusick i = SIGSEGV; 31341475Smckusick break; 31441475Smckusick } 31541475Smckusick ncode = code >> 16; 31641475Smckusick #if defined(HP330) || defined(HP360) || defined(HP370) 31741475Smckusick /* 31841475Smckusick * Crudely map PMMU faults into HP MMU faults. 31941475Smckusick */ 32041475Smckusick if (mmutype != MMU_HP) { 32141475Smckusick int ocode = ncode; 32241475Smckusick ncode = 0; 32341475Smckusick if (ocode & PMMU_WP) 32441475Smckusick ncode |= MMU_WPF; 32541475Smckusick else if (ocode & PMMU_INV) { 32641475Smckusick if ((ocode & PMMU_LVLMASK) == 2) 32741475Smckusick ncode |= MMU_PF; 32841475Smckusick else 32941475Smckusick ncode |= MMU_PTF; 33041475Smckusick } 33141475Smckusick /* 33241475Smckusick * RMW cycle, must load ATC by hand 33341475Smckusick */ 33441475Smckusick else if ((code & (SSW_DF|SSW_RM)) == (SSW_DF|SSW_RM)) { 33541475Smckusick #ifdef DEBUG 33641475Smckusick log(LOG_WARNING, 33741475Smckusick "RMW fault at %x: MMUSR %x SSW %x\n", 33841475Smckusick v, ocode, code & 0xFFFF); 33941475Smckusick #endif 34041475Smckusick ploadw((caddr_t)v); 34141475Smckusick return; 34241475Smckusick } 34341475Smckusick /* 34441475Smckusick * Fault with no fault bits, should indicate bad 34541475Smckusick * hardware but we see this on 340s using starbase 34641475Smckusick * sometimes (faults accessing catseye registers) 34741475Smckusick */ 34841475Smckusick else { 34941475Smckusick log(LOG_WARNING, 35041475Smckusick "Bad PMMU fault at %x: MMUSR %x SSW %x\n", 35141475Smckusick v, ocode, code & 0xFFFF); 35241475Smckusick return; 35341475Smckusick } 35441475Smckusick #ifdef DEBUG 35541475Smckusick if (mmudebug && mmudebug == p->p_pid) 35641475Smckusick printf("MMU %d: v%x, os%x, ns%x\n", 35741475Smckusick p->p_pid, v, ocode, ncode); 35841475Smckusick #endif 35941475Smckusick } 36041475Smckusick #endif 36141475Smckusick #ifdef DEBUG 36241475Smckusick if ((ncode & (MMU_PTF|MMU_PF|MMU_WPF|MMU_FPE)) == 0) { 36341475Smckusick printf("T_MMUFLT with no fault bits\n"); 36441475Smckusick goto dopanic; 36541475Smckusick } 36641475Smckusick #endif 36741475Smckusick if (ncode & MMU_PTF) { 36841475Smckusick #ifdef DEBUG 36941475Smckusick /* 37041475Smckusick * NOTE: we use a u_int instead of an ste since the 37141475Smckusick * current compiler generates bogus code for some 37241475Smckusick * bitfield operations (i.e. attempts to access last 37341475Smckusick * word of a page as a longword causing fault). 37441475Smckusick */ 37541475Smckusick extern struct ste *vtoste(); 37641475Smckusick u_int *ste = (u_int *)vtoste(p, v); 37741475Smckusick 37841475Smckusick if (*ste & SG_V) { 37941475Smckusick if (ncode & MMU_WPF) { 38041475Smckusick printf("PTF|WPF...\n"); 38141475Smckusick if (type == T_MMUFLT) 38241475Smckusick goto copyfault; 38341475Smckusick i = SIGBUS; 38441475Smckusick break; 38541475Smckusick } 38641475Smckusick printf("MMU_PTF with sg_v, ste@%x = %x\n", 38741475Smckusick ste, *ste); 38841475Smckusick goto dopanic; 38941475Smckusick } 39041475Smckusick #endif 39141475Smckusick #ifdef HPUXCOMPAT 39241475Smckusick if (ISHPMMADDR(v)) { 39341475Smckusick extern struct ste *vtoste(); 39441475Smckusick u_int *bste, *nste; 39541475Smckusick 39641475Smckusick bste = (u_int *)vtoste(p, HPMMBASEADDR(v)); 39741475Smckusick nste = (u_int *)vtoste(p, v); 39841475Smckusick if ((*bste & SG_V) && *nste == SG_NV) { 39941475Smckusick *nste = *bste; 40041475Smckusick TBIAU(); 40141475Smckusick return; 40241475Smckusick } 40341475Smckusick } 40441475Smckusick #endif 40541475Smckusick growit: 40641475Smckusick if (type == T_MMUFLT) 40741475Smckusick goto copyfault; 40841475Smckusick if (grow((unsigned)frame.f_regs[SP]) || grow(v)) 40941475Smckusick goto out; 41041475Smckusick i = SIGSEGV; 41141475Smckusick break; 41241475Smckusick } 41341475Smckusick #ifdef HPUXCOMPAT 41441475Smckusick if (ISHPMMADDR(v)) { 41541475Smckusick TBIS(v); 41641475Smckusick v = HPMMBASEADDR(v); 41741475Smckusick } 41841475Smckusick #endif 41941475Smckusick /* 42041475Smckusick * NOTE: WPF without PG_V is possible 42141475Smckusick * (e.g. attempt to write shared text which is paged out) 42241475Smckusick */ 42341475Smckusick if (ncode & MMU_WPF) { 42441475Smckusick #ifdef DEBUG 42541475Smckusick extern struct ste *vtoste(); 42641475Smckusick u_int *ste = (u_int *)vtoste(p, v); 42741475Smckusick 42841475Smckusick if (!(*ste & SG_V)) { 42941475Smckusick printf("MMU_WPF without sg_v, ste@%x = %x\n", 43041475Smckusick ste, *ste); 43141475Smckusick goto dopanic; 43241475Smckusick } 43341475Smckusick #endif 43441475Smckusick if (type == T_MMUFLT) 43541475Smckusick goto copyfault; 43641475Smckusick i = SIGBUS; 43741475Smckusick break; 43841475Smckusick } 43941475Smckusick if (ncode & MMU_PF) { 44041475Smckusick register u_int vp; 44141475Smckusick #ifdef DEBUG 44241475Smckusick extern struct ste *vtoste(); 44341475Smckusick u_int *ste = (u_int *)vtoste(p, v); 44441475Smckusick struct pte *pte; 44541475Smckusick 44641475Smckusick if (!(*ste & SG_V)) { 44741475Smckusick printf("MMU_PF without sg_v, ste@%x = %x\n", 44841475Smckusick ste, *ste); 44941475Smckusick goto dopanic; 45041475Smckusick } 45141475Smckusick #endif 45241475Smckusick vp = btop(v); 45341475Smckusick if (vp >= dptov(p, p->p_dsize) && 45441475Smckusick vp < sptov(p, p->p_ssize-1)) 45541475Smckusick goto growit; 45641475Smckusick #ifdef DEBUG 45741475Smckusick pte = vtopte(p, vp); 45841475Smckusick if (*(u_int *)pte & PG_V) { 45941475Smckusick printf("MMU_PF with pg_v, pte = %x\n", 46041475Smckusick *(u_int *)pte); 46141475Smckusick goto dopanic; 46241475Smckusick } 46341475Smckusick #endif 46441475Smckusick pagein(v, 0); 46541475Smckusick if (type == T_MMUFLT) 46641475Smckusick return; 46741475Smckusick goto out; 46841475Smckusick } 46941475Smckusick #ifdef DEBUG 47041475Smckusick printf("T_MMUFLT: unrecognized scenerio\n"); 47141475Smckusick goto dopanic; 47241475Smckusick #endif 47341475Smckusick } 47441475Smckusick trapsignal(i, ucode); 47541475Smckusick if ((type & USER) == 0) 47641475Smckusick return; 47741475Smckusick out: 47841475Smckusick p = u.u_procp; 47942370Skarels if (i = CURSIG(p)) 48042370Skarels psig(i); 48141475Smckusick p->p_pri = p->p_usrpri; 48241475Smckusick if (runrun) { 48341475Smckusick /* 48441475Smckusick * Since we are u.u_procp, clock will normally just change 48541475Smckusick * our priority without moving us from one queue to another 48641475Smckusick * (since the running process is not on a queue.) 48741475Smckusick * If that happened after we setrq ourselves but before we 48841475Smckusick * swtch()'ed, we might not be on the queue indicated by 48941475Smckusick * our priority. 49041475Smckusick */ 49141475Smckusick (void) splclock(); 49241475Smckusick setrq(p); 49341475Smckusick u.u_ru.ru_nivcsw++; 49441475Smckusick swtch(); 49542370Skarels if (i = CURSIG(p)) 49642370Skarels psig(i); 49741475Smckusick } 49841475Smckusick if (u.u_prof.pr_scale) { 49941475Smckusick int ticks; 50041475Smckusick struct timeval *tv = &u.u_ru.ru_stime; 50141475Smckusick 50241475Smckusick ticks = ((tv->tv_sec - syst.tv_sec) * 1000 + 50341475Smckusick (tv->tv_usec - syst.tv_usec) / 1000) / (tick / 1000); 50441475Smckusick if (ticks) { 50541475Smckusick #ifdef PROFTIMER 50641475Smckusick extern int profscale; 50741475Smckusick addupc(frame.f_pc, &u.u_prof, ticks * profscale); 50841475Smckusick #else 50941475Smckusick addupc(frame.f_pc, &u.u_prof, ticks); 51041475Smckusick #endif 51141475Smckusick } 51241475Smckusick } 51341475Smckusick curpri = p->p_pri; 51441475Smckusick } 51541475Smckusick 51641475Smckusick /* 51741475Smckusick * Called from the trap handler when a system call occurs 51841475Smckusick */ 51941475Smckusick /*ARGSUSED*/ 52041475Smckusick syscall(code, frame) 52141475Smckusick volatile int code; 52241475Smckusick struct frame frame; 52341475Smckusick { 52441475Smckusick register caddr_t params; 52541475Smckusick register int i; 52641475Smckusick register struct sysent *callp; 52742370Skarels register struct proc *p = u.u_procp; 52842370Skarels int error, opc, numsys; 529*44018Skarels struct args { 530*44018Skarels int i[8]; 531*44018Skarels } args; 532*44018Skarels int rval[2]; 53341475Smckusick struct timeval syst; 53441475Smckusick struct sysent *systab; 53541475Smckusick #ifdef HPUXCOMPAT 53641475Smckusick extern struct sysent hpuxsysent[]; 53741475Smckusick extern int hpuxnsysent, notimp(); 53841475Smckusick #endif 53941475Smckusick 54041475Smckusick cnt.v_syscall++; 54142371Smckusick syst = u.u_ru.ru_stime; 54241475Smckusick if (!USERMODE(frame.f_sr)) 54341475Smckusick panic("syscall"); 54442371Smckusick u.u_ar0 = frame.f_regs; 54541475Smckusick opc = frame.f_pc - 2; 54641475Smckusick systab = sysent; 54741475Smckusick numsys = nsysent; 54841475Smckusick #ifdef HPUXCOMPAT 54942370Skarels if (p->p_flag & SHPUX) { 55041475Smckusick systab = hpuxsysent; 55141475Smckusick numsys = hpuxnsysent; 55241475Smckusick } 55341475Smckusick #endif 55441475Smckusick params = (caddr_t)frame.f_regs[SP] + NBPW; 55542370Skarels if (code == 0) { /* indir */ 55642370Skarels code = fuword(params); 55741475Smckusick params += NBPW; 55842370Skarels } 55942370Skarels if (code >= numsys) 56042370Skarels callp = &systab[0]; /* indir (illegal) */ 56142370Skarels else 56242370Skarels callp = &systab[code]; 56341475Smckusick if ((i = callp->sy_narg * sizeof (int)) && 564*44018Skarels (error = copyin(params, (caddr_t)&args, (u_int)i))) { 56541475Smckusick #ifdef HPUXCOMPAT 56641475Smckusick if (p->p_flag & SHPUX) 56742370Skarels error = bsdtohpuxerrno(error); 56841475Smckusick #endif 56942370Skarels frame.f_regs[D0] = (u_char) error; 57041475Smckusick frame.f_sr |= PSL_C; /* carry bit */ 57141475Smckusick #ifdef KTRACE 57243641Skarels if (KTRPOINT(p, KTR_SYSCALL)) 573*44018Skarels ktrsyscall(p->p_tracep, code, callp->sy_narg, args.i); 57441475Smckusick #endif 57541475Smckusick goto done; 57641475Smckusick } 57741475Smckusick #ifdef KTRACE 57843641Skarels if (KTRPOINT(p, KTR_SYSCALL)) 579*44018Skarels ktrsyscall(p->p_tracep, code, callp->sy_narg, args.i); 58041475Smckusick #endif 58143641Skarels rval[0] = 0; 58243641Skarels rval[1] = frame.f_regs[D1]; 58341475Smckusick #ifdef HPUXCOMPAT 58442370Skarels /* debug kludge */ 58542370Skarels if (callp->sy_call == notimp) 586*44018Skarels error = notimp(u.u_procp, args.i, rval, code, callp->sy_narg); 58742370Skarels else 58841475Smckusick #endif 589*44018Skarels error = (*callp->sy_call)(u.u_procp, &args, rval); 59042370Skarels if (error == ERESTART) 59142370Skarels frame.f_pc = opc; 59242370Skarels else if (error != EJUSTRETURN) { 59342370Skarels if (error) { 59441475Smckusick #ifdef HPUXCOMPAT 59542370Skarels if (p->p_flag & SHPUX) 59642370Skarels error = bsdtohpuxerrno(error); 59741475Smckusick #endif 59842370Skarels frame.f_regs[D0] = (u_char) error; 59942370Skarels frame.f_sr |= PSL_C; /* carry bit */ 60041475Smckusick } else { 60143641Skarels frame.f_regs[D0] = rval[0]; 60243641Skarels frame.f_regs[D1] = rval[1]; 60341475Smckusick frame.f_sr &= ~PSL_C; 60441475Smckusick } 60542370Skarels } 60642370Skarels /* else if (error == EJUSTRETURN) */ 60741475Smckusick /* nothing to do */ 60842370Skarels 60941475Smckusick done: 61041475Smckusick /* 61142370Skarels * Reinitialize proc pointer `p' as it may be different 61242370Skarels * if this is a child returning from fork syscall. 61342370Skarels */ 61442371Smckusick p = u.u_procp; 61542370Skarels /* 61642371Smckusick * XXX the check for sigreturn ensures that we don't 61741475Smckusick * attempt to set up a call to a signal handler (sendsig) before 61841475Smckusick * we have cleaned up the stack from the last call (sigreturn). 61941475Smckusick * Allowing this seems to lock up the machine in certain scenarios. 62041475Smckusick * What should really be done is to clean up the signal handling 62141475Smckusick * so that this is not a problem. 62241475Smckusick */ 62342371Smckusick #include "syscall.h" 62442371Smckusick if (code != SYS_sigreturn && (i = CURSIG(p))) 62542370Skarels psig(i); 62641475Smckusick p->p_pri = p->p_usrpri; 62741475Smckusick if (runrun) { 62841475Smckusick /* 62941475Smckusick * Since we are u.u_procp, clock will normally just change 63041475Smckusick * our priority without moving us from one queue to another 63141475Smckusick * (since the running process is not on a queue.) 63241475Smckusick * If that happened after we setrq ourselves but before we 63341475Smckusick * swtch()'ed, we might not be on the queue indicated by 63441475Smckusick * our priority. 63541475Smckusick */ 63641475Smckusick (void) splclock(); 63741475Smckusick setrq(p); 63842371Smckusick u.u_ru.ru_nivcsw++; 63941475Smckusick swtch(); 64043413Shibler if (code != SYS_sigreturn && (i = CURSIG(p))) 64142370Skarels psig(i); 64241475Smckusick } 64342371Smckusick if (u.u_prof.pr_scale) { 64441475Smckusick int ticks; 64542371Smckusick struct timeval *tv = &u.u_ru.ru_stime; 64641475Smckusick 64741475Smckusick ticks = ((tv->tv_sec - syst.tv_sec) * 1000 + 64841475Smckusick (tv->tv_usec - syst.tv_usec) / 1000) / (tick / 1000); 64941475Smckusick if (ticks) { 65041475Smckusick #ifdef PROFTIMER 65141475Smckusick extern int profscale; 65242371Smckusick addupc(frame.f_pc, &u.u_prof, ticks * profscale); 65341475Smckusick #else 65442371Smckusick addupc(frame.f_pc, &u.u_prof, ticks); 65541475Smckusick #endif 65641475Smckusick } 65741475Smckusick } 65841475Smckusick curpri = p->p_pri; 65941475Smckusick #ifdef KTRACE 66043641Skarels if (KTRPOINT(p, KTR_SYSRET)) 66143641Skarels ktrsysret(p->p_tracep, code, error, rval[0]); 66241475Smckusick #endif 66341475Smckusick } 664