xref: /csrg-svn/sys/hp300/hp300/trap.c (revision 53933)
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  *
12*53933Shibler  * from: Utah $Hdr: trap.c 1.35 91/12/26$
1341475Smckusick  *
14*53933Shibler  *	@(#)trap.c	7.20 (Berkeley) 06/05/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
40*53933Shibler #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) */
71*53933Shibler 	FMT3SIZE,	/* type 3 - FP post-instruction (68040) */
7249317Shibler 	-1, -1, -1,	/* type 4-6 - undefined */
73*53933Shibler 	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 
81*53933Shibler #if defined(HP380)
82*53933Shibler #define KDFAULT(c)	(mmutype == MMU_68040 ? \
83*53933Shibler 			    ((c) & SSW4_TMMASK) == SSW4_TMKD : \
84*53933Shibler 			    ((c) & (SSW_DF|FC_SUPERD)) == (SSW_DF|FC_SUPERD))
85*53933Shibler #define WRFAULT(c) 	(mmutype == MMU_68040 ? \
86*53933Shibler 			    ((c) & SSW4_RW) == 0 : \
87*53933Shibler 			    ((c) & (SSW_DF|SSW_RW)) == SSW_DF)
88*53933Shibler #else
89*53933Shibler #define KDFAULT(c)	(((c) & (SSW_DF|SSW_FCMASK)) == (SSW_DF|FC_SUPERD))
90*53933Shibler #define WRFAULT(c)	(((c) & (SSW_DF|SSW_RW)) == SSW_DF)
91*53933Shibler #endif
92*53933Shibler 
9341475Smckusick #ifdef DEBUG
9441475Smckusick int mmudebug = 0;
95*53933Shibler int mmupid = -1;
96*53933Shibler #define MDB_FOLLOW	1
97*53933Shibler #define MDB_WBFOLLOW	2
98*53933Shibler #define MDB_WBFAILED	4
99*53933Shibler #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;
120*53933Shibler #if defined(HP380)
121*53933Shibler 	int beenhere = 0;
122*53933Shibler #endif
12341475Smckusick 
12441475Smckusick 	cnt.v_trap++;
12548465Skarels 	syst = p->p_stime;
12641475Smckusick 	if (USERMODE(frame.f_sr)) {
12749531Skarels 		type |= T_USER;
12852380Smckusick 		p->p_md.md_regs = frame.f_regs;
12941475Smckusick 	}
13041475Smckusick 	switch (type) {
13141475Smckusick 
13241475Smckusick 	default:
13341475Smckusick dopanic:
13441475Smckusick 		printf("trap type %d, code = %x, v = %x\n", type, code, v);
13541475Smckusick 		regdump(frame.f_regs, 128);
13649531Skarels 		type &= ~T_USER;
13741475Smckusick 		if ((unsigned)type < TRAP_TYPES)
13841475Smckusick 			panic(trap_type[type]);
13941475Smckusick 		panic("trap");
14041475Smckusick 
14141475Smckusick 	case T_BUSERR:		/* kernel bus error */
14249125Skarels 		if (!p->p_addr->u_pcb.pcb_onfault)
14341475Smckusick 			goto dopanic;
14441475Smckusick 		/*
14541475Smckusick 		 * If we have arranged to catch this fault in any of the
14641475Smckusick 		 * copy to/from user space routines, set PC to return to
14741475Smckusick 		 * indicated location and set flag informing buserror code
14841475Smckusick 		 * that it may need to clean up stack frame.
14941475Smckusick 		 */
15041475Smckusick copyfault:
15149317Shibler 		frame.f_stackadj = exframesize[frame.f_format];
15249317Shibler 		frame.f_format = frame.f_vector = 0;
15349125Skarels 		frame.f_pc = (int) p->p_addr->u_pcb.pcb_onfault;
15441475Smckusick 		return;
15541475Smckusick 
15649531Skarels 	case T_BUSERR|T_USER:	/* bus error */
15749531Skarels 	case T_ADDRERR|T_USER:	/* address error */
158*53933Shibler 		ucode = v;
15941475Smckusick 		i = SIGBUS;
16041475Smckusick 		break;
16141475Smckusick 
16241475Smckusick #ifdef FPCOPROC
16341475Smckusick 	case T_COPERR:		/* kernel coprocessor violation */
16441475Smckusick #endif
165*53933Shibler 	case T_FMTERR|T_USER:	/* do all RTE errors come in as T_USER? */
166*53933Shibler 	case T_FMTERR:		/* ...just in case... */
16741475Smckusick 	/*
16841475Smckusick 	 * The user has most likely trashed the RTE or FP state info
16941475Smckusick 	 * in the stack frame of a signal handler.
17041475Smckusick 	 */
17149531Skarels 		type |= T_USER;
17248465Skarels 		printf("pid %d: kernel %s exception\n", p->p_pid,
17341475Smckusick 		       type==T_COPERR ? "coprocessor" : "format");
17448465Skarels 		p->p_sigacts->ps_sigact[SIGILL] = SIG_DFL;
17541475Smckusick 		i = sigmask(SIGILL);
17641475Smckusick 		p->p_sigignore &= ~i;
17741475Smckusick 		p->p_sigcatch &= ~i;
17841475Smckusick 		p->p_sigmask &= ~i;
17942370Skarels 		i = SIGILL;
18041475Smckusick 		ucode = frame.f_format;	/* XXX was ILL_RESAD_FAULT */
18142370Skarels 		break;
18241475Smckusick 
18341475Smckusick #ifdef FPCOPROC
18449531Skarels 	case T_COPERR|T_USER:	/* user coprocessor violation */
18541475Smckusick 	/* What is a proper response here? */
18641475Smckusick 		ucode = 0;
18741475Smckusick 		i = SIGFPE;
18841475Smckusick 		break;
18941475Smckusick 
19049531Skarels 	case T_FPERR|T_USER:	/* 68881 exceptions */
19141475Smckusick 	/*
19241475Smckusick 	 * We pass along the 68881 status register which locore stashed
19341475Smckusick 	 * in code for us.  Note that there is a possibility that the
19441475Smckusick 	 * bit pattern of this register will conflict with one of the
19541475Smckusick 	 * FPE_* codes defined in signal.h.  Fortunately for us, the
19641475Smckusick 	 * only such codes we use are all in the range 1-7 and the low
19741475Smckusick 	 * 3 bits of the status register are defined as 0 so there is
19841475Smckusick 	 * no clash.
19941475Smckusick 	 */
20041475Smckusick 		ucode = code;
20141475Smckusick 		i = SIGFPE;
20241475Smckusick 		break;
20341475Smckusick #endif
20441475Smckusick 
205*53933Shibler #if defined(HP380)
206*53933Shibler 	case T_FPEMULI|T_USER:	/* unimplemented FP instuction */
207*53933Shibler 	case T_FPEMULD|T_USER:	/* unimplemented FP data type */
208*53933Shibler 		/* XXX need to FSAVE */
209*53933Shibler 		printf("pid %d(%s): unimplemented FP %s at %x (EA %x)\n",
210*53933Shibler 		       p->p_pid, p->p_comm,
211*53933Shibler 		       frame.f_format == 2 ? "instruction" : "data type",
212*53933Shibler 		       frame.f_pc, frame.f_fmt2.f_iaddr);
213*53933Shibler 		/* XXX need to FRESTORE */
214*53933Shibler 		i = SIGFPE;
215*53933Shibler 		break;
216*53933Shibler #endif
217*53933Shibler 
21849531Skarels 	case T_ILLINST|T_USER:	/* illegal instruction fault */
21941475Smckusick #ifdef HPUXCOMPAT
22048465Skarels 		if (p->p_flag & SHPUX) {
22141475Smckusick 			ucode = HPUX_ILL_ILLINST_TRAP;
22241475Smckusick 			i = SIGILL;
22341475Smckusick 			break;
22441475Smckusick 		}
22541475Smckusick 		/* fall through */
22641475Smckusick #endif
22749531Skarels 	case T_PRIVINST|T_USER:	/* privileged instruction fault */
22841475Smckusick #ifdef HPUXCOMPAT
22948465Skarels 		if (p->p_flag & SHPUX)
23041475Smckusick 			ucode = HPUX_ILL_PRIV_TRAP;
23141475Smckusick 		else
23241475Smckusick #endif
23341475Smckusick 		ucode = frame.f_format;	/* XXX was ILL_PRIVIN_FAULT */
23441475Smckusick 		i = SIGILL;
23541475Smckusick 		break;
23641475Smckusick 
23749531Skarels 	case T_ZERODIV|T_USER:	/* Divide by zero */
23841475Smckusick #ifdef HPUXCOMPAT
23948465Skarels 		if (p->p_flag & SHPUX)
24041475Smckusick 			ucode = HPUX_FPE_INTDIV_TRAP;
24141475Smckusick 		else
24241475Smckusick #endif
24341475Smckusick 		ucode = frame.f_format;	/* XXX was FPE_INTDIV_TRAP */
24441475Smckusick 		i = SIGFPE;
24541475Smckusick 		break;
24641475Smckusick 
24749531Skarels 	case T_CHKINST|T_USER:	/* CHK instruction trap */
24841475Smckusick #ifdef HPUXCOMPAT
24948465Skarels 		if (p->p_flag & SHPUX) {
25041475Smckusick 			/* handled differently under hp-ux */
25141475Smckusick 			i = SIGILL;
25241475Smckusick 			ucode = HPUX_ILL_CHK_TRAP;
25341475Smckusick 			break;
25441475Smckusick 		}
25541475Smckusick #endif
25641475Smckusick 		ucode = frame.f_format;	/* XXX was FPE_SUBRNG_TRAP */
25741475Smckusick 		i = SIGFPE;
25841475Smckusick 		break;
25941475Smckusick 
26049531Skarels 	case T_TRAPVINST|T_USER:	/* TRAPV instruction trap */
26141475Smckusick #ifdef HPUXCOMPAT
26248465Skarels 		if (p->p_flag & SHPUX) {
26341475Smckusick 			/* handled differently under hp-ux */
26441475Smckusick 			i = SIGILL;
26541475Smckusick 			ucode = HPUX_ILL_TRAPV_TRAP;
26641475Smckusick 			break;
26741475Smckusick 		}
26841475Smckusick #endif
26941475Smckusick 		ucode = frame.f_format;	/* XXX was FPE_INTOVF_TRAP */
27041475Smckusick 		i = SIGFPE;
27141475Smckusick 		break;
27241475Smckusick 
27341475Smckusick 	/*
27441475Smckusick 	 * XXX: Trace traps are a nightmare.
27541475Smckusick 	 *
27641475Smckusick 	 *	HP-UX uses trap #1 for breakpoints,
27741475Smckusick 	 *	HPBSD uses trap #2,
27841475Smckusick 	 *	SUN 3.x uses trap #15,
27948465Skarels 	 *	KGDB uses trap #15 (for kernel breakpoints; handled elsewhere).
28041475Smckusick 	 *
28141475Smckusick 	 * HPBSD and HP-UX traps both get mapped by locore.s into T_TRACE.
28241475Smckusick 	 * SUN 3.x traps get passed through as T_TRAP15 and are not really
28348465Skarels 	 * supported yet.
28441475Smckusick 	 */
28541475Smckusick 	case T_TRACE:		/* kernel trace trap */
28648465Skarels 	case T_TRAP15:		/* SUN trace trap */
28741475Smckusick 		frame.f_sr &= ~PSL_T;
28841475Smckusick 		i = SIGTRAP;
28941475Smckusick 		break;
29041475Smckusick 
29149531Skarels 	case T_TRACE|T_USER:	/* user trace trap */
29249531Skarels 	case T_TRAP15|T_USER:	/* SUN user trace trap */
29341475Smckusick 		frame.f_sr &= ~PSL_T;
29441475Smckusick 		i = SIGTRAP;
29541475Smckusick 		break;
29641475Smckusick 
29743413Shibler 	case T_ASTFLT:		/* system async trap, cannot happen */
29841475Smckusick 		goto dopanic;
29941475Smckusick 
30049531Skarels 	case T_ASTFLT|T_USER:	/* user async trap */
30149125Skarels 		astpending = 0;
30241475Smckusick 		/*
30341475Smckusick 		 * We check for software interrupts first.  This is because
30441475Smckusick 		 * they are at a higher level than ASTs, and on a VAX would
30541475Smckusick 		 * interrupt the AST.  We assume that if we are processing
30641475Smckusick 		 * an AST that we must be at IPL0 so we don't bother to
30741475Smckusick 		 * check.  Note that we ensure that we are at least at SIR
30841475Smckusick 		 * IPL while processing the SIR.
30941475Smckusick 		 */
31041475Smckusick 		spl1();
31141475Smckusick 		/* fall into... */
31241475Smckusick 
31341475Smckusick 	case T_SSIR:		/* software interrupt */
31449531Skarels 	case T_SSIR|T_USER:
31541475Smckusick 		if (ssir & SIR_NET) {
31641475Smckusick 			siroff(SIR_NET);
31741475Smckusick 			cnt.v_soft++;
31841475Smckusick 			netintr();
31941475Smckusick 		}
32041475Smckusick 		if (ssir & SIR_CLOCK) {
32141475Smckusick 			siroff(SIR_CLOCK);
32241475Smckusick 			cnt.v_soft++;
32341475Smckusick 			softclock((caddr_t)frame.f_pc, (int)frame.f_sr);
32441475Smckusick 		}
32541475Smckusick 		/*
32641475Smckusick 		 * If this was not an AST trap, we are all done.
32741475Smckusick 		 */
32850753Skarels 		if (type != (T_ASTFLT|T_USER)) {
32941475Smckusick 			cnt.v_trap--;
33041475Smckusick 			return;
33141475Smckusick 		}
33241475Smckusick 		spl0();
33341475Smckusick #ifndef PROFTIMER
33448465Skarels 		if ((p->p_flag&SOWEUPC) && p->p_stats->p_prof.pr_scale) {
33548465Skarels 			addupc(frame.f_pc, &p->p_stats->p_prof, 1);
33648465Skarels 			p->p_flag &= ~SOWEUPC;
33741475Smckusick 		}
33841475Smckusick #endif
33941475Smckusick 		goto out;
34041475Smckusick 
34141475Smckusick 	case T_MMUFLT:		/* kernel mode page fault */
34241475Smckusick 		/* fall into ... */
34341475Smckusick 
34449531Skarels 	case T_MMUFLT|T_USER:	/* page fault */
34545751Smckusick 	    {
34645751Smckusick 		register vm_offset_t va;
34748465Skarels 		register struct vmspace *vm = p->p_vmspace;
34845751Smckusick 		register vm_map_t map;
34945751Smckusick 		int rv;
35045751Smckusick 		vm_prot_t ftype;
35145751Smckusick 		extern vm_map_t kernel_map;
35245751Smckusick 
353*53933Shibler #ifdef DEBUG
354*53933Shibler 		if ((mmudebug & MDB_WBFOLLOW) || MDB_ISPID(p->p_pid))
355*53933Shibler 		printf("trap: T_MMUFLT pid=%d, code=%x, v=%x, pc=%x, sr=%x\n",
356*53933Shibler 		       p->p_pid, code, v, frame.f_pc, frame.f_sr);
357*53933Shibler #endif
35841475Smckusick 		/*
35945751Smckusick 		 * It is only a kernel address space fault iff:
36049531Skarels 		 * 	1. (type & T_USER) == 0  and
36145751Smckusick 		 * 	2. pcb_onfault not set or
36245751Smckusick 		 *	3. pcb_onfault set but supervisor space data fault
36345751Smckusick 		 * The last can occur during an exec() copyin where the
36445751Smckusick 		 * argument space is lazy-allocated.
36541475Smckusick 		 */
36645751Smckusick 		if (type == T_MMUFLT &&
367*53933Shibler 		    (!p->p_addr->u_pcb.pcb_onfault || KDFAULT(code)))
36845751Smckusick 			map = kernel_map;
36945751Smckusick 		else
37048465Skarels 			map = &vm->vm_map;
371*53933Shibler 		if (WRFAULT(code))
37245751Smckusick 			ftype = VM_PROT_READ | VM_PROT_WRITE;
37345751Smckusick 		else
37445751Smckusick 			ftype = VM_PROT_READ;
37545751Smckusick 		va = trunc_page((vm_offset_t)v);
37641475Smckusick #ifdef DEBUG
37745751Smckusick 		if (map == kernel_map && va == 0) {
37845751Smckusick 			printf("trap: bad kernel access at %x\n", v);
37941475Smckusick 			goto dopanic;
38041475Smckusick 		}
38141475Smckusick #endif
38249317Shibler 		rv = vm_fault(map, va, ftype, FALSE);
383*53933Shibler #ifdef DEBUG
384*53933Shibler 		if (rv && MDB_ISPID(p->p_pid))
385*53933Shibler 			printf("vm_fault(%x, %x, %x, 0) -> %x\n",
386*53933Shibler 			       map, va, ftype, rv);
387*53933Shibler #endif
38841475Smckusick 		/*
38949317Shibler 		 * If this was a stack access we keep track of the maximum
39049317Shibler 		 * accessed stack size.  Also, if vm_fault gets a protection
39149317Shibler 		 * failure it is due to accessing the stack region outside
39249317Shibler 		 * the current limit and we need to reflect that as an access
39349317Shibler 		 * error.
39441475Smckusick 		 */
39548465Skarels 		if ((caddr_t)va >= vm->vm_maxsaddr && map != kernel_map) {
39649317Shibler 			if (rv == KERN_SUCCESS) {
39749317Shibler 				unsigned nss;
39849317Shibler 
39949317Shibler 				nss = clrnd(btoc(USRSTACK-(unsigned)va));
40049317Shibler 				if (nss > vm->vm_ssize)
40149317Shibler 					vm->vm_ssize = nss;
40249317Shibler 			} else if (rv == KERN_PROTECTION_FAILURE)
40349317Shibler 				rv = KERN_INVALID_ADDRESS;
40441475Smckusick 		}
40545751Smckusick 		if (rv == KERN_SUCCESS) {
406*53933Shibler 			if (type == T_MMUFLT) {
407*53933Shibler #if defined(HP380)
408*53933Shibler 				if (mmutype == MMU_68040)
409*53933Shibler 					(void) writeback(&frame, 1);
410*53933Shibler #endif
41141475Smckusick 				return;
412*53933Shibler 			}
41341475Smckusick 			goto out;
41441475Smckusick 		}
41545751Smckusick 		if (type == T_MMUFLT) {
41649125Skarels 			if (p->p_addr->u_pcb.pcb_onfault)
41745751Smckusick 				goto copyfault;
41845751Smckusick 			printf("vm_fault(%x, %x, %x, 0) -> %x\n",
41945751Smckusick 			       map, va, ftype, rv);
42045751Smckusick 			printf("  type %x, code [mmu,,ssw]: %x\n",
42145751Smckusick 			       type, code);
42245751Smckusick 			goto dopanic;
42345751Smckusick 		}
42448465Skarels 		ucode = v;
42545751Smckusick 		i = (rv == KERN_PROTECTION_FAILURE) ? SIGBUS : SIGSEGV;
42645751Smckusick 		break;
42745751Smckusick 	    }
42841475Smckusick 	}
42948465Skarels 	trapsignal(p, i, ucode);
43049531Skarels 	if ((type & T_USER) == 0)
43141475Smckusick 		return;
43241475Smckusick out:
43348465Skarels 	while (i = CURSIG(p))
43442370Skarels 		psig(i);
43541475Smckusick 	p->p_pri = p->p_usrpri;
43648465Skarels 	if (want_resched) {
43741475Smckusick 		/*
43848465Skarels 		 * Since we are curproc, clock will normally just change
43941475Smckusick 		 * our priority without moving us from one queue to another
44041475Smckusick 		 * (since the running process is not on a queue.)
44141475Smckusick 		 * If that happened after we setrq ourselves but before we
44241475Smckusick 		 * swtch()'ed, we might not be on the queue indicated by
44341475Smckusick 		 * our priority.
44441475Smckusick 		 */
44550753Skarels 		s = splclock();
44641475Smckusick 		setrq(p);
44748465Skarels 		p->p_stats->p_ru.ru_nivcsw++;
44841475Smckusick 		swtch();
44950753Skarels 		splx(s);
45048465Skarels 		while (i = CURSIG(p))
45142370Skarels 			psig(i);
45241475Smckusick 	}
45348465Skarels 	if (p->p_stats->p_prof.pr_scale) {
45441475Smckusick 		int ticks;
45548465Skarels 		struct timeval *tv = &p->p_stime;
45641475Smckusick 
45741475Smckusick 		ticks = ((tv->tv_sec - syst.tv_sec) * 1000 +
45841475Smckusick 			(tv->tv_usec - syst.tv_usec) / 1000) / (tick / 1000);
45941475Smckusick 		if (ticks) {
46041475Smckusick #ifdef PROFTIMER
46141475Smckusick 			extern int profscale;
46248465Skarels 			addupc(frame.f_pc, &p->p_stats->p_prof,
46348465Skarels 			    ticks * profscale);
46441475Smckusick #else
46548465Skarels 			addupc(frame.f_pc, &p->p_stats->p_prof, ticks);
46641475Smckusick #endif
46741475Smckusick 		}
46841475Smckusick 	}
469*53933Shibler #if defined(HP380)
470*53933Shibler 	/*
471*53933Shibler 	 * Deal with user mode writebacks.
472*53933Shibler 	 * If any writeback fails, go back and attempt signal delivery.
473*53933Shibler 	 * unless we have already been here and attempted the writeback
474*53933Shibler 	 * (e.g. bad address with user ignoring SIGSEGV).  In that case
475*53933Shibler 	 * we just return to the user without sucessfully completing
476*53933Shibler 	 * the writebacks.  Maybe we should just drop the sucker?
477*53933Shibler 	 */
478*53933Shibler 	if (mmutype == MMU_68040 && frame.f_format == FMT7) {
479*53933Shibler 		if (beenhere) {
480*53933Shibler #ifdef DEBUG
481*53933Shibler 			if (mmudebug & MDB_WBFAILED)
482*53933Shibler 			printf("pid %d(%s): writeback aborted, pc=%x, fa=%x\n",
483*53933Shibler 			       p->p_pid, p->p_comm, frame.f_pc, v);
484*53933Shibler #endif
485*53933Shibler 			;
486*53933Shibler 		} else if (i = writeback(&frame, 1)) {
487*53933Shibler 			beenhere++;
488*53933Shibler 			ucode = v;
489*53933Shibler 			syst = p->p_stime;
490*53933Shibler 			trapsignal(p, i, ucode);
491*53933Shibler 			goto out;
492*53933Shibler 		}
493*53933Shibler 	}
494*53933Shibler #endif
49541475Smckusick 	curpri = p->p_pri;
49641475Smckusick }
49741475Smckusick 
498*53933Shibler #if defined(HP380)
499*53933Shibler #ifdef DEBUG
500*53933Shibler struct writebackstats {
501*53933Shibler 	int calls;
502*53933Shibler 	int cpushes;
503*53933Shibler 	int move16s;
504*53933Shibler 	int wb1s, wb2s, wb3s;
505*53933Shibler 	int wbsize[4];
506*53933Shibler } wbstats;
507*53933Shibler 
508*53933Shibler char *f7sz[] = { "longword", "byte", "word", "line" };
509*53933Shibler char *f7tt[] = { "normal", "MOVE16", "AFC", "ACK" };
510*53933Shibler char *f7tm[] = { "d-push", "u-data", "u-code", "M-data",
511*53933Shibler 		 "M-code", "k-data", "k-code", "RES" };
512*53933Shibler char wberrstr[] =
513*53933Shibler     "WARNING: pid %d(%s) writeback [%s] failed, pc=%x fa=%x wba=%x wbd=%x\n";
514*53933Shibler #endif
515*53933Shibler 
516*53933Shibler writeback(fp, docachepush)
517*53933Shibler 	struct frame *fp;
518*53933Shibler 	int docachepush;
519*53933Shibler {
520*53933Shibler 	register struct fmt7 *f = &fp->f_fmt7;
521*53933Shibler 	register struct proc *p = curproc;
522*53933Shibler 	int err = 0;
523*53933Shibler 	u_int fa;
524*53933Shibler 	caddr_t oonfault = p->p_addr->u_pcb.pcb_onfault;
525*53933Shibler 
526*53933Shibler #ifdef DEBUG
527*53933Shibler 	if ((mmudebug & MDB_WBFOLLOW) || MDB_ISPID(p->p_pid)) {
528*53933Shibler 		printf(" pid=%d, fa=%x,", p->p_pid, f->f_fa);
529*53933Shibler 		dumpssw(f->f_ssw);
530*53933Shibler 	}
531*53933Shibler 	wbstats.calls++;
532*53933Shibler #endif
533*53933Shibler 	/*
534*53933Shibler 	 * Deal with special cases first.
535*53933Shibler 	 */
536*53933Shibler 	if ((f->f_ssw & SSW4_TMMASK) == SSW4_TMDCP) {
537*53933Shibler 		/*
538*53933Shibler 		 * Dcache push fault.
539*53933Shibler 		 * Line-align the address and write out the push data to
540*53933Shibler 		 * the indicated physical address.
541*53933Shibler 		 */
542*53933Shibler #ifdef DEBUG
543*53933Shibler 		if ((mmudebug & MDB_WBFOLLOW) || MDB_ISPID(p->p_pid)) {
544*53933Shibler 			printf(" pushing %s to PA %x, data %x",
545*53933Shibler 			       f7sz[(f->f_ssw & SSW4_SZMASK) >> 5],
546*53933Shibler 			       f->f_fa, f->f_pd0);
547*53933Shibler 			if ((f->f_ssw & SSW4_SZMASK) == SSW4_SZLN)
548*53933Shibler 				printf("/%x/%x/%x",
549*53933Shibler 				       f->f_pd1, f->f_pd2, f->f_pd3);
550*53933Shibler 			printf("\n");
551*53933Shibler 		}
552*53933Shibler 		if (f->f_wb1s & SSW4_WBSV)
553*53933Shibler 			panic("writeback: cache push with WB1S valid");
554*53933Shibler 		wbstats.cpushes++;
555*53933Shibler #endif
556*53933Shibler 		/*
557*53933Shibler 		 * XXX there are security problems if we attempt to do a
558*53933Shibler 		 * cache push after a signal handler has been called.
559*53933Shibler 		 */
560*53933Shibler 		if (docachepush) {
561*53933Shibler 			pmap_enter(kernel_pmap, (vm_offset_t)vmmap,
562*53933Shibler 				   trunc_page(f->f_fa), VM_PROT_WRITE, TRUE);
563*53933Shibler 			fa = (u_int)&vmmap[(f->f_fa & PGOFSET) & ~0xF];
564*53933Shibler 			bcopy((caddr_t)&f->f_pd0, (caddr_t)fa, 16);
565*53933Shibler 			DCFL(pmap_extract(kernel_pmap, (vm_offset_t)fa));
566*53933Shibler 			pmap_remove(kernel_pmap, (vm_offset_t)vmmap,
567*53933Shibler 				    (vm_offset_t)&vmmap[NBPG]);
568*53933Shibler 		} else
569*53933Shibler 			printf("WARNING: pid %d(%s) uid %d: CPUSH not done\n",
570*53933Shibler 			       p->p_pid, p->p_comm, p->p_ucred->cr_uid);
571*53933Shibler 	} else if ((f->f_ssw & (SSW4_RW|SSW4_TTMASK)) == SSW4_TTM16) {
572*53933Shibler 		/*
573*53933Shibler 		 * MOVE16 fault.
574*53933Shibler 		 * Line-align the address and write out the push data to
575*53933Shibler 		 * the indicated virtual address.
576*53933Shibler 		 */
577*53933Shibler #ifdef DEBUG
578*53933Shibler 		if ((mmudebug & MDB_WBFOLLOW) || MDB_ISPID(p->p_pid))
579*53933Shibler 			printf(" MOVE16 to VA %x(%x), data %x/%x/%x/%x\n",
580*53933Shibler 			       f->f_fa, f->f_fa & ~0xF, f->f_pd0, f->f_pd1,
581*53933Shibler 			       f->f_pd2, f->f_pd3);
582*53933Shibler 		if (f->f_wb1s & SSW4_WBSV)
583*53933Shibler 			panic("writeback: MOVE16 with WB1S valid");
584*53933Shibler 		wbstats.move16s++;
585*53933Shibler #endif
586*53933Shibler 		if (KDFAULT(f->f_wb1s))
587*53933Shibler 			bcopy((caddr_t)&f->f_pd0, (caddr_t)(f->f_fa & ~0xF), 16);
588*53933Shibler 		else
589*53933Shibler 			err = suline((caddr_t)(f->f_fa & ~0xF), (caddr_t)&f->f_pd0);
590*53933Shibler 		if (err) {
591*53933Shibler 			fa = f->f_fa & ~0xF;
592*53933Shibler #ifdef DEBUG
593*53933Shibler 			if (mmudebug & MDB_WBFAILED)
594*53933Shibler 				printf(wberrstr, p->p_pid, p->p_comm,
595*53933Shibler 				       "MOVE16", fp->f_pc, f->f_fa,
596*53933Shibler 				       f->f_fa & ~0xF, f->f_pd0);
597*53933Shibler #endif
598*53933Shibler 		}
599*53933Shibler 	} else if (f->f_wb1s & SSW4_WBSV) {
600*53933Shibler 		/*
601*53933Shibler 		 * Writeback #1.
602*53933Shibler 		 * Position the "memory-aligned" data and write it out.
603*53933Shibler 		 */
604*53933Shibler 		register u_int wb1d = f->f_wb1d;
605*53933Shibler 		register int off;
606*53933Shibler 
607*53933Shibler #ifdef DEBUG
608*53933Shibler 		if ((mmudebug & MDB_WBFOLLOW) || MDB_ISPID(p->p_pid))
609*53933Shibler 			dumpwb(1, f->f_wb1s, f->f_wb1a, f->f_wb1d);
610*53933Shibler 		wbstats.wb1s++;
611*53933Shibler 		wbstats.wbsize[(f->f_wb2s&SSW4_SZMASK)>>5]++;
612*53933Shibler #endif
613*53933Shibler 		off = (f->f_wb1a & 3) * 8;
614*53933Shibler 		switch (f->f_wb1s & SSW4_SZMASK) {
615*53933Shibler 		case SSW4_SZLW:
616*53933Shibler 			if (off)
617*53933Shibler 				wb1d = (wb1d >> (32 - off)) | (wb1d << off);
618*53933Shibler 			if (KDFAULT(f->f_wb1s))
619*53933Shibler 				*(long *)f->f_wb1a = wb1d;
620*53933Shibler 			else
621*53933Shibler 				err = suword((caddr_t)f->f_wb1a, wb1d);
622*53933Shibler 			break;
623*53933Shibler 		case SSW4_SZB:
624*53933Shibler 			off = 24 - off;
625*53933Shibler 			if (off)
626*53933Shibler 				wb1d >>= off;
627*53933Shibler 			if (KDFAULT(f->f_wb1s))
628*53933Shibler 				*(char *)f->f_wb1a = wb1d;
629*53933Shibler 			else
630*53933Shibler 				err = subyte((caddr_t)f->f_wb1a, wb1d);
631*53933Shibler 			break;
632*53933Shibler 		case SSW4_SZW:
633*53933Shibler 			off = (off + 16) % 32;
634*53933Shibler 			if (off)
635*53933Shibler 				wb1d = (wb1d >> (32 - off)) | (wb1d << off);
636*53933Shibler 			if (KDFAULT(f->f_wb1s))
637*53933Shibler 				*(short *)f->f_wb1a = wb1d;
638*53933Shibler 			else
639*53933Shibler 				err = susword((caddr_t)f->f_wb1a, wb1d);
640*53933Shibler 			break;
641*53933Shibler 		}
642*53933Shibler 		if (err) {
643*53933Shibler 			fa = f->f_wb1a;
644*53933Shibler #ifdef DEBUG
645*53933Shibler 			if (mmudebug & MDB_WBFAILED)
646*53933Shibler 				printf(wberrstr, p->p_pid, p->p_comm,
647*53933Shibler 				       "#1", fp->f_pc, f->f_fa,
648*53933Shibler 				       f->f_wb1a, f->f_wb1d);
649*53933Shibler #endif
650*53933Shibler 		}
651*53933Shibler 	}
652*53933Shibler 	/*
653*53933Shibler 	 * Deal with the "normal" writebacks.
654*53933Shibler 	 *
655*53933Shibler 	 * XXX writeback2 is known to reflect a LINE size writeback after
656*53933Shibler 	 * a MOVE16 was already dealt with above.  Ignore it.
657*53933Shibler 	 */
658*53933Shibler 	if (err == 0 && (f->f_wb2s & SSW4_WBSV) &&
659*53933Shibler 	    (f->f_wb2s & SSW4_SZMASK) != SSW4_SZLN) {
660*53933Shibler #ifdef DEBUG
661*53933Shibler 		if ((mmudebug & MDB_WBFOLLOW) || MDB_ISPID(p->p_pid))
662*53933Shibler 			dumpwb(2, f->f_wb2s, f->f_wb2a, f->f_wb2d);
663*53933Shibler 		wbstats.wb2s++;
664*53933Shibler 		wbstats.wbsize[(f->f_wb2s&SSW4_SZMASK)>>5]++;
665*53933Shibler #endif
666*53933Shibler 		switch (f->f_wb2s & SSW4_SZMASK) {
667*53933Shibler 		case SSW4_SZLW:
668*53933Shibler 			if (KDFAULT(f->f_wb2s))
669*53933Shibler 				*(long *)f->f_wb2a = f->f_wb2d;
670*53933Shibler 			else
671*53933Shibler 				err = suword((caddr_t)f->f_wb2a, f->f_wb2d);
672*53933Shibler 			break;
673*53933Shibler 		case SSW4_SZB:
674*53933Shibler 			if (KDFAULT(f->f_wb2s))
675*53933Shibler 				*(char *)f->f_wb2a = f->f_wb2d;
676*53933Shibler 			else
677*53933Shibler 				err = subyte((caddr_t)f->f_wb2a, f->f_wb2d);
678*53933Shibler 			break;
679*53933Shibler 		case SSW4_SZW:
680*53933Shibler 			if (KDFAULT(f->f_wb2s))
681*53933Shibler 				*(short *)f->f_wb2a = f->f_wb2d;
682*53933Shibler 			else
683*53933Shibler 				err = susword((caddr_t)f->f_wb2a, f->f_wb2d);
684*53933Shibler 			break;
685*53933Shibler 		}
686*53933Shibler 		if (err) {
687*53933Shibler 			fa = f->f_wb2a;
688*53933Shibler #ifdef DEBUG
689*53933Shibler 			if (mmudebug & MDB_WBFAILED) {
690*53933Shibler 				printf(wberrstr, p->p_pid, p->p_comm,
691*53933Shibler 				       "#2", fp->f_pc, f->f_fa,
692*53933Shibler 				       f->f_wb2a, f->f_wb2d);
693*53933Shibler 				dumpssw(f->f_ssw);
694*53933Shibler 				dumpwb(2, f->f_wb2s, f->f_wb2a, f->f_wb2d);
695*53933Shibler 			}
696*53933Shibler #endif
697*53933Shibler 		}
698*53933Shibler 	}
699*53933Shibler 	if (err == 0 && (f->f_wb3s & SSW4_WBSV)) {
700*53933Shibler #ifdef DEBUG
701*53933Shibler 		if ((mmudebug & MDB_WBFOLLOW) || MDB_ISPID(p->p_pid))
702*53933Shibler 			dumpwb(3, f->f_wb3s, f->f_wb3a, f->f_wb3d);
703*53933Shibler 		wbstats.wb3s++;
704*53933Shibler 		wbstats.wbsize[(f->f_wb3s&SSW4_SZMASK)>>5]++;
705*53933Shibler #endif
706*53933Shibler 		switch (f->f_wb3s & SSW4_SZMASK) {
707*53933Shibler 		case SSW4_SZLW:
708*53933Shibler 			if (KDFAULT(f->f_wb3s))
709*53933Shibler 				*(long *)f->f_wb3a = f->f_wb3d;
710*53933Shibler 			else
711*53933Shibler 				err = suword((caddr_t)f->f_wb3a, f->f_wb3d);
712*53933Shibler 			break;
713*53933Shibler 		case SSW4_SZB:
714*53933Shibler 			if (KDFAULT(f->f_wb3s))
715*53933Shibler 				*(char *)f->f_wb3a = f->f_wb3d;
716*53933Shibler 			else
717*53933Shibler 				err = subyte((caddr_t)f->f_wb3a, f->f_wb3d);
718*53933Shibler 			break;
719*53933Shibler 		case SSW4_SZW:
720*53933Shibler 			if (KDFAULT(f->f_wb3s))
721*53933Shibler 				*(short *)f->f_wb3a = f->f_wb3d;
722*53933Shibler 			else
723*53933Shibler 				err = susword((caddr_t)f->f_wb3a, f->f_wb3d);
724*53933Shibler 			break;
725*53933Shibler #ifdef DEBUG
726*53933Shibler 		case SSW4_SZLN:
727*53933Shibler 			panic("writeback: wb3s indicates LINE write");
728*53933Shibler #endif
729*53933Shibler 		}
730*53933Shibler 		if (err) {
731*53933Shibler 			fa = f->f_wb3a;
732*53933Shibler #ifdef DEBUG
733*53933Shibler 			if (mmudebug & MDB_WBFAILED)
734*53933Shibler 				printf(wberrstr, p->p_pid, p->p_comm,
735*53933Shibler 				       "#3", fp->f_pc, f->f_fa,
736*53933Shibler 				       f->f_wb3a, f->f_wb3d);
737*53933Shibler #endif
738*53933Shibler 		}
739*53933Shibler 	}
740*53933Shibler 	p->p_addr->u_pcb.pcb_onfault = oonfault;
741*53933Shibler 	/*
742*53933Shibler 	 * Determine the cause of the failure if any translating to
743*53933Shibler 	 * a signal.  If the corresponding VA is valid and RO it is
744*53933Shibler 	 * a protection fault (SIGBUS) otherwise consider it an
745*53933Shibler 	 * illegal reference (SIGSEGV).
746*53933Shibler 	 */
747*53933Shibler 	if (err) {
748*53933Shibler 		if (vm_map_check_protection(&p->p_vmspace->vm_map,
749*53933Shibler 					    trunc_page(fa), round_page(fa),
750*53933Shibler 					    VM_PROT_READ) &&
751*53933Shibler 		    !vm_map_check_protection(&p->p_vmspace->vm_map,
752*53933Shibler 					     trunc_page(fa), round_page(fa),
753*53933Shibler 					     VM_PROT_WRITE))
754*53933Shibler 			err = SIGBUS;
755*53933Shibler 		else
756*53933Shibler 			err = SIGSEGV;
757*53933Shibler 	}
758*53933Shibler 	return(err);
759*53933Shibler }
760*53933Shibler 
761*53933Shibler #ifdef DEBUG
762*53933Shibler dumpssw(ssw)
763*53933Shibler 	register u_short ssw;
764*53933Shibler {
765*53933Shibler 	printf(" SSW: %x: ", ssw);
766*53933Shibler 	if (ssw & SSW4_CP)
767*53933Shibler 		printf("CP,");
768*53933Shibler 	if (ssw & SSW4_CU)
769*53933Shibler 		printf("CU,");
770*53933Shibler 	if (ssw & SSW4_CT)
771*53933Shibler 		printf("CT,");
772*53933Shibler 	if (ssw & SSW4_CM)
773*53933Shibler 		printf("CM,");
774*53933Shibler 	if (ssw & SSW4_MA)
775*53933Shibler 		printf("MA,");
776*53933Shibler 	if (ssw & SSW4_ATC)
777*53933Shibler 		printf("ATC,");
778*53933Shibler 	if (ssw & SSW4_LK)
779*53933Shibler 		printf("LK,");
780*53933Shibler 	if (ssw & SSW4_RW)
781*53933Shibler 		printf("RW,");
782*53933Shibler 	printf(" SZ=%s, TT=%s, TM=%s\n",
783*53933Shibler 	       f7sz[(ssw & SSW4_SZMASK) >> 5],
784*53933Shibler 	       f7tt[(ssw & SSW4_TTMASK) >> 3],
785*53933Shibler 	       f7tm[ssw & SSW4_TMMASK]);
786*53933Shibler }
787*53933Shibler 
788*53933Shibler dumpwb(num, s, a, d)
789*53933Shibler 	int num;
790*53933Shibler 	u_short s;
791*53933Shibler 	u_int a, d;
792*53933Shibler {
793*53933Shibler 	register struct proc *p = curproc;
794*53933Shibler 	vm_offset_t pa;
795*53933Shibler 
796*53933Shibler 	printf(" writeback #%d: VA %x, data %x, SZ=%s, TT=%s, TM=%s\n",
797*53933Shibler 	       num, a, d, f7sz[(s & SSW4_SZMASK) >> 5],
798*53933Shibler 	       f7tt[(s & SSW4_TTMASK) >> 3], f7tm[s & SSW4_TMMASK]);
799*53933Shibler 	printf("               PA ");
800*53933Shibler 	pa = pmap_extract(&p->p_vmspace->vm_pmap, (vm_offset_t)a);
801*53933Shibler 	if (pa == 0)
802*53933Shibler 		printf("<invalid address>");
803*53933Shibler 	else
804*53933Shibler 		printf("%x, current value %x", pa, fuword((caddr_t)a));
805*53933Shibler 	printf("\n");
806*53933Shibler }
807*53933Shibler 
808*53933Shibler #ifdef HPFPLIB
809*53933Shibler fppanic(frame)
810*53933Shibler 	struct fppanicframe {
811*53933Shibler 		int	fpsaveframe;
812*53933Shibler 		int	regs[16];
813*53933Shibler 		int	fpregs[8*3];
814*53933Shibler 		int	fpcregs[3];
815*53933Shibler 		int	hole[5];
816*53933Shibler 		int	oa6;
817*53933Shibler 		short	sr;
818*53933Shibler 		int	pc;
819*53933Shibler 		short	vector;
820*53933Shibler 	} frame;
821*53933Shibler {
822*53933Shibler 	printf("FP exception: pid %d(%s): no busy frame, ft=%x pc=%x vec=%x\n",
823*53933Shibler 	       curproc->p_pid, curproc->p_comm,
824*53933Shibler 	       frame.fpsaveframe, frame.pc, frame.vector);
825*53933Shibler 	panic("bad FP exception");
826*53933Shibler }
827*53933Shibler #endif
828*53933Shibler #endif
829*53933Shibler #endif
830*53933Shibler 
83141475Smckusick /*
83249531Skarels  * Proces a system call.
83341475Smckusick  */
83441475Smckusick syscall(code, frame)
83553029Shibler 	volatile unsigned code;
83641475Smckusick 	struct frame frame;
83741475Smckusick {
83841475Smckusick 	register caddr_t params;
83941475Smckusick 	register int i;
84041475Smckusick 	register struct sysent *callp;
84148465Skarels 	register struct proc *p = curproc;
84250753Skarels 	int error, opc, numsys, s;
84344018Skarels 	struct args {
84444018Skarels 		int i[8];
84544018Skarels 	} args;
84644018Skarels 	int rval[2];
84741475Smckusick 	struct timeval syst;
84841475Smckusick 	struct sysent *systab;
849*53933Shibler #if defined(HP380)
850*53933Shibler 	int beenhere = 0;
851*53933Shibler #endif
85241475Smckusick #ifdef HPUXCOMPAT
85341475Smckusick 	extern struct sysent hpuxsysent[];
85441475Smckusick 	extern int hpuxnsysent, notimp();
85541475Smckusick #endif
85641475Smckusick 
85741475Smckusick 	cnt.v_syscall++;
85848465Skarels 	syst = p->p_stime;
85941475Smckusick 	if (!USERMODE(frame.f_sr))
86041475Smckusick 		panic("syscall");
86152380Smckusick 	p->p_md.md_regs = frame.f_regs;
86241475Smckusick 	opc = frame.f_pc - 2;
86341475Smckusick 	systab = sysent;
86441475Smckusick 	numsys = nsysent;
86541475Smckusick #ifdef HPUXCOMPAT
86642370Skarels 	if (p->p_flag & SHPUX) {
86741475Smckusick 		systab = hpuxsysent;
86841475Smckusick 		numsys = hpuxnsysent;
86941475Smckusick 	}
87041475Smckusick #endif
87149531Skarels 	params = (caddr_t)frame.f_regs[SP] + sizeof(int);
87242370Skarels 	if (code == 0) {			/* indir */
87342370Skarels 		code = fuword(params);
87449531Skarels 		params += sizeof(int);
87542370Skarels 	}
87642370Skarels 	if (code >= numsys)
87742370Skarels 		callp = &systab[0];		/* indir (illegal) */
87842370Skarels 	else
87942370Skarels 		callp = &systab[code];
88041475Smckusick 	if ((i = callp->sy_narg * sizeof (int)) &&
88144018Skarels 	    (error = copyin(params, (caddr_t)&args, (u_int)i))) {
88241475Smckusick #ifdef HPUXCOMPAT
88341475Smckusick 		if (p->p_flag & SHPUX)
88442370Skarels 			error = bsdtohpuxerrno(error);
88541475Smckusick #endif
88649362Skarels 		frame.f_regs[D0] = error;
88741475Smckusick 		frame.f_sr |= PSL_C;	/* carry bit */
88841475Smckusick #ifdef KTRACE
88943641Skarels 		if (KTRPOINT(p, KTR_SYSCALL))
89044018Skarels 			ktrsyscall(p->p_tracep, code, callp->sy_narg, args.i);
89141475Smckusick #endif
89241475Smckusick 		goto done;
89341475Smckusick 	}
89441475Smckusick #ifdef KTRACE
89543641Skarels 	if (KTRPOINT(p, KTR_SYSCALL))
89644018Skarels 		ktrsyscall(p->p_tracep, code, callp->sy_narg, args.i);
89741475Smckusick #endif
89843641Skarels 	rval[0] = 0;
89943641Skarels 	rval[1] = frame.f_regs[D1];
90041475Smckusick #ifdef HPUXCOMPAT
90142370Skarels 	/* debug kludge */
90242370Skarels 	if (callp->sy_call == notimp)
90348465Skarels 		error = notimp(p, args.i, rval, code, callp->sy_narg);
90442370Skarels 	else
90541475Smckusick #endif
90648465Skarels 	error = (*callp->sy_call)(p, &args, rval);
90742370Skarels 	if (error == ERESTART)
90842370Skarels 		frame.f_pc = opc;
90942370Skarels 	else if (error != EJUSTRETURN) {
91042370Skarels 		if (error) {
91141475Smckusick #ifdef HPUXCOMPAT
91242370Skarels 			if (p->p_flag & SHPUX)
91342370Skarels 				error = bsdtohpuxerrno(error);
91441475Smckusick #endif
91549362Skarels 			frame.f_regs[D0] = error;
91642370Skarels 			frame.f_sr |= PSL_C;	/* carry bit */
91741475Smckusick 		} else {
91843641Skarels 			frame.f_regs[D0] = rval[0];
91943641Skarels 			frame.f_regs[D1] = rval[1];
92041475Smckusick 			frame.f_sr &= ~PSL_C;
92141475Smckusick 		}
92242370Skarels 	}
92342370Skarels 	/* else if (error == EJUSTRETURN) */
92441475Smckusick 		/* nothing to do */
92542370Skarels 
92641475Smckusick done:
92741475Smckusick 	/*
92842370Skarels 	 * Reinitialize proc pointer `p' as it may be different
92942370Skarels 	 * if this is a child returning from fork syscall.
93042370Skarels 	 */
93148465Skarels 	p = curproc;
93249317Shibler 	while (i = CURSIG(p))
93349317Shibler 		psig(i);
93441475Smckusick 	p->p_pri = p->p_usrpri;
93548465Skarels 	if (want_resched) {
93641475Smckusick 		/*
93748465Skarels 		 * Since we are curproc, clock will normally just change
93841475Smckusick 		 * our priority without moving us from one queue to another
93941475Smckusick 		 * (since the running process is not on a queue.)
94041475Smckusick 		 * If that happened after we setrq ourselves but before we
94141475Smckusick 		 * swtch()'ed, we might not be on the queue indicated by
94241475Smckusick 		 * our priority.
94341475Smckusick 		 */
94450753Skarels 		s = splclock();
94541475Smckusick 		setrq(p);
94648465Skarels 		p->p_stats->p_ru.ru_nivcsw++;
94741475Smckusick 		swtch();
94850753Skarels 		splx(s);
94949317Shibler 		while (i = CURSIG(p))
95049317Shibler 			psig(i);
95141475Smckusick 	}
95248465Skarels 	if (p->p_stats->p_prof.pr_scale) {
95341475Smckusick 		int ticks;
95448465Skarels 		struct timeval *tv = &p->p_stime;
95541475Smckusick 
95641475Smckusick 		ticks = ((tv->tv_sec - syst.tv_sec) * 1000 +
95741475Smckusick 			(tv->tv_usec - syst.tv_usec) / 1000) / (tick / 1000);
95841475Smckusick 		if (ticks) {
95941475Smckusick #ifdef PROFTIMER
96041475Smckusick 			extern int profscale;
96148465Skarels 			addupc(frame.f_pc, &p->p_stats->p_prof,
96248465Skarels 			    ticks * profscale);
96341475Smckusick #else
96448465Skarels 			addupc(frame.f_pc, &p->p_stats->p_prof, ticks);
96541475Smckusick #endif
96641475Smckusick 		}
96741475Smckusick 	}
968*53933Shibler #if defined(HP380)
969*53933Shibler 	/*
970*53933Shibler 	 * Deal with writebacks when returning from sigreturn.
971*53933Shibler 	 * They may generate another signal to be processed.
972*53933Shibler 	 * Again, we don't attempt the writeback if we have already
973*53933Shibler 	 * tried and failed (see comment in trap).
974*53933Shibler 	 */
975*53933Shibler 	if (mmutype == MMU_68040 && frame.f_format == FMT7) {
976*53933Shibler 		if (beenhere) {
977*53933Shibler #ifdef DEBUG
978*53933Shibler 			if (mmudebug & MDB_WBFAILED)
979*53933Shibler 			printf("pid %d(%s): writeback aborted in sigreturn, pc=%x\n",
980*53933Shibler 			       p->p_pid, p->p_comm, frame.f_pc);
981*53933Shibler #endif
982*53933Shibler 			;
983*53933Shibler 		} else if (i = writeback(&frame, 0)) {
984*53933Shibler 			beenhere++;
985*53933Shibler 			syst = p->p_stime;
986*53933Shibler 			trapsignal(p, i, 0);
987*53933Shibler 			goto done;
988*53933Shibler 		}
989*53933Shibler 	}
990*53933Shibler #endif
99141475Smckusick 	curpri = p->p_pri;
99241475Smckusick #ifdef KTRACE
99343641Skarels 	if (KTRPOINT(p, KTR_SYSRET))
99443641Skarels 		ktrsysret(p->p_tracep, code, error, rval[0]);
99541475Smckusick #endif
99641475Smckusick }
997