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*42436Smckusick * @(#)trap.c 7.4 (Berkeley) 05/29/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 #ifdef SUNCOMPAT 24841475Smckusick /* 24941475Smckusick * Trap #2 is used to signal a cache flush. 25041475Smckusick * Should we also flush data cache? 25141475Smckusick */ 25241475Smckusick if (type == T_TRACE+USER && (p->p_flag & SSUN)) { 25341475Smckusick ICIA(); 25441475Smckusick goto out; 25541475Smckusick } 25641475Smckusick #endif 25741475Smckusick frame.f_sr &= ~PSL_T; 25841475Smckusick i = SIGTRAP; 25941475Smckusick break; 26041475Smckusick 26141475Smckusick case T_AST: /* system async trap, cannot happen */ 26241475Smckusick goto dopanic; 26341475Smckusick 26441475Smckusick case T_AST+USER: /* user async trap */ 26541475Smckusick astoff(); 26641475Smckusick /* 26741475Smckusick * We check for software interrupts first. This is because 26841475Smckusick * they are at a higher level than ASTs, and on a VAX would 26941475Smckusick * interrupt the AST. We assume that if we are processing 27041475Smckusick * an AST that we must be at IPL0 so we don't bother to 27141475Smckusick * check. Note that we ensure that we are at least at SIR 27241475Smckusick * IPL while processing the SIR. 27341475Smckusick */ 27441475Smckusick spl1(); 27541475Smckusick /* fall into... */ 27641475Smckusick 27741475Smckusick case T_SSIR: /* software interrupt */ 27841475Smckusick case T_SSIR+USER: 27941475Smckusick if (ssir & SIR_NET) { 28041475Smckusick siroff(SIR_NET); 28141475Smckusick cnt.v_soft++; 28241475Smckusick netintr(); 28341475Smckusick } 28441475Smckusick if (ssir & SIR_CLOCK) { 28541475Smckusick siroff(SIR_CLOCK); 28641475Smckusick cnt.v_soft++; 28741475Smckusick softclock((caddr_t)frame.f_pc, (int)frame.f_sr); 28841475Smckusick } 28941475Smckusick /* 29041475Smckusick * If this was not an AST trap, we are all done. 29141475Smckusick */ 29241475Smckusick if (type != T_AST+USER) { 29341475Smckusick cnt.v_trap--; 29441475Smckusick return; 29541475Smckusick } 29641475Smckusick spl0(); 29741475Smckusick #ifndef PROFTIMER 29841475Smckusick if ((u.u_procp->p_flag&SOWEUPC) && u.u_prof.pr_scale) { 29941475Smckusick addupc(frame.f_pc, &u.u_prof, 1); 30041475Smckusick u.u_procp->p_flag &= ~SOWEUPC; 30141475Smckusick } 30241475Smckusick #endif 30341475Smckusick goto out; 30441475Smckusick 30541475Smckusick case T_MMUFLT: /* kernel mode page fault */ 30641475Smckusick /* 30741475Smckusick * Could be caused by a page fault in one of the copy to/from 30841475Smckusick * user space routines. If so, we will have a catch address. 30941475Smckusick */ 31041475Smckusick if (!u.u_pcb.pcb_onfault) 31141475Smckusick goto dopanic; 31241475Smckusick /* fall into ... */ 31341475Smckusick 31441475Smckusick case T_MMUFLT+USER: /* page fault */ 31541475Smckusick /* 31641475Smckusick printf("trap: T_MMUFLT pid %d, code %x, v %x, pc %x, ps %x\n", 31741475Smckusick p->p_pid, code, v, frame.f_pc, frame.f_sr); 31841475Smckusick */ 31941475Smckusick if (v >= USRSTACK) { 32041475Smckusick if (type == T_MMUFLT) 32141475Smckusick goto copyfault; 32241475Smckusick i = SIGSEGV; 32341475Smckusick break; 32441475Smckusick } 32541475Smckusick ncode = code >> 16; 32641475Smckusick #if defined(HP330) || defined(HP360) || defined(HP370) 32741475Smckusick /* 32841475Smckusick * Crudely map PMMU faults into HP MMU faults. 32941475Smckusick */ 33041475Smckusick if (mmutype != MMU_HP) { 33141475Smckusick int ocode = ncode; 33241475Smckusick ncode = 0; 33341475Smckusick if (ocode & PMMU_WP) 33441475Smckusick ncode |= MMU_WPF; 33541475Smckusick else if (ocode & PMMU_INV) { 33641475Smckusick if ((ocode & PMMU_LVLMASK) == 2) 33741475Smckusick ncode |= MMU_PF; 33841475Smckusick else 33941475Smckusick ncode |= MMU_PTF; 34041475Smckusick } 34141475Smckusick /* 34241475Smckusick * RMW cycle, must load ATC by hand 34341475Smckusick */ 34441475Smckusick else if ((code & (SSW_DF|SSW_RM)) == (SSW_DF|SSW_RM)) { 34541475Smckusick #ifdef DEBUG 34641475Smckusick log(LOG_WARNING, 34741475Smckusick "RMW fault at %x: MMUSR %x SSW %x\n", 34841475Smckusick v, ocode, code & 0xFFFF); 34941475Smckusick #endif 35041475Smckusick ploadw((caddr_t)v); 35141475Smckusick return; 35241475Smckusick } 35341475Smckusick /* 35441475Smckusick * Fault with no fault bits, should indicate bad 35541475Smckusick * hardware but we see this on 340s using starbase 35641475Smckusick * sometimes (faults accessing catseye registers) 35741475Smckusick */ 35841475Smckusick else { 35941475Smckusick log(LOG_WARNING, 36041475Smckusick "Bad PMMU fault at %x: MMUSR %x SSW %x\n", 36141475Smckusick v, ocode, code & 0xFFFF); 36241475Smckusick return; 36341475Smckusick } 36441475Smckusick #ifdef DEBUG 36541475Smckusick if (mmudebug && mmudebug == p->p_pid) 36641475Smckusick printf("MMU %d: v%x, os%x, ns%x\n", 36741475Smckusick p->p_pid, v, ocode, ncode); 36841475Smckusick #endif 36941475Smckusick } 37041475Smckusick #endif 37141475Smckusick #ifdef DEBUG 37241475Smckusick if ((ncode & (MMU_PTF|MMU_PF|MMU_WPF|MMU_FPE)) == 0) { 37341475Smckusick printf("T_MMUFLT with no fault bits\n"); 37441475Smckusick goto dopanic; 37541475Smckusick } 37641475Smckusick #endif 37741475Smckusick if (ncode & MMU_PTF) { 37841475Smckusick #ifdef DEBUG 37941475Smckusick /* 38041475Smckusick * NOTE: we use a u_int instead of an ste since the 38141475Smckusick * current compiler generates bogus code for some 38241475Smckusick * bitfield operations (i.e. attempts to access last 38341475Smckusick * word of a page as a longword causing fault). 38441475Smckusick */ 38541475Smckusick extern struct ste *vtoste(); 38641475Smckusick u_int *ste = (u_int *)vtoste(p, v); 38741475Smckusick 38841475Smckusick if (*ste & SG_V) { 38941475Smckusick if (ncode & MMU_WPF) { 39041475Smckusick printf("PTF|WPF...\n"); 39141475Smckusick if (type == T_MMUFLT) 39241475Smckusick goto copyfault; 39341475Smckusick i = SIGBUS; 39441475Smckusick break; 39541475Smckusick } 39641475Smckusick printf("MMU_PTF with sg_v, ste@%x = %x\n", 39741475Smckusick ste, *ste); 39841475Smckusick goto dopanic; 39941475Smckusick } 40041475Smckusick #endif 40141475Smckusick #ifdef HPUXCOMPAT 40241475Smckusick if (ISHPMMADDR(v)) { 40341475Smckusick extern struct ste *vtoste(); 40441475Smckusick u_int *bste, *nste; 40541475Smckusick 40641475Smckusick bste = (u_int *)vtoste(p, HPMMBASEADDR(v)); 40741475Smckusick nste = (u_int *)vtoste(p, v); 40841475Smckusick if ((*bste & SG_V) && *nste == SG_NV) { 40941475Smckusick *nste = *bste; 41041475Smckusick TBIAU(); 41141475Smckusick return; 41241475Smckusick } 41341475Smckusick } 41441475Smckusick #endif 41541475Smckusick growit: 41641475Smckusick if (type == T_MMUFLT) 41741475Smckusick goto copyfault; 41841475Smckusick if (grow((unsigned)frame.f_regs[SP]) || grow(v)) 41941475Smckusick goto out; 42041475Smckusick i = SIGSEGV; 42141475Smckusick break; 42241475Smckusick } 42341475Smckusick #ifdef HPUXCOMPAT 42441475Smckusick if (ISHPMMADDR(v)) { 42541475Smckusick TBIS(v); 42641475Smckusick v = HPMMBASEADDR(v); 42741475Smckusick } 42841475Smckusick #endif 42941475Smckusick /* 43041475Smckusick * NOTE: WPF without PG_V is possible 43141475Smckusick * (e.g. attempt to write shared text which is paged out) 43241475Smckusick */ 43341475Smckusick if (ncode & MMU_WPF) { 43441475Smckusick #ifdef DEBUG 43541475Smckusick extern struct ste *vtoste(); 43641475Smckusick u_int *ste = (u_int *)vtoste(p, v); 43741475Smckusick 43841475Smckusick if (!(*ste & SG_V)) { 43941475Smckusick printf("MMU_WPF without sg_v, ste@%x = %x\n", 44041475Smckusick ste, *ste); 44141475Smckusick goto dopanic; 44241475Smckusick } 44341475Smckusick #endif 44441475Smckusick if (type == T_MMUFLT) 44541475Smckusick goto copyfault; 44641475Smckusick i = SIGBUS; 44741475Smckusick break; 44841475Smckusick } 44941475Smckusick if (ncode & MMU_PF) { 45041475Smckusick register u_int vp; 45141475Smckusick #ifdef DEBUG 45241475Smckusick extern struct ste *vtoste(); 45341475Smckusick u_int *ste = (u_int *)vtoste(p, v); 45441475Smckusick struct pte *pte; 45541475Smckusick 45641475Smckusick if (!(*ste & SG_V)) { 45741475Smckusick printf("MMU_PF without sg_v, ste@%x = %x\n", 45841475Smckusick ste, *ste); 45941475Smckusick goto dopanic; 46041475Smckusick } 46141475Smckusick #endif 46241475Smckusick vp = btop(v); 46341475Smckusick if (vp >= dptov(p, p->p_dsize) && 46441475Smckusick vp < sptov(p, p->p_ssize-1)) 46541475Smckusick goto growit; 46641475Smckusick #ifdef DEBUG 46741475Smckusick pte = vtopte(p, vp); 46841475Smckusick if (*(u_int *)pte & PG_V) { 46941475Smckusick printf("MMU_PF with pg_v, pte = %x\n", 47041475Smckusick *(u_int *)pte); 47141475Smckusick goto dopanic; 47241475Smckusick } 47341475Smckusick #endif 47441475Smckusick i = u.u_error; 47541475Smckusick pagein(v, 0); 47641475Smckusick u.u_error = i; 47741475Smckusick if (type == T_MMUFLT) 47841475Smckusick return; 47941475Smckusick goto out; 48041475Smckusick } 48141475Smckusick #ifdef DEBUG 48241475Smckusick printf("T_MMUFLT: unrecognized scenerio\n"); 48341475Smckusick goto dopanic; 48441475Smckusick #endif 48541475Smckusick } 48641475Smckusick trapsignal(i, ucode); 48741475Smckusick if ((type & USER) == 0) 48841475Smckusick return; 48941475Smckusick out: 49041475Smckusick p = u.u_procp; 49142370Skarels if (i = CURSIG(p)) 49242370Skarels psig(i); 49341475Smckusick p->p_pri = p->p_usrpri; 49441475Smckusick if (runrun) { 49541475Smckusick /* 49641475Smckusick * Since we are u.u_procp, clock will normally just change 49741475Smckusick * our priority without moving us from one queue to another 49841475Smckusick * (since the running process is not on a queue.) 49941475Smckusick * If that happened after we setrq ourselves but before we 50041475Smckusick * swtch()'ed, we might not be on the queue indicated by 50141475Smckusick * our priority. 50241475Smckusick */ 50341475Smckusick (void) splclock(); 50441475Smckusick setrq(p); 50541475Smckusick u.u_ru.ru_nivcsw++; 50641475Smckusick swtch(); 50742370Skarels if (i = CURSIG(p)) 50842370Skarels psig(i); 50941475Smckusick } 51041475Smckusick if (u.u_prof.pr_scale) { 51141475Smckusick int ticks; 51241475Smckusick struct timeval *tv = &u.u_ru.ru_stime; 51341475Smckusick 51441475Smckusick ticks = ((tv->tv_sec - syst.tv_sec) * 1000 + 51541475Smckusick (tv->tv_usec - syst.tv_usec) / 1000) / (tick / 1000); 51641475Smckusick if (ticks) { 51741475Smckusick #ifdef PROFTIMER 51841475Smckusick extern int profscale; 51941475Smckusick addupc(frame.f_pc, &u.u_prof, ticks * profscale); 52041475Smckusick #else 52141475Smckusick addupc(frame.f_pc, &u.u_prof, ticks); 52241475Smckusick #endif 52341475Smckusick } 52441475Smckusick } 52541475Smckusick curpri = p->p_pri; 52641475Smckusick } 52741475Smckusick 52841475Smckusick /* 52941475Smckusick * Called from the trap handler when a system call occurs 53041475Smckusick */ 53141475Smckusick /*ARGSUSED*/ 53241475Smckusick syscall(code, frame) 53341475Smckusick volatile int code; 53441475Smckusick struct frame frame; 53541475Smckusick { 53641475Smckusick register caddr_t params; 53741475Smckusick register int i; 53841475Smckusick register struct sysent *callp; 53942370Skarels register struct proc *p = u.u_procp; 54042370Skarels int error, opc, numsys; 54141475Smckusick struct timeval syst; 54241475Smckusick struct sysent *systab; 54341475Smckusick #ifdef HPUXCOMPAT 54441475Smckusick extern struct sysent hpuxsysent[]; 54541475Smckusick extern int hpuxnsysent, notimp(); 54641475Smckusick #endif 54741475Smckusick 54841475Smckusick cnt.v_syscall++; 54942371Smckusick syst = u.u_ru.ru_stime; 55041475Smckusick if (!USERMODE(frame.f_sr)) 55141475Smckusick panic("syscall"); 55242371Smckusick u.u_ar0 = frame.f_regs; 55342371Smckusick u.u_error = 0; 55441475Smckusick opc = frame.f_pc - 2; 55541475Smckusick systab = sysent; 55641475Smckusick numsys = nsysent; 55741475Smckusick #ifdef HPUXCOMPAT 55842370Skarels if (p->p_flag & SHPUX) { 55941475Smckusick systab = hpuxsysent; 56041475Smckusick numsys = hpuxnsysent; 56141475Smckusick } 56241475Smckusick #endif 56341475Smckusick params = (caddr_t)frame.f_regs[SP] + NBPW; 56442370Skarels if (code == 0) { /* indir */ 56542370Skarels code = fuword(params); 56641475Smckusick params += NBPW; 56742370Skarels } 56842370Skarels if (code >= numsys) 56942370Skarels callp = &systab[0]; /* indir (illegal) */ 57042370Skarels else 57142370Skarels callp = &systab[code]; 57241475Smckusick if ((i = callp->sy_narg * sizeof (int)) && 57342371Smckusick (error = copyin(params, (caddr_t)u.u_arg, (u_int)i))) { 57441475Smckusick #ifdef HPUXCOMPAT 57541475Smckusick if (p->p_flag & SHPUX) 57642370Skarels error = bsdtohpuxerrno(error); 57741475Smckusick #endif 57842370Skarels frame.f_regs[D0] = (u_char) error; 57941475Smckusick frame.f_sr |= PSL_C; /* carry bit */ 58041475Smckusick #ifdef KTRACE 58141475Smckusick if (KTRPOINT(p, KTR_SYSCALL)) 58241475Smckusick ktrsyscall(p->p_tracep, code, callp->sy_narg); 58341475Smckusick #endif 58441475Smckusick goto done; 58541475Smckusick } 58641475Smckusick #ifdef KTRACE 58741475Smckusick if (KTRPOINT(p, KTR_SYSCALL)) 58841475Smckusick ktrsyscall(p->p_tracep, code, callp->sy_narg); 58941475Smckusick #endif 59042371Smckusick u.u_r.r_val1 = 0; 59142371Smckusick u.u_r.r_val2 = frame.f_regs[D0]; 59241475Smckusick #ifdef HPUXCOMPAT 59342370Skarels /* debug kludge */ 59442370Skarels if (callp->sy_call == notimp) 59542370Skarels error = notimp(code, callp->sy_narg); 59642370Skarels else 59741475Smckusick #endif 598*42436Smckusick error = (*callp->sy_call)(u.u_procp, u.u_ap, &u.u_r.r_val1); 59942370Skarels error = u.u_error; /* XXX */ 60042370Skarels if (error == ERESTART) 60142370Skarels frame.f_pc = opc; 60242370Skarels else if (error != EJUSTRETURN) { 60342370Skarels if (error) { 60441475Smckusick #ifdef HPUXCOMPAT 60542370Skarels if (p->p_flag & SHPUX) 60642370Skarels error = bsdtohpuxerrno(error); 60741475Smckusick #endif 60842370Skarels frame.f_regs[D0] = (u_char) error; 60942370Skarels frame.f_sr |= PSL_C; /* carry bit */ 61041475Smckusick } else { 61142371Smckusick frame.f_regs[D0] = u.u_r.r_val1; 61242371Smckusick frame.f_regs[D1] = u.u_r.r_val2; 61341475Smckusick frame.f_sr &= ~PSL_C; 61441475Smckusick } 61542370Skarels } 61642370Skarels /* else if (error == EJUSTRETURN) */ 61741475Smckusick /* nothing to do */ 61842370Skarels 61941475Smckusick done: 62041475Smckusick /* 62142370Skarels * Reinitialize proc pointer `p' as it may be different 62242370Skarels * if this is a child returning from fork syscall. 62342370Skarels */ 62442371Smckusick p = u.u_procp; 62542370Skarels /* 62642371Smckusick * XXX the check for sigreturn ensures that we don't 62741475Smckusick * attempt to set up a call to a signal handler (sendsig) before 62841475Smckusick * we have cleaned up the stack from the last call (sigreturn). 62941475Smckusick * Allowing this seems to lock up the machine in certain scenarios. 63041475Smckusick * What should really be done is to clean up the signal handling 63141475Smckusick * so that this is not a problem. 63241475Smckusick */ 63342371Smckusick #include "syscall.h" 63442371Smckusick if (code != SYS_sigreturn && (i = CURSIG(p))) 63542370Skarels psig(i); 63641475Smckusick p->p_pri = p->p_usrpri; 63741475Smckusick if (runrun) { 63841475Smckusick /* 63941475Smckusick * Since we are u.u_procp, clock will normally just change 64041475Smckusick * our priority without moving us from one queue to another 64141475Smckusick * (since the running process is not on a queue.) 64241475Smckusick * If that happened after we setrq ourselves but before we 64341475Smckusick * swtch()'ed, we might not be on the queue indicated by 64441475Smckusick * our priority. 64541475Smckusick */ 64641475Smckusick (void) splclock(); 64741475Smckusick setrq(p); 64842371Smckusick u.u_ru.ru_nivcsw++; 64941475Smckusick swtch(); 65042370Skarels if (i = CURSIG(p)) 65142370Skarels psig(i); 65241475Smckusick } 65342371Smckusick if (u.u_prof.pr_scale) { 65441475Smckusick int ticks; 65542371Smckusick struct timeval *tv = &u.u_ru.ru_stime; 65641475Smckusick 65741475Smckusick ticks = ((tv->tv_sec - syst.tv_sec) * 1000 + 65841475Smckusick (tv->tv_usec - syst.tv_usec) / 1000) / (tick / 1000); 65941475Smckusick if (ticks) { 66041475Smckusick #ifdef PROFTIMER 66141475Smckusick extern int profscale; 66242371Smckusick addupc(frame.f_pc, &u.u_prof, ticks * profscale); 66341475Smckusick #else 66442371Smckusick addupc(frame.f_pc, &u.u_prof, ticks); 66541475Smckusick #endif 66641475Smckusick } 66741475Smckusick } 66841475Smckusick curpri = p->p_pri; 66941475Smckusick #ifdef KTRACE 67041475Smckusick if (KTRPOINT(p, KTR_SYSRET)) 67141475Smckusick ktrsysret(p->p_tracep, code); 67241475Smckusick #endif 67341475Smckusick } 674