xref: /csrg-svn/sys/hp300/hp300/trap.c (revision 54865)
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  *
1253933Shibler  * from: Utah $Hdr: trap.c 1.35 91/12/26$
1341475Smckusick  *
14*54865Smckusick  *	@(#)trap.c	7.23 (Berkeley) 07/09/92
1541475Smckusick  */
1641475Smckusick 
1748465Skarels #include "param.h"
1848465Skarels #include "systm.h"
1948465Skarels #include "proc.h"
2048465Skarels #include "acct.h"
2148465Skarels #include "kernel.h"
2248465Skarels #include "signalvar.h"
2348465Skarels #include "resourcevar.h"
2454801Storek #include "syscall.h"
2548465Skarels #include "syslog.h"
2648465Skarels #include "user.h"
2748465Skarels #ifdef KTRACE
2848465Skarels #include "ktrace.h"
2948465Skarels #endif
3048465Skarels 
3149125Skarels #include "../include/psl.h"
3248465Skarels #include "../include/trap.h"
3345788Sbostic #include "../include/cpu.h"
3445788Sbostic #include "../include/reg.h"
3545788Sbostic #include "../include/mtpr.h"
3641475Smckusick 
3748465Skarels #include "vm/vm.h"
3845788Sbostic #include "vm/pmap.h"
3945751Smckusick 
4041475Smckusick #ifdef HPUXCOMPAT
4153933Shibler #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)
12354801Storek 		psig(sig);
12454801Storek 	p->p_pri = 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.)
13054801Storek 		 * If that happened after we setrq ourselves but before we
13154801Storek 		 * swtch()'ed, we might not be on the queue indicated by
13254801Storek 		 * our priority.
13354801Storek 		 */
13454801Storek 		s = splstatclock();
13554801Storek 		setrq(p);
13654801Storek 		p->p_stats->p_ru.ru_nivcsw++;
13754801Storek 		swtch();
13854801Storek 		splx(s);
13954801Storek 		while ((sig = CURSIG(p)) != 0)
14054801Storek 			psig(sig);
14154801Storek 	}
14254801Storek 
14354801Storek 	/*
14454801Storek 	 * If profiling, charge system time to the trapped pc.
14554801Storek 	 */
14654801Storek 	if (p->p_flag & SPROFIL)
14754801Storek 		addupc_intr(p, fp->f_pc, (int)(p->p_sticks - oticks));
14854801Storek #ifdef HP380
14954801Storek 	/*
15054801Storek 	 * Deal with user mode writebacks (from trap, or from sigreturn).
15154801Storek 	 * If any writeback fails, go back and attempt signal delivery.
15254801Storek 	 * unless we have already been here and attempted the writeback
15354801Storek 	 * (e.g. bad address with user ignoring SIGSEGV).  In that case
15454801Storek 	 * we just return to the user without sucessfully completing
15554801Storek 	 * the writebacks.  Maybe we should just drop the sucker?
15654801Storek 	 */
15754801Storek 	if (mmutype == MMU_68040 && fp->f_format == FMT7) {
15854801Storek 		if (beenhere) {
15954801Storek #ifdef DEBUG
16054801Storek 			if (mmudebug & MDB_WBFAILED)
16154801Storek 				printf(fromtrap ?
16254801Storek 		"pid %d(%s): writeback aborted, pc=%x, fa=%x\n" :
16354801Storek 		"pid %d(%s): writeback aborted in sigreturn, pc=%x\n",
16454801Storek 				    p->p_pid, p->p_comm, fp->f_pc, faultaddr);
16554801Storek #endif
16654801Storek 		} else if (sig = writeback(fp, fromtrap)) {
16754801Storek 			beenhere = 1;
16854801Storek 			oticks = p->p_sticks;
16954801Storek 			trapsignal(p, sig, faultaddr);
17054801Storek 			goto again;
17154801Storek 		}
17254801Storek 	}
17354801Storek #endif
17454801Storek 	curpri = p->p_pri;
17554801Storek }
17654801Storek 
17754801Storek /*
17849531Skarels  * Trap is called from locore to handle most types of processor traps,
17949531Skarels  * including events such as simulated software interrupts/AST's.
18049531Skarels  * System calls are broken out for efficiency.
18141475Smckusick  */
18241475Smckusick /*ARGSUSED*/
18341475Smckusick trap(type, code, v, frame)
18441475Smckusick 	int type;
18541475Smckusick 	unsigned code;
18641475Smckusick 	register unsigned v;
18741475Smckusick 	struct frame frame;
18841475Smckusick {
18941475Smckusick 	register int i;
19054801Storek 	unsigned ucode;
19154801Storek 	register struct proc *p;
19254801Storek 	u_quad_t sticks;
19341475Smckusick 	unsigned ncode;
19454574Storek 	extern char fswintr[];
19541475Smckusick 
19641475Smckusick 	cnt.v_trap++;
19754801Storek 	p = curproc;
19854801Storek 	ucode = 0;
19941475Smckusick 	if (USERMODE(frame.f_sr)) {
20049531Skarels 		type |= T_USER;
20154801Storek 		sticks = p->p_sticks;
20252380Smckusick 		p->p_md.md_regs = frame.f_regs;
20341475Smckusick 	}
20441475Smckusick 	switch (type) {
20541475Smckusick 
20641475Smckusick 	default:
20741475Smckusick dopanic:
20841475Smckusick 		printf("trap type %d, code = %x, v = %x\n", type, code, v);
20941475Smckusick 		regdump(frame.f_regs, 128);
21049531Skarels 		type &= ~T_USER;
21141475Smckusick 		if ((unsigned)type < TRAP_TYPES)
21241475Smckusick 			panic(trap_type[type]);
21341475Smckusick 		panic("trap");
21441475Smckusick 
21541475Smckusick 	case T_BUSERR:		/* kernel bus error */
21649125Skarels 		if (!p->p_addr->u_pcb.pcb_onfault)
21741475Smckusick 			goto dopanic;
21841475Smckusick 		/*
21941475Smckusick 		 * If we have arranged to catch this fault in any of the
22041475Smckusick 		 * copy to/from user space routines, set PC to return to
22141475Smckusick 		 * indicated location and set flag informing buserror code
22241475Smckusick 		 * that it may need to clean up stack frame.
22341475Smckusick 		 */
22441475Smckusick copyfault:
22549317Shibler 		frame.f_stackadj = exframesize[frame.f_format];
22649317Shibler 		frame.f_format = frame.f_vector = 0;
22749125Skarels 		frame.f_pc = (int) p->p_addr->u_pcb.pcb_onfault;
22841475Smckusick 		return;
22941475Smckusick 
23049531Skarels 	case T_BUSERR|T_USER:	/* bus error */
23149531Skarels 	case T_ADDRERR|T_USER:	/* address error */
23253933Shibler 		ucode = v;
23341475Smckusick 		i = SIGBUS;
23441475Smckusick 		break;
23541475Smckusick 
23641475Smckusick #ifdef FPCOPROC
23741475Smckusick 	case T_COPERR:		/* kernel coprocessor violation */
23841475Smckusick #endif
23953933Shibler 	case T_FMTERR|T_USER:	/* do all RTE errors come in as T_USER? */
24053933Shibler 	case T_FMTERR:		/* ...just in case... */
24141475Smckusick 	/*
24241475Smckusick 	 * The user has most likely trashed the RTE or FP state info
24341475Smckusick 	 * in the stack frame of a signal handler.
24441475Smckusick 	 */
24549531Skarels 		type |= T_USER;
24648465Skarels 		printf("pid %d: kernel %s exception\n", p->p_pid,
24741475Smckusick 		       type==T_COPERR ? "coprocessor" : "format");
24848465Skarels 		p->p_sigacts->ps_sigact[SIGILL] = SIG_DFL;
24941475Smckusick 		i = sigmask(SIGILL);
25041475Smckusick 		p->p_sigignore &= ~i;
25141475Smckusick 		p->p_sigcatch &= ~i;
25241475Smckusick 		p->p_sigmask &= ~i;
25342370Skarels 		i = SIGILL;
25441475Smckusick 		ucode = frame.f_format;	/* XXX was ILL_RESAD_FAULT */
25542370Skarels 		break;
25641475Smckusick 
25741475Smckusick #ifdef FPCOPROC
25849531Skarels 	case T_COPERR|T_USER:	/* user coprocessor violation */
25941475Smckusick 	/* What is a proper response here? */
26041475Smckusick 		ucode = 0;
26141475Smckusick 		i = SIGFPE;
26241475Smckusick 		break;
26341475Smckusick 
26449531Skarels 	case T_FPERR|T_USER:	/* 68881 exceptions */
26541475Smckusick 	/*
26641475Smckusick 	 * We pass along the 68881 status register which locore stashed
26741475Smckusick 	 * in code for us.  Note that there is a possibility that the
26841475Smckusick 	 * bit pattern of this register will conflict with one of the
26941475Smckusick 	 * FPE_* codes defined in signal.h.  Fortunately for us, the
27041475Smckusick 	 * only such codes we use are all in the range 1-7 and the low
27141475Smckusick 	 * 3 bits of the status register are defined as 0 so there is
27241475Smckusick 	 * no clash.
27341475Smckusick 	 */
27441475Smckusick 		ucode = code;
27541475Smckusick 		i = SIGFPE;
27641475Smckusick 		break;
27741475Smckusick #endif
27841475Smckusick 
27954801Storek #ifdef HP380
28053933Shibler 	case T_FPEMULI|T_USER:	/* unimplemented FP instuction */
28153933Shibler 	case T_FPEMULD|T_USER:	/* unimplemented FP data type */
28253933Shibler 		/* XXX need to FSAVE */
28353933Shibler 		printf("pid %d(%s): unimplemented FP %s at %x (EA %x)\n",
28453933Shibler 		       p->p_pid, p->p_comm,
28553933Shibler 		       frame.f_format == 2 ? "instruction" : "data type",
28653933Shibler 		       frame.f_pc, frame.f_fmt2.f_iaddr);
28753933Shibler 		/* XXX need to FRESTORE */
28853933Shibler 		i = SIGFPE;
28953933Shibler 		break;
29053933Shibler #endif
29153933Shibler 
29249531Skarels 	case T_ILLINST|T_USER:	/* illegal instruction fault */
29341475Smckusick #ifdef HPUXCOMPAT
29448465Skarels 		if (p->p_flag & SHPUX) {
29541475Smckusick 			ucode = HPUX_ILL_ILLINST_TRAP;
29641475Smckusick 			i = SIGILL;
29741475Smckusick 			break;
29841475Smckusick 		}
29941475Smckusick 		/* fall through */
30041475Smckusick #endif
30149531Skarels 	case T_PRIVINST|T_USER:	/* privileged instruction fault */
30241475Smckusick #ifdef HPUXCOMPAT
30348465Skarels 		if (p->p_flag & SHPUX)
30441475Smckusick 			ucode = HPUX_ILL_PRIV_TRAP;
30541475Smckusick 		else
30641475Smckusick #endif
30741475Smckusick 		ucode = frame.f_format;	/* XXX was ILL_PRIVIN_FAULT */
30841475Smckusick 		i = SIGILL;
30941475Smckusick 		break;
31041475Smckusick 
31149531Skarels 	case T_ZERODIV|T_USER:	/* Divide by zero */
31241475Smckusick #ifdef HPUXCOMPAT
31348465Skarels 		if (p->p_flag & SHPUX)
31441475Smckusick 			ucode = HPUX_FPE_INTDIV_TRAP;
31541475Smckusick 		else
31641475Smckusick #endif
31741475Smckusick 		ucode = frame.f_format;	/* XXX was FPE_INTDIV_TRAP */
31841475Smckusick 		i = SIGFPE;
31941475Smckusick 		break;
32041475Smckusick 
32149531Skarels 	case T_CHKINST|T_USER:	/* CHK instruction trap */
32241475Smckusick #ifdef HPUXCOMPAT
32348465Skarels 		if (p->p_flag & SHPUX) {
32441475Smckusick 			/* handled differently under hp-ux */
32541475Smckusick 			i = SIGILL;
32641475Smckusick 			ucode = HPUX_ILL_CHK_TRAP;
32741475Smckusick 			break;
32841475Smckusick 		}
32941475Smckusick #endif
33041475Smckusick 		ucode = frame.f_format;	/* XXX was FPE_SUBRNG_TRAP */
33141475Smckusick 		i = SIGFPE;
33241475Smckusick 		break;
33341475Smckusick 
33449531Skarels 	case T_TRAPVINST|T_USER:	/* TRAPV instruction trap */
33541475Smckusick #ifdef HPUXCOMPAT
33648465Skarels 		if (p->p_flag & SHPUX) {
33741475Smckusick 			/* handled differently under hp-ux */
33841475Smckusick 			i = SIGILL;
33941475Smckusick 			ucode = HPUX_ILL_TRAPV_TRAP;
34041475Smckusick 			break;
34141475Smckusick 		}
34241475Smckusick #endif
34341475Smckusick 		ucode = frame.f_format;	/* XXX was FPE_INTOVF_TRAP */
34441475Smckusick 		i = SIGFPE;
34541475Smckusick 		break;
34641475Smckusick 
34741475Smckusick 	/*
34841475Smckusick 	 * XXX: Trace traps are a nightmare.
34941475Smckusick 	 *
35041475Smckusick 	 *	HP-UX uses trap #1 for breakpoints,
35141475Smckusick 	 *	HPBSD uses trap #2,
35241475Smckusick 	 *	SUN 3.x uses trap #15,
35348465Skarels 	 *	KGDB uses trap #15 (for kernel breakpoints; handled elsewhere).
35441475Smckusick 	 *
35541475Smckusick 	 * HPBSD and HP-UX traps both get mapped by locore.s into T_TRACE.
35641475Smckusick 	 * SUN 3.x traps get passed through as T_TRAP15 and are not really
35748465Skarels 	 * supported yet.
35841475Smckusick 	 */
35941475Smckusick 	case T_TRACE:		/* kernel trace trap */
36048465Skarels 	case T_TRAP15:		/* SUN trace trap */
36141475Smckusick 		frame.f_sr &= ~PSL_T;
36241475Smckusick 		i = SIGTRAP;
36341475Smckusick 		break;
36441475Smckusick 
36549531Skarels 	case T_TRACE|T_USER:	/* user trace trap */
36649531Skarels 	case T_TRAP15|T_USER:	/* SUN user trace trap */
36741475Smckusick 		frame.f_sr &= ~PSL_T;
36841475Smckusick 		i = SIGTRAP;
36941475Smckusick 		break;
37041475Smckusick 
37143413Shibler 	case T_ASTFLT:		/* system async trap, cannot happen */
37241475Smckusick 		goto dopanic;
37341475Smckusick 
37449531Skarels 	case T_ASTFLT|T_USER:	/* user async trap */
37549125Skarels 		astpending = 0;
37641475Smckusick 		/*
37741475Smckusick 		 * We check for software interrupts first.  This is because
37841475Smckusick 		 * they are at a higher level than ASTs, and on a VAX would
37941475Smckusick 		 * interrupt the AST.  We assume that if we are processing
38041475Smckusick 		 * an AST that we must be at IPL0 so we don't bother to
38141475Smckusick 		 * check.  Note that we ensure that we are at least at SIR
38241475Smckusick 		 * IPL while processing the SIR.
38341475Smckusick 		 */
38441475Smckusick 		spl1();
38541475Smckusick 		/* fall into... */
38641475Smckusick 
38741475Smckusick 	case T_SSIR:		/* software interrupt */
38849531Skarels 	case T_SSIR|T_USER:
38941475Smckusick 		if (ssir & SIR_NET) {
39041475Smckusick 			siroff(SIR_NET);
39141475Smckusick 			cnt.v_soft++;
39241475Smckusick 			netintr();
39341475Smckusick 		}
39441475Smckusick 		if (ssir & SIR_CLOCK) {
39541475Smckusick 			siroff(SIR_CLOCK);
39641475Smckusick 			cnt.v_soft++;
39754801Storek 			softclock();
39841475Smckusick 		}
39941475Smckusick 		/*
40041475Smckusick 		 * If this was not an AST trap, we are all done.
40141475Smckusick 		 */
40250753Skarels 		if (type != (T_ASTFLT|T_USER)) {
40341475Smckusick 			cnt.v_trap--;
40441475Smckusick 			return;
40541475Smckusick 		}
40641475Smckusick 		spl0();
40754801Storek 		if (p->p_flag & SOWEUPC) {
40848465Skarels 			p->p_flag &= ~SOWEUPC;
40954801Storek 			ADDUPROF(p);
41041475Smckusick 		}
41141475Smckusick 		goto out;
41241475Smckusick 
41341475Smckusick 	case T_MMUFLT:		/* kernel mode page fault */
41454574Storek 		/*
41554574Storek 		 * If we were doing profiling ticks or other user mode
41654574Storek 		 * stuff from interrupt code, Just Say No.
41754574Storek 		 */
41854574Storek 		if (p->p_addr->u_pcb.pcb_onfault == fswintr)
41954574Storek 			goto copyfault;
42041475Smckusick 		/* fall into ... */
42141475Smckusick 
42249531Skarels 	case T_MMUFLT|T_USER:	/* page fault */
42345751Smckusick 	    {
42445751Smckusick 		register vm_offset_t va;
42548465Skarels 		register struct vmspace *vm = p->p_vmspace;
42645751Smckusick 		register vm_map_t map;
42745751Smckusick 		int rv;
42845751Smckusick 		vm_prot_t ftype;
42945751Smckusick 		extern vm_map_t kernel_map;
43045751Smckusick 
43153933Shibler #ifdef DEBUG
43253933Shibler 		if ((mmudebug & MDB_WBFOLLOW) || MDB_ISPID(p->p_pid))
43353933Shibler 		printf("trap: T_MMUFLT pid=%d, code=%x, v=%x, pc=%x, sr=%x\n",
43453933Shibler 		       p->p_pid, code, v, frame.f_pc, frame.f_sr);
43553933Shibler #endif
43641475Smckusick 		/*
43745751Smckusick 		 * It is only a kernel address space fault iff:
43849531Skarels 		 * 	1. (type & T_USER) == 0  and
43945751Smckusick 		 * 	2. pcb_onfault not set or
44045751Smckusick 		 *	3. pcb_onfault set but supervisor space data fault
44145751Smckusick 		 * The last can occur during an exec() copyin where the
44245751Smckusick 		 * argument space is lazy-allocated.
44341475Smckusick 		 */
44445751Smckusick 		if (type == T_MMUFLT &&
44553933Shibler 		    (!p->p_addr->u_pcb.pcb_onfault || KDFAULT(code)))
44645751Smckusick 			map = kernel_map;
44745751Smckusick 		else
44848465Skarels 			map = &vm->vm_map;
44953933Shibler 		if (WRFAULT(code))
45045751Smckusick 			ftype = VM_PROT_READ | VM_PROT_WRITE;
45145751Smckusick 		else
45245751Smckusick 			ftype = VM_PROT_READ;
45345751Smckusick 		va = trunc_page((vm_offset_t)v);
45441475Smckusick #ifdef DEBUG
45545751Smckusick 		if (map == kernel_map && va == 0) {
45645751Smckusick 			printf("trap: bad kernel access at %x\n", v);
45741475Smckusick 			goto dopanic;
45841475Smckusick 		}
45941475Smckusick #endif
46049317Shibler 		rv = vm_fault(map, va, ftype, FALSE);
46153933Shibler #ifdef DEBUG
46253933Shibler 		if (rv && MDB_ISPID(p->p_pid))
46353933Shibler 			printf("vm_fault(%x, %x, %x, 0) -> %x\n",
46453933Shibler 			       map, va, ftype, rv);
46553933Shibler #endif
46641475Smckusick 		/*
46749317Shibler 		 * If this was a stack access we keep track of the maximum
46849317Shibler 		 * accessed stack size.  Also, if vm_fault gets a protection
46949317Shibler 		 * failure it is due to accessing the stack region outside
47049317Shibler 		 * the current limit and we need to reflect that as an access
47149317Shibler 		 * error.
47241475Smckusick 		 */
47348465Skarels 		if ((caddr_t)va >= vm->vm_maxsaddr && map != kernel_map) {
47449317Shibler 			if (rv == KERN_SUCCESS) {
47549317Shibler 				unsigned nss;
47649317Shibler 
47749317Shibler 				nss = clrnd(btoc(USRSTACK-(unsigned)va));
47849317Shibler 				if (nss > vm->vm_ssize)
47949317Shibler 					vm->vm_ssize = nss;
48049317Shibler 			} else if (rv == KERN_PROTECTION_FAILURE)
48149317Shibler 				rv = KERN_INVALID_ADDRESS;
48241475Smckusick 		}
48345751Smckusick 		if (rv == KERN_SUCCESS) {
48453933Shibler 			if (type == T_MMUFLT) {
48554801Storek #ifdef HP380
48653933Shibler 				if (mmutype == MMU_68040)
48753933Shibler 					(void) writeback(&frame, 1);
48853933Shibler #endif
48941475Smckusick 				return;
49053933Shibler 			}
49141475Smckusick 			goto out;
49241475Smckusick 		}
49345751Smckusick 		if (type == T_MMUFLT) {
49449125Skarels 			if (p->p_addr->u_pcb.pcb_onfault)
49545751Smckusick 				goto copyfault;
49645751Smckusick 			printf("vm_fault(%x, %x, %x, 0) -> %x\n",
49745751Smckusick 			       map, va, ftype, rv);
49845751Smckusick 			printf("  type %x, code [mmu,,ssw]: %x\n",
49945751Smckusick 			       type, code);
50045751Smckusick 			goto dopanic;
50145751Smckusick 		}
50248465Skarels 		ucode = v;
50345751Smckusick 		i = (rv == KERN_PROTECTION_FAILURE) ? SIGBUS : SIGSEGV;
50445751Smckusick 		break;
50545751Smckusick 	    }
50641475Smckusick 	}
50748465Skarels 	trapsignal(p, i, ucode);
50849531Skarels 	if ((type & T_USER) == 0)
50941475Smckusick 		return;
51041475Smckusick out:
51154801Storek 	userret(p, &frame, sticks, v, 1);
51241475Smckusick }
51341475Smckusick 
51454801Storek #ifdef HP380
51553933Shibler #ifdef DEBUG
51653933Shibler struct writebackstats {
51753933Shibler 	int calls;
51853933Shibler 	int cpushes;
51953933Shibler 	int move16s;
52053933Shibler 	int wb1s, wb2s, wb3s;
52153933Shibler 	int wbsize[4];
52253933Shibler } wbstats;
52353933Shibler 
52453933Shibler char *f7sz[] = { "longword", "byte", "word", "line" };
52553933Shibler char *f7tt[] = { "normal", "MOVE16", "AFC", "ACK" };
52653933Shibler char *f7tm[] = { "d-push", "u-data", "u-code", "M-data",
52753933Shibler 		 "M-code", "k-data", "k-code", "RES" };
52853933Shibler char wberrstr[] =
52953933Shibler     "WARNING: pid %d(%s) writeback [%s] failed, pc=%x fa=%x wba=%x wbd=%x\n";
53053933Shibler #endif
53153933Shibler 
53253933Shibler writeback(fp, docachepush)
53353933Shibler 	struct frame *fp;
53453933Shibler 	int docachepush;
53553933Shibler {
53653933Shibler 	register struct fmt7 *f = &fp->f_fmt7;
53753933Shibler 	register struct proc *p = curproc;
53853933Shibler 	int err = 0;
53953933Shibler 	u_int fa;
54053933Shibler 	caddr_t oonfault = p->p_addr->u_pcb.pcb_onfault;
54153933Shibler 
54253933Shibler #ifdef DEBUG
54353933Shibler 	if ((mmudebug & MDB_WBFOLLOW) || MDB_ISPID(p->p_pid)) {
54453933Shibler 		printf(" pid=%d, fa=%x,", p->p_pid, f->f_fa);
54553933Shibler 		dumpssw(f->f_ssw);
54653933Shibler 	}
54753933Shibler 	wbstats.calls++;
54853933Shibler #endif
54953933Shibler 	/*
55053933Shibler 	 * Deal with special cases first.
55153933Shibler 	 */
55253933Shibler 	if ((f->f_ssw & SSW4_TMMASK) == SSW4_TMDCP) {
55353933Shibler 		/*
55453933Shibler 		 * Dcache push fault.
55553933Shibler 		 * Line-align the address and write out the push data to
55653933Shibler 		 * the indicated physical address.
55753933Shibler 		 */
55853933Shibler #ifdef DEBUG
55953933Shibler 		if ((mmudebug & MDB_WBFOLLOW) || MDB_ISPID(p->p_pid)) {
56053933Shibler 			printf(" pushing %s to PA %x, data %x",
56153933Shibler 			       f7sz[(f->f_ssw & SSW4_SZMASK) >> 5],
56253933Shibler 			       f->f_fa, f->f_pd0);
56353933Shibler 			if ((f->f_ssw & SSW4_SZMASK) == SSW4_SZLN)
56453933Shibler 				printf("/%x/%x/%x",
56553933Shibler 				       f->f_pd1, f->f_pd2, f->f_pd3);
56653933Shibler 			printf("\n");
56753933Shibler 		}
56853933Shibler 		if (f->f_wb1s & SSW4_WBSV)
56953933Shibler 			panic("writeback: cache push with WB1S valid");
57053933Shibler 		wbstats.cpushes++;
57153933Shibler #endif
57253933Shibler 		/*
57353933Shibler 		 * XXX there are security problems if we attempt to do a
57453933Shibler 		 * cache push after a signal handler has been called.
57553933Shibler 		 */
57653933Shibler 		if (docachepush) {
57753933Shibler 			pmap_enter(kernel_pmap, (vm_offset_t)vmmap,
57853933Shibler 				   trunc_page(f->f_fa), VM_PROT_WRITE, TRUE);
57953933Shibler 			fa = (u_int)&vmmap[(f->f_fa & PGOFSET) & ~0xF];
58053933Shibler 			bcopy((caddr_t)&f->f_pd0, (caddr_t)fa, 16);
58153933Shibler 			DCFL(pmap_extract(kernel_pmap, (vm_offset_t)fa));
58253933Shibler 			pmap_remove(kernel_pmap, (vm_offset_t)vmmap,
58353933Shibler 				    (vm_offset_t)&vmmap[NBPG]);
58453933Shibler 		} else
58553933Shibler 			printf("WARNING: pid %d(%s) uid %d: CPUSH not done\n",
58653933Shibler 			       p->p_pid, p->p_comm, p->p_ucred->cr_uid);
58753933Shibler 	} else if ((f->f_ssw & (SSW4_RW|SSW4_TTMASK)) == SSW4_TTM16) {
58853933Shibler 		/*
58953933Shibler 		 * MOVE16 fault.
59053933Shibler 		 * Line-align the address and write out the push data to
59153933Shibler 		 * the indicated virtual address.
59253933Shibler 		 */
59353933Shibler #ifdef DEBUG
59453933Shibler 		if ((mmudebug & MDB_WBFOLLOW) || MDB_ISPID(p->p_pid))
59553933Shibler 			printf(" MOVE16 to VA %x(%x), data %x/%x/%x/%x\n",
59653933Shibler 			       f->f_fa, f->f_fa & ~0xF, f->f_pd0, f->f_pd1,
59753933Shibler 			       f->f_pd2, f->f_pd3);
59853933Shibler 		if (f->f_wb1s & SSW4_WBSV)
59953933Shibler 			panic("writeback: MOVE16 with WB1S valid");
60053933Shibler 		wbstats.move16s++;
60153933Shibler #endif
60253933Shibler 		if (KDFAULT(f->f_wb1s))
60353933Shibler 			bcopy((caddr_t)&f->f_pd0, (caddr_t)(f->f_fa & ~0xF), 16);
60453933Shibler 		else
60553933Shibler 			err = suline((caddr_t)(f->f_fa & ~0xF), (caddr_t)&f->f_pd0);
60653933Shibler 		if (err) {
60753933Shibler 			fa = f->f_fa & ~0xF;
60853933Shibler #ifdef DEBUG
60953933Shibler 			if (mmudebug & MDB_WBFAILED)
61053933Shibler 				printf(wberrstr, p->p_pid, p->p_comm,
61153933Shibler 				       "MOVE16", fp->f_pc, f->f_fa,
61253933Shibler 				       f->f_fa & ~0xF, f->f_pd0);
61353933Shibler #endif
61453933Shibler 		}
61553933Shibler 	} else if (f->f_wb1s & SSW4_WBSV) {
61653933Shibler 		/*
61753933Shibler 		 * Writeback #1.
61853933Shibler 		 * Position the "memory-aligned" data and write it out.
61953933Shibler 		 */
62053933Shibler 		register u_int wb1d = f->f_wb1d;
62153933Shibler 		register int off;
62253933Shibler 
62353933Shibler #ifdef DEBUG
62453933Shibler 		if ((mmudebug & MDB_WBFOLLOW) || MDB_ISPID(p->p_pid))
62553933Shibler 			dumpwb(1, f->f_wb1s, f->f_wb1a, f->f_wb1d);
62653933Shibler 		wbstats.wb1s++;
62753933Shibler 		wbstats.wbsize[(f->f_wb2s&SSW4_SZMASK)>>5]++;
62853933Shibler #endif
62953933Shibler 		off = (f->f_wb1a & 3) * 8;
63053933Shibler 		switch (f->f_wb1s & SSW4_SZMASK) {
63153933Shibler 		case SSW4_SZLW:
63253933Shibler 			if (off)
63353933Shibler 				wb1d = (wb1d >> (32 - off)) | (wb1d << off);
63453933Shibler 			if (KDFAULT(f->f_wb1s))
63553933Shibler 				*(long *)f->f_wb1a = wb1d;
63653933Shibler 			else
63753933Shibler 				err = suword((caddr_t)f->f_wb1a, wb1d);
63853933Shibler 			break;
63953933Shibler 		case SSW4_SZB:
64053933Shibler 			off = 24 - off;
64153933Shibler 			if (off)
64253933Shibler 				wb1d >>= off;
64353933Shibler 			if (KDFAULT(f->f_wb1s))
64453933Shibler 				*(char *)f->f_wb1a = wb1d;
64553933Shibler 			else
64653933Shibler 				err = subyte((caddr_t)f->f_wb1a, wb1d);
64753933Shibler 			break;
64853933Shibler 		case SSW4_SZW:
64953933Shibler 			off = (off + 16) % 32;
65053933Shibler 			if (off)
65153933Shibler 				wb1d = (wb1d >> (32 - off)) | (wb1d << off);
65253933Shibler 			if (KDFAULT(f->f_wb1s))
65353933Shibler 				*(short *)f->f_wb1a = wb1d;
65453933Shibler 			else
65553933Shibler 				err = susword((caddr_t)f->f_wb1a, wb1d);
65653933Shibler 			break;
65753933Shibler 		}
65853933Shibler 		if (err) {
65953933Shibler 			fa = f->f_wb1a;
66053933Shibler #ifdef DEBUG
66153933Shibler 			if (mmudebug & MDB_WBFAILED)
66253933Shibler 				printf(wberrstr, p->p_pid, p->p_comm,
66353933Shibler 				       "#1", fp->f_pc, f->f_fa,
66453933Shibler 				       f->f_wb1a, f->f_wb1d);
66553933Shibler #endif
66653933Shibler 		}
66753933Shibler 	}
66853933Shibler 	/*
66953933Shibler 	 * Deal with the "normal" writebacks.
67053933Shibler 	 *
67153933Shibler 	 * XXX writeback2 is known to reflect a LINE size writeback after
67253933Shibler 	 * a MOVE16 was already dealt with above.  Ignore it.
67353933Shibler 	 */
67453933Shibler 	if (err == 0 && (f->f_wb2s & SSW4_WBSV) &&
67553933Shibler 	    (f->f_wb2s & SSW4_SZMASK) != SSW4_SZLN) {
67653933Shibler #ifdef DEBUG
67753933Shibler 		if ((mmudebug & MDB_WBFOLLOW) || MDB_ISPID(p->p_pid))
67853933Shibler 			dumpwb(2, f->f_wb2s, f->f_wb2a, f->f_wb2d);
67953933Shibler 		wbstats.wb2s++;
68053933Shibler 		wbstats.wbsize[(f->f_wb2s&SSW4_SZMASK)>>5]++;
68153933Shibler #endif
68253933Shibler 		switch (f->f_wb2s & SSW4_SZMASK) {
68353933Shibler 		case SSW4_SZLW:
68453933Shibler 			if (KDFAULT(f->f_wb2s))
68553933Shibler 				*(long *)f->f_wb2a = f->f_wb2d;
68653933Shibler 			else
68753933Shibler 				err = suword((caddr_t)f->f_wb2a, f->f_wb2d);
68853933Shibler 			break;
68953933Shibler 		case SSW4_SZB:
69053933Shibler 			if (KDFAULT(f->f_wb2s))
69153933Shibler 				*(char *)f->f_wb2a = f->f_wb2d;
69253933Shibler 			else
69353933Shibler 				err = subyte((caddr_t)f->f_wb2a, f->f_wb2d);
69453933Shibler 			break;
69553933Shibler 		case SSW4_SZW:
69653933Shibler 			if (KDFAULT(f->f_wb2s))
69753933Shibler 				*(short *)f->f_wb2a = f->f_wb2d;
69853933Shibler 			else
69953933Shibler 				err = susword((caddr_t)f->f_wb2a, f->f_wb2d);
70053933Shibler 			break;
70153933Shibler 		}
70253933Shibler 		if (err) {
70353933Shibler 			fa = f->f_wb2a;
70453933Shibler #ifdef DEBUG
70553933Shibler 			if (mmudebug & MDB_WBFAILED) {
70653933Shibler 				printf(wberrstr, p->p_pid, p->p_comm,
70753933Shibler 				       "#2", fp->f_pc, f->f_fa,
70853933Shibler 				       f->f_wb2a, f->f_wb2d);
70953933Shibler 				dumpssw(f->f_ssw);
71053933Shibler 				dumpwb(2, f->f_wb2s, f->f_wb2a, f->f_wb2d);
71153933Shibler 			}
71253933Shibler #endif
71353933Shibler 		}
71453933Shibler 	}
71553933Shibler 	if (err == 0 && (f->f_wb3s & SSW4_WBSV)) {
71653933Shibler #ifdef DEBUG
71753933Shibler 		if ((mmudebug & MDB_WBFOLLOW) || MDB_ISPID(p->p_pid))
71853933Shibler 			dumpwb(3, f->f_wb3s, f->f_wb3a, f->f_wb3d);
71953933Shibler 		wbstats.wb3s++;
72053933Shibler 		wbstats.wbsize[(f->f_wb3s&SSW4_SZMASK)>>5]++;
72153933Shibler #endif
72253933Shibler 		switch (f->f_wb3s & SSW4_SZMASK) {
72353933Shibler 		case SSW4_SZLW:
72453933Shibler 			if (KDFAULT(f->f_wb3s))
72553933Shibler 				*(long *)f->f_wb3a = f->f_wb3d;
72653933Shibler 			else
72753933Shibler 				err = suword((caddr_t)f->f_wb3a, f->f_wb3d);
72853933Shibler 			break;
72953933Shibler 		case SSW4_SZB:
73053933Shibler 			if (KDFAULT(f->f_wb3s))
73153933Shibler 				*(char *)f->f_wb3a = f->f_wb3d;
73253933Shibler 			else
73353933Shibler 				err = subyte((caddr_t)f->f_wb3a, f->f_wb3d);
73453933Shibler 			break;
73553933Shibler 		case SSW4_SZW:
73653933Shibler 			if (KDFAULT(f->f_wb3s))
73753933Shibler 				*(short *)f->f_wb3a = f->f_wb3d;
73853933Shibler 			else
73953933Shibler 				err = susword((caddr_t)f->f_wb3a, f->f_wb3d);
74053933Shibler 			break;
74153933Shibler #ifdef DEBUG
74253933Shibler 		case SSW4_SZLN:
74353933Shibler 			panic("writeback: wb3s indicates LINE write");
74453933Shibler #endif
74553933Shibler 		}
74653933Shibler 		if (err) {
74753933Shibler 			fa = f->f_wb3a;
74853933Shibler #ifdef DEBUG
74953933Shibler 			if (mmudebug & MDB_WBFAILED)
75053933Shibler 				printf(wberrstr, p->p_pid, p->p_comm,
75153933Shibler 				       "#3", fp->f_pc, f->f_fa,
75253933Shibler 				       f->f_wb3a, f->f_wb3d);
75353933Shibler #endif
75453933Shibler 		}
75553933Shibler 	}
75653933Shibler 	p->p_addr->u_pcb.pcb_onfault = oonfault;
75753933Shibler 	/*
75853933Shibler 	 * Determine the cause of the failure if any translating to
75953933Shibler 	 * a signal.  If the corresponding VA is valid and RO it is
76053933Shibler 	 * a protection fault (SIGBUS) otherwise consider it an
76153933Shibler 	 * illegal reference (SIGSEGV).
76253933Shibler 	 */
76353933Shibler 	if (err) {
76453933Shibler 		if (vm_map_check_protection(&p->p_vmspace->vm_map,
76553933Shibler 					    trunc_page(fa), round_page(fa),
76653933Shibler 					    VM_PROT_READ) &&
76753933Shibler 		    !vm_map_check_protection(&p->p_vmspace->vm_map,
76853933Shibler 					     trunc_page(fa), round_page(fa),
76953933Shibler 					     VM_PROT_WRITE))
77053933Shibler 			err = SIGBUS;
77153933Shibler 		else
77253933Shibler 			err = SIGSEGV;
77353933Shibler 	}
77453933Shibler 	return(err);
77553933Shibler }
77653933Shibler 
77753933Shibler #ifdef DEBUG
77853933Shibler dumpssw(ssw)
77953933Shibler 	register u_short ssw;
78053933Shibler {
78153933Shibler 	printf(" SSW: %x: ", ssw);
78253933Shibler 	if (ssw & SSW4_CP)
78353933Shibler 		printf("CP,");
78453933Shibler 	if (ssw & SSW4_CU)
78553933Shibler 		printf("CU,");
78653933Shibler 	if (ssw & SSW4_CT)
78753933Shibler 		printf("CT,");
78853933Shibler 	if (ssw & SSW4_CM)
78953933Shibler 		printf("CM,");
79053933Shibler 	if (ssw & SSW4_MA)
79153933Shibler 		printf("MA,");
79253933Shibler 	if (ssw & SSW4_ATC)
79353933Shibler 		printf("ATC,");
79453933Shibler 	if (ssw & SSW4_LK)
79553933Shibler 		printf("LK,");
79653933Shibler 	if (ssw & SSW4_RW)
79753933Shibler 		printf("RW,");
79853933Shibler 	printf(" SZ=%s, TT=%s, TM=%s\n",
79953933Shibler 	       f7sz[(ssw & SSW4_SZMASK) >> 5],
80053933Shibler 	       f7tt[(ssw & SSW4_TTMASK) >> 3],
80153933Shibler 	       f7tm[ssw & SSW4_TMMASK]);
80253933Shibler }
80353933Shibler 
80453933Shibler dumpwb(num, s, a, d)
80553933Shibler 	int num;
80653933Shibler 	u_short s;
80753933Shibler 	u_int a, d;
80853933Shibler {
80953933Shibler 	register struct proc *p = curproc;
81053933Shibler 	vm_offset_t pa;
81153933Shibler 
81253933Shibler 	printf(" writeback #%d: VA %x, data %x, SZ=%s, TT=%s, TM=%s\n",
81353933Shibler 	       num, a, d, f7sz[(s & SSW4_SZMASK) >> 5],
81453933Shibler 	       f7tt[(s & SSW4_TTMASK) >> 3], f7tm[s & SSW4_TMMASK]);
81553933Shibler 	printf("               PA ");
81653933Shibler 	pa = pmap_extract(&p->p_vmspace->vm_pmap, (vm_offset_t)a);
81753933Shibler 	if (pa == 0)
81853933Shibler 		printf("<invalid address>");
81953933Shibler 	else
82053933Shibler 		printf("%x, current value %x", pa, fuword((caddr_t)a));
82153933Shibler 	printf("\n");
82253933Shibler }
82353933Shibler 
82453933Shibler #ifdef HPFPLIB
82553933Shibler fppanic(frame)
82653933Shibler 	struct fppanicframe {
82753933Shibler 		int	fpsaveframe;
82853933Shibler 		int	regs[16];
82953933Shibler 		int	fpregs[8*3];
83053933Shibler 		int	fpcregs[3];
83153933Shibler 		int	hole[5];
83253933Shibler 		int	oa6;
83353933Shibler 		short	sr;
83453933Shibler 		int	pc;
83553933Shibler 		short	vector;
83653933Shibler 	} frame;
83753933Shibler {
83853933Shibler 	printf("FP exception: pid %d(%s): no busy frame, ft=%x pc=%x vec=%x\n",
83953933Shibler 	       curproc->p_pid, curproc->p_comm,
84053933Shibler 	       frame.fpsaveframe, frame.pc, frame.vector);
84153933Shibler 	panic("bad FP exception");
84253933Shibler }
84353933Shibler #endif
84453933Shibler #endif
84553933Shibler #endif
84653933Shibler 
84741475Smckusick /*
84849531Skarels  * Proces a system call.
84941475Smckusick  */
85041475Smckusick syscall(code, frame)
85154801Storek 	u_int code;
85241475Smckusick 	struct frame frame;
85341475Smckusick {
85441475Smckusick 	register caddr_t params;
85541475Smckusick 	register struct sysent *callp;
85654801Storek 	register struct proc *p;
85750753Skarels 	int error, opc, numsys, s;
85854801Storek 	u_int argsize;
85944018Skarels 	struct args {
86044018Skarels 		int i[8];
86144018Skarels 	} args;
86244018Skarels 	int rval[2];
86354801Storek 	u_quad_t sticks;
86441475Smckusick #ifdef HPUXCOMPAT
86541475Smckusick 	extern struct sysent hpuxsysent[];
86641475Smckusick 	extern int hpuxnsysent, notimp();
86741475Smckusick #endif
86841475Smckusick 
86941475Smckusick 	cnt.v_syscall++;
87041475Smckusick 	if (!USERMODE(frame.f_sr))
87141475Smckusick 		panic("syscall");
87254801Storek 	p = curproc;
87354801Storek 	sticks = p->p_sticks;
87452380Smckusick 	p->p_md.md_regs = frame.f_regs;
87541475Smckusick 	opc = frame.f_pc - 2;
87641475Smckusick #ifdef HPUXCOMPAT
87754801Storek 	if (p->p_flag & SHPUX)
87854801Storek 		callp = hpuxsysent, numsys = hpuxnsysent;
87954801Storek 	else
88041475Smckusick #endif
88154801Storek 		callp = sysent, numsys = nsysent;
88249531Skarels 	params = (caddr_t)frame.f_regs[SP] + sizeof(int);
88354801Storek 	switch (code) {
88454801Storek 
88554801Storek 	case SYS_indir:
88654801Storek 		/*
88754801Storek 		 * Code is first argument, followed by actual args.
88854801Storek 		 */
88942370Skarels 		code = fuword(params);
89049531Skarels 		params += sizeof(int);
89154801Storek 		break;
89254801Storek 
89354801Storek 	case SYS___indir:
89454801Storek 		/*
89554801Storek 		 * Like indir, but code is a quad, so as to maintain
89654801Storek 		 * quad alignment for the rest of the arguments.
89754801Storek 		 */
89841475Smckusick #ifdef HPUXCOMPAT
89941475Smckusick 		if (p->p_flag & SHPUX)
90054801Storek 			break;
90141475Smckusick #endif
902*54865Smckusick 		code = fuword(params + _QUAD_LOWWORD * sizeof(int));
903*54865Smckusick 		params += sizeof(quad_t);
90454801Storek 		break;
90554801Storek 
906*54865Smckusick 	default:
907*54865Smckusick 		/* nothing to do by default */
908*54865Smckusick 		break;
90954801Storek 	}
91054801Storek 	if (code < numsys)
91154801Storek 		callp += code;
91254801Storek 	else
91354801Storek 		callp += SYS_indir;	/* => nosys */
91454801Storek 	argsize = callp->sy_narg * sizeof(int);
91554801Storek 	if (argsize && (error = copyin(params, (caddr_t)&args, argsize))) {
91641475Smckusick #ifdef KTRACE
91743641Skarels 		if (KTRPOINT(p, KTR_SYSCALL))
91844018Skarels 			ktrsyscall(p->p_tracep, code, callp->sy_narg, args.i);
91941475Smckusick #endif
92054801Storek 		goto bad;
92141475Smckusick 	}
92241475Smckusick #ifdef KTRACE
92343641Skarels 	if (KTRPOINT(p, KTR_SYSCALL))
92444018Skarels 		ktrsyscall(p->p_tracep, code, callp->sy_narg, args.i);
92541475Smckusick #endif
92643641Skarels 	rval[0] = 0;
92743641Skarels 	rval[1] = frame.f_regs[D1];
92841475Smckusick #ifdef HPUXCOMPAT
92942370Skarels 	/* debug kludge */
93042370Skarels 	if (callp->sy_call == notimp)
93148465Skarels 		error = notimp(p, args.i, rval, code, callp->sy_narg);
93242370Skarels 	else
93341475Smckusick #endif
93454801Storek 		error = (*callp->sy_call)(p, &args, rval);
93554801Storek 	switch (error) {
93642370Skarels 
93754801Storek 	case 0:
93841475Smckusick 		/*
93954801Storek 		 * Reinitialize proc pointer `p' as it may be different
94054801Storek 		 * if this is a child returning from fork syscall.
94141475Smckusick 		 */
94254801Storek 		p = curproc;
94354801Storek 		frame.f_regs[D0] = rval[0];
94454801Storek 		frame.f_regs[D1] = rval[1];
94554801Storek 		frame.f_sr &= ~PSL_C;
94654801Storek 		break;
94741475Smckusick 
94854801Storek 	case ERESTART:
94954801Storek 		frame.f_pc = opc;
95054801Storek 		break;
95154801Storek 
95254801Storek 	case EJUSTRETURN:
95354801Storek 		break;		/* nothing to do */
95454801Storek 
95554801Storek 	default:
95654801Storek 	bad:
95754801Storek #ifdef HPUXCOMPAT
95854801Storek 		if (p->p_flag & SHPUX)
95954801Storek 			error = bsdtohpuxerrno(error);
96041475Smckusick #endif
96154801Storek 		frame.f_regs[D0] = error;
96254801Storek 		frame.f_sr |= PSL_C;
96354801Storek 		break;
96441475Smckusick 	}
96554801Storek 
96654801Storek 	userret(p, &frame, sticks, (u_int)0, 0);
96741475Smckusick #ifdef KTRACE
96843641Skarels 	if (KTRPOINT(p, KTR_SYSRET))
96943641Skarels 		ktrsysret(p->p_tracep, code, error, rval[0]);
97041475Smckusick #endif
97141475Smckusick }
972