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