xref: /csrg-svn/sys/hp300/hp300/trap.c (revision 43413)
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