xref: /csrg-svn/sys/hp300/hp300/trap.c (revision 49362)
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*49362Skarels  *	@(#)trap.c	7.13 (Berkeley) 05/07/91
1541475Smckusick  */
1641475Smckusick 
1748465Skarels #include "param.h"
1848465Skarels #include "systm.h"
1948465Skarels #include "proc.h"
2048465Skarels #include "seg.h"
2148465Skarels #include "acct.h"
2248465Skarels #include "kernel.h"
2348465Skarels #include "signalvar.h"
2448465Skarels #include "resourcevar.h"
2548465Skarels #include "syslog.h"
2648465Skarels #include "user.h"
2748465Skarels #ifdef KTRACE
2848465Skarels #include "ktrace.h"
2948465Skarels #endif
3048465Skarels 
3149125Skarels #include "../include/psl.h"
3248465Skarels #include "../include/trap.h"
3345788Sbostic #include "../include/cpu.h"
3445788Sbostic #include "../include/reg.h"
3545788Sbostic #include "../include/mtpr.h"
3641475Smckusick 
3748465Skarels #include "vm/vm.h"
3845788Sbostic #include "vm/pmap.h"
3948465Skarels #include "vmmeter.h"
4045751Smckusick 
4141475Smckusick #ifdef HPUXCOMPAT
4241475Smckusick #include "../hpux/hpux.h"
4341475Smckusick #endif
4441475Smckusick 
4541475Smckusick #define	USER	040		/* user-mode flag added to type */
4641475Smckusick 
4741475Smckusick struct	sysent	sysent[];
4841475Smckusick int	nsysent;
4941475Smckusick 
5041475Smckusick char	*trap_type[] = {
5141475Smckusick 	"Bus error",
5241475Smckusick 	"Address error",
5341475Smckusick 	"Illegal instruction",
5441475Smckusick 	"Zero divide",
5541475Smckusick 	"CHK instruction",
5641475Smckusick 	"TRAPV instruction",
5741475Smckusick 	"Privilege violation",
5841475Smckusick 	"Trace trap",
5941475Smckusick 	"MMU fault",
6041475Smckusick 	"SSIR trap",
6141475Smckusick 	"Format error",
6241475Smckusick 	"68881 exception",
6341475Smckusick 	"Coprocessor violation",
6441475Smckusick 	"Async system trap"
6541475Smckusick };
6641475Smckusick #define	TRAP_TYPES	(sizeof trap_type / sizeof trap_type[0])
6741475Smckusick 
6849317Shibler /*
6949317Shibler  * Size of various exception stack frames (minus the standard 8 bytes)
7049317Shibler  */
7149317Shibler short	exframesize[] = {
7249317Shibler 	FMT0SIZE,	/* type 0 - normal (68020/030/040) */
7349317Shibler 	FMT1SIZE,	/* type 1 - throwaway (68020/030/040) */
7449317Shibler 	FMT2SIZE,	/* type 2 - normal 6-word (68020/030/040) */
7549317Shibler 	-1,		/* type 3 - FP post-instruction (68040) */
7649317Shibler 	-1, -1, -1,	/* type 4-6 - undefined */
7749317Shibler 	-1,		/* type 7 - access error (68040) */
7849317Shibler 	58,		/* type 8 - bus fault (68010) */
7949317Shibler 	FMT9SIZE,	/* type 9 - coprocessor mid-instruction (68020/030) */
8049317Shibler 	FMTASIZE,	/* type A - short bus fault (68020/030) */
8149317Shibler 	FMTBSIZE,	/* type B - long bus fault (68020/030) */
8249317Shibler 	-1, -1, -1, -1	/* type C-F - undefined */
8349317Shibler };
8449317Shibler 
8541475Smckusick #ifdef DEBUG
8641475Smckusick int mmudebug = 0;
8741475Smckusick #endif
8841475Smckusick 
8941475Smckusick /*
9041475Smckusick  * Called from the trap handler when a processor trap occurs.
9141475Smckusick  */
9241475Smckusick /*ARGSUSED*/
9341475Smckusick trap(type, code, v, frame)
9441475Smckusick 	int type;
9541475Smckusick 	unsigned code;
9641475Smckusick 	register unsigned v;
9741475Smckusick 	struct frame frame;
9841475Smckusick {
9941475Smckusick 	register int i;
10041475Smckusick 	unsigned ucode = 0;
10148465Skarels 	register struct proc *p = curproc;
10241475Smckusick 	struct timeval syst;
10341475Smckusick 	unsigned ncode;
10441475Smckusick 
10541475Smckusick 	cnt.v_trap++;
10648465Skarels 	syst = p->p_stime;
10741475Smckusick 	if (USERMODE(frame.f_sr)) {
10841475Smckusick 		type |= USER;
10948465Skarels 		p->p_regs = frame.f_regs;
11041475Smckusick 	}
11141475Smckusick 	switch (type) {
11241475Smckusick 
11341475Smckusick 	default:
11441475Smckusick dopanic:
11541475Smckusick 		printf("trap type %d, code = %x, v = %x\n", type, code, v);
11641475Smckusick 		regdump(frame.f_regs, 128);
11741475Smckusick 		type &= ~USER;
11841475Smckusick 		if ((unsigned)type < TRAP_TYPES)
11941475Smckusick 			panic(trap_type[type]);
12041475Smckusick 		panic("trap");
12141475Smckusick 
12241475Smckusick 	case T_BUSERR:		/* kernel bus error */
12349125Skarels 		if (!p->p_addr->u_pcb.pcb_onfault)
12441475Smckusick 			goto dopanic;
12541475Smckusick 		/*
12641475Smckusick 		 * If we have arranged to catch this fault in any of the
12741475Smckusick 		 * copy to/from user space routines, set PC to return to
12841475Smckusick 		 * indicated location and set flag informing buserror code
12941475Smckusick 		 * that it may need to clean up stack frame.
13041475Smckusick 		 */
13141475Smckusick copyfault:
13249317Shibler 		frame.f_stackadj = exframesize[frame.f_format];
13349317Shibler 		frame.f_format = frame.f_vector = 0;
13449125Skarels 		frame.f_pc = (int) p->p_addr->u_pcb.pcb_onfault;
13541475Smckusick 		return;
13641475Smckusick 
13741475Smckusick 	case T_BUSERR+USER:	/* bus error */
13841475Smckusick 	case T_ADDRERR+USER:	/* address error */
13941475Smckusick 		i = SIGBUS;
14041475Smckusick 		break;
14141475Smckusick 
14241475Smckusick #ifdef FPCOPROC
14341475Smckusick 	case T_COPERR:		/* kernel coprocessor violation */
14441475Smckusick #endif
14541475Smckusick 	case T_FMTERR:		/* kernel format error */
14641475Smckusick 	/*
14741475Smckusick 	 * The user has most likely trashed the RTE or FP state info
14841475Smckusick 	 * in the stack frame of a signal handler.
14941475Smckusick 	 */
15042370Skarels 		type |= USER;
15148465Skarels 		printf("pid %d: kernel %s exception\n", p->p_pid,
15241475Smckusick 		       type==T_COPERR ? "coprocessor" : "format");
15348465Skarels 		p->p_sigacts->ps_sigact[SIGILL] = SIG_DFL;
15441475Smckusick 		i = sigmask(SIGILL);
15541475Smckusick 		p->p_sigignore &= ~i;
15641475Smckusick 		p->p_sigcatch &= ~i;
15741475Smckusick 		p->p_sigmask &= ~i;
15842370Skarels 		i = SIGILL;
15941475Smckusick 		ucode = frame.f_format;	/* XXX was ILL_RESAD_FAULT */
16042370Skarels 		break;
16141475Smckusick 
16241475Smckusick #ifdef FPCOPROC
16341475Smckusick 	case T_COPERR+USER:	/* user coprocessor violation */
16441475Smckusick 	/* What is a proper response here? */
16541475Smckusick 		ucode = 0;
16641475Smckusick 		i = SIGFPE;
16741475Smckusick 		break;
16841475Smckusick 
16949317Shibler 	case T_FPERR+USER:	/* 68881 exceptions */
17041475Smckusick 	/*
17141475Smckusick 	 * We pass along the 68881 status register which locore stashed
17241475Smckusick 	 * in code for us.  Note that there is a possibility that the
17341475Smckusick 	 * bit pattern of this register will conflict with one of the
17441475Smckusick 	 * FPE_* codes defined in signal.h.  Fortunately for us, the
17541475Smckusick 	 * only such codes we use are all in the range 1-7 and the low
17641475Smckusick 	 * 3 bits of the status register are defined as 0 so there is
17741475Smckusick 	 * no clash.
17841475Smckusick 	 */
17941475Smckusick 		ucode = code;
18041475Smckusick 		i = SIGFPE;
18141475Smckusick 		break;
18241475Smckusick #endif
18341475Smckusick 
18441475Smckusick 	case T_ILLINST+USER:	/* illegal instruction fault */
18541475Smckusick #ifdef HPUXCOMPAT
18648465Skarels 		if (p->p_flag & SHPUX) {
18741475Smckusick 			ucode = HPUX_ILL_ILLINST_TRAP;
18841475Smckusick 			i = SIGILL;
18941475Smckusick 			break;
19041475Smckusick 		}
19141475Smckusick 		/* fall through */
19241475Smckusick #endif
19341475Smckusick 	case T_PRIVINST+USER:	/* privileged instruction fault */
19441475Smckusick #ifdef HPUXCOMPAT
19548465Skarels 		if (p->p_flag & SHPUX)
19641475Smckusick 			ucode = HPUX_ILL_PRIV_TRAP;
19741475Smckusick 		else
19841475Smckusick #endif
19941475Smckusick 		ucode = frame.f_format;	/* XXX was ILL_PRIVIN_FAULT */
20041475Smckusick 		i = SIGILL;
20141475Smckusick 		break;
20241475Smckusick 
20341475Smckusick 	case T_ZERODIV+USER:	/* Divide by zero */
20441475Smckusick #ifdef HPUXCOMPAT
20548465Skarels 		if (p->p_flag & SHPUX)
20641475Smckusick 			ucode = HPUX_FPE_INTDIV_TRAP;
20741475Smckusick 		else
20841475Smckusick #endif
20941475Smckusick 		ucode = frame.f_format;	/* XXX was FPE_INTDIV_TRAP */
21041475Smckusick 		i = SIGFPE;
21141475Smckusick 		break;
21241475Smckusick 
21341475Smckusick 	case T_CHKINST+USER:	/* CHK instruction trap */
21441475Smckusick #ifdef HPUXCOMPAT
21548465Skarels 		if (p->p_flag & SHPUX) {
21641475Smckusick 			/* handled differently under hp-ux */
21741475Smckusick 			i = SIGILL;
21841475Smckusick 			ucode = HPUX_ILL_CHK_TRAP;
21941475Smckusick 			break;
22041475Smckusick 		}
22141475Smckusick #endif
22241475Smckusick 		ucode = frame.f_format;	/* XXX was FPE_SUBRNG_TRAP */
22341475Smckusick 		i = SIGFPE;
22441475Smckusick 		break;
22541475Smckusick 
22641475Smckusick 	case T_TRAPVINST+USER:	/* TRAPV instruction trap */
22741475Smckusick #ifdef HPUXCOMPAT
22848465Skarels 		if (p->p_flag & SHPUX) {
22941475Smckusick 			/* handled differently under hp-ux */
23041475Smckusick 			i = SIGILL;
23141475Smckusick 			ucode = HPUX_ILL_TRAPV_TRAP;
23241475Smckusick 			break;
23341475Smckusick 		}
23441475Smckusick #endif
23541475Smckusick 		ucode = frame.f_format;	/* XXX was FPE_INTOVF_TRAP */
23641475Smckusick 		i = SIGFPE;
23741475Smckusick 		break;
23841475Smckusick 
23941475Smckusick 	/*
24041475Smckusick 	 * XXX: Trace traps are a nightmare.
24141475Smckusick 	 *
24241475Smckusick 	 *	HP-UX uses trap #1 for breakpoints,
24341475Smckusick 	 *	HPBSD uses trap #2,
24441475Smckusick 	 *	SUN 3.x uses trap #15,
24548465Skarels 	 *	KGDB uses trap #15 (for kernel breakpoints; handled elsewhere).
24641475Smckusick 	 *
24741475Smckusick 	 * HPBSD and HP-UX traps both get mapped by locore.s into T_TRACE.
24841475Smckusick 	 * SUN 3.x traps get passed through as T_TRAP15 and are not really
24948465Skarels 	 * supported yet.
25041475Smckusick 	 */
25141475Smckusick 	case T_TRACE:		/* kernel trace trap */
25248465Skarels 	case T_TRAP15:		/* SUN trace trap */
25341475Smckusick 		frame.f_sr &= ~PSL_T;
25441475Smckusick 		i = SIGTRAP;
25541475Smckusick 		break;
25641475Smckusick 
25741475Smckusick 	case T_TRACE+USER:	/* user trace trap */
25841475Smckusick 	case T_TRAP15+USER:	/* SUN user trace trap */
25941475Smckusick 		frame.f_sr &= ~PSL_T;
26041475Smckusick 		i = SIGTRAP;
26141475Smckusick 		break;
26241475Smckusick 
26343413Shibler 	case T_ASTFLT:		/* system async trap, cannot happen */
26441475Smckusick 		goto dopanic;
26541475Smckusick 
26643413Shibler 	case T_ASTFLT+USER:	/* user async trap */
26749125Skarels 		astpending = 0;
26841475Smckusick 		/*
26941475Smckusick 		 * We check for software interrupts first.  This is because
27041475Smckusick 		 * they are at a higher level than ASTs, and on a VAX would
27141475Smckusick 		 * interrupt the AST.  We assume that if we are processing
27241475Smckusick 		 * an AST that we must be at IPL0 so we don't bother to
27341475Smckusick 		 * check.  Note that we ensure that we are at least at SIR
27441475Smckusick 		 * IPL while processing the SIR.
27541475Smckusick 		 */
27641475Smckusick 		spl1();
27741475Smckusick 		/* fall into... */
27841475Smckusick 
27941475Smckusick 	case T_SSIR:		/* software interrupt */
28041475Smckusick 	case T_SSIR+USER:
28141475Smckusick 		if (ssir & SIR_NET) {
28241475Smckusick 			siroff(SIR_NET);
28341475Smckusick 			cnt.v_soft++;
28441475Smckusick 			netintr();
28541475Smckusick 		}
28641475Smckusick 		if (ssir & SIR_CLOCK) {
28741475Smckusick 			siroff(SIR_CLOCK);
28841475Smckusick 			cnt.v_soft++;
28941475Smckusick 			softclock((caddr_t)frame.f_pc, (int)frame.f_sr);
29041475Smckusick 		}
29141475Smckusick 		/*
29241475Smckusick 		 * If this was not an AST trap, we are all done.
29341475Smckusick 		 */
29443413Shibler 		if (type != T_ASTFLT+USER) {
29541475Smckusick 			cnt.v_trap--;
29641475Smckusick 			return;
29741475Smckusick 		}
29841475Smckusick 		spl0();
29941475Smckusick #ifndef PROFTIMER
30048465Skarels 		if ((p->p_flag&SOWEUPC) && p->p_stats->p_prof.pr_scale) {
30148465Skarels 			addupc(frame.f_pc, &p->p_stats->p_prof, 1);
30248465Skarels 			p->p_flag &= ~SOWEUPC;
30341475Smckusick 		}
30441475Smckusick #endif
30541475Smckusick 		goto out;
30641475Smckusick 
30741475Smckusick 	case T_MMUFLT:		/* kernel mode page fault */
30841475Smckusick 		/* fall into ... */
30941475Smckusick 
31041475Smckusick 	case T_MMUFLT+USER:	/* page fault */
31145751Smckusick 	    {
31245751Smckusick 		register vm_offset_t va;
31348465Skarels 		register struct vmspace *vm = p->p_vmspace;
31445751Smckusick 		register vm_map_t map;
31545751Smckusick 		int rv;
31645751Smckusick 		vm_prot_t ftype;
31745751Smckusick 		extern vm_map_t kernel_map;
31845751Smckusick 
31941475Smckusick 		/*
32045751Smckusick 		 * It is only a kernel address space fault iff:
32145751Smckusick 		 * 	1. (type & USER) == 0  and
32245751Smckusick 		 * 	2. pcb_onfault not set or
32345751Smckusick 		 *	3. pcb_onfault set but supervisor space data fault
32445751Smckusick 		 * The last can occur during an exec() copyin where the
32545751Smckusick 		 * argument space is lazy-allocated.
32641475Smckusick 		 */
32745751Smckusick 		if (type == T_MMUFLT &&
32849125Skarels 		    (!p->p_addr->u_pcb.pcb_onfault ||
32945751Smckusick 		     (code & (SSW_DF|FC_SUPERD)) == (SSW_DF|FC_SUPERD)))
33045751Smckusick 			map = kernel_map;
33145751Smckusick 		else
33248465Skarels 			map = &vm->vm_map;
33345751Smckusick 		if ((code & (SSW_DF|SSW_RW)) == SSW_DF)	/* what about RMW? */
33445751Smckusick 			ftype = VM_PROT_READ | VM_PROT_WRITE;
33545751Smckusick 		else
33645751Smckusick 			ftype = VM_PROT_READ;
33745751Smckusick 		va = trunc_page((vm_offset_t)v);
33841475Smckusick #ifdef DEBUG
33945751Smckusick 		if (map == kernel_map && va == 0) {
34045751Smckusick 			printf("trap: bad kernel access at %x\n", v);
34141475Smckusick 			goto dopanic;
34241475Smckusick 		}
34341475Smckusick #endif
34449317Shibler 		rv = vm_fault(map, va, ftype, FALSE);
34541475Smckusick 		/*
34649317Shibler 		 * If this was a stack access we keep track of the maximum
34749317Shibler 		 * accessed stack size.  Also, if vm_fault gets a protection
34849317Shibler 		 * failure it is due to accessing the stack region outside
34949317Shibler 		 * the current limit and we need to reflect that as an access
35049317Shibler 		 * error.
35141475Smckusick 		 */
35248465Skarels 		if ((caddr_t)va >= vm->vm_maxsaddr && map != kernel_map) {
35349317Shibler 			if (rv == KERN_SUCCESS) {
35449317Shibler 				unsigned nss;
35549317Shibler 
35649317Shibler 				nss = clrnd(btoc(USRSTACK-(unsigned)va));
35749317Shibler 				if (nss > vm->vm_ssize)
35849317Shibler 					vm->vm_ssize = nss;
35949317Shibler 			} else if (rv == KERN_PROTECTION_FAILURE)
36049317Shibler 				rv = KERN_INVALID_ADDRESS;
36141475Smckusick 		}
36245751Smckusick 		if (rv == KERN_SUCCESS) {
36341475Smckusick 			if (type == T_MMUFLT)
36441475Smckusick 				return;
36541475Smckusick 			goto out;
36641475Smckusick 		}
36745751Smckusick 		if (type == T_MMUFLT) {
36849125Skarels 			if (p->p_addr->u_pcb.pcb_onfault)
36945751Smckusick 				goto copyfault;
37045751Smckusick 			printf("vm_fault(%x, %x, %x, 0) -> %x\n",
37145751Smckusick 			       map, va, ftype, rv);
37245751Smckusick 			printf("  type %x, code [mmu,,ssw]: %x\n",
37345751Smckusick 			       type, code);
37445751Smckusick 			goto dopanic;
37545751Smckusick 		}
37648465Skarels 		ucode = v;
37745751Smckusick 		i = (rv == KERN_PROTECTION_FAILURE) ? SIGBUS : SIGSEGV;
37845751Smckusick 		break;
37945751Smckusick 	    }
38041475Smckusick 	}
38148465Skarels 	trapsignal(p, i, ucode);
38241475Smckusick 	if ((type & USER) == 0)
38341475Smckusick 		return;
38441475Smckusick out:
38548465Skarels 	while (i = CURSIG(p))
38642370Skarels 		psig(i);
38741475Smckusick 	p->p_pri = p->p_usrpri;
38848465Skarels 	if (want_resched) {
38941475Smckusick 		/*
39048465Skarels 		 * Since we are curproc, clock will normally just change
39141475Smckusick 		 * our priority without moving us from one queue to another
39241475Smckusick 		 * (since the running process is not on a queue.)
39341475Smckusick 		 * If that happened after we setrq ourselves but before we
39441475Smckusick 		 * swtch()'ed, we might not be on the queue indicated by
39541475Smckusick 		 * our priority.
39641475Smckusick 		 */
39741475Smckusick 		(void) splclock();
39841475Smckusick 		setrq(p);
39948465Skarels 		p->p_stats->p_ru.ru_nivcsw++;
40041475Smckusick 		swtch();
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 /*
42441475Smckusick  * Called from the trap handler when a system call occurs
42541475Smckusick  */
42641475Smckusick /*ARGSUSED*/
42741475Smckusick syscall(code, frame)
42841475Smckusick 	volatile int code;
42941475Smckusick 	struct frame frame;
43041475Smckusick {
43141475Smckusick 	register caddr_t params;
43241475Smckusick 	register int i;
43341475Smckusick 	register struct sysent *callp;
43448465Skarels 	register struct proc *p = curproc;
43542370Skarels 	int error, opc, numsys;
43644018Skarels 	struct args {
43744018Skarels 		int i[8];
43844018Skarels 	} args;
43944018Skarels 	int rval[2];
44041475Smckusick 	struct timeval syst;
44141475Smckusick 	struct sysent *systab;
44241475Smckusick #ifdef HPUXCOMPAT
44341475Smckusick 	extern struct sysent hpuxsysent[];
44441475Smckusick 	extern int hpuxnsysent, notimp();
44541475Smckusick #endif
44641475Smckusick 
44741475Smckusick 	cnt.v_syscall++;
44848465Skarels 	syst = p->p_stime;
44941475Smckusick 	if (!USERMODE(frame.f_sr))
45041475Smckusick 		panic("syscall");
45148465Skarels 	p->p_regs = frame.f_regs;
45241475Smckusick 	opc = frame.f_pc - 2;
45341475Smckusick 	systab = sysent;
45441475Smckusick 	numsys = nsysent;
45541475Smckusick #ifdef HPUXCOMPAT
45642370Skarels 	if (p->p_flag & SHPUX) {
45741475Smckusick 		systab = hpuxsysent;
45841475Smckusick 		numsys = hpuxnsysent;
45941475Smckusick 	}
46041475Smckusick #endif
46141475Smckusick 	params = (caddr_t)frame.f_regs[SP] + NBPW;
46242370Skarels 	if (code == 0) {			/* indir */
46342370Skarels 		code = fuword(params);
46441475Smckusick 		params += NBPW;
46542370Skarels 	}
46642370Skarels 	if (code >= numsys)
46742370Skarels 		callp = &systab[0];		/* indir (illegal) */
46842370Skarels 	else
46942370Skarels 		callp = &systab[code];
47041475Smckusick 	if ((i = callp->sy_narg * sizeof (int)) &&
47144018Skarels 	    (error = copyin(params, (caddr_t)&args, (u_int)i))) {
47241475Smckusick #ifdef HPUXCOMPAT
47341475Smckusick 		if (p->p_flag & SHPUX)
47442370Skarels 			error = bsdtohpuxerrno(error);
47541475Smckusick #endif
476*49362Skarels 		frame.f_regs[D0] = error;
47741475Smckusick 		frame.f_sr |= PSL_C;	/* carry bit */
47841475Smckusick #ifdef KTRACE
47943641Skarels 		if (KTRPOINT(p, KTR_SYSCALL))
48044018Skarels 			ktrsyscall(p->p_tracep, code, callp->sy_narg, args.i);
48141475Smckusick #endif
48241475Smckusick 		goto done;
48341475Smckusick 	}
48441475Smckusick #ifdef KTRACE
48543641Skarels 	if (KTRPOINT(p, KTR_SYSCALL))
48644018Skarels 		ktrsyscall(p->p_tracep, code, callp->sy_narg, args.i);
48741475Smckusick #endif
48843641Skarels 	rval[0] = 0;
48943641Skarels 	rval[1] = frame.f_regs[D1];
49041475Smckusick #ifdef HPUXCOMPAT
49142370Skarels 	/* debug kludge */
49242370Skarels 	if (callp->sy_call == notimp)
49348465Skarels 		error = notimp(p, args.i, rval, code, callp->sy_narg);
49442370Skarels 	else
49541475Smckusick #endif
49648465Skarels 	error = (*callp->sy_call)(p, &args, rval);
49742370Skarels 	if (error == ERESTART)
49842370Skarels 		frame.f_pc = opc;
49942370Skarels 	else if (error != EJUSTRETURN) {
50042370Skarels 		if (error) {
50141475Smckusick #ifdef HPUXCOMPAT
50242370Skarels 			if (p->p_flag & SHPUX)
50342370Skarels 				error = bsdtohpuxerrno(error);
50441475Smckusick #endif
505*49362Skarels 			frame.f_regs[D0] = error;
50642370Skarels 			frame.f_sr |= PSL_C;	/* carry bit */
50741475Smckusick 		} else {
50843641Skarels 			frame.f_regs[D0] = rval[0];
50943641Skarels 			frame.f_regs[D1] = rval[1];
51041475Smckusick 			frame.f_sr &= ~PSL_C;
51141475Smckusick 		}
51242370Skarels 	}
51342370Skarels 	/* else if (error == EJUSTRETURN) */
51441475Smckusick 		/* nothing to do */
51542370Skarels 
51641475Smckusick done:
51741475Smckusick 	/*
51842370Skarels 	 * Reinitialize proc pointer `p' as it may be different
51942370Skarels 	 * if this is a child returning from fork syscall.
52042370Skarels 	 */
52148465Skarels 	p = curproc;
52249317Shibler 	while (i = CURSIG(p))
52349317Shibler 		psig(i);
52441475Smckusick 	p->p_pri = p->p_usrpri;
52548465Skarels 	if (want_resched) {
52641475Smckusick 		/*
52748465Skarels 		 * Since we are curproc, clock will normally just change
52841475Smckusick 		 * our priority without moving us from one queue to another
52941475Smckusick 		 * (since the running process is not on a queue.)
53041475Smckusick 		 * If that happened after we setrq ourselves but before we
53141475Smckusick 		 * swtch()'ed, we might not be on the queue indicated by
53241475Smckusick 		 * our priority.
53341475Smckusick 		 */
53441475Smckusick 		(void) splclock();
53541475Smckusick 		setrq(p);
53648465Skarels 		p->p_stats->p_ru.ru_nivcsw++;
53741475Smckusick 		swtch();
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