1*41475Smckusick /* 2*41475Smckusick * Copyright (c) 1988 University of Utah. 3*41475Smckusick * Copyright (c) 1982, 1986, 1990 The Regents of the University of California. 4*41475Smckusick * All rights reserved. 5*41475Smckusick * 6*41475Smckusick * This code is derived from software contributed to Berkeley by 7*41475Smckusick * the Systems Programming Group of the University of Utah Computer 8*41475Smckusick * Science Department. 9*41475Smckusick * 10*41475Smckusick * %sccs.include.redist.c% 11*41475Smckusick * 12*41475Smckusick * from: Utah $Hdr: trap.c 1.28 89/09/25$ 13*41475Smckusick * 14*41475Smckusick * @(#)trap.c 7.1 (Berkeley) 05/08/90 15*41475Smckusick */ 16*41475Smckusick 17*41475Smckusick #include "cpu.h" 18*41475Smckusick #include "psl.h" 19*41475Smckusick #include "reg.h" 20*41475Smckusick #include "pte.h" 21*41475Smckusick #include "mtpr.h" 22*41475Smckusick 23*41475Smckusick #include "param.h" 24*41475Smckusick #include "systm.h" 25*41475Smckusick #include "user.h" 26*41475Smckusick #include "proc.h" 27*41475Smckusick #include "seg.h" 28*41475Smckusick #include "trap.h" 29*41475Smckusick #include "acct.h" 30*41475Smckusick #include "kernel.h" 31*41475Smckusick #include "vm.h" 32*41475Smckusick #include "cmap.h" 33*41475Smckusick #include "syslog.h" 34*41475Smckusick #ifdef KTRACE 35*41475Smckusick #include "ktrace.h" 36*41475Smckusick #endif 37*41475Smckusick 38*41475Smckusick #ifdef HPUXCOMPAT 39*41475Smckusick #include "../hpux/hpux.h" 40*41475Smckusick #endif 41*41475Smckusick 42*41475Smckusick #define USER 040 /* user-mode flag added to type */ 43*41475Smckusick 44*41475Smckusick struct sysent sysent[]; 45*41475Smckusick int nsysent; 46*41475Smckusick 47*41475Smckusick char *trap_type[] = { 48*41475Smckusick "Bus error", 49*41475Smckusick "Address error", 50*41475Smckusick "Illegal instruction", 51*41475Smckusick "Zero divide", 52*41475Smckusick "CHK instruction", 53*41475Smckusick "TRAPV instruction", 54*41475Smckusick "Privilege violation", 55*41475Smckusick "Trace trap", 56*41475Smckusick "MMU fault", 57*41475Smckusick "SSIR trap", 58*41475Smckusick "Format error", 59*41475Smckusick "68881 exception", 60*41475Smckusick "Coprocessor violation", 61*41475Smckusick "Async system trap" 62*41475Smckusick }; 63*41475Smckusick #define TRAP_TYPES (sizeof trap_type / sizeof trap_type[0]) 64*41475Smckusick 65*41475Smckusick #ifdef DEBUG 66*41475Smckusick int mmudebug = 0; 67*41475Smckusick #endif 68*41475Smckusick 69*41475Smckusick /* 70*41475Smckusick * Called from the trap handler when a processor trap occurs. 71*41475Smckusick */ 72*41475Smckusick /*ARGSUSED*/ 73*41475Smckusick trap(type, code, v, frame) 74*41475Smckusick int type; 75*41475Smckusick unsigned code; 76*41475Smckusick register unsigned v; 77*41475Smckusick struct frame frame; 78*41475Smckusick { 79*41475Smckusick register int i; 80*41475Smckusick unsigned ucode = 0; 81*41475Smckusick register struct proc *p = u.u_procp; 82*41475Smckusick struct timeval syst; 83*41475Smckusick unsigned ncode; 84*41475Smckusick 85*41475Smckusick cnt.v_trap++; 86*41475Smckusick syst = u.u_ru.ru_stime; 87*41475Smckusick if (USERMODE(frame.f_sr)) { 88*41475Smckusick type |= USER; 89*41475Smckusick u.u_ar0 = frame.f_regs; 90*41475Smckusick } 91*41475Smckusick switch (type) { 92*41475Smckusick 93*41475Smckusick default: 94*41475Smckusick dopanic: 95*41475Smckusick #ifdef KGDB 96*41475Smckusick if (!panicstr && kgdb_trap(type, code, v, &frame)) 97*41475Smckusick return; 98*41475Smckusick #endif 99*41475Smckusick printf("trap type %d, code = %x, v = %x\n", type, code, v); 100*41475Smckusick regdump(frame.f_regs, 128); 101*41475Smckusick type &= ~USER; 102*41475Smckusick if ((unsigned)type < TRAP_TYPES) 103*41475Smckusick panic(trap_type[type]); 104*41475Smckusick panic("trap"); 105*41475Smckusick 106*41475Smckusick case T_BUSERR: /* kernel bus error */ 107*41475Smckusick if (!u.u_pcb.pcb_onfault) 108*41475Smckusick goto dopanic; 109*41475Smckusick /* 110*41475Smckusick * If we have arranged to catch this fault in any of the 111*41475Smckusick * copy to/from user space routines, set PC to return to 112*41475Smckusick * indicated location and set flag informing buserror code 113*41475Smckusick * that it may need to clean up stack frame. 114*41475Smckusick */ 115*41475Smckusick copyfault: 116*41475Smckusick frame.f_pc = (int) u.u_pcb.pcb_onfault; 117*41475Smckusick frame.f_stackadj = -1; 118*41475Smckusick return; 119*41475Smckusick 120*41475Smckusick case T_BUSERR+USER: /* bus error */ 121*41475Smckusick case T_ADDRERR+USER: /* address error */ 122*41475Smckusick i = SIGBUS; 123*41475Smckusick break; 124*41475Smckusick 125*41475Smckusick #ifdef FPCOPROC 126*41475Smckusick case T_COPERR: /* kernel coprocessor violation */ 127*41475Smckusick #endif 128*41475Smckusick case T_FMTERR: /* kernel format error */ 129*41475Smckusick /* 130*41475Smckusick * The user has most likely trashed the RTE or FP state info 131*41475Smckusick * in the stack frame of a signal handler. 132*41475Smckusick */ 133*41475Smckusick printf("pid %d: kernel %s exception\n", u.u_procp->p_pid, 134*41475Smckusick type==T_COPERR ? "coprocessor" : "format"); 135*41475Smckusick u.u_signal[SIGILL] = SIG_DFL; 136*41475Smckusick i = sigmask(SIGILL); 137*41475Smckusick p->p_sigignore &= ~i; 138*41475Smckusick p->p_sigcatch &= ~i; 139*41475Smckusick p->p_sigmask &= ~i; 140*41475Smckusick ucode = frame.f_format; /* XXX was ILL_RESAD_FAULT */ 141*41475Smckusick psignal(u.u_procp, SIGILL); 142*41475Smckusick goto out; 143*41475Smckusick 144*41475Smckusick #ifdef FPCOPROC 145*41475Smckusick case T_COPERR+USER: /* user coprocessor violation */ 146*41475Smckusick /* What is a proper response here? */ 147*41475Smckusick ucode = 0; 148*41475Smckusick i = SIGFPE; 149*41475Smckusick break; 150*41475Smckusick 151*41475Smckusick case T_FPERR+USER: /* 68881 exceptions */ 152*41475Smckusick /* 153*41475Smckusick * We pass along the 68881 status register which locore stashed 154*41475Smckusick * in code for us. Note that there is a possibility that the 155*41475Smckusick * bit pattern of this register will conflict with one of the 156*41475Smckusick * FPE_* codes defined in signal.h. Fortunately for us, the 157*41475Smckusick * only such codes we use are all in the range 1-7 and the low 158*41475Smckusick * 3 bits of the status register are defined as 0 so there is 159*41475Smckusick * no clash. 160*41475Smckusick */ 161*41475Smckusick ucode = code; 162*41475Smckusick i = SIGFPE; 163*41475Smckusick break; 164*41475Smckusick #endif 165*41475Smckusick 166*41475Smckusick case T_ILLINST+USER: /* illegal instruction fault */ 167*41475Smckusick #ifdef HPUXCOMPAT 168*41475Smckusick if (u.u_procp->p_flag & SHPUX) { 169*41475Smckusick ucode = HPUX_ILL_ILLINST_TRAP; 170*41475Smckusick i = SIGILL; 171*41475Smckusick break; 172*41475Smckusick } 173*41475Smckusick /* fall through */ 174*41475Smckusick #endif 175*41475Smckusick case T_PRIVINST+USER: /* privileged instruction fault */ 176*41475Smckusick #ifdef HPUXCOMPAT 177*41475Smckusick if (u.u_procp->p_flag & SHPUX) 178*41475Smckusick ucode = HPUX_ILL_PRIV_TRAP; 179*41475Smckusick else 180*41475Smckusick #endif 181*41475Smckusick ucode = frame.f_format; /* XXX was ILL_PRIVIN_FAULT */ 182*41475Smckusick i = SIGILL; 183*41475Smckusick break; 184*41475Smckusick 185*41475Smckusick case T_ZERODIV+USER: /* Divide by zero */ 186*41475Smckusick #ifdef HPUXCOMPAT 187*41475Smckusick if (u.u_procp->p_flag & SHPUX) 188*41475Smckusick ucode = HPUX_FPE_INTDIV_TRAP; 189*41475Smckusick else 190*41475Smckusick #endif 191*41475Smckusick ucode = frame.f_format; /* XXX was FPE_INTDIV_TRAP */ 192*41475Smckusick i = SIGFPE; 193*41475Smckusick break; 194*41475Smckusick 195*41475Smckusick case T_CHKINST+USER: /* CHK instruction trap */ 196*41475Smckusick #ifdef HPUXCOMPAT 197*41475Smckusick if (u.u_procp->p_flag & SHPUX) { 198*41475Smckusick /* handled differently under hp-ux */ 199*41475Smckusick i = SIGILL; 200*41475Smckusick ucode = HPUX_ILL_CHK_TRAP; 201*41475Smckusick break; 202*41475Smckusick } 203*41475Smckusick #endif 204*41475Smckusick ucode = frame.f_format; /* XXX was FPE_SUBRNG_TRAP */ 205*41475Smckusick i = SIGFPE; 206*41475Smckusick break; 207*41475Smckusick 208*41475Smckusick case T_TRAPVINST+USER: /* TRAPV instruction trap */ 209*41475Smckusick #ifdef HPUXCOMPAT 210*41475Smckusick if (u.u_procp->p_flag & SHPUX) { 211*41475Smckusick /* handled differently under hp-ux */ 212*41475Smckusick i = SIGILL; 213*41475Smckusick ucode = HPUX_ILL_TRAPV_TRAP; 214*41475Smckusick break; 215*41475Smckusick } 216*41475Smckusick #endif 217*41475Smckusick ucode = frame.f_format; /* XXX was FPE_INTOVF_TRAP */ 218*41475Smckusick i = SIGFPE; 219*41475Smckusick break; 220*41475Smckusick 221*41475Smckusick /* 222*41475Smckusick * XXX: Trace traps are a nightmare. 223*41475Smckusick * 224*41475Smckusick * HP-UX uses trap #1 for breakpoints, 225*41475Smckusick * HPBSD uses trap #2, 226*41475Smckusick * SUN 3.x uses trap #15, 227*41475Smckusick * KGDB uses trap #15 (for kernel breakpoints). 228*41475Smckusick * 229*41475Smckusick * HPBSD and HP-UX traps both get mapped by locore.s into T_TRACE. 230*41475Smckusick * SUN 3.x traps get passed through as T_TRAP15 and are not really 231*41475Smckusick * supported yet. KGDB traps are also passed through as T_TRAP15 232*41475Smckusick * and are not used yet. 233*41475Smckusick */ 234*41475Smckusick case T_TRACE: /* kernel trace trap */ 235*41475Smckusick case T_TRAP15: /* SUN (or KGDB) kernel trace trap */ 236*41475Smckusick #ifdef KGDB 237*41475Smckusick if (kgdb_trap(type, code, v, &frame)) 238*41475Smckusick return; 239*41475Smckusick #endif 240*41475Smckusick frame.f_sr &= ~PSL_T; 241*41475Smckusick i = SIGTRAP; 242*41475Smckusick break; 243*41475Smckusick 244*41475Smckusick case T_TRACE+USER: /* user trace trap */ 245*41475Smckusick case T_TRAP15+USER: /* SUN user trace trap */ 246*41475Smckusick #ifdef SUNCOMPAT 247*41475Smckusick /* 248*41475Smckusick * Trap #2 is used to signal a cache flush. 249*41475Smckusick * Should we also flush data cache? 250*41475Smckusick */ 251*41475Smckusick if (type == T_TRACE+USER && (p->p_flag & SSUN)) { 252*41475Smckusick ICIA(); 253*41475Smckusick goto out; 254*41475Smckusick } 255*41475Smckusick #endif 256*41475Smckusick frame.f_sr &= ~PSL_T; 257*41475Smckusick i = SIGTRAP; 258*41475Smckusick break; 259*41475Smckusick 260*41475Smckusick case T_AST: /* system async trap, cannot happen */ 261*41475Smckusick goto dopanic; 262*41475Smckusick 263*41475Smckusick case T_AST+USER: /* user async trap */ 264*41475Smckusick astoff(); 265*41475Smckusick /* 266*41475Smckusick * We check for software interrupts first. This is because 267*41475Smckusick * they are at a higher level than ASTs, and on a VAX would 268*41475Smckusick * interrupt the AST. We assume that if we are processing 269*41475Smckusick * an AST that we must be at IPL0 so we don't bother to 270*41475Smckusick * check. Note that we ensure that we are at least at SIR 271*41475Smckusick * IPL while processing the SIR. 272*41475Smckusick */ 273*41475Smckusick spl1(); 274*41475Smckusick /* fall into... */ 275*41475Smckusick 276*41475Smckusick case T_SSIR: /* software interrupt */ 277*41475Smckusick case T_SSIR+USER: 278*41475Smckusick if (ssir & SIR_NET) { 279*41475Smckusick siroff(SIR_NET); 280*41475Smckusick cnt.v_soft++; 281*41475Smckusick netintr(); 282*41475Smckusick } 283*41475Smckusick if (ssir & SIR_CLOCK) { 284*41475Smckusick siroff(SIR_CLOCK); 285*41475Smckusick cnt.v_soft++; 286*41475Smckusick softclock((caddr_t)frame.f_pc, (int)frame.f_sr); 287*41475Smckusick } 288*41475Smckusick /* 289*41475Smckusick * If this was not an AST trap, we are all done. 290*41475Smckusick */ 291*41475Smckusick if (type != T_AST+USER) { 292*41475Smckusick cnt.v_trap--; 293*41475Smckusick return; 294*41475Smckusick } 295*41475Smckusick spl0(); 296*41475Smckusick #ifndef PROFTIMER 297*41475Smckusick if ((u.u_procp->p_flag&SOWEUPC) && u.u_prof.pr_scale) { 298*41475Smckusick addupc(frame.f_pc, &u.u_prof, 1); 299*41475Smckusick u.u_procp->p_flag &= ~SOWEUPC; 300*41475Smckusick } 301*41475Smckusick #endif 302*41475Smckusick goto out; 303*41475Smckusick 304*41475Smckusick case T_MMUFLT: /* kernel mode page fault */ 305*41475Smckusick /* 306*41475Smckusick * Could be caused by a page fault in one of the copy to/from 307*41475Smckusick * user space routines. If so, we will have a catch address. 308*41475Smckusick */ 309*41475Smckusick if (!u.u_pcb.pcb_onfault) 310*41475Smckusick goto dopanic; 311*41475Smckusick /* fall into ... */ 312*41475Smckusick 313*41475Smckusick case T_MMUFLT+USER: /* page fault */ 314*41475Smckusick /* 315*41475Smckusick printf("trap: T_MMUFLT pid %d, code %x, v %x, pc %x, ps %x\n", 316*41475Smckusick p->p_pid, code, v, frame.f_pc, frame.f_sr); 317*41475Smckusick */ 318*41475Smckusick if (v >= USRSTACK) { 319*41475Smckusick if (type == T_MMUFLT) 320*41475Smckusick goto copyfault; 321*41475Smckusick i = SIGSEGV; 322*41475Smckusick break; 323*41475Smckusick } 324*41475Smckusick ncode = code >> 16; 325*41475Smckusick #if defined(HP330) || defined(HP360) || defined(HP370) 326*41475Smckusick /* 327*41475Smckusick * Crudely map PMMU faults into HP MMU faults. 328*41475Smckusick */ 329*41475Smckusick if (mmutype != MMU_HP) { 330*41475Smckusick int ocode = ncode; 331*41475Smckusick ncode = 0; 332*41475Smckusick if (ocode & PMMU_WP) 333*41475Smckusick ncode |= MMU_WPF; 334*41475Smckusick else if (ocode & PMMU_INV) { 335*41475Smckusick if ((ocode & PMMU_LVLMASK) == 2) 336*41475Smckusick ncode |= MMU_PF; 337*41475Smckusick else 338*41475Smckusick ncode |= MMU_PTF; 339*41475Smckusick } 340*41475Smckusick /* 341*41475Smckusick * RMW cycle, must load ATC by hand 342*41475Smckusick */ 343*41475Smckusick else if ((code & (SSW_DF|SSW_RM)) == (SSW_DF|SSW_RM)) { 344*41475Smckusick #ifdef DEBUG 345*41475Smckusick log(LOG_WARNING, 346*41475Smckusick "RMW fault at %x: MMUSR %x SSW %x\n", 347*41475Smckusick v, ocode, code & 0xFFFF); 348*41475Smckusick #endif 349*41475Smckusick ploadw((caddr_t)v); 350*41475Smckusick return; 351*41475Smckusick } 352*41475Smckusick /* 353*41475Smckusick * Fault with no fault bits, should indicate bad 354*41475Smckusick * hardware but we see this on 340s using starbase 355*41475Smckusick * sometimes (faults accessing catseye registers) 356*41475Smckusick */ 357*41475Smckusick else { 358*41475Smckusick log(LOG_WARNING, 359*41475Smckusick "Bad PMMU fault at %x: MMUSR %x SSW %x\n", 360*41475Smckusick v, ocode, code & 0xFFFF); 361*41475Smckusick return; 362*41475Smckusick } 363*41475Smckusick #ifdef DEBUG 364*41475Smckusick if (mmudebug && mmudebug == p->p_pid) 365*41475Smckusick printf("MMU %d: v%x, os%x, ns%x\n", 366*41475Smckusick p->p_pid, v, ocode, ncode); 367*41475Smckusick #endif 368*41475Smckusick } 369*41475Smckusick #endif 370*41475Smckusick #ifdef DEBUG 371*41475Smckusick if ((ncode & (MMU_PTF|MMU_PF|MMU_WPF|MMU_FPE)) == 0) { 372*41475Smckusick printf("T_MMUFLT with no fault bits\n"); 373*41475Smckusick goto dopanic; 374*41475Smckusick } 375*41475Smckusick #endif 376*41475Smckusick if (ncode & MMU_PTF) { 377*41475Smckusick #ifdef DEBUG 378*41475Smckusick /* 379*41475Smckusick * NOTE: we use a u_int instead of an ste since the 380*41475Smckusick * current compiler generates bogus code for some 381*41475Smckusick * bitfield operations (i.e. attempts to access last 382*41475Smckusick * word of a page as a longword causing fault). 383*41475Smckusick */ 384*41475Smckusick extern struct ste *vtoste(); 385*41475Smckusick u_int *ste = (u_int *)vtoste(p, v); 386*41475Smckusick 387*41475Smckusick if (*ste & SG_V) { 388*41475Smckusick if (ncode & MMU_WPF) { 389*41475Smckusick printf("PTF|WPF...\n"); 390*41475Smckusick if (type == T_MMUFLT) 391*41475Smckusick goto copyfault; 392*41475Smckusick i = SIGBUS; 393*41475Smckusick break; 394*41475Smckusick } 395*41475Smckusick printf("MMU_PTF with sg_v, ste@%x = %x\n", 396*41475Smckusick ste, *ste); 397*41475Smckusick goto dopanic; 398*41475Smckusick } 399*41475Smckusick #endif 400*41475Smckusick #ifdef HPUXCOMPAT 401*41475Smckusick if (ISHPMMADDR(v)) { 402*41475Smckusick extern struct ste *vtoste(); 403*41475Smckusick u_int *bste, *nste; 404*41475Smckusick 405*41475Smckusick bste = (u_int *)vtoste(p, HPMMBASEADDR(v)); 406*41475Smckusick nste = (u_int *)vtoste(p, v); 407*41475Smckusick if ((*bste & SG_V) && *nste == SG_NV) { 408*41475Smckusick *nste = *bste; 409*41475Smckusick TBIAU(); 410*41475Smckusick return; 411*41475Smckusick } 412*41475Smckusick } 413*41475Smckusick #endif 414*41475Smckusick growit: 415*41475Smckusick if (type == T_MMUFLT) 416*41475Smckusick goto copyfault; 417*41475Smckusick if (grow((unsigned)frame.f_regs[SP]) || grow(v)) 418*41475Smckusick goto out; 419*41475Smckusick i = SIGSEGV; 420*41475Smckusick break; 421*41475Smckusick } 422*41475Smckusick #ifdef HPUXCOMPAT 423*41475Smckusick if (ISHPMMADDR(v)) { 424*41475Smckusick TBIS(v); 425*41475Smckusick v = HPMMBASEADDR(v); 426*41475Smckusick } 427*41475Smckusick #endif 428*41475Smckusick /* 429*41475Smckusick * NOTE: WPF without PG_V is possible 430*41475Smckusick * (e.g. attempt to write shared text which is paged out) 431*41475Smckusick */ 432*41475Smckusick if (ncode & MMU_WPF) { 433*41475Smckusick #ifdef DEBUG 434*41475Smckusick extern struct ste *vtoste(); 435*41475Smckusick u_int *ste = (u_int *)vtoste(p, v); 436*41475Smckusick 437*41475Smckusick if (!(*ste & SG_V)) { 438*41475Smckusick printf("MMU_WPF without sg_v, ste@%x = %x\n", 439*41475Smckusick ste, *ste); 440*41475Smckusick goto dopanic; 441*41475Smckusick } 442*41475Smckusick #endif 443*41475Smckusick if (type == T_MMUFLT) 444*41475Smckusick goto copyfault; 445*41475Smckusick i = SIGBUS; 446*41475Smckusick break; 447*41475Smckusick } 448*41475Smckusick if (ncode & MMU_PF) { 449*41475Smckusick register u_int vp; 450*41475Smckusick #ifdef DEBUG 451*41475Smckusick extern struct ste *vtoste(); 452*41475Smckusick u_int *ste = (u_int *)vtoste(p, v); 453*41475Smckusick struct pte *pte; 454*41475Smckusick 455*41475Smckusick if (!(*ste & SG_V)) { 456*41475Smckusick printf("MMU_PF without sg_v, ste@%x = %x\n", 457*41475Smckusick ste, *ste); 458*41475Smckusick goto dopanic; 459*41475Smckusick } 460*41475Smckusick #endif 461*41475Smckusick vp = btop(v); 462*41475Smckusick if (vp >= dptov(p, p->p_dsize) && 463*41475Smckusick vp < sptov(p, p->p_ssize-1)) 464*41475Smckusick goto growit; 465*41475Smckusick #ifdef DEBUG 466*41475Smckusick pte = vtopte(p, vp); 467*41475Smckusick if (*(u_int *)pte & PG_V) { 468*41475Smckusick printf("MMU_PF with pg_v, pte = %x\n", 469*41475Smckusick *(u_int *)pte); 470*41475Smckusick goto dopanic; 471*41475Smckusick } 472*41475Smckusick #endif 473*41475Smckusick i = u.u_error; 474*41475Smckusick pagein(v, 0); 475*41475Smckusick u.u_error = i; 476*41475Smckusick if (type == T_MMUFLT) 477*41475Smckusick return; 478*41475Smckusick goto out; 479*41475Smckusick } 480*41475Smckusick #ifdef DEBUG 481*41475Smckusick printf("T_MMUFLT: unrecognized scenerio\n"); 482*41475Smckusick goto dopanic; 483*41475Smckusick #endif 484*41475Smckusick } 485*41475Smckusick trapsignal(i, ucode); 486*41475Smckusick if ((type & USER) == 0) 487*41475Smckusick return; 488*41475Smckusick out: 489*41475Smckusick p = u.u_procp; 490*41475Smckusick if (p->p_cursig || ISSIG(p)) 491*41475Smckusick psig(); 492*41475Smckusick p->p_pri = p->p_usrpri; 493*41475Smckusick if (runrun) { 494*41475Smckusick /* 495*41475Smckusick * Since we are u.u_procp, clock will normally just change 496*41475Smckusick * our priority without moving us from one queue to another 497*41475Smckusick * (since the running process is not on a queue.) 498*41475Smckusick * If that happened after we setrq ourselves but before we 499*41475Smckusick * swtch()'ed, we might not be on the queue indicated by 500*41475Smckusick * our priority. 501*41475Smckusick */ 502*41475Smckusick (void) splclock(); 503*41475Smckusick setrq(p); 504*41475Smckusick u.u_ru.ru_nivcsw++; 505*41475Smckusick swtch(); 506*41475Smckusick if (ISSIG(p)) 507*41475Smckusick psig(); 508*41475Smckusick } 509*41475Smckusick if (u.u_prof.pr_scale) { 510*41475Smckusick int ticks; 511*41475Smckusick struct timeval *tv = &u.u_ru.ru_stime; 512*41475Smckusick 513*41475Smckusick ticks = ((tv->tv_sec - syst.tv_sec) * 1000 + 514*41475Smckusick (tv->tv_usec - syst.tv_usec) / 1000) / (tick / 1000); 515*41475Smckusick if (ticks) { 516*41475Smckusick #ifdef PROFTIMER 517*41475Smckusick extern int profscale; 518*41475Smckusick addupc(frame.f_pc, &u.u_prof, ticks * profscale); 519*41475Smckusick #else 520*41475Smckusick addupc(frame.f_pc, &u.u_prof, ticks); 521*41475Smckusick #endif 522*41475Smckusick } 523*41475Smckusick } 524*41475Smckusick curpri = p->p_pri; 525*41475Smckusick } 526*41475Smckusick 527*41475Smckusick /* 528*41475Smckusick * Called from the trap handler when a system call occurs 529*41475Smckusick */ 530*41475Smckusick /*ARGSUSED*/ 531*41475Smckusick syscall(code, frame) 532*41475Smckusick volatile int code; 533*41475Smckusick struct frame frame; 534*41475Smckusick { 535*41475Smckusick register caddr_t params; 536*41475Smckusick register int i; 537*41475Smckusick register struct sysent *callp; 538*41475Smckusick register struct proc *p; 539*41475Smckusick register struct user *up; 540*41475Smckusick int opc, numsys; 541*41475Smckusick struct timeval syst; 542*41475Smckusick struct sysent *systab; 543*41475Smckusick #ifdef HPUXCOMPAT 544*41475Smckusick extern struct sysent hpuxsysent[]; 545*41475Smckusick extern int hpuxnsysent, notimp(); 546*41475Smckusick #endif 547*41475Smckusick 548*41475Smckusick /* 549*41475Smckusick * We assign &u to a local variable for GCC. This ensures that 550*41475Smckusick * we can explicitly reload it after the call to qsetjmp below. 551*41475Smckusick * If we don't do this, GCC may itself have assigned &u to a 552*41475Smckusick * register variable which will not be properly reloaded, since 553*41475Smckusick * GCC knows nothing of the funky semantics of qsetjmp. 554*41475Smckusick */ 555*41475Smckusick up = &u; 556*41475Smckusick 557*41475Smckusick cnt.v_syscall++; 558*41475Smckusick syst = up->u_ru.ru_stime; 559*41475Smckusick if (!USERMODE(frame.f_sr)) 560*41475Smckusick panic("syscall"); 561*41475Smckusick up->u_ar0 = frame.f_regs; 562*41475Smckusick up->u_error = 0; 563*41475Smckusick opc = frame.f_pc - 2; 564*41475Smckusick systab = sysent; 565*41475Smckusick numsys = nsysent; 566*41475Smckusick #ifdef HPUXCOMPAT 567*41475Smckusick if (up->u_procp->p_flag & SHPUX) { 568*41475Smckusick systab = hpuxsysent; 569*41475Smckusick numsys = hpuxnsysent; 570*41475Smckusick } 571*41475Smckusick #endif 572*41475Smckusick params = (caddr_t)frame.f_regs[SP] + NBPW; 573*41475Smckusick /* 574*41475Smckusick * We use entry 0 instead of 63 to signify an invalid syscall because 575*41475Smckusick * HPUX uses 63 and 0 works just as well for our purposes. 576*41475Smckusick */ 577*41475Smckusick if (code == 0) { 578*41475Smckusick i = fuword(params); 579*41475Smckusick params += NBPW; 580*41475Smckusick callp = ((unsigned)i >= numsys) ? &systab[0] : &systab[i]; 581*41475Smckusick } else 582*41475Smckusick callp = (code >= numsys) ? &systab[0] : &systab[code]; 583*41475Smckusick p = up->u_procp; 584*41475Smckusick if ((i = callp->sy_narg * sizeof (int)) && 585*41475Smckusick (up->u_error = copyin(params, (caddr_t)up->u_arg, (u_int)i))) { 586*41475Smckusick #ifdef HPUXCOMPAT 587*41475Smckusick if (p->p_flag & SHPUX) 588*41475Smckusick up->u_error = bsdtohpuxerrno(up->u_error); 589*41475Smckusick #endif 590*41475Smckusick frame.f_regs[D0] = (u_char) up->u_error; 591*41475Smckusick frame.f_sr |= PSL_C; /* carry bit */ 592*41475Smckusick #ifdef KTRACE 593*41475Smckusick if (KTRPOINT(p, KTR_SYSCALL)) 594*41475Smckusick ktrsyscall(p->p_tracep, code, callp->sy_narg); 595*41475Smckusick #endif 596*41475Smckusick goto done; 597*41475Smckusick } 598*41475Smckusick #ifdef KTRACE 599*41475Smckusick if (KTRPOINT(p, KTR_SYSCALL)) 600*41475Smckusick ktrsyscall(p->p_tracep, code, callp->sy_narg); 601*41475Smckusick #endif 602*41475Smckusick up->u_r.r_val1 = 0; 603*41475Smckusick up->u_r.r_val2 = frame.f_regs[D0]; 604*41475Smckusick /* 605*41475Smckusick * qsetjmp only saves a6/a7. This speeds things up in the common 606*41475Smckusick * case (where saved values are never used). There is a side effect 607*41475Smckusick * however. Namely, if we do return via longjmp() we must restore 608*41475Smckusick * our own register variables. 609*41475Smckusick */ 610*41475Smckusick if (qsetjmp(&up->u_qsave)) { 611*41475Smckusick up = &u; 612*41475Smckusick if (up->u_error == 0 && up->u_eosys != RESTARTSYS) 613*41475Smckusick up->u_error = EINTR; 614*41475Smckusick #ifdef HPUXCOMPAT 615*41475Smckusick /* there are some HPUX calls where we change u_ap */ 616*41475Smckusick if (up->u_ap != up->u_arg) { 617*41475Smckusick up->u_ap = up->u_arg; 618*41475Smckusick printf("syscall(%d): u_ap changed\n", code); 619*41475Smckusick } 620*41475Smckusick #endif 621*41475Smckusick } else { 622*41475Smckusick up->u_eosys = NORMALRETURN; 623*41475Smckusick #ifdef HPUXCOMPAT 624*41475Smckusick /* debug kludge */ 625*41475Smckusick if (callp->sy_call == notimp) 626*41475Smckusick notimp(code, callp->sy_narg); 627*41475Smckusick else 628*41475Smckusick #endif 629*41475Smckusick (*(callp->sy_call))(up); 630*41475Smckusick } 631*41475Smckusick /* 632*41475Smckusick * Need to reinit p for two reason. One, it is a register var 633*41475Smckusick * and is not saved in the qsetjmp so a EINTR return will leave 634*41475Smckusick * it with garbage. Two, even on a normal return, it will be 635*41475Smckusick * wrong for the child process of a fork (it will point to the 636*41475Smckusick * parent). 637*41475Smckusick */ 638*41475Smckusick p = up->u_procp; 639*41475Smckusick if (up->u_eosys == NORMALRETURN) { 640*41475Smckusick if (up->u_error) { 641*41475Smckusick #ifdef HPUXCOMPAT 642*41475Smckusick if (p->p_flag & SHPUX) 643*41475Smckusick up->u_error = bsdtohpuxerrno(up->u_error); 644*41475Smckusick #endif 645*41475Smckusick frame.f_regs[D0] = (u_char) up->u_error; 646*41475Smckusick frame.f_sr |= PSL_C; /* carry bit */ 647*41475Smckusick } else { 648*41475Smckusick frame.f_regs[D0] = up->u_r.r_val1; 649*41475Smckusick frame.f_regs[D1] = up->u_r.r_val2; 650*41475Smckusick frame.f_sr &= ~PSL_C; 651*41475Smckusick } 652*41475Smckusick } else if (up->u_eosys == RESTARTSYS) 653*41475Smckusick frame.f_pc = opc; 654*41475Smckusick /* else if (up->u_eosys == JUSTRETURN) */ 655*41475Smckusick /* nothing to do */ 656*41475Smckusick done: 657*41475Smckusick /* 658*41475Smckusick * The check for sigreturn (code 103) ensures that we don't 659*41475Smckusick * attempt to set up a call to a signal handler (sendsig) before 660*41475Smckusick * we have cleaned up the stack from the last call (sigreturn). 661*41475Smckusick * Allowing this seems to lock up the machine in certain scenarios. 662*41475Smckusick * What should really be done is to clean up the signal handling 663*41475Smckusick * so that this is not a problem. 664*41475Smckusick */ 665*41475Smckusick if (code != 103 && (p->p_cursig || ISSIG(p))) 666*41475Smckusick psig(); 667*41475Smckusick p->p_pri = p->p_usrpri; 668*41475Smckusick if (runrun) { 669*41475Smckusick /* 670*41475Smckusick * Since we are u.u_procp, clock will normally just change 671*41475Smckusick * our priority without moving us from one queue to another 672*41475Smckusick * (since the running process is not on a queue.) 673*41475Smckusick * If that happened after we setrq ourselves but before we 674*41475Smckusick * swtch()'ed, we might not be on the queue indicated by 675*41475Smckusick * our priority. 676*41475Smckusick */ 677*41475Smckusick (void) splclock(); 678*41475Smckusick setrq(p); 679*41475Smckusick up->u_ru.ru_nivcsw++; 680*41475Smckusick swtch(); 681*41475Smckusick } 682*41475Smckusick if (up->u_prof.pr_scale) { 683*41475Smckusick int ticks; 684*41475Smckusick struct timeval *tv = &up->u_ru.ru_stime; 685*41475Smckusick 686*41475Smckusick ticks = ((tv->tv_sec - syst.tv_sec) * 1000 + 687*41475Smckusick (tv->tv_usec - syst.tv_usec) / 1000) / (tick / 1000); 688*41475Smckusick if (ticks) { 689*41475Smckusick #ifdef PROFTIMER 690*41475Smckusick extern int profscale; 691*41475Smckusick addupc(frame.f_pc, &up->u_prof, ticks * profscale); 692*41475Smckusick #else 693*41475Smckusick addupc(frame.f_pc, &up->u_prof, ticks); 694*41475Smckusick #endif 695*41475Smckusick } 696*41475Smckusick } 697*41475Smckusick curpri = p->p_pri; 698*41475Smckusick #ifdef KTRACE 699*41475Smckusick if (KTRPOINT(p, KTR_SYSRET)) 700*41475Smckusick ktrsysret(p->p_tracep, code); 701*41475Smckusick #endif 702*41475Smckusick } 703