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*43413Shibler * @(#)trap.c 7.5 (Berkeley) 06/22/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 251*43413Shibler case T_ASTFLT: /* system async trap, cannot happen */ 25241475Smckusick goto dopanic; 25341475Smckusick 254*43413Shibler 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 */ 282*43413Shibler 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 i = u.u_error; 46541475Smckusick pagein(v, 0); 46641475Smckusick u.u_error = i; 46741475Smckusick if (type == T_MMUFLT) 46841475Smckusick return; 46941475Smckusick goto out; 47041475Smckusick } 47141475Smckusick #ifdef DEBUG 47241475Smckusick printf("T_MMUFLT: unrecognized scenerio\n"); 47341475Smckusick goto dopanic; 47441475Smckusick #endif 47541475Smckusick } 47641475Smckusick trapsignal(i, ucode); 47741475Smckusick if ((type & USER) == 0) 47841475Smckusick return; 47941475Smckusick out: 48041475Smckusick p = u.u_procp; 48142370Skarels if (i = CURSIG(p)) 48242370Skarels psig(i); 48341475Smckusick p->p_pri = p->p_usrpri; 48441475Smckusick if (runrun) { 48541475Smckusick /* 48641475Smckusick * Since we are u.u_procp, clock will normally just change 48741475Smckusick * our priority without moving us from one queue to another 48841475Smckusick * (since the running process is not on a queue.) 48941475Smckusick * If that happened after we setrq ourselves but before we 49041475Smckusick * swtch()'ed, we might not be on the queue indicated by 49141475Smckusick * our priority. 49241475Smckusick */ 49341475Smckusick (void) splclock(); 49441475Smckusick setrq(p); 49541475Smckusick u.u_ru.ru_nivcsw++; 49641475Smckusick swtch(); 49742370Skarels if (i = CURSIG(p)) 49842370Skarels psig(i); 49941475Smckusick } 50041475Smckusick if (u.u_prof.pr_scale) { 50141475Smckusick int ticks; 50241475Smckusick struct timeval *tv = &u.u_ru.ru_stime; 50341475Smckusick 50441475Smckusick ticks = ((tv->tv_sec - syst.tv_sec) * 1000 + 50541475Smckusick (tv->tv_usec - syst.tv_usec) / 1000) / (tick / 1000); 50641475Smckusick if (ticks) { 50741475Smckusick #ifdef PROFTIMER 50841475Smckusick extern int profscale; 50941475Smckusick addupc(frame.f_pc, &u.u_prof, ticks * profscale); 51041475Smckusick #else 51141475Smckusick addupc(frame.f_pc, &u.u_prof, ticks); 51241475Smckusick #endif 51341475Smckusick } 51441475Smckusick } 51541475Smckusick curpri = p->p_pri; 51641475Smckusick } 51741475Smckusick 51841475Smckusick /* 51941475Smckusick * Called from the trap handler when a system call occurs 52041475Smckusick */ 52141475Smckusick /*ARGSUSED*/ 52241475Smckusick syscall(code, frame) 52341475Smckusick volatile int code; 52441475Smckusick struct frame frame; 52541475Smckusick { 52641475Smckusick register caddr_t params; 52741475Smckusick register int i; 52841475Smckusick register struct sysent *callp; 52942370Skarels register struct proc *p = u.u_procp; 53042370Skarels int error, opc, numsys; 53141475Smckusick struct timeval syst; 53241475Smckusick struct sysent *systab; 53341475Smckusick #ifdef HPUXCOMPAT 53441475Smckusick extern struct sysent hpuxsysent[]; 53541475Smckusick extern int hpuxnsysent, notimp(); 53641475Smckusick #endif 53741475Smckusick 53841475Smckusick cnt.v_syscall++; 53942371Smckusick syst = u.u_ru.ru_stime; 54041475Smckusick if (!USERMODE(frame.f_sr)) 54141475Smckusick panic("syscall"); 54242371Smckusick u.u_ar0 = frame.f_regs; 54342371Smckusick u.u_error = 0; 54441475Smckusick opc = frame.f_pc - 2; 54541475Smckusick systab = sysent; 54641475Smckusick numsys = nsysent; 54741475Smckusick #ifdef HPUXCOMPAT 54842370Skarels if (p->p_flag & SHPUX) { 54941475Smckusick systab = hpuxsysent; 55041475Smckusick numsys = hpuxnsysent; 55141475Smckusick } 55241475Smckusick #endif 55341475Smckusick params = (caddr_t)frame.f_regs[SP] + NBPW; 55442370Skarels if (code == 0) { /* indir */ 55542370Skarels code = fuword(params); 55641475Smckusick params += NBPW; 55742370Skarels } 55842370Skarels if (code >= numsys) 55942370Skarels callp = &systab[0]; /* indir (illegal) */ 56042370Skarels else 56142370Skarels callp = &systab[code]; 56241475Smckusick if ((i = callp->sy_narg * sizeof (int)) && 56342371Smckusick (error = copyin(params, (caddr_t)u.u_arg, (u_int)i))) { 56441475Smckusick #ifdef HPUXCOMPAT 56541475Smckusick if (p->p_flag & SHPUX) 56642370Skarels error = bsdtohpuxerrno(error); 56741475Smckusick #endif 56842370Skarels frame.f_regs[D0] = (u_char) error; 56941475Smckusick frame.f_sr |= PSL_C; /* carry bit */ 57041475Smckusick #ifdef KTRACE 57141475Smckusick if (KTRPOINT(p, KTR_SYSCALL)) 57241475Smckusick ktrsyscall(p->p_tracep, code, callp->sy_narg); 57341475Smckusick #endif 57441475Smckusick goto done; 57541475Smckusick } 57641475Smckusick #ifdef KTRACE 57741475Smckusick if (KTRPOINT(p, KTR_SYSCALL)) 57841475Smckusick ktrsyscall(p->p_tracep, code, callp->sy_narg); 57941475Smckusick #endif 58042371Smckusick u.u_r.r_val1 = 0; 58142371Smckusick u.u_r.r_val2 = frame.f_regs[D0]; 58241475Smckusick #ifdef HPUXCOMPAT 58342370Skarels /* debug kludge */ 58442370Skarels if (callp->sy_call == notimp) 585*43413Shibler error = notimp(u.u_procp, u.u_ap, &u.u_r.r_val1, 586*43413Shibler code, callp->sy_narg); 58742370Skarels else 58841475Smckusick #endif 58942436Smckusick error = (*callp->sy_call)(u.u_procp, u.u_ap, &u.u_r.r_val1); 59042370Skarels error = u.u_error; /* XXX */ 59142370Skarels if (error == ERESTART) 59242370Skarels frame.f_pc = opc; 59342370Skarels else if (error != EJUSTRETURN) { 59442370Skarels if (error) { 59541475Smckusick #ifdef HPUXCOMPAT 59642370Skarels if (p->p_flag & SHPUX) 59742370Skarels error = bsdtohpuxerrno(error); 59841475Smckusick #endif 59942370Skarels frame.f_regs[D0] = (u_char) error; 60042370Skarels frame.f_sr |= PSL_C; /* carry bit */ 60141475Smckusick } else { 60242371Smckusick frame.f_regs[D0] = u.u_r.r_val1; 60342371Smckusick frame.f_regs[D1] = u.u_r.r_val2; 60441475Smckusick frame.f_sr &= ~PSL_C; 60541475Smckusick } 60642370Skarels } 60742370Skarels /* else if (error == EJUSTRETURN) */ 60841475Smckusick /* nothing to do */ 60942370Skarels 61041475Smckusick done: 61141475Smckusick /* 61242370Skarels * Reinitialize proc pointer `p' as it may be different 61342370Skarels * if this is a child returning from fork syscall. 61442370Skarels */ 61542371Smckusick p = u.u_procp; 61642370Skarels /* 61742371Smckusick * XXX the check for sigreturn ensures that we don't 61841475Smckusick * attempt to set up a call to a signal handler (sendsig) before 61941475Smckusick * we have cleaned up the stack from the last call (sigreturn). 62041475Smckusick * Allowing this seems to lock up the machine in certain scenarios. 62141475Smckusick * What should really be done is to clean up the signal handling 62241475Smckusick * so that this is not a problem. 62341475Smckusick */ 62442371Smckusick #include "syscall.h" 62542371Smckusick if (code != SYS_sigreturn && (i = CURSIG(p))) 62642370Skarels psig(i); 62741475Smckusick p->p_pri = p->p_usrpri; 62841475Smckusick if (runrun) { 62941475Smckusick /* 63041475Smckusick * Since we are u.u_procp, clock will normally just change 63141475Smckusick * our priority without moving us from one queue to another 63241475Smckusick * (since the running process is not on a queue.) 63341475Smckusick * If that happened after we setrq ourselves but before we 63441475Smckusick * swtch()'ed, we might not be on the queue indicated by 63541475Smckusick * our priority. 63641475Smckusick */ 63741475Smckusick (void) splclock(); 63841475Smckusick setrq(p); 63942371Smckusick u.u_ru.ru_nivcsw++; 64041475Smckusick swtch(); 641*43413Shibler if (code != SYS_sigreturn && (i = CURSIG(p))) 64242370Skarels psig(i); 64341475Smckusick } 64442371Smckusick if (u.u_prof.pr_scale) { 64541475Smckusick int ticks; 64642371Smckusick struct timeval *tv = &u.u_ru.ru_stime; 64741475Smckusick 64841475Smckusick ticks = ((tv->tv_sec - syst.tv_sec) * 1000 + 64941475Smckusick (tv->tv_usec - syst.tv_usec) / 1000) / (tick / 1000); 65041475Smckusick if (ticks) { 65141475Smckusick #ifdef PROFTIMER 65241475Smckusick extern int profscale; 65342371Smckusick addupc(frame.f_pc, &u.u_prof, ticks * profscale); 65441475Smckusick #else 65542371Smckusick addupc(frame.f_pc, &u.u_prof, ticks); 65641475Smckusick #endif 65741475Smckusick } 65841475Smckusick } 65941475Smckusick curpri = p->p_pri; 66041475Smckusick #ifdef KTRACE 66141475Smckusick if (KTRPOINT(p, KTR_SYSRET)) 66241475Smckusick ktrsysret(p->p_tracep, code); 66341475Smckusick #endif 66441475Smckusick } 665