xref: /csrg-svn/sys/hp300/hp300/trap.c (revision 54574)
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*54574Storek  *	@(#)trap.c	7.21 (Berkeley) 06/30/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"
2448465Skarels #include "syslog.h"
2548465Skarels #include "user.h"
2648465Skarels #ifdef KTRACE
2748465Skarels #include "ktrace.h"
2848465Skarels #endif
2948465Skarels 
3049125Skarels #include "../include/psl.h"
3148465Skarels #include "../include/trap.h"
3245788Sbostic #include "../include/cpu.h"
3345788Sbostic #include "../include/reg.h"
3445788Sbostic #include "../include/mtpr.h"
3541475Smckusick 
3648465Skarels #include "vm/vm.h"
3745788Sbostic #include "vm/pmap.h"
3845751Smckusick 
3941475Smckusick #ifdef HPUXCOMPAT
4053933Shibler #include "hp/hpux/hpux.h"
4141475Smckusick #endif
4241475Smckusick 
4341475Smckusick struct	sysent	sysent[];
4441475Smckusick int	nsysent;
4541475Smckusick 
4641475Smckusick char	*trap_type[] = {
4741475Smckusick 	"Bus error",
4841475Smckusick 	"Address error",
4941475Smckusick 	"Illegal instruction",
5041475Smckusick 	"Zero divide",
5141475Smckusick 	"CHK instruction",
5241475Smckusick 	"TRAPV instruction",
5341475Smckusick 	"Privilege violation",
5441475Smckusick 	"Trace trap",
5541475Smckusick 	"MMU fault",
5641475Smckusick 	"SSIR trap",
5741475Smckusick 	"Format error",
5841475Smckusick 	"68881 exception",
5941475Smckusick 	"Coprocessor violation",
6041475Smckusick 	"Async system trap"
6141475Smckusick };
6241475Smckusick #define	TRAP_TYPES	(sizeof trap_type / sizeof trap_type[0])
6341475Smckusick 
6449317Shibler /*
6549317Shibler  * Size of various exception stack frames (minus the standard 8 bytes)
6649317Shibler  */
6749317Shibler short	exframesize[] = {
6849317Shibler 	FMT0SIZE,	/* type 0 - normal (68020/030/040) */
6949317Shibler 	FMT1SIZE,	/* type 1 - throwaway (68020/030/040) */
7049317Shibler 	FMT2SIZE,	/* type 2 - normal 6-word (68020/030/040) */
7153933Shibler 	FMT3SIZE,	/* type 3 - FP post-instruction (68040) */
7249317Shibler 	-1, -1, -1,	/* type 4-6 - undefined */
7353933Shibler 	FMT7SIZE,	/* type 7 - access error (68040) */
7449317Shibler 	58,		/* type 8 - bus fault (68010) */
7549317Shibler 	FMT9SIZE,	/* type 9 - coprocessor mid-instruction (68020/030) */
7649317Shibler 	FMTASIZE,	/* type A - short bus fault (68020/030) */
7749317Shibler 	FMTBSIZE,	/* type B - long bus fault (68020/030) */
7849317Shibler 	-1, -1, -1, -1	/* type C-F - undefined */
7949317Shibler };
8049317Shibler 
8153933Shibler #if defined(HP380)
8253933Shibler #define KDFAULT(c)	(mmutype == MMU_68040 ? \
8353933Shibler 			    ((c) & SSW4_TMMASK) == SSW4_TMKD : \
8453933Shibler 			    ((c) & (SSW_DF|FC_SUPERD)) == (SSW_DF|FC_SUPERD))
8553933Shibler #define WRFAULT(c) 	(mmutype == MMU_68040 ? \
8653933Shibler 			    ((c) & SSW4_RW) == 0 : \
8753933Shibler 			    ((c) & (SSW_DF|SSW_RW)) == SSW_DF)
8853933Shibler #else
8953933Shibler #define KDFAULT(c)	(((c) & (SSW_DF|SSW_FCMASK)) == (SSW_DF|FC_SUPERD))
9053933Shibler #define WRFAULT(c)	(((c) & (SSW_DF|SSW_RW)) == SSW_DF)
9153933Shibler #endif
9253933Shibler 
9341475Smckusick #ifdef DEBUG
9441475Smckusick int mmudebug = 0;
9553933Shibler int mmupid = -1;
9653933Shibler #define MDB_FOLLOW	1
9753933Shibler #define MDB_WBFOLLOW	2
9853933Shibler #define MDB_WBFAILED	4
9953933Shibler #define MDB_ISPID(p)	(p) == mmupid
10041475Smckusick #endif
10141475Smckusick 
10241475Smckusick /*
10349531Skarels  * Trap is called from locore to handle most types of processor traps,
10449531Skarels  * including events such as simulated software interrupts/AST's.
10549531Skarels  * System calls are broken out for efficiency.
10641475Smckusick  */
10741475Smckusick /*ARGSUSED*/
10841475Smckusick trap(type, code, v, frame)
10941475Smckusick 	int type;
11041475Smckusick 	unsigned code;
11141475Smckusick 	register unsigned v;
11241475Smckusick 	struct frame frame;
11341475Smckusick {
11441475Smckusick 	register int i;
11541475Smckusick 	unsigned ucode = 0;
11648465Skarels 	register struct proc *p = curproc;
11741475Smckusick 	struct timeval syst;
11841475Smckusick 	unsigned ncode;
11950753Skarels 	int s;
12053933Shibler #if defined(HP380)
12153933Shibler 	int beenhere = 0;
12253933Shibler #endif
123*54574Storek 	extern char fswintr[];
12441475Smckusick 
12541475Smckusick 	cnt.v_trap++;
12648465Skarels 	syst = p->p_stime;
12741475Smckusick 	if (USERMODE(frame.f_sr)) {
12849531Skarels 		type |= T_USER;
12952380Smckusick 		p->p_md.md_regs = frame.f_regs;
13041475Smckusick 	}
13141475Smckusick 	switch (type) {
13241475Smckusick 
13341475Smckusick 	default:
13441475Smckusick dopanic:
13541475Smckusick 		printf("trap type %d, code = %x, v = %x\n", type, code, v);
13641475Smckusick 		regdump(frame.f_regs, 128);
13749531Skarels 		type &= ~T_USER;
13841475Smckusick 		if ((unsigned)type < TRAP_TYPES)
13941475Smckusick 			panic(trap_type[type]);
14041475Smckusick 		panic("trap");
14141475Smckusick 
14241475Smckusick 	case T_BUSERR:		/* kernel bus error */
14349125Skarels 		if (!p->p_addr->u_pcb.pcb_onfault)
14441475Smckusick 			goto dopanic;
14541475Smckusick 		/*
14641475Smckusick 		 * If we have arranged to catch this fault in any of the
14741475Smckusick 		 * copy to/from user space routines, set PC to return to
14841475Smckusick 		 * indicated location and set flag informing buserror code
14941475Smckusick 		 * that it may need to clean up stack frame.
15041475Smckusick 		 */
15141475Smckusick copyfault:
15249317Shibler 		frame.f_stackadj = exframesize[frame.f_format];
15349317Shibler 		frame.f_format = frame.f_vector = 0;
15449125Skarels 		frame.f_pc = (int) p->p_addr->u_pcb.pcb_onfault;
15541475Smckusick 		return;
15641475Smckusick 
15749531Skarels 	case T_BUSERR|T_USER:	/* bus error */
15849531Skarels 	case T_ADDRERR|T_USER:	/* address error */
15953933Shibler 		ucode = v;
16041475Smckusick 		i = SIGBUS;
16141475Smckusick 		break;
16241475Smckusick 
16341475Smckusick #ifdef FPCOPROC
16441475Smckusick 	case T_COPERR:		/* kernel coprocessor violation */
16541475Smckusick #endif
16653933Shibler 	case T_FMTERR|T_USER:	/* do all RTE errors come in as T_USER? */
16753933Shibler 	case T_FMTERR:		/* ...just in case... */
16841475Smckusick 	/*
16941475Smckusick 	 * The user has most likely trashed the RTE or FP state info
17041475Smckusick 	 * in the stack frame of a signal handler.
17141475Smckusick 	 */
17249531Skarels 		type |= T_USER;
17348465Skarels 		printf("pid %d: kernel %s exception\n", p->p_pid,
17441475Smckusick 		       type==T_COPERR ? "coprocessor" : "format");
17548465Skarels 		p->p_sigacts->ps_sigact[SIGILL] = SIG_DFL;
17641475Smckusick 		i = sigmask(SIGILL);
17741475Smckusick 		p->p_sigignore &= ~i;
17841475Smckusick 		p->p_sigcatch &= ~i;
17941475Smckusick 		p->p_sigmask &= ~i;
18042370Skarels 		i = SIGILL;
18141475Smckusick 		ucode = frame.f_format;	/* XXX was ILL_RESAD_FAULT */
18242370Skarels 		break;
18341475Smckusick 
18441475Smckusick #ifdef FPCOPROC
18549531Skarels 	case T_COPERR|T_USER:	/* user coprocessor violation */
18641475Smckusick 	/* What is a proper response here? */
18741475Smckusick 		ucode = 0;
18841475Smckusick 		i = SIGFPE;
18941475Smckusick 		break;
19041475Smckusick 
19149531Skarels 	case T_FPERR|T_USER:	/* 68881 exceptions */
19241475Smckusick 	/*
19341475Smckusick 	 * We pass along the 68881 status register which locore stashed
19441475Smckusick 	 * in code for us.  Note that there is a possibility that the
19541475Smckusick 	 * bit pattern of this register will conflict with one of the
19641475Smckusick 	 * FPE_* codes defined in signal.h.  Fortunately for us, the
19741475Smckusick 	 * only such codes we use are all in the range 1-7 and the low
19841475Smckusick 	 * 3 bits of the status register are defined as 0 so there is
19941475Smckusick 	 * no clash.
20041475Smckusick 	 */
20141475Smckusick 		ucode = code;
20241475Smckusick 		i = SIGFPE;
20341475Smckusick 		break;
20441475Smckusick #endif
20541475Smckusick 
20653933Shibler #if defined(HP380)
20753933Shibler 	case T_FPEMULI|T_USER:	/* unimplemented FP instuction */
20853933Shibler 	case T_FPEMULD|T_USER:	/* unimplemented FP data type */
20953933Shibler 		/* XXX need to FSAVE */
21053933Shibler 		printf("pid %d(%s): unimplemented FP %s at %x (EA %x)\n",
21153933Shibler 		       p->p_pid, p->p_comm,
21253933Shibler 		       frame.f_format == 2 ? "instruction" : "data type",
21353933Shibler 		       frame.f_pc, frame.f_fmt2.f_iaddr);
21453933Shibler 		/* XXX need to FRESTORE */
21553933Shibler 		i = SIGFPE;
21653933Shibler 		break;
21753933Shibler #endif
21853933Shibler 
21949531Skarels 	case T_ILLINST|T_USER:	/* illegal instruction fault */
22041475Smckusick #ifdef HPUXCOMPAT
22148465Skarels 		if (p->p_flag & SHPUX) {
22241475Smckusick 			ucode = HPUX_ILL_ILLINST_TRAP;
22341475Smckusick 			i = SIGILL;
22441475Smckusick 			break;
22541475Smckusick 		}
22641475Smckusick 		/* fall through */
22741475Smckusick #endif
22849531Skarels 	case T_PRIVINST|T_USER:	/* privileged instruction fault */
22941475Smckusick #ifdef HPUXCOMPAT
23048465Skarels 		if (p->p_flag & SHPUX)
23141475Smckusick 			ucode = HPUX_ILL_PRIV_TRAP;
23241475Smckusick 		else
23341475Smckusick #endif
23441475Smckusick 		ucode = frame.f_format;	/* XXX was ILL_PRIVIN_FAULT */
23541475Smckusick 		i = SIGILL;
23641475Smckusick 		break;
23741475Smckusick 
23849531Skarels 	case T_ZERODIV|T_USER:	/* Divide by zero */
23941475Smckusick #ifdef HPUXCOMPAT
24048465Skarels 		if (p->p_flag & SHPUX)
24141475Smckusick 			ucode = HPUX_FPE_INTDIV_TRAP;
24241475Smckusick 		else
24341475Smckusick #endif
24441475Smckusick 		ucode = frame.f_format;	/* XXX was FPE_INTDIV_TRAP */
24541475Smckusick 		i = SIGFPE;
24641475Smckusick 		break;
24741475Smckusick 
24849531Skarels 	case T_CHKINST|T_USER:	/* CHK instruction trap */
24941475Smckusick #ifdef HPUXCOMPAT
25048465Skarels 		if (p->p_flag & SHPUX) {
25141475Smckusick 			/* handled differently under hp-ux */
25241475Smckusick 			i = SIGILL;
25341475Smckusick 			ucode = HPUX_ILL_CHK_TRAP;
25441475Smckusick 			break;
25541475Smckusick 		}
25641475Smckusick #endif
25741475Smckusick 		ucode = frame.f_format;	/* XXX was FPE_SUBRNG_TRAP */
25841475Smckusick 		i = SIGFPE;
25941475Smckusick 		break;
26041475Smckusick 
26149531Skarels 	case T_TRAPVINST|T_USER:	/* TRAPV instruction trap */
26241475Smckusick #ifdef HPUXCOMPAT
26348465Skarels 		if (p->p_flag & SHPUX) {
26441475Smckusick 			/* handled differently under hp-ux */
26541475Smckusick 			i = SIGILL;
26641475Smckusick 			ucode = HPUX_ILL_TRAPV_TRAP;
26741475Smckusick 			break;
26841475Smckusick 		}
26941475Smckusick #endif
27041475Smckusick 		ucode = frame.f_format;	/* XXX was FPE_INTOVF_TRAP */
27141475Smckusick 		i = SIGFPE;
27241475Smckusick 		break;
27341475Smckusick 
27441475Smckusick 	/*
27541475Smckusick 	 * XXX: Trace traps are a nightmare.
27641475Smckusick 	 *
27741475Smckusick 	 *	HP-UX uses trap #1 for breakpoints,
27841475Smckusick 	 *	HPBSD uses trap #2,
27941475Smckusick 	 *	SUN 3.x uses trap #15,
28048465Skarels 	 *	KGDB uses trap #15 (for kernel breakpoints; handled elsewhere).
28141475Smckusick 	 *
28241475Smckusick 	 * HPBSD and HP-UX traps both get mapped by locore.s into T_TRACE.
28341475Smckusick 	 * SUN 3.x traps get passed through as T_TRAP15 and are not really
28448465Skarels 	 * supported yet.
28541475Smckusick 	 */
28641475Smckusick 	case T_TRACE:		/* kernel trace trap */
28748465Skarels 	case T_TRAP15:		/* SUN trace trap */
28841475Smckusick 		frame.f_sr &= ~PSL_T;
28941475Smckusick 		i = SIGTRAP;
29041475Smckusick 		break;
29141475Smckusick 
29249531Skarels 	case T_TRACE|T_USER:	/* user trace trap */
29349531Skarels 	case T_TRAP15|T_USER:	/* SUN user trace trap */
29441475Smckusick 		frame.f_sr &= ~PSL_T;
29541475Smckusick 		i = SIGTRAP;
29641475Smckusick 		break;
29741475Smckusick 
29843413Shibler 	case T_ASTFLT:		/* system async trap, cannot happen */
29941475Smckusick 		goto dopanic;
30041475Smckusick 
30149531Skarels 	case T_ASTFLT|T_USER:	/* user async trap */
30249125Skarels 		astpending = 0;
30341475Smckusick 		/*
30441475Smckusick 		 * We check for software interrupts first.  This is because
30541475Smckusick 		 * they are at a higher level than ASTs, and on a VAX would
30641475Smckusick 		 * interrupt the AST.  We assume that if we are processing
30741475Smckusick 		 * an AST that we must be at IPL0 so we don't bother to
30841475Smckusick 		 * check.  Note that we ensure that we are at least at SIR
30941475Smckusick 		 * IPL while processing the SIR.
31041475Smckusick 		 */
31141475Smckusick 		spl1();
31241475Smckusick 		/* fall into... */
31341475Smckusick 
31441475Smckusick 	case T_SSIR:		/* software interrupt */
31549531Skarels 	case T_SSIR|T_USER:
31641475Smckusick 		if (ssir & SIR_NET) {
31741475Smckusick 			siroff(SIR_NET);
31841475Smckusick 			cnt.v_soft++;
31941475Smckusick 			netintr();
32041475Smckusick 		}
32141475Smckusick 		if (ssir & SIR_CLOCK) {
32241475Smckusick 			siroff(SIR_CLOCK);
32341475Smckusick 			cnt.v_soft++;
32441475Smckusick 			softclock((caddr_t)frame.f_pc, (int)frame.f_sr);
32541475Smckusick 		}
32641475Smckusick 		/*
32741475Smckusick 		 * If this was not an AST trap, we are all done.
32841475Smckusick 		 */
32950753Skarels 		if (type != (T_ASTFLT|T_USER)) {
33041475Smckusick 			cnt.v_trap--;
33141475Smckusick 			return;
33241475Smckusick 		}
33341475Smckusick 		spl0();
33441475Smckusick #ifndef PROFTIMER
33548465Skarels 		if ((p->p_flag&SOWEUPC) && p->p_stats->p_prof.pr_scale) {
33648465Skarels 			addupc(frame.f_pc, &p->p_stats->p_prof, 1);
33748465Skarels 			p->p_flag &= ~SOWEUPC;
33841475Smckusick 		}
33941475Smckusick #endif
34041475Smckusick 		goto out;
34141475Smckusick 
34241475Smckusick 	case T_MMUFLT:		/* kernel mode page fault */
343*54574Storek 		/*
344*54574Storek 		 * If we were doing profiling ticks or other user mode
345*54574Storek 		 * stuff from interrupt code, Just Say No.
346*54574Storek 		 */
347*54574Storek 		if (p->p_addr->u_pcb.pcb_onfault == fswintr)
348*54574Storek 			goto copyfault;
34941475Smckusick 		/* fall into ... */
35041475Smckusick 
35149531Skarels 	case T_MMUFLT|T_USER:	/* page fault */
35245751Smckusick 	    {
35345751Smckusick 		register vm_offset_t va;
35448465Skarels 		register struct vmspace *vm = p->p_vmspace;
35545751Smckusick 		register vm_map_t map;
35645751Smckusick 		int rv;
35745751Smckusick 		vm_prot_t ftype;
35845751Smckusick 		extern vm_map_t kernel_map;
35945751Smckusick 
36053933Shibler #ifdef DEBUG
36153933Shibler 		if ((mmudebug & MDB_WBFOLLOW) || MDB_ISPID(p->p_pid))
36253933Shibler 		printf("trap: T_MMUFLT pid=%d, code=%x, v=%x, pc=%x, sr=%x\n",
36353933Shibler 		       p->p_pid, code, v, frame.f_pc, frame.f_sr);
36453933Shibler #endif
36541475Smckusick 		/*
36645751Smckusick 		 * It is only a kernel address space fault iff:
36749531Skarels 		 * 	1. (type & T_USER) == 0  and
36845751Smckusick 		 * 	2. pcb_onfault not set or
36945751Smckusick 		 *	3. pcb_onfault set but supervisor space data fault
37045751Smckusick 		 * The last can occur during an exec() copyin where the
37145751Smckusick 		 * argument space is lazy-allocated.
37241475Smckusick 		 */
37345751Smckusick 		if (type == T_MMUFLT &&
37453933Shibler 		    (!p->p_addr->u_pcb.pcb_onfault || KDFAULT(code)))
37545751Smckusick 			map = kernel_map;
37645751Smckusick 		else
37748465Skarels 			map = &vm->vm_map;
37853933Shibler 		if (WRFAULT(code))
37945751Smckusick 			ftype = VM_PROT_READ | VM_PROT_WRITE;
38045751Smckusick 		else
38145751Smckusick 			ftype = VM_PROT_READ;
38245751Smckusick 		va = trunc_page((vm_offset_t)v);
38341475Smckusick #ifdef DEBUG
38445751Smckusick 		if (map == kernel_map && va == 0) {
38545751Smckusick 			printf("trap: bad kernel access at %x\n", v);
38641475Smckusick 			goto dopanic;
38741475Smckusick 		}
38841475Smckusick #endif
38949317Shibler 		rv = vm_fault(map, va, ftype, FALSE);
39053933Shibler #ifdef DEBUG
39153933Shibler 		if (rv && MDB_ISPID(p->p_pid))
39253933Shibler 			printf("vm_fault(%x, %x, %x, 0) -> %x\n",
39353933Shibler 			       map, va, ftype, rv);
39453933Shibler #endif
39541475Smckusick 		/*
39649317Shibler 		 * If this was a stack access we keep track of the maximum
39749317Shibler 		 * accessed stack size.  Also, if vm_fault gets a protection
39849317Shibler 		 * failure it is due to accessing the stack region outside
39949317Shibler 		 * the current limit and we need to reflect that as an access
40049317Shibler 		 * error.
40141475Smckusick 		 */
40248465Skarels 		if ((caddr_t)va >= vm->vm_maxsaddr && map != kernel_map) {
40349317Shibler 			if (rv == KERN_SUCCESS) {
40449317Shibler 				unsigned nss;
40549317Shibler 
40649317Shibler 				nss = clrnd(btoc(USRSTACK-(unsigned)va));
40749317Shibler 				if (nss > vm->vm_ssize)
40849317Shibler 					vm->vm_ssize = nss;
40949317Shibler 			} else if (rv == KERN_PROTECTION_FAILURE)
41049317Shibler 				rv = KERN_INVALID_ADDRESS;
41141475Smckusick 		}
41245751Smckusick 		if (rv == KERN_SUCCESS) {
41353933Shibler 			if (type == T_MMUFLT) {
41453933Shibler #if defined(HP380)
41553933Shibler 				if (mmutype == MMU_68040)
41653933Shibler 					(void) writeback(&frame, 1);
41753933Shibler #endif
41841475Smckusick 				return;
41953933Shibler 			}
42041475Smckusick 			goto out;
42141475Smckusick 		}
42245751Smckusick 		if (type == T_MMUFLT) {
42349125Skarels 			if (p->p_addr->u_pcb.pcb_onfault)
42445751Smckusick 				goto copyfault;
42545751Smckusick 			printf("vm_fault(%x, %x, %x, 0) -> %x\n",
42645751Smckusick 			       map, va, ftype, rv);
42745751Smckusick 			printf("  type %x, code [mmu,,ssw]: %x\n",
42845751Smckusick 			       type, code);
42945751Smckusick 			goto dopanic;
43045751Smckusick 		}
43148465Skarels 		ucode = v;
43245751Smckusick 		i = (rv == KERN_PROTECTION_FAILURE) ? SIGBUS : SIGSEGV;
43345751Smckusick 		break;
43445751Smckusick 	    }
43541475Smckusick 	}
43648465Skarels 	trapsignal(p, i, ucode);
43749531Skarels 	if ((type & T_USER) == 0)
43841475Smckusick 		return;
43941475Smckusick out:
44048465Skarels 	while (i = CURSIG(p))
44142370Skarels 		psig(i);
44241475Smckusick 	p->p_pri = p->p_usrpri;
44348465Skarels 	if (want_resched) {
44441475Smckusick 		/*
44548465Skarels 		 * Since we are curproc, clock will normally just change
44641475Smckusick 		 * our priority without moving us from one queue to another
44741475Smckusick 		 * (since the running process is not on a queue.)
44841475Smckusick 		 * If that happened after we setrq ourselves but before we
44941475Smckusick 		 * swtch()'ed, we might not be on the queue indicated by
45041475Smckusick 		 * our priority.
45141475Smckusick 		 */
45250753Skarels 		s = splclock();
45341475Smckusick 		setrq(p);
45448465Skarels 		p->p_stats->p_ru.ru_nivcsw++;
45541475Smckusick 		swtch();
45650753Skarels 		splx(s);
45748465Skarels 		while (i = CURSIG(p))
45842370Skarels 			psig(i);
45941475Smckusick 	}
46048465Skarels 	if (p->p_stats->p_prof.pr_scale) {
46141475Smckusick 		int ticks;
46248465Skarels 		struct timeval *tv = &p->p_stime;
46341475Smckusick 
46441475Smckusick 		ticks = ((tv->tv_sec - syst.tv_sec) * 1000 +
46541475Smckusick 			(tv->tv_usec - syst.tv_usec) / 1000) / (tick / 1000);
46641475Smckusick 		if (ticks) {
46741475Smckusick #ifdef PROFTIMER
46841475Smckusick 			extern int profscale;
46948465Skarels 			addupc(frame.f_pc, &p->p_stats->p_prof,
47048465Skarels 			    ticks * profscale);
47141475Smckusick #else
47248465Skarels 			addupc(frame.f_pc, &p->p_stats->p_prof, ticks);
47341475Smckusick #endif
47441475Smckusick 		}
47541475Smckusick 	}
47653933Shibler #if defined(HP380)
47753933Shibler 	/*
47853933Shibler 	 * Deal with user mode writebacks.
47953933Shibler 	 * If any writeback fails, go back and attempt signal delivery.
48053933Shibler 	 * unless we have already been here and attempted the writeback
48153933Shibler 	 * (e.g. bad address with user ignoring SIGSEGV).  In that case
48253933Shibler 	 * we just return to the user without sucessfully completing
48353933Shibler 	 * the writebacks.  Maybe we should just drop the sucker?
48453933Shibler 	 */
48553933Shibler 	if (mmutype == MMU_68040 && frame.f_format == FMT7) {
48653933Shibler 		if (beenhere) {
48753933Shibler #ifdef DEBUG
48853933Shibler 			if (mmudebug & MDB_WBFAILED)
48953933Shibler 			printf("pid %d(%s): writeback aborted, pc=%x, fa=%x\n",
49053933Shibler 			       p->p_pid, p->p_comm, frame.f_pc, v);
49153933Shibler #endif
49253933Shibler 			;
49353933Shibler 		} else if (i = writeback(&frame, 1)) {
49453933Shibler 			beenhere++;
49553933Shibler 			ucode = v;
49653933Shibler 			syst = p->p_stime;
49753933Shibler 			trapsignal(p, i, ucode);
49853933Shibler 			goto out;
49953933Shibler 		}
50053933Shibler 	}
50153933Shibler #endif
50241475Smckusick 	curpri = p->p_pri;
50341475Smckusick }
50441475Smckusick 
50553933Shibler #if defined(HP380)
50653933Shibler #ifdef DEBUG
50753933Shibler struct writebackstats {
50853933Shibler 	int calls;
50953933Shibler 	int cpushes;
51053933Shibler 	int move16s;
51153933Shibler 	int wb1s, wb2s, wb3s;
51253933Shibler 	int wbsize[4];
51353933Shibler } wbstats;
51453933Shibler 
51553933Shibler char *f7sz[] = { "longword", "byte", "word", "line" };
51653933Shibler char *f7tt[] = { "normal", "MOVE16", "AFC", "ACK" };
51753933Shibler char *f7tm[] = { "d-push", "u-data", "u-code", "M-data",
51853933Shibler 		 "M-code", "k-data", "k-code", "RES" };
51953933Shibler char wberrstr[] =
52053933Shibler     "WARNING: pid %d(%s) writeback [%s] failed, pc=%x fa=%x wba=%x wbd=%x\n";
52153933Shibler #endif
52253933Shibler 
52353933Shibler writeback(fp, docachepush)
52453933Shibler 	struct frame *fp;
52553933Shibler 	int docachepush;
52653933Shibler {
52753933Shibler 	register struct fmt7 *f = &fp->f_fmt7;
52853933Shibler 	register struct proc *p = curproc;
52953933Shibler 	int err = 0;
53053933Shibler 	u_int fa;
53153933Shibler 	caddr_t oonfault = p->p_addr->u_pcb.pcb_onfault;
53253933Shibler 
53353933Shibler #ifdef DEBUG
53453933Shibler 	if ((mmudebug & MDB_WBFOLLOW) || MDB_ISPID(p->p_pid)) {
53553933Shibler 		printf(" pid=%d, fa=%x,", p->p_pid, f->f_fa);
53653933Shibler 		dumpssw(f->f_ssw);
53753933Shibler 	}
53853933Shibler 	wbstats.calls++;
53953933Shibler #endif
54053933Shibler 	/*
54153933Shibler 	 * Deal with special cases first.
54253933Shibler 	 */
54353933Shibler 	if ((f->f_ssw & SSW4_TMMASK) == SSW4_TMDCP) {
54453933Shibler 		/*
54553933Shibler 		 * Dcache push fault.
54653933Shibler 		 * Line-align the address and write out the push data to
54753933Shibler 		 * the indicated physical address.
54853933Shibler 		 */
54953933Shibler #ifdef DEBUG
55053933Shibler 		if ((mmudebug & MDB_WBFOLLOW) || MDB_ISPID(p->p_pid)) {
55153933Shibler 			printf(" pushing %s to PA %x, data %x",
55253933Shibler 			       f7sz[(f->f_ssw & SSW4_SZMASK) >> 5],
55353933Shibler 			       f->f_fa, f->f_pd0);
55453933Shibler 			if ((f->f_ssw & SSW4_SZMASK) == SSW4_SZLN)
55553933Shibler 				printf("/%x/%x/%x",
55653933Shibler 				       f->f_pd1, f->f_pd2, f->f_pd3);
55753933Shibler 			printf("\n");
55853933Shibler 		}
55953933Shibler 		if (f->f_wb1s & SSW4_WBSV)
56053933Shibler 			panic("writeback: cache push with WB1S valid");
56153933Shibler 		wbstats.cpushes++;
56253933Shibler #endif
56353933Shibler 		/*
56453933Shibler 		 * XXX there are security problems if we attempt to do a
56553933Shibler 		 * cache push after a signal handler has been called.
56653933Shibler 		 */
56753933Shibler 		if (docachepush) {
56853933Shibler 			pmap_enter(kernel_pmap, (vm_offset_t)vmmap,
56953933Shibler 				   trunc_page(f->f_fa), VM_PROT_WRITE, TRUE);
57053933Shibler 			fa = (u_int)&vmmap[(f->f_fa & PGOFSET) & ~0xF];
57153933Shibler 			bcopy((caddr_t)&f->f_pd0, (caddr_t)fa, 16);
57253933Shibler 			DCFL(pmap_extract(kernel_pmap, (vm_offset_t)fa));
57353933Shibler 			pmap_remove(kernel_pmap, (vm_offset_t)vmmap,
57453933Shibler 				    (vm_offset_t)&vmmap[NBPG]);
57553933Shibler 		} else
57653933Shibler 			printf("WARNING: pid %d(%s) uid %d: CPUSH not done\n",
57753933Shibler 			       p->p_pid, p->p_comm, p->p_ucred->cr_uid);
57853933Shibler 	} else if ((f->f_ssw & (SSW4_RW|SSW4_TTMASK)) == SSW4_TTM16) {
57953933Shibler 		/*
58053933Shibler 		 * MOVE16 fault.
58153933Shibler 		 * Line-align the address and write out the push data to
58253933Shibler 		 * the indicated virtual address.
58353933Shibler 		 */
58453933Shibler #ifdef DEBUG
58553933Shibler 		if ((mmudebug & MDB_WBFOLLOW) || MDB_ISPID(p->p_pid))
58653933Shibler 			printf(" MOVE16 to VA %x(%x), data %x/%x/%x/%x\n",
58753933Shibler 			       f->f_fa, f->f_fa & ~0xF, f->f_pd0, f->f_pd1,
58853933Shibler 			       f->f_pd2, f->f_pd3);
58953933Shibler 		if (f->f_wb1s & SSW4_WBSV)
59053933Shibler 			panic("writeback: MOVE16 with WB1S valid");
59153933Shibler 		wbstats.move16s++;
59253933Shibler #endif
59353933Shibler 		if (KDFAULT(f->f_wb1s))
59453933Shibler 			bcopy((caddr_t)&f->f_pd0, (caddr_t)(f->f_fa & ~0xF), 16);
59553933Shibler 		else
59653933Shibler 			err = suline((caddr_t)(f->f_fa & ~0xF), (caddr_t)&f->f_pd0);
59753933Shibler 		if (err) {
59853933Shibler 			fa = f->f_fa & ~0xF;
59953933Shibler #ifdef DEBUG
60053933Shibler 			if (mmudebug & MDB_WBFAILED)
60153933Shibler 				printf(wberrstr, p->p_pid, p->p_comm,
60253933Shibler 				       "MOVE16", fp->f_pc, f->f_fa,
60353933Shibler 				       f->f_fa & ~0xF, f->f_pd0);
60453933Shibler #endif
60553933Shibler 		}
60653933Shibler 	} else if (f->f_wb1s & SSW4_WBSV) {
60753933Shibler 		/*
60853933Shibler 		 * Writeback #1.
60953933Shibler 		 * Position the "memory-aligned" data and write it out.
61053933Shibler 		 */
61153933Shibler 		register u_int wb1d = f->f_wb1d;
61253933Shibler 		register int off;
61353933Shibler 
61453933Shibler #ifdef DEBUG
61553933Shibler 		if ((mmudebug & MDB_WBFOLLOW) || MDB_ISPID(p->p_pid))
61653933Shibler 			dumpwb(1, f->f_wb1s, f->f_wb1a, f->f_wb1d);
61753933Shibler 		wbstats.wb1s++;
61853933Shibler 		wbstats.wbsize[(f->f_wb2s&SSW4_SZMASK)>>5]++;
61953933Shibler #endif
62053933Shibler 		off = (f->f_wb1a & 3) * 8;
62153933Shibler 		switch (f->f_wb1s & SSW4_SZMASK) {
62253933Shibler 		case SSW4_SZLW:
62353933Shibler 			if (off)
62453933Shibler 				wb1d = (wb1d >> (32 - off)) | (wb1d << off);
62553933Shibler 			if (KDFAULT(f->f_wb1s))
62653933Shibler 				*(long *)f->f_wb1a = wb1d;
62753933Shibler 			else
62853933Shibler 				err = suword((caddr_t)f->f_wb1a, wb1d);
62953933Shibler 			break;
63053933Shibler 		case SSW4_SZB:
63153933Shibler 			off = 24 - off;
63253933Shibler 			if (off)
63353933Shibler 				wb1d >>= off;
63453933Shibler 			if (KDFAULT(f->f_wb1s))
63553933Shibler 				*(char *)f->f_wb1a = wb1d;
63653933Shibler 			else
63753933Shibler 				err = subyte((caddr_t)f->f_wb1a, wb1d);
63853933Shibler 			break;
63953933Shibler 		case SSW4_SZW:
64053933Shibler 			off = (off + 16) % 32;
64153933Shibler 			if (off)
64253933Shibler 				wb1d = (wb1d >> (32 - off)) | (wb1d << off);
64353933Shibler 			if (KDFAULT(f->f_wb1s))
64453933Shibler 				*(short *)f->f_wb1a = wb1d;
64553933Shibler 			else
64653933Shibler 				err = susword((caddr_t)f->f_wb1a, wb1d);
64753933Shibler 			break;
64853933Shibler 		}
64953933Shibler 		if (err) {
65053933Shibler 			fa = f->f_wb1a;
65153933Shibler #ifdef DEBUG
65253933Shibler 			if (mmudebug & MDB_WBFAILED)
65353933Shibler 				printf(wberrstr, p->p_pid, p->p_comm,
65453933Shibler 				       "#1", fp->f_pc, f->f_fa,
65553933Shibler 				       f->f_wb1a, f->f_wb1d);
65653933Shibler #endif
65753933Shibler 		}
65853933Shibler 	}
65953933Shibler 	/*
66053933Shibler 	 * Deal with the "normal" writebacks.
66153933Shibler 	 *
66253933Shibler 	 * XXX writeback2 is known to reflect a LINE size writeback after
66353933Shibler 	 * a MOVE16 was already dealt with above.  Ignore it.
66453933Shibler 	 */
66553933Shibler 	if (err == 0 && (f->f_wb2s & SSW4_WBSV) &&
66653933Shibler 	    (f->f_wb2s & SSW4_SZMASK) != SSW4_SZLN) {
66753933Shibler #ifdef DEBUG
66853933Shibler 		if ((mmudebug & MDB_WBFOLLOW) || MDB_ISPID(p->p_pid))
66953933Shibler 			dumpwb(2, f->f_wb2s, f->f_wb2a, f->f_wb2d);
67053933Shibler 		wbstats.wb2s++;
67153933Shibler 		wbstats.wbsize[(f->f_wb2s&SSW4_SZMASK)>>5]++;
67253933Shibler #endif
67353933Shibler 		switch (f->f_wb2s & SSW4_SZMASK) {
67453933Shibler 		case SSW4_SZLW:
67553933Shibler 			if (KDFAULT(f->f_wb2s))
67653933Shibler 				*(long *)f->f_wb2a = f->f_wb2d;
67753933Shibler 			else
67853933Shibler 				err = suword((caddr_t)f->f_wb2a, f->f_wb2d);
67953933Shibler 			break;
68053933Shibler 		case SSW4_SZB:
68153933Shibler 			if (KDFAULT(f->f_wb2s))
68253933Shibler 				*(char *)f->f_wb2a = f->f_wb2d;
68353933Shibler 			else
68453933Shibler 				err = subyte((caddr_t)f->f_wb2a, f->f_wb2d);
68553933Shibler 			break;
68653933Shibler 		case SSW4_SZW:
68753933Shibler 			if (KDFAULT(f->f_wb2s))
68853933Shibler 				*(short *)f->f_wb2a = f->f_wb2d;
68953933Shibler 			else
69053933Shibler 				err = susword((caddr_t)f->f_wb2a, f->f_wb2d);
69153933Shibler 			break;
69253933Shibler 		}
69353933Shibler 		if (err) {
69453933Shibler 			fa = f->f_wb2a;
69553933Shibler #ifdef DEBUG
69653933Shibler 			if (mmudebug & MDB_WBFAILED) {
69753933Shibler 				printf(wberrstr, p->p_pid, p->p_comm,
69853933Shibler 				       "#2", fp->f_pc, f->f_fa,
69953933Shibler 				       f->f_wb2a, f->f_wb2d);
70053933Shibler 				dumpssw(f->f_ssw);
70153933Shibler 				dumpwb(2, f->f_wb2s, f->f_wb2a, f->f_wb2d);
70253933Shibler 			}
70353933Shibler #endif
70453933Shibler 		}
70553933Shibler 	}
70653933Shibler 	if (err == 0 && (f->f_wb3s & SSW4_WBSV)) {
70753933Shibler #ifdef DEBUG
70853933Shibler 		if ((mmudebug & MDB_WBFOLLOW) || MDB_ISPID(p->p_pid))
70953933Shibler 			dumpwb(3, f->f_wb3s, f->f_wb3a, f->f_wb3d);
71053933Shibler 		wbstats.wb3s++;
71153933Shibler 		wbstats.wbsize[(f->f_wb3s&SSW4_SZMASK)>>5]++;
71253933Shibler #endif
71353933Shibler 		switch (f->f_wb3s & SSW4_SZMASK) {
71453933Shibler 		case SSW4_SZLW:
71553933Shibler 			if (KDFAULT(f->f_wb3s))
71653933Shibler 				*(long *)f->f_wb3a = f->f_wb3d;
71753933Shibler 			else
71853933Shibler 				err = suword((caddr_t)f->f_wb3a, f->f_wb3d);
71953933Shibler 			break;
72053933Shibler 		case SSW4_SZB:
72153933Shibler 			if (KDFAULT(f->f_wb3s))
72253933Shibler 				*(char *)f->f_wb3a = f->f_wb3d;
72353933Shibler 			else
72453933Shibler 				err = subyte((caddr_t)f->f_wb3a, f->f_wb3d);
72553933Shibler 			break;
72653933Shibler 		case SSW4_SZW:
72753933Shibler 			if (KDFAULT(f->f_wb3s))
72853933Shibler 				*(short *)f->f_wb3a = f->f_wb3d;
72953933Shibler 			else
73053933Shibler 				err = susword((caddr_t)f->f_wb3a, f->f_wb3d);
73153933Shibler 			break;
73253933Shibler #ifdef DEBUG
73353933Shibler 		case SSW4_SZLN:
73453933Shibler 			panic("writeback: wb3s indicates LINE write");
73553933Shibler #endif
73653933Shibler 		}
73753933Shibler 		if (err) {
73853933Shibler 			fa = f->f_wb3a;
73953933Shibler #ifdef DEBUG
74053933Shibler 			if (mmudebug & MDB_WBFAILED)
74153933Shibler 				printf(wberrstr, p->p_pid, p->p_comm,
74253933Shibler 				       "#3", fp->f_pc, f->f_fa,
74353933Shibler 				       f->f_wb3a, f->f_wb3d);
74453933Shibler #endif
74553933Shibler 		}
74653933Shibler 	}
74753933Shibler 	p->p_addr->u_pcb.pcb_onfault = oonfault;
74853933Shibler 	/*
74953933Shibler 	 * Determine the cause of the failure if any translating to
75053933Shibler 	 * a signal.  If the corresponding VA is valid and RO it is
75153933Shibler 	 * a protection fault (SIGBUS) otherwise consider it an
75253933Shibler 	 * illegal reference (SIGSEGV).
75353933Shibler 	 */
75453933Shibler 	if (err) {
75553933Shibler 		if (vm_map_check_protection(&p->p_vmspace->vm_map,
75653933Shibler 					    trunc_page(fa), round_page(fa),
75753933Shibler 					    VM_PROT_READ) &&
75853933Shibler 		    !vm_map_check_protection(&p->p_vmspace->vm_map,
75953933Shibler 					     trunc_page(fa), round_page(fa),
76053933Shibler 					     VM_PROT_WRITE))
76153933Shibler 			err = SIGBUS;
76253933Shibler 		else
76353933Shibler 			err = SIGSEGV;
76453933Shibler 	}
76553933Shibler 	return(err);
76653933Shibler }
76753933Shibler 
76853933Shibler #ifdef DEBUG
76953933Shibler dumpssw(ssw)
77053933Shibler 	register u_short ssw;
77153933Shibler {
77253933Shibler 	printf(" SSW: %x: ", ssw);
77353933Shibler 	if (ssw & SSW4_CP)
77453933Shibler 		printf("CP,");
77553933Shibler 	if (ssw & SSW4_CU)
77653933Shibler 		printf("CU,");
77753933Shibler 	if (ssw & SSW4_CT)
77853933Shibler 		printf("CT,");
77953933Shibler 	if (ssw & SSW4_CM)
78053933Shibler 		printf("CM,");
78153933Shibler 	if (ssw & SSW4_MA)
78253933Shibler 		printf("MA,");
78353933Shibler 	if (ssw & SSW4_ATC)
78453933Shibler 		printf("ATC,");
78553933Shibler 	if (ssw & SSW4_LK)
78653933Shibler 		printf("LK,");
78753933Shibler 	if (ssw & SSW4_RW)
78853933Shibler 		printf("RW,");
78953933Shibler 	printf(" SZ=%s, TT=%s, TM=%s\n",
79053933Shibler 	       f7sz[(ssw & SSW4_SZMASK) >> 5],
79153933Shibler 	       f7tt[(ssw & SSW4_TTMASK) >> 3],
79253933Shibler 	       f7tm[ssw & SSW4_TMMASK]);
79353933Shibler }
79453933Shibler 
79553933Shibler dumpwb(num, s, a, d)
79653933Shibler 	int num;
79753933Shibler 	u_short s;
79853933Shibler 	u_int a, d;
79953933Shibler {
80053933Shibler 	register struct proc *p = curproc;
80153933Shibler 	vm_offset_t pa;
80253933Shibler 
80353933Shibler 	printf(" writeback #%d: VA %x, data %x, SZ=%s, TT=%s, TM=%s\n",
80453933Shibler 	       num, a, d, f7sz[(s & SSW4_SZMASK) >> 5],
80553933Shibler 	       f7tt[(s & SSW4_TTMASK) >> 3], f7tm[s & SSW4_TMMASK]);
80653933Shibler 	printf("               PA ");
80753933Shibler 	pa = pmap_extract(&p->p_vmspace->vm_pmap, (vm_offset_t)a);
80853933Shibler 	if (pa == 0)
80953933Shibler 		printf("<invalid address>");
81053933Shibler 	else
81153933Shibler 		printf("%x, current value %x", pa, fuword((caddr_t)a));
81253933Shibler 	printf("\n");
81353933Shibler }
81453933Shibler 
81553933Shibler #ifdef HPFPLIB
81653933Shibler fppanic(frame)
81753933Shibler 	struct fppanicframe {
81853933Shibler 		int	fpsaveframe;
81953933Shibler 		int	regs[16];
82053933Shibler 		int	fpregs[8*3];
82153933Shibler 		int	fpcregs[3];
82253933Shibler 		int	hole[5];
82353933Shibler 		int	oa6;
82453933Shibler 		short	sr;
82553933Shibler 		int	pc;
82653933Shibler 		short	vector;
82753933Shibler 	} frame;
82853933Shibler {
82953933Shibler 	printf("FP exception: pid %d(%s): no busy frame, ft=%x pc=%x vec=%x\n",
83053933Shibler 	       curproc->p_pid, curproc->p_comm,
83153933Shibler 	       frame.fpsaveframe, frame.pc, frame.vector);
83253933Shibler 	panic("bad FP exception");
83353933Shibler }
83453933Shibler #endif
83553933Shibler #endif
83653933Shibler #endif
83753933Shibler 
83841475Smckusick /*
83949531Skarels  * Proces a system call.
84041475Smckusick  */
84141475Smckusick syscall(code, frame)
84253029Shibler 	volatile unsigned code;
84341475Smckusick 	struct frame frame;
84441475Smckusick {
84541475Smckusick 	register caddr_t params;
84641475Smckusick 	register int i;
84741475Smckusick 	register struct sysent *callp;
84848465Skarels 	register struct proc *p = curproc;
84950753Skarels 	int error, opc, numsys, s;
85044018Skarels 	struct args {
85144018Skarels 		int i[8];
85244018Skarels 	} args;
85344018Skarels 	int rval[2];
85441475Smckusick 	struct timeval syst;
85541475Smckusick 	struct sysent *systab;
85653933Shibler #if defined(HP380)
85753933Shibler 	int beenhere = 0;
85853933Shibler #endif
85941475Smckusick #ifdef HPUXCOMPAT
86041475Smckusick 	extern struct sysent hpuxsysent[];
86141475Smckusick 	extern int hpuxnsysent, notimp();
86241475Smckusick #endif
86341475Smckusick 
86441475Smckusick 	cnt.v_syscall++;
86548465Skarels 	syst = p->p_stime;
86641475Smckusick 	if (!USERMODE(frame.f_sr))
86741475Smckusick 		panic("syscall");
86852380Smckusick 	p->p_md.md_regs = frame.f_regs;
86941475Smckusick 	opc = frame.f_pc - 2;
87041475Smckusick 	systab = sysent;
87141475Smckusick 	numsys = nsysent;
87241475Smckusick #ifdef HPUXCOMPAT
87342370Skarels 	if (p->p_flag & SHPUX) {
87441475Smckusick 		systab = hpuxsysent;
87541475Smckusick 		numsys = hpuxnsysent;
87641475Smckusick 	}
87741475Smckusick #endif
87849531Skarels 	params = (caddr_t)frame.f_regs[SP] + sizeof(int);
87942370Skarels 	if (code == 0) {			/* indir */
88042370Skarels 		code = fuword(params);
88149531Skarels 		params += sizeof(int);
88242370Skarels 	}
88342370Skarels 	if (code >= numsys)
88442370Skarels 		callp = &systab[0];		/* indir (illegal) */
88542370Skarels 	else
88642370Skarels 		callp = &systab[code];
88741475Smckusick 	if ((i = callp->sy_narg * sizeof (int)) &&
88844018Skarels 	    (error = copyin(params, (caddr_t)&args, (u_int)i))) {
88941475Smckusick #ifdef HPUXCOMPAT
89041475Smckusick 		if (p->p_flag & SHPUX)
89142370Skarels 			error = bsdtohpuxerrno(error);
89241475Smckusick #endif
89349362Skarels 		frame.f_regs[D0] = error;
89441475Smckusick 		frame.f_sr |= PSL_C;	/* carry bit */
89541475Smckusick #ifdef KTRACE
89643641Skarels 		if (KTRPOINT(p, KTR_SYSCALL))
89744018Skarels 			ktrsyscall(p->p_tracep, code, callp->sy_narg, args.i);
89841475Smckusick #endif
89941475Smckusick 		goto done;
90041475Smckusick 	}
90141475Smckusick #ifdef KTRACE
90243641Skarels 	if (KTRPOINT(p, KTR_SYSCALL))
90344018Skarels 		ktrsyscall(p->p_tracep, code, callp->sy_narg, args.i);
90441475Smckusick #endif
90543641Skarels 	rval[0] = 0;
90643641Skarels 	rval[1] = frame.f_regs[D1];
90741475Smckusick #ifdef HPUXCOMPAT
90842370Skarels 	/* debug kludge */
90942370Skarels 	if (callp->sy_call == notimp)
91048465Skarels 		error = notimp(p, args.i, rval, code, callp->sy_narg);
91142370Skarels 	else
91241475Smckusick #endif
91348465Skarels 	error = (*callp->sy_call)(p, &args, rval);
91442370Skarels 	if (error == ERESTART)
91542370Skarels 		frame.f_pc = opc;
91642370Skarels 	else if (error != EJUSTRETURN) {
91742370Skarels 		if (error) {
91841475Smckusick #ifdef HPUXCOMPAT
91942370Skarels 			if (p->p_flag & SHPUX)
92042370Skarels 				error = bsdtohpuxerrno(error);
92141475Smckusick #endif
92249362Skarels 			frame.f_regs[D0] = error;
92342370Skarels 			frame.f_sr |= PSL_C;	/* carry bit */
92441475Smckusick 		} else {
92543641Skarels 			frame.f_regs[D0] = rval[0];
92643641Skarels 			frame.f_regs[D1] = rval[1];
92741475Smckusick 			frame.f_sr &= ~PSL_C;
92841475Smckusick 		}
92942370Skarels 	}
93042370Skarels 	/* else if (error == EJUSTRETURN) */
93141475Smckusick 		/* nothing to do */
93242370Skarels 
93341475Smckusick done:
93441475Smckusick 	/*
93542370Skarels 	 * Reinitialize proc pointer `p' as it may be different
93642370Skarels 	 * if this is a child returning from fork syscall.
93742370Skarels 	 */
93848465Skarels 	p = curproc;
93949317Shibler 	while (i = CURSIG(p))
94049317Shibler 		psig(i);
94141475Smckusick 	p->p_pri = p->p_usrpri;
94248465Skarels 	if (want_resched) {
94341475Smckusick 		/*
94448465Skarels 		 * Since we are curproc, clock will normally just change
94541475Smckusick 		 * our priority without moving us from one queue to another
94641475Smckusick 		 * (since the running process is not on a queue.)
94741475Smckusick 		 * If that happened after we setrq ourselves but before we
94841475Smckusick 		 * swtch()'ed, we might not be on the queue indicated by
94941475Smckusick 		 * our priority.
95041475Smckusick 		 */
95150753Skarels 		s = splclock();
95241475Smckusick 		setrq(p);
95348465Skarels 		p->p_stats->p_ru.ru_nivcsw++;
95441475Smckusick 		swtch();
95550753Skarels 		splx(s);
95649317Shibler 		while (i = CURSIG(p))
95749317Shibler 			psig(i);
95841475Smckusick 	}
95948465Skarels 	if (p->p_stats->p_prof.pr_scale) {
96041475Smckusick 		int ticks;
96148465Skarels 		struct timeval *tv = &p->p_stime;
96241475Smckusick 
96341475Smckusick 		ticks = ((tv->tv_sec - syst.tv_sec) * 1000 +
96441475Smckusick 			(tv->tv_usec - syst.tv_usec) / 1000) / (tick / 1000);
96541475Smckusick 		if (ticks) {
96641475Smckusick #ifdef PROFTIMER
96741475Smckusick 			extern int profscale;
96848465Skarels 			addupc(frame.f_pc, &p->p_stats->p_prof,
96948465Skarels 			    ticks * profscale);
97041475Smckusick #else
97148465Skarels 			addupc(frame.f_pc, &p->p_stats->p_prof, ticks);
97241475Smckusick #endif
97341475Smckusick 		}
97441475Smckusick 	}
97553933Shibler #if defined(HP380)
97653933Shibler 	/*
97753933Shibler 	 * Deal with writebacks when returning from sigreturn.
97853933Shibler 	 * They may generate another signal to be processed.
97953933Shibler 	 * Again, we don't attempt the writeback if we have already
98053933Shibler 	 * tried and failed (see comment in trap).
98153933Shibler 	 */
98253933Shibler 	if (mmutype == MMU_68040 && frame.f_format == FMT7) {
98353933Shibler 		if (beenhere) {
98453933Shibler #ifdef DEBUG
98553933Shibler 			if (mmudebug & MDB_WBFAILED)
98653933Shibler 			printf("pid %d(%s): writeback aborted in sigreturn, pc=%x\n",
98753933Shibler 			       p->p_pid, p->p_comm, frame.f_pc);
98853933Shibler #endif
98953933Shibler 			;
99053933Shibler 		} else if (i = writeback(&frame, 0)) {
99153933Shibler 			beenhere++;
99253933Shibler 			syst = p->p_stime;
99353933Shibler 			trapsignal(p, i, 0);
99453933Shibler 			goto done;
99553933Shibler 		}
99653933Shibler 	}
99753933Shibler #endif
99841475Smckusick 	curpri = p->p_pri;
99941475Smckusick #ifdef KTRACE
100043641Skarels 	if (KTRPOINT(p, KTR_SYSRET))
100143641Skarels 		ktrsysret(p->p_tracep, code, error, rval[0]);
100241475Smckusick #endif
100341475Smckusick }
1004