xref: /csrg-svn/sys/hp300/hp300/trap.c (revision 52380)
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  *
1249317Shibler  * from: Utah $Hdr: trap.c 1.32 91/04/06$
1341475Smckusick  *
14*52380Smckusick  *	@(#)trap.c	7.18 (Berkeley) 02/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
4041475Smckusick #include "../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) */
7149317Shibler 	-1,		/* type 3 - FP post-instruction (68040) */
7249317Shibler 	-1, -1, -1,	/* type 4-6 - undefined */
7349317Shibler 	-1,		/* 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 
8141475Smckusick #ifdef DEBUG
8241475Smckusick int mmudebug = 0;
8341475Smckusick #endif
8441475Smckusick 
8541475Smckusick /*
8649531Skarels  * Trap is called from locore to handle most types of processor traps,
8749531Skarels  * including events such as simulated software interrupts/AST's.
8849531Skarels  * System calls are broken out for efficiency.
8941475Smckusick  */
9041475Smckusick /*ARGSUSED*/
9141475Smckusick trap(type, code, v, frame)
9241475Smckusick 	int type;
9341475Smckusick 	unsigned code;
9441475Smckusick 	register unsigned v;
9541475Smckusick 	struct frame frame;
9641475Smckusick {
9741475Smckusick 	register int i;
9841475Smckusick 	unsigned ucode = 0;
9948465Skarels 	register struct proc *p = curproc;
10041475Smckusick 	struct timeval syst;
10141475Smckusick 	unsigned ncode;
10250753Skarels 	int s;
10341475Smckusick 
10441475Smckusick 	cnt.v_trap++;
10548465Skarels 	syst = p->p_stime;
10641475Smckusick 	if (USERMODE(frame.f_sr)) {
10749531Skarels 		type |= T_USER;
108*52380Smckusick 		p->p_md.md_regs = frame.f_regs;
10941475Smckusick 	}
11041475Smckusick 	switch (type) {
11141475Smckusick 
11241475Smckusick 	default:
11341475Smckusick dopanic:
11441475Smckusick 		printf("trap type %d, code = %x, v = %x\n", type, code, v);
11541475Smckusick 		regdump(frame.f_regs, 128);
11649531Skarels 		type &= ~T_USER;
11741475Smckusick 		if ((unsigned)type < TRAP_TYPES)
11841475Smckusick 			panic(trap_type[type]);
11941475Smckusick 		panic("trap");
12041475Smckusick 
12141475Smckusick 	case T_BUSERR:		/* kernel bus error */
12249125Skarels 		if (!p->p_addr->u_pcb.pcb_onfault)
12341475Smckusick 			goto dopanic;
12441475Smckusick 		/*
12541475Smckusick 		 * If we have arranged to catch this fault in any of the
12641475Smckusick 		 * copy to/from user space routines, set PC to return to
12741475Smckusick 		 * indicated location and set flag informing buserror code
12841475Smckusick 		 * that it may need to clean up stack frame.
12941475Smckusick 		 */
13041475Smckusick copyfault:
13149317Shibler 		frame.f_stackadj = exframesize[frame.f_format];
13249317Shibler 		frame.f_format = frame.f_vector = 0;
13349125Skarels 		frame.f_pc = (int) p->p_addr->u_pcb.pcb_onfault;
13441475Smckusick 		return;
13541475Smckusick 
13649531Skarels 	case T_BUSERR|T_USER:	/* bus error */
13749531Skarels 	case T_ADDRERR|T_USER:	/* address error */
13841475Smckusick 		i = SIGBUS;
13941475Smckusick 		break;
14041475Smckusick 
14141475Smckusick #ifdef FPCOPROC
14241475Smckusick 	case T_COPERR:		/* kernel coprocessor violation */
14341475Smckusick #endif
14441475Smckusick 	case T_FMTERR:		/* kernel format error */
14541475Smckusick 	/*
14641475Smckusick 	 * The user has most likely trashed the RTE or FP state info
14741475Smckusick 	 * in the stack frame of a signal handler.
14841475Smckusick 	 */
14949531Skarels 		type |= T_USER;
15048465Skarels 		printf("pid %d: kernel %s exception\n", p->p_pid,
15141475Smckusick 		       type==T_COPERR ? "coprocessor" : "format");
15248465Skarels 		p->p_sigacts->ps_sigact[SIGILL] = SIG_DFL;
15341475Smckusick 		i = sigmask(SIGILL);
15441475Smckusick 		p->p_sigignore &= ~i;
15541475Smckusick 		p->p_sigcatch &= ~i;
15641475Smckusick 		p->p_sigmask &= ~i;
15742370Skarels 		i = SIGILL;
15841475Smckusick 		ucode = frame.f_format;	/* XXX was ILL_RESAD_FAULT */
15942370Skarels 		break;
16041475Smckusick 
16141475Smckusick #ifdef FPCOPROC
16249531Skarels 	case T_COPERR|T_USER:	/* user coprocessor violation */
16341475Smckusick 	/* What is a proper response here? */
16441475Smckusick 		ucode = 0;
16541475Smckusick 		i = SIGFPE;
16641475Smckusick 		break;
16741475Smckusick 
16849531Skarels 	case T_FPERR|T_USER:	/* 68881 exceptions */
16941475Smckusick 	/*
17041475Smckusick 	 * We pass along the 68881 status register which locore stashed
17141475Smckusick 	 * in code for us.  Note that there is a possibility that the
17241475Smckusick 	 * bit pattern of this register will conflict with one of the
17341475Smckusick 	 * FPE_* codes defined in signal.h.  Fortunately for us, the
17441475Smckusick 	 * only such codes we use are all in the range 1-7 and the low
17541475Smckusick 	 * 3 bits of the status register are defined as 0 so there is
17641475Smckusick 	 * no clash.
17741475Smckusick 	 */
17841475Smckusick 		ucode = code;
17941475Smckusick 		i = SIGFPE;
18041475Smckusick 		break;
18141475Smckusick #endif
18241475Smckusick 
18349531Skarels 	case T_ILLINST|T_USER:	/* illegal instruction fault */
18441475Smckusick #ifdef HPUXCOMPAT
18548465Skarels 		if (p->p_flag & SHPUX) {
18641475Smckusick 			ucode = HPUX_ILL_ILLINST_TRAP;
18741475Smckusick 			i = SIGILL;
18841475Smckusick 			break;
18941475Smckusick 		}
19041475Smckusick 		/* fall through */
19141475Smckusick #endif
19249531Skarels 	case T_PRIVINST|T_USER:	/* privileged instruction fault */
19341475Smckusick #ifdef HPUXCOMPAT
19448465Skarels 		if (p->p_flag & SHPUX)
19541475Smckusick 			ucode = HPUX_ILL_PRIV_TRAP;
19641475Smckusick 		else
19741475Smckusick #endif
19841475Smckusick 		ucode = frame.f_format;	/* XXX was ILL_PRIVIN_FAULT */
19941475Smckusick 		i = SIGILL;
20041475Smckusick 		break;
20141475Smckusick 
20249531Skarels 	case T_ZERODIV|T_USER:	/* Divide by zero */
20341475Smckusick #ifdef HPUXCOMPAT
20448465Skarels 		if (p->p_flag & SHPUX)
20541475Smckusick 			ucode = HPUX_FPE_INTDIV_TRAP;
20641475Smckusick 		else
20741475Smckusick #endif
20841475Smckusick 		ucode = frame.f_format;	/* XXX was FPE_INTDIV_TRAP */
20941475Smckusick 		i = SIGFPE;
21041475Smckusick 		break;
21141475Smckusick 
21249531Skarels 	case T_CHKINST|T_USER:	/* CHK instruction trap */
21341475Smckusick #ifdef HPUXCOMPAT
21448465Skarels 		if (p->p_flag & SHPUX) {
21541475Smckusick 			/* handled differently under hp-ux */
21641475Smckusick 			i = SIGILL;
21741475Smckusick 			ucode = HPUX_ILL_CHK_TRAP;
21841475Smckusick 			break;
21941475Smckusick 		}
22041475Smckusick #endif
22141475Smckusick 		ucode = frame.f_format;	/* XXX was FPE_SUBRNG_TRAP */
22241475Smckusick 		i = SIGFPE;
22341475Smckusick 		break;
22441475Smckusick 
22549531Skarels 	case T_TRAPVINST|T_USER:	/* TRAPV instruction trap */
22641475Smckusick #ifdef HPUXCOMPAT
22748465Skarels 		if (p->p_flag & SHPUX) {
22841475Smckusick 			/* handled differently under hp-ux */
22941475Smckusick 			i = SIGILL;
23041475Smckusick 			ucode = HPUX_ILL_TRAPV_TRAP;
23141475Smckusick 			break;
23241475Smckusick 		}
23341475Smckusick #endif
23441475Smckusick 		ucode = frame.f_format;	/* XXX was FPE_INTOVF_TRAP */
23541475Smckusick 		i = SIGFPE;
23641475Smckusick 		break;
23741475Smckusick 
23841475Smckusick 	/*
23941475Smckusick 	 * XXX: Trace traps are a nightmare.
24041475Smckusick 	 *
24141475Smckusick 	 *	HP-UX uses trap #1 for breakpoints,
24241475Smckusick 	 *	HPBSD uses trap #2,
24341475Smckusick 	 *	SUN 3.x uses trap #15,
24448465Skarels 	 *	KGDB uses trap #15 (for kernel breakpoints; handled elsewhere).
24541475Smckusick 	 *
24641475Smckusick 	 * HPBSD and HP-UX traps both get mapped by locore.s into T_TRACE.
24741475Smckusick 	 * SUN 3.x traps get passed through as T_TRAP15 and are not really
24848465Skarels 	 * supported yet.
24941475Smckusick 	 */
25041475Smckusick 	case T_TRACE:		/* kernel trace trap */
25148465Skarels 	case T_TRAP15:		/* SUN trace trap */
25241475Smckusick 		frame.f_sr &= ~PSL_T;
25341475Smckusick 		i = SIGTRAP;
25441475Smckusick 		break;
25541475Smckusick 
25649531Skarels 	case T_TRACE|T_USER:	/* user trace trap */
25749531Skarels 	case T_TRAP15|T_USER:	/* SUN user trace trap */
25841475Smckusick 		frame.f_sr &= ~PSL_T;
25941475Smckusick 		i = SIGTRAP;
26041475Smckusick 		break;
26141475Smckusick 
26243413Shibler 	case T_ASTFLT:		/* system async trap, cannot happen */
26341475Smckusick 		goto dopanic;
26441475Smckusick 
26549531Skarels 	case T_ASTFLT|T_USER:	/* user async trap */
26649125Skarels 		astpending = 0;
26741475Smckusick 		/*
26841475Smckusick 		 * We check for software interrupts first.  This is because
26941475Smckusick 		 * they are at a higher level than ASTs, and on a VAX would
27041475Smckusick 		 * interrupt the AST.  We assume that if we are processing
27141475Smckusick 		 * an AST that we must be at IPL0 so we don't bother to
27241475Smckusick 		 * check.  Note that we ensure that we are at least at SIR
27341475Smckusick 		 * IPL while processing the SIR.
27441475Smckusick 		 */
27541475Smckusick 		spl1();
27641475Smckusick 		/* fall into... */
27741475Smckusick 
27841475Smckusick 	case T_SSIR:		/* software interrupt */
27949531Skarels 	case T_SSIR|T_USER:
28041475Smckusick 		if (ssir & SIR_NET) {
28141475Smckusick 			siroff(SIR_NET);
28241475Smckusick 			cnt.v_soft++;
28341475Smckusick 			netintr();
28441475Smckusick 		}
28541475Smckusick 		if (ssir & SIR_CLOCK) {
28641475Smckusick 			siroff(SIR_CLOCK);
28741475Smckusick 			cnt.v_soft++;
28841475Smckusick 			softclock((caddr_t)frame.f_pc, (int)frame.f_sr);
28941475Smckusick 		}
29041475Smckusick 		/*
29141475Smckusick 		 * If this was not an AST trap, we are all done.
29241475Smckusick 		 */
29350753Skarels 		if (type != (T_ASTFLT|T_USER)) {
29441475Smckusick 			cnt.v_trap--;
29541475Smckusick 			return;
29641475Smckusick 		}
29741475Smckusick 		spl0();
29841475Smckusick #ifndef PROFTIMER
29948465Skarels 		if ((p->p_flag&SOWEUPC) && p->p_stats->p_prof.pr_scale) {
30048465Skarels 			addupc(frame.f_pc, &p->p_stats->p_prof, 1);
30148465Skarels 			p->p_flag &= ~SOWEUPC;
30241475Smckusick 		}
30341475Smckusick #endif
30441475Smckusick 		goto out;
30541475Smckusick 
30641475Smckusick 	case T_MMUFLT:		/* kernel mode page fault */
30741475Smckusick 		/* fall into ... */
30841475Smckusick 
30949531Skarels 	case T_MMUFLT|T_USER:	/* page fault */
31045751Smckusick 	    {
31145751Smckusick 		register vm_offset_t va;
31248465Skarels 		register struct vmspace *vm = p->p_vmspace;
31345751Smckusick 		register vm_map_t map;
31445751Smckusick 		int rv;
31545751Smckusick 		vm_prot_t ftype;
31645751Smckusick 		extern vm_map_t kernel_map;
31745751Smckusick 
31841475Smckusick 		/*
31945751Smckusick 		 * It is only a kernel address space fault iff:
32049531Skarels 		 * 	1. (type & T_USER) == 0  and
32145751Smckusick 		 * 	2. pcb_onfault not set or
32245751Smckusick 		 *	3. pcb_onfault set but supervisor space data fault
32345751Smckusick 		 * The last can occur during an exec() copyin where the
32445751Smckusick 		 * argument space is lazy-allocated.
32541475Smckusick 		 */
32645751Smckusick 		if (type == T_MMUFLT &&
32749125Skarels 		    (!p->p_addr->u_pcb.pcb_onfault ||
32845751Smckusick 		     (code & (SSW_DF|FC_SUPERD)) == (SSW_DF|FC_SUPERD)))
32945751Smckusick 			map = kernel_map;
33045751Smckusick 		else
33148465Skarels 			map = &vm->vm_map;
33245751Smckusick 		if ((code & (SSW_DF|SSW_RW)) == SSW_DF)	/* what about RMW? */
33345751Smckusick 			ftype = VM_PROT_READ | VM_PROT_WRITE;
33445751Smckusick 		else
33545751Smckusick 			ftype = VM_PROT_READ;
33645751Smckusick 		va = trunc_page((vm_offset_t)v);
33741475Smckusick #ifdef DEBUG
33845751Smckusick 		if (map == kernel_map && va == 0) {
33945751Smckusick 			printf("trap: bad kernel access at %x\n", v);
34041475Smckusick 			goto dopanic;
34141475Smckusick 		}
34241475Smckusick #endif
34349317Shibler 		rv = vm_fault(map, va, ftype, FALSE);
34441475Smckusick 		/*
34549317Shibler 		 * If this was a stack access we keep track of the maximum
34649317Shibler 		 * accessed stack size.  Also, if vm_fault gets a protection
34749317Shibler 		 * failure it is due to accessing the stack region outside
34849317Shibler 		 * the current limit and we need to reflect that as an access
34949317Shibler 		 * error.
35041475Smckusick 		 */
35148465Skarels 		if ((caddr_t)va >= vm->vm_maxsaddr && map != kernel_map) {
35249317Shibler 			if (rv == KERN_SUCCESS) {
35349317Shibler 				unsigned nss;
35449317Shibler 
35549317Shibler 				nss = clrnd(btoc(USRSTACK-(unsigned)va));
35649317Shibler 				if (nss > vm->vm_ssize)
35749317Shibler 					vm->vm_ssize = nss;
35849317Shibler 			} else if (rv == KERN_PROTECTION_FAILURE)
35949317Shibler 				rv = KERN_INVALID_ADDRESS;
36041475Smckusick 		}
36145751Smckusick 		if (rv == KERN_SUCCESS) {
36241475Smckusick 			if (type == T_MMUFLT)
36341475Smckusick 				return;
36441475Smckusick 			goto out;
36541475Smckusick 		}
36645751Smckusick 		if (type == T_MMUFLT) {
36749125Skarels 			if (p->p_addr->u_pcb.pcb_onfault)
36845751Smckusick 				goto copyfault;
36945751Smckusick 			printf("vm_fault(%x, %x, %x, 0) -> %x\n",
37045751Smckusick 			       map, va, ftype, rv);
37145751Smckusick 			printf("  type %x, code [mmu,,ssw]: %x\n",
37245751Smckusick 			       type, code);
37345751Smckusick 			goto dopanic;
37445751Smckusick 		}
37548465Skarels 		ucode = v;
37645751Smckusick 		i = (rv == KERN_PROTECTION_FAILURE) ? SIGBUS : SIGSEGV;
37745751Smckusick 		break;
37845751Smckusick 	    }
37941475Smckusick 	}
38048465Skarels 	trapsignal(p, i, ucode);
38149531Skarels 	if ((type & T_USER) == 0)
38241475Smckusick 		return;
38341475Smckusick out:
38448465Skarels 	while (i = CURSIG(p))
38542370Skarels 		psig(i);
38641475Smckusick 	p->p_pri = p->p_usrpri;
38748465Skarels 	if (want_resched) {
38841475Smckusick 		/*
38948465Skarels 		 * Since we are curproc, clock will normally just change
39041475Smckusick 		 * our priority without moving us from one queue to another
39141475Smckusick 		 * (since the running process is not on a queue.)
39241475Smckusick 		 * If that happened after we setrq ourselves but before we
39341475Smckusick 		 * swtch()'ed, we might not be on the queue indicated by
39441475Smckusick 		 * our priority.
39541475Smckusick 		 */
39650753Skarels 		s = splclock();
39741475Smckusick 		setrq(p);
39848465Skarels 		p->p_stats->p_ru.ru_nivcsw++;
39941475Smckusick 		swtch();
40050753Skarels 		splx(s);
40148465Skarels 		while (i = CURSIG(p))
40242370Skarels 			psig(i);
40341475Smckusick 	}
40448465Skarels 	if (p->p_stats->p_prof.pr_scale) {
40541475Smckusick 		int ticks;
40648465Skarels 		struct timeval *tv = &p->p_stime;
40741475Smckusick 
40841475Smckusick 		ticks = ((tv->tv_sec - syst.tv_sec) * 1000 +
40941475Smckusick 			(tv->tv_usec - syst.tv_usec) / 1000) / (tick / 1000);
41041475Smckusick 		if (ticks) {
41141475Smckusick #ifdef PROFTIMER
41241475Smckusick 			extern int profscale;
41348465Skarels 			addupc(frame.f_pc, &p->p_stats->p_prof,
41448465Skarels 			    ticks * profscale);
41541475Smckusick #else
41648465Skarels 			addupc(frame.f_pc, &p->p_stats->p_prof, ticks);
41741475Smckusick #endif
41841475Smckusick 		}
41941475Smckusick 	}
42041475Smckusick 	curpri = p->p_pri;
42141475Smckusick }
42241475Smckusick 
42341475Smckusick /*
42449531Skarels  * Proces a system call.
42541475Smckusick  */
42641475Smckusick syscall(code, frame)
42741475Smckusick 	volatile int code;
42841475Smckusick 	struct frame frame;
42941475Smckusick {
43041475Smckusick 	register caddr_t params;
43141475Smckusick 	register int i;
43241475Smckusick 	register struct sysent *callp;
43348465Skarels 	register struct proc *p = curproc;
43450753Skarels 	int error, opc, numsys, s;
43544018Skarels 	struct args {
43644018Skarels 		int i[8];
43744018Skarels 	} args;
43844018Skarels 	int rval[2];
43941475Smckusick 	struct timeval syst;
44041475Smckusick 	struct sysent *systab;
44141475Smckusick #ifdef HPUXCOMPAT
44241475Smckusick 	extern struct sysent hpuxsysent[];
44341475Smckusick 	extern int hpuxnsysent, notimp();
44441475Smckusick #endif
44541475Smckusick 
44641475Smckusick 	cnt.v_syscall++;
44748465Skarels 	syst = p->p_stime;
44841475Smckusick 	if (!USERMODE(frame.f_sr))
44941475Smckusick 		panic("syscall");
450*52380Smckusick 	p->p_md.md_regs = frame.f_regs;
45141475Smckusick 	opc = frame.f_pc - 2;
45241475Smckusick 	systab = sysent;
45341475Smckusick 	numsys = nsysent;
45441475Smckusick #ifdef HPUXCOMPAT
45542370Skarels 	if (p->p_flag & SHPUX) {
45641475Smckusick 		systab = hpuxsysent;
45741475Smckusick 		numsys = hpuxnsysent;
45841475Smckusick 	}
45941475Smckusick #endif
46049531Skarels 	params = (caddr_t)frame.f_regs[SP] + sizeof(int);
46142370Skarels 	if (code == 0) {			/* indir */
46242370Skarels 		code = fuword(params);
46349531Skarels 		params += sizeof(int);
46442370Skarels 	}
46542370Skarels 	if (code >= numsys)
46642370Skarels 		callp = &systab[0];		/* indir (illegal) */
46742370Skarels 	else
46842370Skarels 		callp = &systab[code];
46941475Smckusick 	if ((i = callp->sy_narg * sizeof (int)) &&
47044018Skarels 	    (error = copyin(params, (caddr_t)&args, (u_int)i))) {
47141475Smckusick #ifdef HPUXCOMPAT
47241475Smckusick 		if (p->p_flag & SHPUX)
47342370Skarels 			error = bsdtohpuxerrno(error);
47441475Smckusick #endif
47549362Skarels 		frame.f_regs[D0] = error;
47641475Smckusick 		frame.f_sr |= PSL_C;	/* carry bit */
47741475Smckusick #ifdef KTRACE
47843641Skarels 		if (KTRPOINT(p, KTR_SYSCALL))
47944018Skarels 			ktrsyscall(p->p_tracep, code, callp->sy_narg, args.i);
48041475Smckusick #endif
48141475Smckusick 		goto done;
48241475Smckusick 	}
48341475Smckusick #ifdef KTRACE
48443641Skarels 	if (KTRPOINT(p, KTR_SYSCALL))
48544018Skarels 		ktrsyscall(p->p_tracep, code, callp->sy_narg, args.i);
48641475Smckusick #endif
48743641Skarels 	rval[0] = 0;
48843641Skarels 	rval[1] = frame.f_regs[D1];
48941475Smckusick #ifdef HPUXCOMPAT
49042370Skarels 	/* debug kludge */
49142370Skarels 	if (callp->sy_call == notimp)
49248465Skarels 		error = notimp(p, args.i, rval, code, callp->sy_narg);
49342370Skarels 	else
49441475Smckusick #endif
49548465Skarels 	error = (*callp->sy_call)(p, &args, rval);
49642370Skarels 	if (error == ERESTART)
49742370Skarels 		frame.f_pc = opc;
49842370Skarels 	else if (error != EJUSTRETURN) {
49942370Skarels 		if (error) {
50041475Smckusick #ifdef HPUXCOMPAT
50142370Skarels 			if (p->p_flag & SHPUX)
50242370Skarels 				error = bsdtohpuxerrno(error);
50341475Smckusick #endif
50449362Skarels 			frame.f_regs[D0] = error;
50542370Skarels 			frame.f_sr |= PSL_C;	/* carry bit */
50641475Smckusick 		} else {
50743641Skarels 			frame.f_regs[D0] = rval[0];
50843641Skarels 			frame.f_regs[D1] = rval[1];
50941475Smckusick 			frame.f_sr &= ~PSL_C;
51041475Smckusick 		}
51142370Skarels 	}
51242370Skarels 	/* else if (error == EJUSTRETURN) */
51341475Smckusick 		/* nothing to do */
51442370Skarels 
51541475Smckusick done:
51641475Smckusick 	/*
51742370Skarels 	 * Reinitialize proc pointer `p' as it may be different
51842370Skarels 	 * if this is a child returning from fork syscall.
51942370Skarels 	 */
52048465Skarels 	p = curproc;
52149317Shibler 	while (i = CURSIG(p))
52249317Shibler 		psig(i);
52341475Smckusick 	p->p_pri = p->p_usrpri;
52448465Skarels 	if (want_resched) {
52541475Smckusick 		/*
52648465Skarels 		 * Since we are curproc, clock will normally just change
52741475Smckusick 		 * our priority without moving us from one queue to another
52841475Smckusick 		 * (since the running process is not on a queue.)
52941475Smckusick 		 * If that happened after we setrq ourselves but before we
53041475Smckusick 		 * swtch()'ed, we might not be on the queue indicated by
53141475Smckusick 		 * our priority.
53241475Smckusick 		 */
53350753Skarels 		s = splclock();
53441475Smckusick 		setrq(p);
53548465Skarels 		p->p_stats->p_ru.ru_nivcsw++;
53641475Smckusick 		swtch();
53750753Skarels 		splx(s);
53849317Shibler 		while (i = CURSIG(p))
53949317Shibler 			psig(i);
54041475Smckusick 	}
54148465Skarels 	if (p->p_stats->p_prof.pr_scale) {
54241475Smckusick 		int ticks;
54348465Skarels 		struct timeval *tv = &p->p_stime;
54441475Smckusick 
54541475Smckusick 		ticks = ((tv->tv_sec - syst.tv_sec) * 1000 +
54641475Smckusick 			(tv->tv_usec - syst.tv_usec) / 1000) / (tick / 1000);
54741475Smckusick 		if (ticks) {
54841475Smckusick #ifdef PROFTIMER
54941475Smckusick 			extern int profscale;
55048465Skarels 			addupc(frame.f_pc, &p->p_stats->p_prof,
55148465Skarels 			    ticks * profscale);
55241475Smckusick #else
55348465Skarels 			addupc(frame.f_pc, &p->p_stats->p_prof, ticks);
55441475Smckusick #endif
55541475Smckusick 		}
55641475Smckusick 	}
55741475Smckusick 	curpri = p->p_pri;
55841475Smckusick #ifdef KTRACE
55943641Skarels 	if (KTRPOINT(p, KTR_SYSRET))
56043641Skarels 		ktrsysret(p->p_tracep, code, error, rval[0]);
56141475Smckusick #endif
56241475Smckusick }
563