xref: /csrg-svn/sys/hp300/hp300/trap.c (revision 65483)
141475Smckusick /*
241475Smckusick  * Copyright (c) 1988 University of Utah.
363472Sbostic  * Copyright (c) 1982, 1986, 1990, 1993
463472Sbostic  *	The Regents of the University of California.  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  *
1257344Shibler  * from: Utah $Hdr: trap.c 1.37 92/12/20$
1341475Smckusick  *
14*65483Sbostic  *	@(#)trap.c	8.5 (Berkeley) 01/04/94
1541475Smckusick  */
1641475Smckusick 
1756508Sbostic #include <sys/param.h>
1856508Sbostic #include <sys/systm.h>
1956508Sbostic #include <sys/proc.h>
2056508Sbostic #include <sys/acct.h>
2156508Sbostic #include <sys/kernel.h>
2256508Sbostic #include <sys/signalvar.h>
2356508Sbostic #include <sys/resourcevar.h>
2456508Sbostic #include <sys/syscall.h>
2556508Sbostic #include <sys/syslog.h>
2656508Sbostic #include <sys/user.h>
2748465Skarels #ifdef KTRACE
2856508Sbostic #include <sys/ktrace.h>
2948465Skarels #endif
3048465Skarels 
3156508Sbostic #include <machine/psl.h>
3256508Sbostic #include <machine/trap.h>
3356508Sbostic #include <machine/cpu.h>
3456508Sbostic #include <machine/reg.h>
3556508Sbostic #include <machine/mtpr.h>
3641475Smckusick 
3756508Sbostic #include <vm/vm.h>
3856508Sbostic #include <vm/pmap.h>
3945751Smckusick 
4041475Smckusick #ifdef HPUXCOMPAT
4156508Sbostic #include <hp/hpux/hpux.h>
4241475Smckusick #endif
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 
6549317Shibler /*
6649317Shibler  * Size of various exception stack frames (minus the standard 8 bytes)
6749317Shibler  */
6849317Shibler short	exframesize[] = {
6949317Shibler 	FMT0SIZE,	/* type 0 - normal (68020/030/040) */
7049317Shibler 	FMT1SIZE,	/* type 1 - throwaway (68020/030/040) */
7149317Shibler 	FMT2SIZE,	/* type 2 - normal 6-word (68020/030/040) */
7253933Shibler 	FMT3SIZE,	/* type 3 - FP post-instruction (68040) */
7349317Shibler 	-1, -1, -1,	/* type 4-6 - undefined */
7453933Shibler 	FMT7SIZE,	/* type 7 - access error (68040) */
7549317Shibler 	58,		/* type 8 - bus fault (68010) */
7649317Shibler 	FMT9SIZE,	/* type 9 - coprocessor mid-instruction (68020/030) */
7749317Shibler 	FMTASIZE,	/* type A - short bus fault (68020/030) */
7849317Shibler 	FMTBSIZE,	/* type B - long bus fault (68020/030) */
7949317Shibler 	-1, -1, -1, -1	/* type C-F - undefined */
8049317Shibler };
8149317Shibler 
8254801Storek #ifdef HP380
8353933Shibler #define KDFAULT(c)	(mmutype == MMU_68040 ? \
8453933Shibler 			    ((c) & SSW4_TMMASK) == SSW4_TMKD : \
8553933Shibler 			    ((c) & (SSW_DF|FC_SUPERD)) == (SSW_DF|FC_SUPERD))
8653933Shibler #define WRFAULT(c) 	(mmutype == MMU_68040 ? \
8753933Shibler 			    ((c) & SSW4_RW) == 0 : \
8853933Shibler 			    ((c) & (SSW_DF|SSW_RW)) == SSW_DF)
8953933Shibler #else
9053933Shibler #define KDFAULT(c)	(((c) & (SSW_DF|SSW_FCMASK)) == (SSW_DF|FC_SUPERD))
9153933Shibler #define WRFAULT(c)	(((c) & (SSW_DF|SSW_RW)) == SSW_DF)
9253933Shibler #endif
9353933Shibler 
9441475Smckusick #ifdef DEBUG
9541475Smckusick int mmudebug = 0;
9653933Shibler int mmupid = -1;
9753933Shibler #define MDB_FOLLOW	1
9853933Shibler #define MDB_WBFOLLOW	2
9953933Shibler #define MDB_WBFAILED	4
10053933Shibler #define MDB_ISPID(p)	(p) == mmupid
10141475Smckusick #endif
10241475Smckusick 
10341475Smckusick /*
10454801Storek  * trap and syscall both need the following work done before returning
10554801Storek  * to user mode.
10654801Storek  */
10754801Storek static inline void
10854801Storek userret(p, fp, oticks, faultaddr, fromtrap)
10954801Storek 	register struct proc *p;
11054801Storek 	register struct frame *fp;
11154801Storek 	u_quad_t oticks;
11254801Storek 	u_int faultaddr;
11354801Storek 	int fromtrap;
11454801Storek {
11554801Storek 	int sig, s;
11654801Storek #ifdef HP380
11754801Storek 	int beenhere = 0;
11854801Storek 
11954801Storek again:
12054801Storek #endif
12154801Storek 	/* take pending signals */
12254801Storek 	while ((sig = CURSIG(p)) != 0)
12364615Sbostic 		postsig(sig);
12464615Sbostic 	p->p_priority = p->p_usrpri;
12554801Storek 	if (want_resched) {
12654801Storek 		/*
12754801Storek 		 * Since we are curproc, clock will normally just change
12854801Storek 		 * our priority without moving us from one queue to another
12954801Storek 		 * (since the running process is not on a queue.)
13064542Sbostic 		 * If that happened after we put ourselves on the run queue
13164615Sbostic 		 * but before we mi_switch()'ed, we might not be on the queue
13264542Sbostic 		 * indicated by our priority.
13354801Storek 		 */
13454801Storek 		s = splstatclock();
13564542Sbostic 		setrunqueue(p);
13654801Storek 		p->p_stats->p_ru.ru_nivcsw++;
13764615Sbostic 		mi_switch();
13854801Storek 		splx(s);
13954801Storek 		while ((sig = CURSIG(p)) != 0)
14064615Sbostic 			postsig(sig);
14154801Storek 	}
14254801Storek 
14354801Storek 	/*
14454801Storek 	 * If profiling, charge system time to the trapped pc.
14554801Storek 	 */
14664615Sbostic 	if (p->p_flag & P_PROFIL) {
14756318Shibler 		extern int psratio;
14856318Shibler 
14956318Shibler 		addupc_task(p, fp->f_pc,
15056318Shibler 			    (int)(p->p_sticks - oticks) * psratio);
15156318Shibler 	}
15254801Storek #ifdef HP380
15354801Storek 	/*
15454801Storek 	 * Deal with user mode writebacks (from trap, or from sigreturn).
15554801Storek 	 * If any writeback fails, go back and attempt signal delivery.
15654801Storek 	 * unless we have already been here and attempted the writeback
15754801Storek 	 * (e.g. bad address with user ignoring SIGSEGV).  In that case
15854801Storek 	 * we just return to the user without sucessfully completing
15954801Storek 	 * the writebacks.  Maybe we should just drop the sucker?
16054801Storek 	 */
16154801Storek 	if (mmutype == MMU_68040 && fp->f_format == FMT7) {
16254801Storek 		if (beenhere) {
16354801Storek #ifdef DEBUG
16454801Storek 			if (mmudebug & MDB_WBFAILED)
16554801Storek 				printf(fromtrap ?
16654801Storek 		"pid %d(%s): writeback aborted, pc=%x, fa=%x\n" :
16754801Storek 		"pid %d(%s): writeback aborted in sigreturn, pc=%x\n",
16854801Storek 				    p->p_pid, p->p_comm, fp->f_pc, faultaddr);
16954801Storek #endif
17054801Storek 		} else if (sig = writeback(fp, fromtrap)) {
17154801Storek 			beenhere = 1;
17254801Storek 			oticks = p->p_sticks;
17354801Storek 			trapsignal(p, sig, faultaddr);
17454801Storek 			goto again;
17554801Storek 		}
17654801Storek 	}
17754801Storek #endif
17864615Sbostic 	curpriority = p->p_priority;
17954801Storek }
18054801Storek 
18154801Storek /*
18249531Skarels  * Trap is called from locore to handle most types of processor traps,
18349531Skarels  * including events such as simulated software interrupts/AST's.
18449531Skarels  * System calls are broken out for efficiency.
18541475Smckusick  */
18641475Smckusick /*ARGSUSED*/
18741475Smckusick trap(type, code, v, frame)
18841475Smckusick 	int type;
18941475Smckusick 	unsigned code;
19041475Smckusick 	register unsigned v;
19141475Smckusick 	struct frame frame;
19241475Smckusick {
193*65483Sbostic 	extern char fswintr[];
194*65483Sbostic 	register struct proc *p;
19541475Smckusick 	register int i;
196*65483Sbostic 	u_int ucode;
19754801Storek 	u_quad_t sticks;
19841475Smckusick 
19941475Smckusick 	cnt.v_trap++;
20054801Storek 	p = curproc;
20154801Storek 	ucode = 0;
20241475Smckusick 	if (USERMODE(frame.f_sr)) {
20349531Skarels 		type |= T_USER;
20454801Storek 		sticks = p->p_sticks;
20552380Smckusick 		p->p_md.md_regs = frame.f_regs;
20641475Smckusick 	}
20741475Smckusick 	switch (type) {
20841475Smckusick 
20941475Smckusick 	default:
21041475Smckusick dopanic:
21141475Smckusick 		printf("trap type %d, code = %x, v = %x\n", type, code, v);
21257344Shibler 		regdump(&frame, 128);
21349531Skarels 		type &= ~T_USER;
21441475Smckusick 		if ((unsigned)type < TRAP_TYPES)
21541475Smckusick 			panic(trap_type[type]);
21641475Smckusick 		panic("trap");
21741475Smckusick 
21841475Smckusick 	case T_BUSERR:		/* kernel bus error */
21949125Skarels 		if (!p->p_addr->u_pcb.pcb_onfault)
22041475Smckusick 			goto dopanic;
22141475Smckusick 		/*
22241475Smckusick 		 * If we have arranged to catch this fault in any of the
22341475Smckusick 		 * copy to/from user space routines, set PC to return to
22441475Smckusick 		 * indicated location and set flag informing buserror code
22541475Smckusick 		 * that it may need to clean up stack frame.
22641475Smckusick 		 */
22741475Smckusick copyfault:
22849317Shibler 		frame.f_stackadj = exframesize[frame.f_format];
22949317Shibler 		frame.f_format = frame.f_vector = 0;
23049125Skarels 		frame.f_pc = (int) p->p_addr->u_pcb.pcb_onfault;
23141475Smckusick 		return;
23241475Smckusick 
23349531Skarels 	case T_BUSERR|T_USER:	/* bus error */
23449531Skarels 	case T_ADDRERR|T_USER:	/* address error */
23553933Shibler 		ucode = v;
23641475Smckusick 		i = SIGBUS;
23741475Smckusick 		break;
23841475Smckusick 
23941475Smckusick #ifdef FPCOPROC
24041475Smckusick 	case T_COPERR:		/* kernel coprocessor violation */
24141475Smckusick #endif
24253933Shibler 	case T_FMTERR|T_USER:	/* do all RTE errors come in as T_USER? */
24353933Shibler 	case T_FMTERR:		/* ...just in case... */
24441475Smckusick 	/*
24541475Smckusick 	 * The user has most likely trashed the RTE or FP state info
24641475Smckusick 	 * in the stack frame of a signal handler.
24741475Smckusick 	 */
24849531Skarels 		type |= T_USER;
24948465Skarels 		printf("pid %d: kernel %s exception\n", p->p_pid,
25041475Smckusick 		       type==T_COPERR ? "coprocessor" : "format");
25148465Skarels 		p->p_sigacts->ps_sigact[SIGILL] = SIG_DFL;
25241475Smckusick 		i = sigmask(SIGILL);
25341475Smckusick 		p->p_sigignore &= ~i;
25441475Smckusick 		p->p_sigcatch &= ~i;
25541475Smckusick 		p->p_sigmask &= ~i;
25642370Skarels 		i = SIGILL;
25741475Smckusick 		ucode = frame.f_format;	/* XXX was ILL_RESAD_FAULT */
25842370Skarels 		break;
25941475Smckusick 
26041475Smckusick #ifdef FPCOPROC
26149531Skarels 	case T_COPERR|T_USER:	/* user coprocessor violation */
26241475Smckusick 	/* What is a proper response here? */
26341475Smckusick 		ucode = 0;
26441475Smckusick 		i = SIGFPE;
26541475Smckusick 		break;
26641475Smckusick 
26749531Skarels 	case T_FPERR|T_USER:	/* 68881 exceptions */
26841475Smckusick 	/*
26941475Smckusick 	 * We pass along the 68881 status register which locore stashed
27041475Smckusick 	 * in code for us.  Note that there is a possibility that the
27141475Smckusick 	 * bit pattern of this register will conflict with one of the
27241475Smckusick 	 * FPE_* codes defined in signal.h.  Fortunately for us, the
27341475Smckusick 	 * only such codes we use are all in the range 1-7 and the low
27441475Smckusick 	 * 3 bits of the status register are defined as 0 so there is
27541475Smckusick 	 * no clash.
27641475Smckusick 	 */
27741475Smckusick 		ucode = code;
27841475Smckusick 		i = SIGFPE;
27941475Smckusick 		break;
28041475Smckusick #endif
28141475Smckusick 
28254801Storek #ifdef HP380
28353933Shibler 	case T_FPEMULI|T_USER:	/* unimplemented FP instuction */
28453933Shibler 	case T_FPEMULD|T_USER:	/* unimplemented FP data type */
28553933Shibler 		/* XXX need to FSAVE */
28653933Shibler 		printf("pid %d(%s): unimplemented FP %s at %x (EA %x)\n",
28753933Shibler 		       p->p_pid, p->p_comm,
28853933Shibler 		       frame.f_format == 2 ? "instruction" : "data type",
28953933Shibler 		       frame.f_pc, frame.f_fmt2.f_iaddr);
29053933Shibler 		/* XXX need to FRESTORE */
29153933Shibler 		i = SIGFPE;
29253933Shibler 		break;
29353933Shibler #endif
29453933Shibler 
29549531Skarels 	case T_ILLINST|T_USER:	/* illegal instruction fault */
29641475Smckusick #ifdef HPUXCOMPAT
29757344Shibler 		if (p->p_md.md_flags & MDP_HPUX) {
29841475Smckusick 			ucode = HPUX_ILL_ILLINST_TRAP;
29941475Smckusick 			i = SIGILL;
30041475Smckusick 			break;
30141475Smckusick 		}
30241475Smckusick 		/* fall through */
30341475Smckusick #endif
30449531Skarels 	case T_PRIVINST|T_USER:	/* privileged instruction fault */
30541475Smckusick #ifdef HPUXCOMPAT
30657344Shibler 		if (p->p_md.md_flags & MDP_HPUX)
30741475Smckusick 			ucode = HPUX_ILL_PRIV_TRAP;
30841475Smckusick 		else
30941475Smckusick #endif
31041475Smckusick 		ucode = frame.f_format;	/* XXX was ILL_PRIVIN_FAULT */
31141475Smckusick 		i = SIGILL;
31241475Smckusick 		break;
31341475Smckusick 
31449531Skarels 	case T_ZERODIV|T_USER:	/* Divide by zero */
31541475Smckusick #ifdef HPUXCOMPAT
31657344Shibler 		if (p->p_md.md_flags & MDP_HPUX)
31741475Smckusick 			ucode = HPUX_FPE_INTDIV_TRAP;
31841475Smckusick 		else
31941475Smckusick #endif
32041475Smckusick 		ucode = frame.f_format;	/* XXX was FPE_INTDIV_TRAP */
32141475Smckusick 		i = SIGFPE;
32241475Smckusick 		break;
32341475Smckusick 
32449531Skarels 	case T_CHKINST|T_USER:	/* CHK instruction trap */
32541475Smckusick #ifdef HPUXCOMPAT
32657344Shibler 		if (p->p_md.md_flags & MDP_HPUX) {
32741475Smckusick 			/* handled differently under hp-ux */
32841475Smckusick 			i = SIGILL;
32941475Smckusick 			ucode = HPUX_ILL_CHK_TRAP;
33041475Smckusick 			break;
33141475Smckusick 		}
33241475Smckusick #endif
33341475Smckusick 		ucode = frame.f_format;	/* XXX was FPE_SUBRNG_TRAP */
33441475Smckusick 		i = SIGFPE;
33541475Smckusick 		break;
33641475Smckusick 
33749531Skarels 	case T_TRAPVINST|T_USER:	/* TRAPV instruction trap */
33841475Smckusick #ifdef HPUXCOMPAT
33957344Shibler 		if (p->p_md.md_flags & MDP_HPUX) {
34041475Smckusick 			/* handled differently under hp-ux */
34141475Smckusick 			i = SIGILL;
34241475Smckusick 			ucode = HPUX_ILL_TRAPV_TRAP;
34341475Smckusick 			break;
34441475Smckusick 		}
34541475Smckusick #endif
34641475Smckusick 		ucode = frame.f_format;	/* XXX was FPE_INTOVF_TRAP */
34741475Smckusick 		i = SIGFPE;
34841475Smckusick 		break;
34941475Smckusick 
35041475Smckusick 	/*
35141475Smckusick 	 * XXX: Trace traps are a nightmare.
35241475Smckusick 	 *
35341475Smckusick 	 *	HP-UX uses trap #1 for breakpoints,
35441475Smckusick 	 *	HPBSD uses trap #2,
35541475Smckusick 	 *	SUN 3.x uses trap #15,
35648465Skarels 	 *	KGDB uses trap #15 (for kernel breakpoints; handled elsewhere).
35741475Smckusick 	 *
35841475Smckusick 	 * HPBSD and HP-UX traps both get mapped by locore.s into T_TRACE.
35941475Smckusick 	 * SUN 3.x traps get passed through as T_TRAP15 and are not really
36048465Skarels 	 * supported yet.
36141475Smckusick 	 */
36241475Smckusick 	case T_TRACE:		/* kernel trace trap */
36348465Skarels 	case T_TRAP15:		/* SUN trace trap */
36441475Smckusick 		frame.f_sr &= ~PSL_T;
36541475Smckusick 		i = SIGTRAP;
36641475Smckusick 		break;
36741475Smckusick 
36849531Skarels 	case T_TRACE|T_USER:	/* user trace trap */
36949531Skarels 	case T_TRAP15|T_USER:	/* SUN user trace trap */
37041475Smckusick 		frame.f_sr &= ~PSL_T;
37141475Smckusick 		i = SIGTRAP;
37241475Smckusick 		break;
37341475Smckusick 
37443413Shibler 	case T_ASTFLT:		/* system async trap, cannot happen */
37541475Smckusick 		goto dopanic;
37641475Smckusick 
37749531Skarels 	case T_ASTFLT|T_USER:	/* user async trap */
37849125Skarels 		astpending = 0;
37941475Smckusick 		/*
38041475Smckusick 		 * We check for software interrupts first.  This is because
38141475Smckusick 		 * they are at a higher level than ASTs, and on a VAX would
38241475Smckusick 		 * interrupt the AST.  We assume that if we are processing
38341475Smckusick 		 * an AST that we must be at IPL0 so we don't bother to
38441475Smckusick 		 * check.  Note that we ensure that we are at least at SIR
38541475Smckusick 		 * IPL while processing the SIR.
38641475Smckusick 		 */
38741475Smckusick 		spl1();
38841475Smckusick 		/* fall into... */
38941475Smckusick 
39041475Smckusick 	case T_SSIR:		/* software interrupt */
39149531Skarels 	case T_SSIR|T_USER:
39241475Smckusick 		if (ssir & SIR_NET) {
39341475Smckusick 			siroff(SIR_NET);
39441475Smckusick 			cnt.v_soft++;
39541475Smckusick 			netintr();
39641475Smckusick 		}
39741475Smckusick 		if (ssir & SIR_CLOCK) {
39841475Smckusick 			siroff(SIR_CLOCK);
39941475Smckusick 			cnt.v_soft++;
40054801Storek 			softclock();
40141475Smckusick 		}
40241475Smckusick 		/*
40341475Smckusick 		 * If this was not an AST trap, we are all done.
40441475Smckusick 		 */
40550753Skarels 		if (type != (T_ASTFLT|T_USER)) {
40641475Smckusick 			cnt.v_trap--;
40741475Smckusick 			return;
40841475Smckusick 		}
40941475Smckusick 		spl0();
41064615Sbostic 		if (p->p_flag & P_OWEUPC) {
41164615Sbostic 			p->p_flag &= ~P_OWEUPC;
41254801Storek 			ADDUPROF(p);
41341475Smckusick 		}
41441475Smckusick 		goto out;
41541475Smckusick 
41641475Smckusick 	case T_MMUFLT:		/* kernel mode page fault */
41754574Storek 		/*
41854574Storek 		 * If we were doing profiling ticks or other user mode
41954574Storek 		 * stuff from interrupt code, Just Say No.
42054574Storek 		 */
42154574Storek 		if (p->p_addr->u_pcb.pcb_onfault == fswintr)
42254574Storek 			goto copyfault;
42341475Smckusick 		/* fall into ... */
42441475Smckusick 
42549531Skarels 	case T_MMUFLT|T_USER:	/* page fault */
42645751Smckusick 	    {
42745751Smckusick 		register vm_offset_t va;
42848465Skarels 		register struct vmspace *vm = p->p_vmspace;
42945751Smckusick 		register vm_map_t map;
43045751Smckusick 		int rv;
43145751Smckusick 		vm_prot_t ftype;
43245751Smckusick 		extern vm_map_t kernel_map;
43345751Smckusick 
43453933Shibler #ifdef DEBUG
43553933Shibler 		if ((mmudebug & MDB_WBFOLLOW) || MDB_ISPID(p->p_pid))
43653933Shibler 		printf("trap: T_MMUFLT pid=%d, code=%x, v=%x, pc=%x, sr=%x\n",
43753933Shibler 		       p->p_pid, code, v, frame.f_pc, frame.f_sr);
43853933Shibler #endif
43941475Smckusick 		/*
44045751Smckusick 		 * It is only a kernel address space fault iff:
44149531Skarels 		 * 	1. (type & T_USER) == 0  and
44245751Smckusick 		 * 	2. pcb_onfault not set or
44345751Smckusick 		 *	3. pcb_onfault set but supervisor space data fault
44445751Smckusick 		 * The last can occur during an exec() copyin where the
44545751Smckusick 		 * argument space is lazy-allocated.
44641475Smckusick 		 */
44745751Smckusick 		if (type == T_MMUFLT &&
44853933Shibler 		    (!p->p_addr->u_pcb.pcb_onfault || KDFAULT(code)))
44945751Smckusick 			map = kernel_map;
45045751Smckusick 		else
45148465Skarels 			map = &vm->vm_map;
45253933Shibler 		if (WRFAULT(code))
45345751Smckusick 			ftype = VM_PROT_READ | VM_PROT_WRITE;
45445751Smckusick 		else
45545751Smckusick 			ftype = VM_PROT_READ;
45645751Smckusick 		va = trunc_page((vm_offset_t)v);
45741475Smckusick #ifdef DEBUG
45845751Smckusick 		if (map == kernel_map && va == 0) {
45945751Smckusick 			printf("trap: bad kernel access at %x\n", v);
46041475Smckusick 			goto dopanic;
46141475Smckusick 		}
46241475Smckusick #endif
46357344Shibler #ifdef HPUXCOMPAT
46457344Shibler 		if (ISHPMMADDR(va)) {
46557344Shibler 			vm_offset_t bva;
46657344Shibler 
46757344Shibler 			rv = pmap_mapmulti(map->pmap, va);
46857344Shibler 			if (rv != KERN_SUCCESS) {
46957344Shibler 				bva = HPMMBASEADDR(va);
47057344Shibler 				rv = vm_fault(map, bva, ftype, FALSE);
47157344Shibler 				if (rv == KERN_SUCCESS)
47257344Shibler 					(void) pmap_mapmulti(map->pmap, va);
47357344Shibler 			}
47457344Shibler 		} else
47557344Shibler #endif
47649317Shibler 		rv = vm_fault(map, va, ftype, FALSE);
47753933Shibler #ifdef DEBUG
47853933Shibler 		if (rv && MDB_ISPID(p->p_pid))
47953933Shibler 			printf("vm_fault(%x, %x, %x, 0) -> %x\n",
48053933Shibler 			       map, va, ftype, rv);
48153933Shibler #endif
48241475Smckusick 		/*
48349317Shibler 		 * If this was a stack access we keep track of the maximum
48449317Shibler 		 * accessed stack size.  Also, if vm_fault gets a protection
48549317Shibler 		 * failure it is due to accessing the stack region outside
48649317Shibler 		 * the current limit and we need to reflect that as an access
48749317Shibler 		 * error.
48841475Smckusick 		 */
48948465Skarels 		if ((caddr_t)va >= vm->vm_maxsaddr && map != kernel_map) {
49049317Shibler 			if (rv == KERN_SUCCESS) {
49149317Shibler 				unsigned nss;
49249317Shibler 
49349317Shibler 				nss = clrnd(btoc(USRSTACK-(unsigned)va));
49449317Shibler 				if (nss > vm->vm_ssize)
49549317Shibler 					vm->vm_ssize = nss;
49649317Shibler 			} else if (rv == KERN_PROTECTION_FAILURE)
49749317Shibler 				rv = KERN_INVALID_ADDRESS;
49841475Smckusick 		}
49945751Smckusick 		if (rv == KERN_SUCCESS) {
50053933Shibler 			if (type == T_MMUFLT) {
50154801Storek #ifdef HP380
50253933Shibler 				if (mmutype == MMU_68040)
50353933Shibler 					(void) writeback(&frame, 1);
50453933Shibler #endif
50541475Smckusick 				return;
50653933Shibler 			}
50741475Smckusick 			goto out;
50841475Smckusick 		}
50945751Smckusick 		if (type == T_MMUFLT) {
51049125Skarels 			if (p->p_addr->u_pcb.pcb_onfault)
51145751Smckusick 				goto copyfault;
51245751Smckusick 			printf("vm_fault(%x, %x, %x, 0) -> %x\n",
51345751Smckusick 			       map, va, ftype, rv);
51445751Smckusick 			printf("  type %x, code [mmu,,ssw]: %x\n",
51545751Smckusick 			       type, code);
51645751Smckusick 			goto dopanic;
51745751Smckusick 		}
51848465Skarels 		ucode = v;
51945751Smckusick 		i = (rv == KERN_PROTECTION_FAILURE) ? SIGBUS : SIGSEGV;
52045751Smckusick 		break;
52145751Smckusick 	    }
52241475Smckusick 	}
52348465Skarels 	trapsignal(p, i, ucode);
52449531Skarels 	if ((type & T_USER) == 0)
52541475Smckusick 		return;
52641475Smckusick out:
52754801Storek 	userret(p, &frame, sticks, v, 1);
52841475Smckusick }
52941475Smckusick 
53054801Storek #ifdef HP380
53153933Shibler #ifdef DEBUG
53253933Shibler struct writebackstats {
53353933Shibler 	int calls;
53453933Shibler 	int cpushes;
53553933Shibler 	int move16s;
53653933Shibler 	int wb1s, wb2s, wb3s;
53753933Shibler 	int wbsize[4];
53853933Shibler } wbstats;
53953933Shibler 
54053933Shibler char *f7sz[] = { "longword", "byte", "word", "line" };
54153933Shibler char *f7tt[] = { "normal", "MOVE16", "AFC", "ACK" };
54253933Shibler char *f7tm[] = { "d-push", "u-data", "u-code", "M-data",
54353933Shibler 		 "M-code", "k-data", "k-code", "RES" };
54453933Shibler char wberrstr[] =
54553933Shibler     "WARNING: pid %d(%s) writeback [%s] failed, pc=%x fa=%x wba=%x wbd=%x\n";
54653933Shibler #endif
54753933Shibler 
54853933Shibler writeback(fp, docachepush)
54953933Shibler 	struct frame *fp;
55053933Shibler 	int docachepush;
55153933Shibler {
55253933Shibler 	register struct fmt7 *f = &fp->f_fmt7;
55353933Shibler 	register struct proc *p = curproc;
55453933Shibler 	int err = 0;
55553933Shibler 	u_int fa;
55653933Shibler 	caddr_t oonfault = p->p_addr->u_pcb.pcb_onfault;
55753933Shibler 
55853933Shibler #ifdef DEBUG
55953933Shibler 	if ((mmudebug & MDB_WBFOLLOW) || MDB_ISPID(p->p_pid)) {
56053933Shibler 		printf(" pid=%d, fa=%x,", p->p_pid, f->f_fa);
56153933Shibler 		dumpssw(f->f_ssw);
56253933Shibler 	}
56353933Shibler 	wbstats.calls++;
56453933Shibler #endif
56553933Shibler 	/*
56653933Shibler 	 * Deal with special cases first.
56753933Shibler 	 */
56853933Shibler 	if ((f->f_ssw & SSW4_TMMASK) == SSW4_TMDCP) {
56953933Shibler 		/*
57053933Shibler 		 * Dcache push fault.
57153933Shibler 		 * Line-align the address and write out the push data to
57253933Shibler 		 * the indicated physical address.
57353933Shibler 		 */
57453933Shibler #ifdef DEBUG
57553933Shibler 		if ((mmudebug & MDB_WBFOLLOW) || MDB_ISPID(p->p_pid)) {
57653933Shibler 			printf(" pushing %s to PA %x, data %x",
57753933Shibler 			       f7sz[(f->f_ssw & SSW4_SZMASK) >> 5],
57853933Shibler 			       f->f_fa, f->f_pd0);
57953933Shibler 			if ((f->f_ssw & SSW4_SZMASK) == SSW4_SZLN)
58053933Shibler 				printf("/%x/%x/%x",
58153933Shibler 				       f->f_pd1, f->f_pd2, f->f_pd3);
58253933Shibler 			printf("\n");
58353933Shibler 		}
58453933Shibler 		if (f->f_wb1s & SSW4_WBSV)
58553933Shibler 			panic("writeback: cache push with WB1S valid");
58653933Shibler 		wbstats.cpushes++;
58753933Shibler #endif
58853933Shibler 		/*
58953933Shibler 		 * XXX there are security problems if we attempt to do a
59053933Shibler 		 * cache push after a signal handler has been called.
59153933Shibler 		 */
59253933Shibler 		if (docachepush) {
59353933Shibler 			pmap_enter(kernel_pmap, (vm_offset_t)vmmap,
59453933Shibler 				   trunc_page(f->f_fa), VM_PROT_WRITE, TRUE);
59553933Shibler 			fa = (u_int)&vmmap[(f->f_fa & PGOFSET) & ~0xF];
59653933Shibler 			bcopy((caddr_t)&f->f_pd0, (caddr_t)fa, 16);
59753933Shibler 			DCFL(pmap_extract(kernel_pmap, (vm_offset_t)fa));
59853933Shibler 			pmap_remove(kernel_pmap, (vm_offset_t)vmmap,
59953933Shibler 				    (vm_offset_t)&vmmap[NBPG]);
60053933Shibler 		} else
60153933Shibler 			printf("WARNING: pid %d(%s) uid %d: CPUSH not done\n",
60253933Shibler 			       p->p_pid, p->p_comm, p->p_ucred->cr_uid);
60353933Shibler 	} else if ((f->f_ssw & (SSW4_RW|SSW4_TTMASK)) == SSW4_TTM16) {
60453933Shibler 		/*
60553933Shibler 		 * MOVE16 fault.
60653933Shibler 		 * Line-align the address and write out the push data to
60753933Shibler 		 * the indicated virtual address.
60853933Shibler 		 */
60953933Shibler #ifdef DEBUG
61053933Shibler 		if ((mmudebug & MDB_WBFOLLOW) || MDB_ISPID(p->p_pid))
61153933Shibler 			printf(" MOVE16 to VA %x(%x), data %x/%x/%x/%x\n",
61253933Shibler 			       f->f_fa, f->f_fa & ~0xF, f->f_pd0, f->f_pd1,
61353933Shibler 			       f->f_pd2, f->f_pd3);
61453933Shibler 		if (f->f_wb1s & SSW4_WBSV)
61553933Shibler 			panic("writeback: MOVE16 with WB1S valid");
61653933Shibler 		wbstats.move16s++;
61753933Shibler #endif
61853933Shibler 		if (KDFAULT(f->f_wb1s))
61953933Shibler 			bcopy((caddr_t)&f->f_pd0, (caddr_t)(f->f_fa & ~0xF), 16);
62053933Shibler 		else
62153933Shibler 			err = suline((caddr_t)(f->f_fa & ~0xF), (caddr_t)&f->f_pd0);
62253933Shibler 		if (err) {
62353933Shibler 			fa = f->f_fa & ~0xF;
62453933Shibler #ifdef DEBUG
62553933Shibler 			if (mmudebug & MDB_WBFAILED)
62653933Shibler 				printf(wberrstr, p->p_pid, p->p_comm,
62753933Shibler 				       "MOVE16", fp->f_pc, f->f_fa,
62853933Shibler 				       f->f_fa & ~0xF, f->f_pd0);
62953933Shibler #endif
63053933Shibler 		}
63153933Shibler 	} else if (f->f_wb1s & SSW4_WBSV) {
63253933Shibler 		/*
63353933Shibler 		 * Writeback #1.
63453933Shibler 		 * Position the "memory-aligned" data and write it out.
63553933Shibler 		 */
63653933Shibler 		register u_int wb1d = f->f_wb1d;
63753933Shibler 		register int off;
63853933Shibler 
63953933Shibler #ifdef DEBUG
64053933Shibler 		if ((mmudebug & MDB_WBFOLLOW) || MDB_ISPID(p->p_pid))
64153933Shibler 			dumpwb(1, f->f_wb1s, f->f_wb1a, f->f_wb1d);
64253933Shibler 		wbstats.wb1s++;
64353933Shibler 		wbstats.wbsize[(f->f_wb2s&SSW4_SZMASK)>>5]++;
64453933Shibler #endif
64553933Shibler 		off = (f->f_wb1a & 3) * 8;
64653933Shibler 		switch (f->f_wb1s & SSW4_SZMASK) {
64753933Shibler 		case SSW4_SZLW:
64853933Shibler 			if (off)
64953933Shibler 				wb1d = (wb1d >> (32 - off)) | (wb1d << off);
65053933Shibler 			if (KDFAULT(f->f_wb1s))
65153933Shibler 				*(long *)f->f_wb1a = wb1d;
65253933Shibler 			else
65353933Shibler 				err = suword((caddr_t)f->f_wb1a, wb1d);
65453933Shibler 			break;
65553933Shibler 		case SSW4_SZB:
65653933Shibler 			off = 24 - off;
65753933Shibler 			if (off)
65853933Shibler 				wb1d >>= off;
65953933Shibler 			if (KDFAULT(f->f_wb1s))
66053933Shibler 				*(char *)f->f_wb1a = wb1d;
66153933Shibler 			else
66253933Shibler 				err = subyte((caddr_t)f->f_wb1a, wb1d);
66353933Shibler 			break;
66453933Shibler 		case SSW4_SZW:
66553933Shibler 			off = (off + 16) % 32;
66653933Shibler 			if (off)
66753933Shibler 				wb1d = (wb1d >> (32 - off)) | (wb1d << off);
66853933Shibler 			if (KDFAULT(f->f_wb1s))
66953933Shibler 				*(short *)f->f_wb1a = wb1d;
67053933Shibler 			else
67153933Shibler 				err = susword((caddr_t)f->f_wb1a, wb1d);
67253933Shibler 			break;
67353933Shibler 		}
67453933Shibler 		if (err) {
67553933Shibler 			fa = f->f_wb1a;
67653933Shibler #ifdef DEBUG
67753933Shibler 			if (mmudebug & MDB_WBFAILED)
67853933Shibler 				printf(wberrstr, p->p_pid, p->p_comm,
67953933Shibler 				       "#1", fp->f_pc, f->f_fa,
68053933Shibler 				       f->f_wb1a, f->f_wb1d);
68153933Shibler #endif
68253933Shibler 		}
68353933Shibler 	}
68453933Shibler 	/*
68553933Shibler 	 * Deal with the "normal" writebacks.
68653933Shibler 	 *
68753933Shibler 	 * XXX writeback2 is known to reflect a LINE size writeback after
68853933Shibler 	 * a MOVE16 was already dealt with above.  Ignore it.
68953933Shibler 	 */
69053933Shibler 	if (err == 0 && (f->f_wb2s & SSW4_WBSV) &&
69153933Shibler 	    (f->f_wb2s & SSW4_SZMASK) != SSW4_SZLN) {
69253933Shibler #ifdef DEBUG
69353933Shibler 		if ((mmudebug & MDB_WBFOLLOW) || MDB_ISPID(p->p_pid))
69453933Shibler 			dumpwb(2, f->f_wb2s, f->f_wb2a, f->f_wb2d);
69553933Shibler 		wbstats.wb2s++;
69653933Shibler 		wbstats.wbsize[(f->f_wb2s&SSW4_SZMASK)>>5]++;
69753933Shibler #endif
69853933Shibler 		switch (f->f_wb2s & SSW4_SZMASK) {
69953933Shibler 		case SSW4_SZLW:
70053933Shibler 			if (KDFAULT(f->f_wb2s))
70153933Shibler 				*(long *)f->f_wb2a = f->f_wb2d;
70253933Shibler 			else
70353933Shibler 				err = suword((caddr_t)f->f_wb2a, f->f_wb2d);
70453933Shibler 			break;
70553933Shibler 		case SSW4_SZB:
70653933Shibler 			if (KDFAULT(f->f_wb2s))
70753933Shibler 				*(char *)f->f_wb2a = f->f_wb2d;
70853933Shibler 			else
70953933Shibler 				err = subyte((caddr_t)f->f_wb2a, f->f_wb2d);
71053933Shibler 			break;
71153933Shibler 		case SSW4_SZW:
71253933Shibler 			if (KDFAULT(f->f_wb2s))
71353933Shibler 				*(short *)f->f_wb2a = f->f_wb2d;
71453933Shibler 			else
71553933Shibler 				err = susword((caddr_t)f->f_wb2a, f->f_wb2d);
71653933Shibler 			break;
71753933Shibler 		}
71853933Shibler 		if (err) {
71953933Shibler 			fa = f->f_wb2a;
72053933Shibler #ifdef DEBUG
72153933Shibler 			if (mmudebug & MDB_WBFAILED) {
72253933Shibler 				printf(wberrstr, p->p_pid, p->p_comm,
72353933Shibler 				       "#2", fp->f_pc, f->f_fa,
72453933Shibler 				       f->f_wb2a, f->f_wb2d);
72553933Shibler 				dumpssw(f->f_ssw);
72653933Shibler 				dumpwb(2, f->f_wb2s, f->f_wb2a, f->f_wb2d);
72753933Shibler 			}
72853933Shibler #endif
72953933Shibler 		}
73053933Shibler 	}
73153933Shibler 	if (err == 0 && (f->f_wb3s & SSW4_WBSV)) {
73253933Shibler #ifdef DEBUG
73353933Shibler 		if ((mmudebug & MDB_WBFOLLOW) || MDB_ISPID(p->p_pid))
73453933Shibler 			dumpwb(3, f->f_wb3s, f->f_wb3a, f->f_wb3d);
73553933Shibler 		wbstats.wb3s++;
73653933Shibler 		wbstats.wbsize[(f->f_wb3s&SSW4_SZMASK)>>5]++;
73753933Shibler #endif
73853933Shibler 		switch (f->f_wb3s & SSW4_SZMASK) {
73953933Shibler 		case SSW4_SZLW:
74053933Shibler 			if (KDFAULT(f->f_wb3s))
74153933Shibler 				*(long *)f->f_wb3a = f->f_wb3d;
74253933Shibler 			else
74353933Shibler 				err = suword((caddr_t)f->f_wb3a, f->f_wb3d);
74453933Shibler 			break;
74553933Shibler 		case SSW4_SZB:
74653933Shibler 			if (KDFAULT(f->f_wb3s))
74753933Shibler 				*(char *)f->f_wb3a = f->f_wb3d;
74853933Shibler 			else
74953933Shibler 				err = subyte((caddr_t)f->f_wb3a, f->f_wb3d);
75053933Shibler 			break;
75153933Shibler 		case SSW4_SZW:
75253933Shibler 			if (KDFAULT(f->f_wb3s))
75353933Shibler 				*(short *)f->f_wb3a = f->f_wb3d;
75453933Shibler 			else
75553933Shibler 				err = susword((caddr_t)f->f_wb3a, f->f_wb3d);
75653933Shibler 			break;
75753933Shibler #ifdef DEBUG
75853933Shibler 		case SSW4_SZLN:
75953933Shibler 			panic("writeback: wb3s indicates LINE write");
76053933Shibler #endif
76153933Shibler 		}
76253933Shibler 		if (err) {
76353933Shibler 			fa = f->f_wb3a;
76453933Shibler #ifdef DEBUG
76553933Shibler 			if (mmudebug & MDB_WBFAILED)
76653933Shibler 				printf(wberrstr, p->p_pid, p->p_comm,
76753933Shibler 				       "#3", fp->f_pc, f->f_fa,
76853933Shibler 				       f->f_wb3a, f->f_wb3d);
76953933Shibler #endif
77053933Shibler 		}
77153933Shibler 	}
77253933Shibler 	p->p_addr->u_pcb.pcb_onfault = oonfault;
77353933Shibler 	/*
77453933Shibler 	 * Determine the cause of the failure if any translating to
77553933Shibler 	 * a signal.  If the corresponding VA is valid and RO it is
77653933Shibler 	 * a protection fault (SIGBUS) otherwise consider it an
77753933Shibler 	 * illegal reference (SIGSEGV).
77853933Shibler 	 */
77953933Shibler 	if (err) {
78053933Shibler 		if (vm_map_check_protection(&p->p_vmspace->vm_map,
78153933Shibler 					    trunc_page(fa), round_page(fa),
78253933Shibler 					    VM_PROT_READ) &&
78353933Shibler 		    !vm_map_check_protection(&p->p_vmspace->vm_map,
78453933Shibler 					     trunc_page(fa), round_page(fa),
78553933Shibler 					     VM_PROT_WRITE))
78653933Shibler 			err = SIGBUS;
78753933Shibler 		else
78853933Shibler 			err = SIGSEGV;
78953933Shibler 	}
79053933Shibler 	return(err);
79153933Shibler }
79253933Shibler 
79353933Shibler #ifdef DEBUG
79453933Shibler dumpssw(ssw)
79553933Shibler 	register u_short ssw;
79653933Shibler {
79753933Shibler 	printf(" SSW: %x: ", ssw);
79853933Shibler 	if (ssw & SSW4_CP)
79953933Shibler 		printf("CP,");
80053933Shibler 	if (ssw & SSW4_CU)
80153933Shibler 		printf("CU,");
80253933Shibler 	if (ssw & SSW4_CT)
80353933Shibler 		printf("CT,");
80453933Shibler 	if (ssw & SSW4_CM)
80553933Shibler 		printf("CM,");
80653933Shibler 	if (ssw & SSW4_MA)
80753933Shibler 		printf("MA,");
80853933Shibler 	if (ssw & SSW4_ATC)
80953933Shibler 		printf("ATC,");
81053933Shibler 	if (ssw & SSW4_LK)
81153933Shibler 		printf("LK,");
81253933Shibler 	if (ssw & SSW4_RW)
81353933Shibler 		printf("RW,");
81453933Shibler 	printf(" SZ=%s, TT=%s, TM=%s\n",
81553933Shibler 	       f7sz[(ssw & SSW4_SZMASK) >> 5],
81653933Shibler 	       f7tt[(ssw & SSW4_TTMASK) >> 3],
81753933Shibler 	       f7tm[ssw & SSW4_TMMASK]);
81853933Shibler }
81953933Shibler 
82053933Shibler dumpwb(num, s, a, d)
82153933Shibler 	int num;
82253933Shibler 	u_short s;
82353933Shibler 	u_int a, d;
82453933Shibler {
82553933Shibler 	register struct proc *p = curproc;
82653933Shibler 	vm_offset_t pa;
82753933Shibler 
82853933Shibler 	printf(" writeback #%d: VA %x, data %x, SZ=%s, TT=%s, TM=%s\n",
82953933Shibler 	       num, a, d, f7sz[(s & SSW4_SZMASK) >> 5],
83053933Shibler 	       f7tt[(s & SSW4_TTMASK) >> 3], f7tm[s & SSW4_TMMASK]);
83153933Shibler 	printf("               PA ");
83253933Shibler 	pa = pmap_extract(&p->p_vmspace->vm_pmap, (vm_offset_t)a);
83353933Shibler 	if (pa == 0)
83453933Shibler 		printf("<invalid address>");
83553933Shibler 	else
83653933Shibler 		printf("%x, current value %x", pa, fuword((caddr_t)a));
83753933Shibler 	printf("\n");
83853933Shibler }
83953933Shibler #endif
84053933Shibler #endif
84153933Shibler 
84241475Smckusick /*
84349531Skarels  * Proces a system call.
84441475Smckusick  */
84541475Smckusick syscall(code, frame)
84654801Storek 	u_int code;
84741475Smckusick 	struct frame frame;
84841475Smckusick {
84941475Smckusick 	register caddr_t params;
85041475Smckusick 	register struct sysent *callp;
85154801Storek 	register struct proc *p;
852*65483Sbostic 	int error, opc, numsys;
85354801Storek 	u_int argsize;
85444018Skarels 	struct args {
85544018Skarels 		int i[8];
85644018Skarels 	} args;
85744018Skarels 	int rval[2];
85854801Storek 	u_quad_t sticks;
85941475Smckusick #ifdef HPUXCOMPAT
86041475Smckusick 	extern struct sysent hpuxsysent[];
86141475Smckusick 	extern int hpuxnsysent, notimp();
86241475Smckusick #endif
86341475Smckusick 
86441475Smckusick 	cnt.v_syscall++;
86541475Smckusick 	if (!USERMODE(frame.f_sr))
86641475Smckusick 		panic("syscall");
86754801Storek 	p = curproc;
86854801Storek 	sticks = p->p_sticks;
86952380Smckusick 	p->p_md.md_regs = frame.f_regs;
87041475Smckusick 	opc = frame.f_pc - 2;
87141475Smckusick #ifdef HPUXCOMPAT
87257344Shibler 	if (p->p_md.md_flags & MDP_HPUX)
87354801Storek 		callp = hpuxsysent, numsys = hpuxnsysent;
87454801Storek 	else
87541475Smckusick #endif
87654801Storek 		callp = sysent, numsys = nsysent;
87749531Skarels 	params = (caddr_t)frame.f_regs[SP] + sizeof(int);
87854801Storek 	switch (code) {
87954801Storek 
88063469Smckusick 	case SYS_syscall:
88154801Storek 		/*
88254801Storek 		 * Code is first argument, followed by actual args.
88354801Storek 		 */
88442370Skarels 		code = fuword(params);
88549531Skarels 		params += sizeof(int);
88657344Shibler 		/*
88757344Shibler 		 * XXX sigreturn requires special stack manipulation
88857344Shibler 		 * that is only done if entered via the sigreturn
88957344Shibler 		 * trap.  Cannot allow it here so make sure we fail.
89057344Shibler 		 */
89157344Shibler 		if (code == SYS_sigreturn)
89257344Shibler 			code = numsys;
89354801Storek 		break;
89454801Storek 
89563469Smckusick 	case SYS___syscall:
89654801Storek 		/*
89763469Smckusick 		 * Like syscall, but code is a quad, so as to maintain
89854801Storek 		 * quad alignment for the rest of the arguments.
89954801Storek 		 */
90041475Smckusick #ifdef HPUXCOMPAT
90157344Shibler 		if (p->p_md.md_flags & MDP_HPUX)
90254801Storek 			break;
90341475Smckusick #endif
90454865Smckusick 		code = fuword(params + _QUAD_LOWWORD * sizeof(int));
90554865Smckusick 		params += sizeof(quad_t);
90654801Storek 		break;
90754801Storek 
90854865Smckusick 	default:
90954865Smckusick 		/* nothing to do by default */
91054865Smckusick 		break;
91154801Storek 	}
91254801Storek 	if (code < numsys)
91354801Storek 		callp += code;
91454801Storek 	else
91563469Smckusick 		callp += SYS_syscall;	/* => nosys */
91654801Storek 	argsize = callp->sy_narg * sizeof(int);
91754801Storek 	if (argsize && (error = copyin(params, (caddr_t)&args, argsize))) {
91841475Smckusick #ifdef KTRACE
91943641Skarels 		if (KTRPOINT(p, KTR_SYSCALL))
92044018Skarels 			ktrsyscall(p->p_tracep, code, callp->sy_narg, args.i);
92141475Smckusick #endif
92254801Storek 		goto bad;
92341475Smckusick 	}
92441475Smckusick #ifdef KTRACE
92543641Skarels 	if (KTRPOINT(p, KTR_SYSCALL))
92644018Skarels 		ktrsyscall(p->p_tracep, code, callp->sy_narg, args.i);
92741475Smckusick #endif
92843641Skarels 	rval[0] = 0;
92943641Skarels 	rval[1] = frame.f_regs[D1];
93041475Smckusick #ifdef HPUXCOMPAT
93142370Skarels 	/* debug kludge */
93242370Skarels 	if (callp->sy_call == notimp)
93348465Skarels 		error = notimp(p, args.i, rval, code, callp->sy_narg);
93442370Skarels 	else
93541475Smckusick #endif
93654801Storek 		error = (*callp->sy_call)(p, &args, rval);
93754801Storek 	switch (error) {
93842370Skarels 
93954801Storek 	case 0:
94041475Smckusick 		/*
94154801Storek 		 * Reinitialize proc pointer `p' as it may be different
94254801Storek 		 * if this is a child returning from fork syscall.
94341475Smckusick 		 */
94454801Storek 		p = curproc;
94554801Storek 		frame.f_regs[D0] = rval[0];
94654801Storek 		frame.f_regs[D1] = rval[1];
94754801Storek 		frame.f_sr &= ~PSL_C;
94854801Storek 		break;
94941475Smckusick 
95054801Storek 	case ERESTART:
95154801Storek 		frame.f_pc = opc;
95254801Storek 		break;
95354801Storek 
95454801Storek 	case EJUSTRETURN:
95554801Storek 		break;		/* nothing to do */
95654801Storek 
95754801Storek 	default:
95854801Storek 	bad:
95954801Storek #ifdef HPUXCOMPAT
96057344Shibler 		if (p->p_md.md_flags & MDP_HPUX)
96154801Storek 			error = bsdtohpuxerrno(error);
96241475Smckusick #endif
96354801Storek 		frame.f_regs[D0] = error;
96454801Storek 		frame.f_sr |= PSL_C;
96554801Storek 		break;
96641475Smckusick 	}
96754801Storek 
96854801Storek 	userret(p, &frame, sticks, (u_int)0, 0);
96941475Smckusick #ifdef KTRACE
97043641Skarels 	if (KTRPOINT(p, KTR_SYSRET))
97143641Skarels 		ktrsysret(p->p_tracep, code, error, rval[0]);
97241475Smckusick #endif
97341475Smckusick }
974