xref: /csrg-svn/sys/hp300/hp300/trap.c (revision 63472)
141475Smckusick /*
241475Smckusick  * Copyright (c) 1988 University of Utah.
3*63472Sbostic  * Copyright (c) 1982, 1986, 1990, 1993
4*63472Sbostic  *	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*63472Sbostic  *	@(#)trap.c	8.1 (Berkeley) 06/16/93
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)
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 	 */
14656318Shibler 	if (p->p_flag & SPROFIL) {
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
17854801Storek 	curpri = p->p_pri;
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 {
19341475Smckusick 	register int i;
19454801Storek 	unsigned ucode;
19554801Storek 	register struct proc *p;
19654801Storek 	u_quad_t sticks;
19741475Smckusick 	unsigned ncode;
19854574Storek 	extern char fswintr[];
19941475Smckusick 
20041475Smckusick 	cnt.v_trap++;
20154801Storek 	p = curproc;
20254801Storek 	ucode = 0;
20341475Smckusick 	if (USERMODE(frame.f_sr)) {
20449531Skarels 		type |= T_USER;
20554801Storek 		sticks = p->p_sticks;
20652380Smckusick 		p->p_md.md_regs = frame.f_regs;
20741475Smckusick 	}
20841475Smckusick 	switch (type) {
20941475Smckusick 
21041475Smckusick 	default:
21141475Smckusick dopanic:
21241475Smckusick 		printf("trap type %d, code = %x, v = %x\n", type, code, v);
21357344Shibler 		regdump(&frame, 128);
21449531Skarels 		type &= ~T_USER;
21541475Smckusick 		if ((unsigned)type < TRAP_TYPES)
21641475Smckusick 			panic(trap_type[type]);
21741475Smckusick 		panic("trap");
21841475Smckusick 
21941475Smckusick 	case T_BUSERR:		/* kernel bus error */
22049125Skarels 		if (!p->p_addr->u_pcb.pcb_onfault)
22141475Smckusick 			goto dopanic;
22241475Smckusick 		/*
22341475Smckusick 		 * If we have arranged to catch this fault in any of the
22441475Smckusick 		 * copy to/from user space routines, set PC to return to
22541475Smckusick 		 * indicated location and set flag informing buserror code
22641475Smckusick 		 * that it may need to clean up stack frame.
22741475Smckusick 		 */
22841475Smckusick copyfault:
22949317Shibler 		frame.f_stackadj = exframesize[frame.f_format];
23049317Shibler 		frame.f_format = frame.f_vector = 0;
23149125Skarels 		frame.f_pc = (int) p->p_addr->u_pcb.pcb_onfault;
23241475Smckusick 		return;
23341475Smckusick 
23449531Skarels 	case T_BUSERR|T_USER:	/* bus error */
23549531Skarels 	case T_ADDRERR|T_USER:	/* address error */
23653933Shibler 		ucode = v;
23741475Smckusick 		i = SIGBUS;
23841475Smckusick 		break;
23941475Smckusick 
24041475Smckusick #ifdef FPCOPROC
24141475Smckusick 	case T_COPERR:		/* kernel coprocessor violation */
24241475Smckusick #endif
24353933Shibler 	case T_FMTERR|T_USER:	/* do all RTE errors come in as T_USER? */
24453933Shibler 	case T_FMTERR:		/* ...just in case... */
24541475Smckusick 	/*
24641475Smckusick 	 * The user has most likely trashed the RTE or FP state info
24741475Smckusick 	 * in the stack frame of a signal handler.
24841475Smckusick 	 */
24949531Skarels 		type |= T_USER;
25048465Skarels 		printf("pid %d: kernel %s exception\n", p->p_pid,
25141475Smckusick 		       type==T_COPERR ? "coprocessor" : "format");
25248465Skarels 		p->p_sigacts->ps_sigact[SIGILL] = SIG_DFL;
25341475Smckusick 		i = sigmask(SIGILL);
25441475Smckusick 		p->p_sigignore &= ~i;
25541475Smckusick 		p->p_sigcatch &= ~i;
25641475Smckusick 		p->p_sigmask &= ~i;
25742370Skarels 		i = SIGILL;
25841475Smckusick 		ucode = frame.f_format;	/* XXX was ILL_RESAD_FAULT */
25942370Skarels 		break;
26041475Smckusick 
26141475Smckusick #ifdef FPCOPROC
26249531Skarels 	case T_COPERR|T_USER:	/* user coprocessor violation */
26341475Smckusick 	/* What is a proper response here? */
26441475Smckusick 		ucode = 0;
26541475Smckusick 		i = SIGFPE;
26641475Smckusick 		break;
26741475Smckusick 
26849531Skarels 	case T_FPERR|T_USER:	/* 68881 exceptions */
26941475Smckusick 	/*
27041475Smckusick 	 * We pass along the 68881 status register which locore stashed
27141475Smckusick 	 * in code for us.  Note that there is a possibility that the
27241475Smckusick 	 * bit pattern of this register will conflict with one of the
27341475Smckusick 	 * FPE_* codes defined in signal.h.  Fortunately for us, the
27441475Smckusick 	 * only such codes we use are all in the range 1-7 and the low
27541475Smckusick 	 * 3 bits of the status register are defined as 0 so there is
27641475Smckusick 	 * no clash.
27741475Smckusick 	 */
27841475Smckusick 		ucode = code;
27941475Smckusick 		i = SIGFPE;
28041475Smckusick 		break;
28141475Smckusick #endif
28241475Smckusick 
28354801Storek #ifdef HP380
28453933Shibler 	case T_FPEMULI|T_USER:	/* unimplemented FP instuction */
28553933Shibler 	case T_FPEMULD|T_USER:	/* unimplemented FP data type */
28653933Shibler 		/* XXX need to FSAVE */
28753933Shibler 		printf("pid %d(%s): unimplemented FP %s at %x (EA %x)\n",
28853933Shibler 		       p->p_pid, p->p_comm,
28953933Shibler 		       frame.f_format == 2 ? "instruction" : "data type",
29053933Shibler 		       frame.f_pc, frame.f_fmt2.f_iaddr);
29153933Shibler 		/* XXX need to FRESTORE */
29253933Shibler 		i = SIGFPE;
29353933Shibler 		break;
29453933Shibler #endif
29553933Shibler 
29649531Skarels 	case T_ILLINST|T_USER:	/* illegal instruction fault */
29741475Smckusick #ifdef HPUXCOMPAT
29857344Shibler 		if (p->p_md.md_flags & MDP_HPUX) {
29941475Smckusick 			ucode = HPUX_ILL_ILLINST_TRAP;
30041475Smckusick 			i = SIGILL;
30141475Smckusick 			break;
30241475Smckusick 		}
30341475Smckusick 		/* fall through */
30441475Smckusick #endif
30549531Skarels 	case T_PRIVINST|T_USER:	/* privileged instruction fault */
30641475Smckusick #ifdef HPUXCOMPAT
30757344Shibler 		if (p->p_md.md_flags & MDP_HPUX)
30841475Smckusick 			ucode = HPUX_ILL_PRIV_TRAP;
30941475Smckusick 		else
31041475Smckusick #endif
31141475Smckusick 		ucode = frame.f_format;	/* XXX was ILL_PRIVIN_FAULT */
31241475Smckusick 		i = SIGILL;
31341475Smckusick 		break;
31441475Smckusick 
31549531Skarels 	case T_ZERODIV|T_USER:	/* Divide by zero */
31641475Smckusick #ifdef HPUXCOMPAT
31757344Shibler 		if (p->p_md.md_flags & MDP_HPUX)
31841475Smckusick 			ucode = HPUX_FPE_INTDIV_TRAP;
31941475Smckusick 		else
32041475Smckusick #endif
32141475Smckusick 		ucode = frame.f_format;	/* XXX was FPE_INTDIV_TRAP */
32241475Smckusick 		i = SIGFPE;
32341475Smckusick 		break;
32441475Smckusick 
32549531Skarels 	case T_CHKINST|T_USER:	/* CHK instruction trap */
32641475Smckusick #ifdef HPUXCOMPAT
32757344Shibler 		if (p->p_md.md_flags & MDP_HPUX) {
32841475Smckusick 			/* handled differently under hp-ux */
32941475Smckusick 			i = SIGILL;
33041475Smckusick 			ucode = HPUX_ILL_CHK_TRAP;
33141475Smckusick 			break;
33241475Smckusick 		}
33341475Smckusick #endif
33441475Smckusick 		ucode = frame.f_format;	/* XXX was FPE_SUBRNG_TRAP */
33541475Smckusick 		i = SIGFPE;
33641475Smckusick 		break;
33741475Smckusick 
33849531Skarels 	case T_TRAPVINST|T_USER:	/* TRAPV instruction trap */
33941475Smckusick #ifdef HPUXCOMPAT
34057344Shibler 		if (p->p_md.md_flags & MDP_HPUX) {
34141475Smckusick 			/* handled differently under hp-ux */
34241475Smckusick 			i = SIGILL;
34341475Smckusick 			ucode = HPUX_ILL_TRAPV_TRAP;
34441475Smckusick 			break;
34541475Smckusick 		}
34641475Smckusick #endif
34741475Smckusick 		ucode = frame.f_format;	/* XXX was FPE_INTOVF_TRAP */
34841475Smckusick 		i = SIGFPE;
34941475Smckusick 		break;
35041475Smckusick 
35141475Smckusick 	/*
35241475Smckusick 	 * XXX: Trace traps are a nightmare.
35341475Smckusick 	 *
35441475Smckusick 	 *	HP-UX uses trap #1 for breakpoints,
35541475Smckusick 	 *	HPBSD uses trap #2,
35641475Smckusick 	 *	SUN 3.x uses trap #15,
35748465Skarels 	 *	KGDB uses trap #15 (for kernel breakpoints; handled elsewhere).
35841475Smckusick 	 *
35941475Smckusick 	 * HPBSD and HP-UX traps both get mapped by locore.s into T_TRACE.
36041475Smckusick 	 * SUN 3.x traps get passed through as T_TRAP15 and are not really
36148465Skarels 	 * supported yet.
36241475Smckusick 	 */
36341475Smckusick 	case T_TRACE:		/* kernel trace trap */
36448465Skarels 	case T_TRAP15:		/* SUN trace trap */
36541475Smckusick 		frame.f_sr &= ~PSL_T;
36641475Smckusick 		i = SIGTRAP;
36741475Smckusick 		break;
36841475Smckusick 
36949531Skarels 	case T_TRACE|T_USER:	/* user trace trap */
37049531Skarels 	case T_TRAP15|T_USER:	/* SUN user trace trap */
37141475Smckusick 		frame.f_sr &= ~PSL_T;
37241475Smckusick 		i = SIGTRAP;
37341475Smckusick 		break;
37441475Smckusick 
37543413Shibler 	case T_ASTFLT:		/* system async trap, cannot happen */
37641475Smckusick 		goto dopanic;
37741475Smckusick 
37849531Skarels 	case T_ASTFLT|T_USER:	/* user async trap */
37949125Skarels 		astpending = 0;
38041475Smckusick 		/*
38141475Smckusick 		 * We check for software interrupts first.  This is because
38241475Smckusick 		 * they are at a higher level than ASTs, and on a VAX would
38341475Smckusick 		 * interrupt the AST.  We assume that if we are processing
38441475Smckusick 		 * an AST that we must be at IPL0 so we don't bother to
38541475Smckusick 		 * check.  Note that we ensure that we are at least at SIR
38641475Smckusick 		 * IPL while processing the SIR.
38741475Smckusick 		 */
38841475Smckusick 		spl1();
38941475Smckusick 		/* fall into... */
39041475Smckusick 
39141475Smckusick 	case T_SSIR:		/* software interrupt */
39249531Skarels 	case T_SSIR|T_USER:
39341475Smckusick 		if (ssir & SIR_NET) {
39441475Smckusick 			siroff(SIR_NET);
39541475Smckusick 			cnt.v_soft++;
39641475Smckusick 			netintr();
39741475Smckusick 		}
39841475Smckusick 		if (ssir & SIR_CLOCK) {
39941475Smckusick 			siroff(SIR_CLOCK);
40041475Smckusick 			cnt.v_soft++;
40154801Storek 			softclock();
40241475Smckusick 		}
40341475Smckusick 		/*
40441475Smckusick 		 * If this was not an AST trap, we are all done.
40541475Smckusick 		 */
40650753Skarels 		if (type != (T_ASTFLT|T_USER)) {
40741475Smckusick 			cnt.v_trap--;
40841475Smckusick 			return;
40941475Smckusick 		}
41041475Smckusick 		spl0();
41154801Storek 		if (p->p_flag & SOWEUPC) {
41248465Skarels 			p->p_flag &= ~SOWEUPC;
41354801Storek 			ADDUPROF(p);
41441475Smckusick 		}
41541475Smckusick 		goto out;
41641475Smckusick 
41741475Smckusick 	case T_MMUFLT:		/* kernel mode page fault */
41854574Storek 		/*
41954574Storek 		 * If we were doing profiling ticks or other user mode
42054574Storek 		 * stuff from interrupt code, Just Say No.
42154574Storek 		 */
42254574Storek 		if (p->p_addr->u_pcb.pcb_onfault == fswintr)
42354574Storek 			goto copyfault;
42441475Smckusick 		/* fall into ... */
42541475Smckusick 
42649531Skarels 	case T_MMUFLT|T_USER:	/* page fault */
42745751Smckusick 	    {
42845751Smckusick 		register vm_offset_t va;
42948465Skarels 		register struct vmspace *vm = p->p_vmspace;
43045751Smckusick 		register vm_map_t map;
43145751Smckusick 		int rv;
43245751Smckusick 		vm_prot_t ftype;
43345751Smckusick 		extern vm_map_t kernel_map;
43445751Smckusick 
43553933Shibler #ifdef DEBUG
43653933Shibler 		if ((mmudebug & MDB_WBFOLLOW) || MDB_ISPID(p->p_pid))
43753933Shibler 		printf("trap: T_MMUFLT pid=%d, code=%x, v=%x, pc=%x, sr=%x\n",
43853933Shibler 		       p->p_pid, code, v, frame.f_pc, frame.f_sr);
43953933Shibler #endif
44041475Smckusick 		/*
44145751Smckusick 		 * It is only a kernel address space fault iff:
44249531Skarels 		 * 	1. (type & T_USER) == 0  and
44345751Smckusick 		 * 	2. pcb_onfault not set or
44445751Smckusick 		 *	3. pcb_onfault set but supervisor space data fault
44545751Smckusick 		 * The last can occur during an exec() copyin where the
44645751Smckusick 		 * argument space is lazy-allocated.
44741475Smckusick 		 */
44845751Smckusick 		if (type == T_MMUFLT &&
44953933Shibler 		    (!p->p_addr->u_pcb.pcb_onfault || KDFAULT(code)))
45045751Smckusick 			map = kernel_map;
45145751Smckusick 		else
45248465Skarels 			map = &vm->vm_map;
45353933Shibler 		if (WRFAULT(code))
45445751Smckusick 			ftype = VM_PROT_READ | VM_PROT_WRITE;
45545751Smckusick 		else
45645751Smckusick 			ftype = VM_PROT_READ;
45745751Smckusick 		va = trunc_page((vm_offset_t)v);
45841475Smckusick #ifdef DEBUG
45945751Smckusick 		if (map == kernel_map && va == 0) {
46045751Smckusick 			printf("trap: bad kernel access at %x\n", v);
46141475Smckusick 			goto dopanic;
46241475Smckusick 		}
46341475Smckusick #endif
46457344Shibler #ifdef HPUXCOMPAT
46557344Shibler 		if (ISHPMMADDR(va)) {
46657344Shibler 			vm_offset_t bva;
46757344Shibler 
46857344Shibler 			rv = pmap_mapmulti(map->pmap, va);
46957344Shibler 			if (rv != KERN_SUCCESS) {
47057344Shibler 				bva = HPMMBASEADDR(va);
47157344Shibler 				rv = vm_fault(map, bva, ftype, FALSE);
47257344Shibler 				if (rv == KERN_SUCCESS)
47357344Shibler 					(void) pmap_mapmulti(map->pmap, va);
47457344Shibler 			}
47557344Shibler 		} else
47657344Shibler #endif
47749317Shibler 		rv = vm_fault(map, va, ftype, FALSE);
47853933Shibler #ifdef DEBUG
47953933Shibler 		if (rv && MDB_ISPID(p->p_pid))
48053933Shibler 			printf("vm_fault(%x, %x, %x, 0) -> %x\n",
48153933Shibler 			       map, va, ftype, rv);
48253933Shibler #endif
48341475Smckusick 		/*
48449317Shibler 		 * If this was a stack access we keep track of the maximum
48549317Shibler 		 * accessed stack size.  Also, if vm_fault gets a protection
48649317Shibler 		 * failure it is due to accessing the stack region outside
48749317Shibler 		 * the current limit and we need to reflect that as an access
48849317Shibler 		 * error.
48941475Smckusick 		 */
49048465Skarels 		if ((caddr_t)va >= vm->vm_maxsaddr && map != kernel_map) {
49149317Shibler 			if (rv == KERN_SUCCESS) {
49249317Shibler 				unsigned nss;
49349317Shibler 
49449317Shibler 				nss = clrnd(btoc(USRSTACK-(unsigned)va));
49549317Shibler 				if (nss > vm->vm_ssize)
49649317Shibler 					vm->vm_ssize = nss;
49749317Shibler 			} else if (rv == KERN_PROTECTION_FAILURE)
49849317Shibler 				rv = KERN_INVALID_ADDRESS;
49941475Smckusick 		}
50045751Smckusick 		if (rv == KERN_SUCCESS) {
50153933Shibler 			if (type == T_MMUFLT) {
50254801Storek #ifdef HP380
50353933Shibler 				if (mmutype == MMU_68040)
50453933Shibler 					(void) writeback(&frame, 1);
50553933Shibler #endif
50641475Smckusick 				return;
50753933Shibler 			}
50841475Smckusick 			goto out;
50941475Smckusick 		}
51045751Smckusick 		if (type == T_MMUFLT) {
51149125Skarels 			if (p->p_addr->u_pcb.pcb_onfault)
51245751Smckusick 				goto copyfault;
51345751Smckusick 			printf("vm_fault(%x, %x, %x, 0) -> %x\n",
51445751Smckusick 			       map, va, ftype, rv);
51545751Smckusick 			printf("  type %x, code [mmu,,ssw]: %x\n",
51645751Smckusick 			       type, code);
51745751Smckusick 			goto dopanic;
51845751Smckusick 		}
51948465Skarels 		ucode = v;
52045751Smckusick 		i = (rv == KERN_PROTECTION_FAILURE) ? SIGBUS : SIGSEGV;
52145751Smckusick 		break;
52245751Smckusick 	    }
52341475Smckusick 	}
52448465Skarels 	trapsignal(p, i, ucode);
52549531Skarels 	if ((type & T_USER) == 0)
52641475Smckusick 		return;
52741475Smckusick out:
52854801Storek 	userret(p, &frame, sticks, v, 1);
52941475Smckusick }
53041475Smckusick 
53154801Storek #ifdef HP380
53253933Shibler #ifdef DEBUG
53353933Shibler struct writebackstats {
53453933Shibler 	int calls;
53553933Shibler 	int cpushes;
53653933Shibler 	int move16s;
53753933Shibler 	int wb1s, wb2s, wb3s;
53853933Shibler 	int wbsize[4];
53953933Shibler } wbstats;
54053933Shibler 
54153933Shibler char *f7sz[] = { "longword", "byte", "word", "line" };
54253933Shibler char *f7tt[] = { "normal", "MOVE16", "AFC", "ACK" };
54353933Shibler char *f7tm[] = { "d-push", "u-data", "u-code", "M-data",
54453933Shibler 		 "M-code", "k-data", "k-code", "RES" };
54553933Shibler char wberrstr[] =
54653933Shibler     "WARNING: pid %d(%s) writeback [%s] failed, pc=%x fa=%x wba=%x wbd=%x\n";
54753933Shibler #endif
54853933Shibler 
54953933Shibler writeback(fp, docachepush)
55053933Shibler 	struct frame *fp;
55153933Shibler 	int docachepush;
55253933Shibler {
55353933Shibler 	register struct fmt7 *f = &fp->f_fmt7;
55453933Shibler 	register struct proc *p = curproc;
55553933Shibler 	int err = 0;
55653933Shibler 	u_int fa;
55753933Shibler 	caddr_t oonfault = p->p_addr->u_pcb.pcb_onfault;
55853933Shibler 
55953933Shibler #ifdef DEBUG
56053933Shibler 	if ((mmudebug & MDB_WBFOLLOW) || MDB_ISPID(p->p_pid)) {
56153933Shibler 		printf(" pid=%d, fa=%x,", p->p_pid, f->f_fa);
56253933Shibler 		dumpssw(f->f_ssw);
56353933Shibler 	}
56453933Shibler 	wbstats.calls++;
56553933Shibler #endif
56653933Shibler 	/*
56753933Shibler 	 * Deal with special cases first.
56853933Shibler 	 */
56953933Shibler 	if ((f->f_ssw & SSW4_TMMASK) == SSW4_TMDCP) {
57053933Shibler 		/*
57153933Shibler 		 * Dcache push fault.
57253933Shibler 		 * Line-align the address and write out the push data to
57353933Shibler 		 * the indicated physical address.
57453933Shibler 		 */
57553933Shibler #ifdef DEBUG
57653933Shibler 		if ((mmudebug & MDB_WBFOLLOW) || MDB_ISPID(p->p_pid)) {
57753933Shibler 			printf(" pushing %s to PA %x, data %x",
57853933Shibler 			       f7sz[(f->f_ssw & SSW4_SZMASK) >> 5],
57953933Shibler 			       f->f_fa, f->f_pd0);
58053933Shibler 			if ((f->f_ssw & SSW4_SZMASK) == SSW4_SZLN)
58153933Shibler 				printf("/%x/%x/%x",
58253933Shibler 				       f->f_pd1, f->f_pd2, f->f_pd3);
58353933Shibler 			printf("\n");
58453933Shibler 		}
58553933Shibler 		if (f->f_wb1s & SSW4_WBSV)
58653933Shibler 			panic("writeback: cache push with WB1S valid");
58753933Shibler 		wbstats.cpushes++;
58853933Shibler #endif
58953933Shibler 		/*
59053933Shibler 		 * XXX there are security problems if we attempt to do a
59153933Shibler 		 * cache push after a signal handler has been called.
59253933Shibler 		 */
59353933Shibler 		if (docachepush) {
59453933Shibler 			pmap_enter(kernel_pmap, (vm_offset_t)vmmap,
59553933Shibler 				   trunc_page(f->f_fa), VM_PROT_WRITE, TRUE);
59653933Shibler 			fa = (u_int)&vmmap[(f->f_fa & PGOFSET) & ~0xF];
59753933Shibler 			bcopy((caddr_t)&f->f_pd0, (caddr_t)fa, 16);
59853933Shibler 			DCFL(pmap_extract(kernel_pmap, (vm_offset_t)fa));
59953933Shibler 			pmap_remove(kernel_pmap, (vm_offset_t)vmmap,
60053933Shibler 				    (vm_offset_t)&vmmap[NBPG]);
60153933Shibler 		} else
60253933Shibler 			printf("WARNING: pid %d(%s) uid %d: CPUSH not done\n",
60353933Shibler 			       p->p_pid, p->p_comm, p->p_ucred->cr_uid);
60453933Shibler 	} else if ((f->f_ssw & (SSW4_RW|SSW4_TTMASK)) == SSW4_TTM16) {
60553933Shibler 		/*
60653933Shibler 		 * MOVE16 fault.
60753933Shibler 		 * Line-align the address and write out the push data to
60853933Shibler 		 * the indicated virtual address.
60953933Shibler 		 */
61053933Shibler #ifdef DEBUG
61153933Shibler 		if ((mmudebug & MDB_WBFOLLOW) || MDB_ISPID(p->p_pid))
61253933Shibler 			printf(" MOVE16 to VA %x(%x), data %x/%x/%x/%x\n",
61353933Shibler 			       f->f_fa, f->f_fa & ~0xF, f->f_pd0, f->f_pd1,
61453933Shibler 			       f->f_pd2, f->f_pd3);
61553933Shibler 		if (f->f_wb1s & SSW4_WBSV)
61653933Shibler 			panic("writeback: MOVE16 with WB1S valid");
61753933Shibler 		wbstats.move16s++;
61853933Shibler #endif
61953933Shibler 		if (KDFAULT(f->f_wb1s))
62053933Shibler 			bcopy((caddr_t)&f->f_pd0, (caddr_t)(f->f_fa & ~0xF), 16);
62153933Shibler 		else
62253933Shibler 			err = suline((caddr_t)(f->f_fa & ~0xF), (caddr_t)&f->f_pd0);
62353933Shibler 		if (err) {
62453933Shibler 			fa = f->f_fa & ~0xF;
62553933Shibler #ifdef DEBUG
62653933Shibler 			if (mmudebug & MDB_WBFAILED)
62753933Shibler 				printf(wberrstr, p->p_pid, p->p_comm,
62853933Shibler 				       "MOVE16", fp->f_pc, f->f_fa,
62953933Shibler 				       f->f_fa & ~0xF, f->f_pd0);
63053933Shibler #endif
63153933Shibler 		}
63253933Shibler 	} else if (f->f_wb1s & SSW4_WBSV) {
63353933Shibler 		/*
63453933Shibler 		 * Writeback #1.
63553933Shibler 		 * Position the "memory-aligned" data and write it out.
63653933Shibler 		 */
63753933Shibler 		register u_int wb1d = f->f_wb1d;
63853933Shibler 		register int off;
63953933Shibler 
64053933Shibler #ifdef DEBUG
64153933Shibler 		if ((mmudebug & MDB_WBFOLLOW) || MDB_ISPID(p->p_pid))
64253933Shibler 			dumpwb(1, f->f_wb1s, f->f_wb1a, f->f_wb1d);
64353933Shibler 		wbstats.wb1s++;
64453933Shibler 		wbstats.wbsize[(f->f_wb2s&SSW4_SZMASK)>>5]++;
64553933Shibler #endif
64653933Shibler 		off = (f->f_wb1a & 3) * 8;
64753933Shibler 		switch (f->f_wb1s & SSW4_SZMASK) {
64853933Shibler 		case SSW4_SZLW:
64953933Shibler 			if (off)
65053933Shibler 				wb1d = (wb1d >> (32 - off)) | (wb1d << off);
65153933Shibler 			if (KDFAULT(f->f_wb1s))
65253933Shibler 				*(long *)f->f_wb1a = wb1d;
65353933Shibler 			else
65453933Shibler 				err = suword((caddr_t)f->f_wb1a, wb1d);
65553933Shibler 			break;
65653933Shibler 		case SSW4_SZB:
65753933Shibler 			off = 24 - off;
65853933Shibler 			if (off)
65953933Shibler 				wb1d >>= off;
66053933Shibler 			if (KDFAULT(f->f_wb1s))
66153933Shibler 				*(char *)f->f_wb1a = wb1d;
66253933Shibler 			else
66353933Shibler 				err = subyte((caddr_t)f->f_wb1a, wb1d);
66453933Shibler 			break;
66553933Shibler 		case SSW4_SZW:
66653933Shibler 			off = (off + 16) % 32;
66753933Shibler 			if (off)
66853933Shibler 				wb1d = (wb1d >> (32 - off)) | (wb1d << off);
66953933Shibler 			if (KDFAULT(f->f_wb1s))
67053933Shibler 				*(short *)f->f_wb1a = wb1d;
67153933Shibler 			else
67253933Shibler 				err = susword((caddr_t)f->f_wb1a, wb1d);
67353933Shibler 			break;
67453933Shibler 		}
67553933Shibler 		if (err) {
67653933Shibler 			fa = f->f_wb1a;
67753933Shibler #ifdef DEBUG
67853933Shibler 			if (mmudebug & MDB_WBFAILED)
67953933Shibler 				printf(wberrstr, p->p_pid, p->p_comm,
68053933Shibler 				       "#1", fp->f_pc, f->f_fa,
68153933Shibler 				       f->f_wb1a, f->f_wb1d);
68253933Shibler #endif
68353933Shibler 		}
68453933Shibler 	}
68553933Shibler 	/*
68653933Shibler 	 * Deal with the "normal" writebacks.
68753933Shibler 	 *
68853933Shibler 	 * XXX writeback2 is known to reflect a LINE size writeback after
68953933Shibler 	 * a MOVE16 was already dealt with above.  Ignore it.
69053933Shibler 	 */
69153933Shibler 	if (err == 0 && (f->f_wb2s & SSW4_WBSV) &&
69253933Shibler 	    (f->f_wb2s & SSW4_SZMASK) != SSW4_SZLN) {
69353933Shibler #ifdef DEBUG
69453933Shibler 		if ((mmudebug & MDB_WBFOLLOW) || MDB_ISPID(p->p_pid))
69553933Shibler 			dumpwb(2, f->f_wb2s, f->f_wb2a, f->f_wb2d);
69653933Shibler 		wbstats.wb2s++;
69753933Shibler 		wbstats.wbsize[(f->f_wb2s&SSW4_SZMASK)>>5]++;
69853933Shibler #endif
69953933Shibler 		switch (f->f_wb2s & SSW4_SZMASK) {
70053933Shibler 		case SSW4_SZLW:
70153933Shibler 			if (KDFAULT(f->f_wb2s))
70253933Shibler 				*(long *)f->f_wb2a = f->f_wb2d;
70353933Shibler 			else
70453933Shibler 				err = suword((caddr_t)f->f_wb2a, f->f_wb2d);
70553933Shibler 			break;
70653933Shibler 		case SSW4_SZB:
70753933Shibler 			if (KDFAULT(f->f_wb2s))
70853933Shibler 				*(char *)f->f_wb2a = f->f_wb2d;
70953933Shibler 			else
71053933Shibler 				err = subyte((caddr_t)f->f_wb2a, f->f_wb2d);
71153933Shibler 			break;
71253933Shibler 		case SSW4_SZW:
71353933Shibler 			if (KDFAULT(f->f_wb2s))
71453933Shibler 				*(short *)f->f_wb2a = f->f_wb2d;
71553933Shibler 			else
71653933Shibler 				err = susword((caddr_t)f->f_wb2a, f->f_wb2d);
71753933Shibler 			break;
71853933Shibler 		}
71953933Shibler 		if (err) {
72053933Shibler 			fa = f->f_wb2a;
72153933Shibler #ifdef DEBUG
72253933Shibler 			if (mmudebug & MDB_WBFAILED) {
72353933Shibler 				printf(wberrstr, p->p_pid, p->p_comm,
72453933Shibler 				       "#2", fp->f_pc, f->f_fa,
72553933Shibler 				       f->f_wb2a, f->f_wb2d);
72653933Shibler 				dumpssw(f->f_ssw);
72753933Shibler 				dumpwb(2, f->f_wb2s, f->f_wb2a, f->f_wb2d);
72853933Shibler 			}
72953933Shibler #endif
73053933Shibler 		}
73153933Shibler 	}
73253933Shibler 	if (err == 0 && (f->f_wb3s & SSW4_WBSV)) {
73353933Shibler #ifdef DEBUG
73453933Shibler 		if ((mmudebug & MDB_WBFOLLOW) || MDB_ISPID(p->p_pid))
73553933Shibler 			dumpwb(3, f->f_wb3s, f->f_wb3a, f->f_wb3d);
73653933Shibler 		wbstats.wb3s++;
73753933Shibler 		wbstats.wbsize[(f->f_wb3s&SSW4_SZMASK)>>5]++;
73853933Shibler #endif
73953933Shibler 		switch (f->f_wb3s & SSW4_SZMASK) {
74053933Shibler 		case SSW4_SZLW:
74153933Shibler 			if (KDFAULT(f->f_wb3s))
74253933Shibler 				*(long *)f->f_wb3a = f->f_wb3d;
74353933Shibler 			else
74453933Shibler 				err = suword((caddr_t)f->f_wb3a, f->f_wb3d);
74553933Shibler 			break;
74653933Shibler 		case SSW4_SZB:
74753933Shibler 			if (KDFAULT(f->f_wb3s))
74853933Shibler 				*(char *)f->f_wb3a = f->f_wb3d;
74953933Shibler 			else
75053933Shibler 				err = subyte((caddr_t)f->f_wb3a, f->f_wb3d);
75153933Shibler 			break;
75253933Shibler 		case SSW4_SZW:
75353933Shibler 			if (KDFAULT(f->f_wb3s))
75453933Shibler 				*(short *)f->f_wb3a = f->f_wb3d;
75553933Shibler 			else
75653933Shibler 				err = susword((caddr_t)f->f_wb3a, f->f_wb3d);
75753933Shibler 			break;
75853933Shibler #ifdef DEBUG
75953933Shibler 		case SSW4_SZLN:
76053933Shibler 			panic("writeback: wb3s indicates LINE write");
76153933Shibler #endif
76253933Shibler 		}
76353933Shibler 		if (err) {
76453933Shibler 			fa = f->f_wb3a;
76553933Shibler #ifdef DEBUG
76653933Shibler 			if (mmudebug & MDB_WBFAILED)
76753933Shibler 				printf(wberrstr, p->p_pid, p->p_comm,
76853933Shibler 				       "#3", fp->f_pc, f->f_fa,
76953933Shibler 				       f->f_wb3a, f->f_wb3d);
77053933Shibler #endif
77153933Shibler 		}
77253933Shibler 	}
77353933Shibler 	p->p_addr->u_pcb.pcb_onfault = oonfault;
77453933Shibler 	/*
77553933Shibler 	 * Determine the cause of the failure if any translating to
77653933Shibler 	 * a signal.  If the corresponding VA is valid and RO it is
77753933Shibler 	 * a protection fault (SIGBUS) otherwise consider it an
77853933Shibler 	 * illegal reference (SIGSEGV).
77953933Shibler 	 */
78053933Shibler 	if (err) {
78153933Shibler 		if (vm_map_check_protection(&p->p_vmspace->vm_map,
78253933Shibler 					    trunc_page(fa), round_page(fa),
78353933Shibler 					    VM_PROT_READ) &&
78453933Shibler 		    !vm_map_check_protection(&p->p_vmspace->vm_map,
78553933Shibler 					     trunc_page(fa), round_page(fa),
78653933Shibler 					     VM_PROT_WRITE))
78753933Shibler 			err = SIGBUS;
78853933Shibler 		else
78953933Shibler 			err = SIGSEGV;
79053933Shibler 	}
79153933Shibler 	return(err);
79253933Shibler }
79353933Shibler 
79453933Shibler #ifdef DEBUG
79553933Shibler dumpssw(ssw)
79653933Shibler 	register u_short ssw;
79753933Shibler {
79853933Shibler 	printf(" SSW: %x: ", ssw);
79953933Shibler 	if (ssw & SSW4_CP)
80053933Shibler 		printf("CP,");
80153933Shibler 	if (ssw & SSW4_CU)
80253933Shibler 		printf("CU,");
80353933Shibler 	if (ssw & SSW4_CT)
80453933Shibler 		printf("CT,");
80553933Shibler 	if (ssw & SSW4_CM)
80653933Shibler 		printf("CM,");
80753933Shibler 	if (ssw & SSW4_MA)
80853933Shibler 		printf("MA,");
80953933Shibler 	if (ssw & SSW4_ATC)
81053933Shibler 		printf("ATC,");
81153933Shibler 	if (ssw & SSW4_LK)
81253933Shibler 		printf("LK,");
81353933Shibler 	if (ssw & SSW4_RW)
81453933Shibler 		printf("RW,");
81553933Shibler 	printf(" SZ=%s, TT=%s, TM=%s\n",
81653933Shibler 	       f7sz[(ssw & SSW4_SZMASK) >> 5],
81753933Shibler 	       f7tt[(ssw & SSW4_TTMASK) >> 3],
81853933Shibler 	       f7tm[ssw & SSW4_TMMASK]);
81953933Shibler }
82053933Shibler 
82153933Shibler dumpwb(num, s, a, d)
82253933Shibler 	int num;
82353933Shibler 	u_short s;
82453933Shibler 	u_int a, d;
82553933Shibler {
82653933Shibler 	register struct proc *p = curproc;
82753933Shibler 	vm_offset_t pa;
82853933Shibler 
82953933Shibler 	printf(" writeback #%d: VA %x, data %x, SZ=%s, TT=%s, TM=%s\n",
83053933Shibler 	       num, a, d, f7sz[(s & SSW4_SZMASK) >> 5],
83153933Shibler 	       f7tt[(s & SSW4_TTMASK) >> 3], f7tm[s & SSW4_TMMASK]);
83253933Shibler 	printf("               PA ");
83353933Shibler 	pa = pmap_extract(&p->p_vmspace->vm_pmap, (vm_offset_t)a);
83453933Shibler 	if (pa == 0)
83553933Shibler 		printf("<invalid address>");
83653933Shibler 	else
83753933Shibler 		printf("%x, current value %x", pa, fuword((caddr_t)a));
83853933Shibler 	printf("\n");
83953933Shibler }
84053933Shibler #endif
84153933Shibler #endif
84253933Shibler 
84341475Smckusick /*
84449531Skarels  * Proces a system call.
84541475Smckusick  */
84641475Smckusick syscall(code, frame)
84754801Storek 	u_int code;
84841475Smckusick 	struct frame frame;
84941475Smckusick {
85041475Smckusick 	register caddr_t params;
85141475Smckusick 	register struct sysent *callp;
85254801Storek 	register struct proc *p;
85350753Skarels 	int error, opc, numsys, s;
85454801Storek 	u_int argsize;
85544018Skarels 	struct args {
85644018Skarels 		int i[8];
85744018Skarels 	} args;
85844018Skarels 	int rval[2];
85954801Storek 	u_quad_t sticks;
86041475Smckusick #ifdef HPUXCOMPAT
86141475Smckusick 	extern struct sysent hpuxsysent[];
86241475Smckusick 	extern int hpuxnsysent, notimp();
86341475Smckusick #endif
86441475Smckusick 
86541475Smckusick 	cnt.v_syscall++;
86641475Smckusick 	if (!USERMODE(frame.f_sr))
86741475Smckusick 		panic("syscall");
86854801Storek 	p = curproc;
86954801Storek 	sticks = p->p_sticks;
87052380Smckusick 	p->p_md.md_regs = frame.f_regs;
87141475Smckusick 	opc = frame.f_pc - 2;
87241475Smckusick #ifdef HPUXCOMPAT
87357344Shibler 	if (p->p_md.md_flags & MDP_HPUX)
87454801Storek 		callp = hpuxsysent, numsys = hpuxnsysent;
87554801Storek 	else
87641475Smckusick #endif
87754801Storek 		callp = sysent, numsys = nsysent;
87849531Skarels 	params = (caddr_t)frame.f_regs[SP] + sizeof(int);
87954801Storek 	switch (code) {
88054801Storek 
88163469Smckusick 	case SYS_syscall:
88254801Storek 		/*
88354801Storek 		 * Code is first argument, followed by actual args.
88454801Storek 		 */
88542370Skarels 		code = fuword(params);
88649531Skarels 		params += sizeof(int);
88757344Shibler 		/*
88857344Shibler 		 * XXX sigreturn requires special stack manipulation
88957344Shibler 		 * that is only done if entered via the sigreturn
89057344Shibler 		 * trap.  Cannot allow it here so make sure we fail.
89157344Shibler 		 */
89257344Shibler 		if (code == SYS_sigreturn)
89357344Shibler 			code = numsys;
89454801Storek 		break;
89554801Storek 
89663469Smckusick 	case SYS___syscall:
89754801Storek 		/*
89863469Smckusick 		 * Like syscall, but code is a quad, so as to maintain
89954801Storek 		 * quad alignment for the rest of the arguments.
90054801Storek 		 */
90141475Smckusick #ifdef HPUXCOMPAT
90257344Shibler 		if (p->p_md.md_flags & MDP_HPUX)
90354801Storek 			break;
90441475Smckusick #endif
90554865Smckusick 		code = fuword(params + _QUAD_LOWWORD * sizeof(int));
90654865Smckusick 		params += sizeof(quad_t);
90754801Storek 		break;
90854801Storek 
90954865Smckusick 	default:
91054865Smckusick 		/* nothing to do by default */
91154865Smckusick 		break;
91254801Storek 	}
91354801Storek 	if (code < numsys)
91454801Storek 		callp += code;
91554801Storek 	else
91663469Smckusick 		callp += SYS_syscall;	/* => nosys */
91754801Storek 	argsize = callp->sy_narg * sizeof(int);
91854801Storek 	if (argsize && (error = copyin(params, (caddr_t)&args, argsize))) {
91941475Smckusick #ifdef KTRACE
92043641Skarels 		if (KTRPOINT(p, KTR_SYSCALL))
92144018Skarels 			ktrsyscall(p->p_tracep, code, callp->sy_narg, args.i);
92241475Smckusick #endif
92354801Storek 		goto bad;
92441475Smckusick 	}
92541475Smckusick #ifdef KTRACE
92643641Skarels 	if (KTRPOINT(p, KTR_SYSCALL))
92744018Skarels 		ktrsyscall(p->p_tracep, code, callp->sy_narg, args.i);
92841475Smckusick #endif
92943641Skarels 	rval[0] = 0;
93043641Skarels 	rval[1] = frame.f_regs[D1];
93141475Smckusick #ifdef HPUXCOMPAT
93242370Skarels 	/* debug kludge */
93342370Skarels 	if (callp->sy_call == notimp)
93448465Skarels 		error = notimp(p, args.i, rval, code, callp->sy_narg);
93542370Skarels 	else
93641475Smckusick #endif
93754801Storek 		error = (*callp->sy_call)(p, &args, rval);
93854801Storek 	switch (error) {
93942370Skarels 
94054801Storek 	case 0:
94141475Smckusick 		/*
94254801Storek 		 * Reinitialize proc pointer `p' as it may be different
94354801Storek 		 * if this is a child returning from fork syscall.
94441475Smckusick 		 */
94554801Storek 		p = curproc;
94654801Storek 		frame.f_regs[D0] = rval[0];
94754801Storek 		frame.f_regs[D1] = rval[1];
94854801Storek 		frame.f_sr &= ~PSL_C;
94954801Storek 		break;
95041475Smckusick 
95154801Storek 	case ERESTART:
95254801Storek 		frame.f_pc = opc;
95354801Storek 		break;
95454801Storek 
95554801Storek 	case EJUSTRETURN:
95654801Storek 		break;		/* nothing to do */
95754801Storek 
95854801Storek 	default:
95954801Storek 	bad:
96054801Storek #ifdef HPUXCOMPAT
96157344Shibler 		if (p->p_md.md_flags & MDP_HPUX)
96254801Storek 			error = bsdtohpuxerrno(error);
96341475Smckusick #endif
96454801Storek 		frame.f_regs[D0] = error;
96554801Storek 		frame.f_sr |= PSL_C;
96654801Storek 		break;
96741475Smckusick 	}
96854801Storek 
96954801Storek 	userret(p, &frame, sticks, (u_int)0, 0);
97041475Smckusick #ifdef KTRACE
97143641Skarels 	if (KTRPOINT(p, KTR_SYSRET))
97243641Skarels 		ktrsysret(p->p_tracep, code, error, rval[0]);
97341475Smckusick #endif
97441475Smckusick }
975