xref: /csrg-svn/sys/hp300/hp300/trap.c (revision 49911)
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*49911Smckusick  *	@(#)trap.c	7.14.1.2 (Berkeley) 05/28/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 struct	sysent	sysent[];
4641475Smckusick int	nsysent;
4741475Smckusick 
4841475Smckusick char	*trap_type[] = {
4941475Smckusick 	"Bus error",
5041475Smckusick 	"Address error",
5141475Smckusick 	"Illegal instruction",
5241475Smckusick 	"Zero divide",
5341475Smckusick 	"CHK instruction",
5441475Smckusick 	"TRAPV instruction",
5541475Smckusick 	"Privilege violation",
5641475Smckusick 	"Trace trap",
5741475Smckusick 	"MMU fault",
5841475Smckusick 	"SSIR trap",
5941475Smckusick 	"Format error",
6041475Smckusick 	"68881 exception",
6141475Smckusick 	"Coprocessor violation",
6241475Smckusick 	"Async system trap"
6341475Smckusick };
6441475Smckusick #define	TRAP_TYPES	(sizeof trap_type / sizeof trap_type[0])
6541475Smckusick 
6649317Shibler /*
6749317Shibler  * Size of various exception stack frames (minus the standard 8 bytes)
6849317Shibler  */
6949317Shibler short	exframesize[] = {
7049317Shibler 	FMT0SIZE,	/* type 0 - normal (68020/030/040) */
7149317Shibler 	FMT1SIZE,	/* type 1 - throwaway (68020/030/040) */
7249317Shibler 	FMT2SIZE,	/* type 2 - normal 6-word (68020/030/040) */
7349317Shibler 	-1,		/* type 3 - FP post-instruction (68040) */
7449317Shibler 	-1, -1, -1,	/* type 4-6 - undefined */
7549317Shibler 	-1,		/* type 7 - access error (68040) */
7649317Shibler 	58,		/* type 8 - bus fault (68010) */
7749317Shibler 	FMT9SIZE,	/* type 9 - coprocessor mid-instruction (68020/030) */
7849317Shibler 	FMTASIZE,	/* type A - short bus fault (68020/030) */
7949317Shibler 	FMTBSIZE,	/* type B - long bus fault (68020/030) */
8049317Shibler 	-1, -1, -1, -1	/* type C-F - undefined */
8149317Shibler };
8249317Shibler 
8341475Smckusick #ifdef DEBUG
8441475Smckusick int mmudebug = 0;
8541475Smckusick #endif
8641475Smckusick 
8741475Smckusick /*
8849531Skarels  * Trap is called from locore to handle most types of processor traps,
8949531Skarels  * including events such as simulated software interrupts/AST's.
9049531Skarels  * System calls are broken out for efficiency.
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)) {
10849531Skarels 		type |= T_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);
11749531Skarels 		type &= ~T_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 
13749531Skarels 	case T_BUSERR|T_USER:	/* bus error */
13849531Skarels 	case T_ADDRERR|T_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 	 */
15049531Skarels 		type |= T_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
16349531Skarels 	case T_COPERR|T_USER:	/* user coprocessor violation */
16441475Smckusick 	/* What is a proper response here? */
16541475Smckusick 		ucode = 0;
16641475Smckusick 		i = SIGFPE;
16741475Smckusick 		break;
16841475Smckusick 
16949531Skarels 	case T_FPERR|T_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 
18449531Skarels 	case T_ILLINST|T_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
19349531Skarels 	case T_PRIVINST|T_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 
20349531Skarels 	case T_ZERODIV|T_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 
21349531Skarels 	case T_CHKINST|T_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 
22649531Skarels 	case T_TRAPVINST|T_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 
25749531Skarels 	case T_TRACE|T_USER:	/* user trace trap */
25849531Skarels 	case T_TRAP15|T_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 
26649531Skarels 	case T_ASTFLT|T_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 */
28049531Skarels 	case T_SSIR|T_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 		 */
29449531Skarels 		if (type != T_ASTFLT|T_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 
31049531Skarels 	case T_MMUFLT|T_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:
32149531Skarels 		 * 	1. (type & T_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);
38249531Skarels 	if ((type & T_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 /*
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;
43442370Skarels 	int error, opc, numsys;
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");
45048465Skarels 	p->p_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);
49649817Smckusick #ifdef DIAGNOSTIC
49749817Smckusick 	if (curproc->p_spare[0])
49849817Smckusick 		panic("syscall: M_NAMEI");
49949817Smckusick 	if (curproc->p_spare[1])
50049817Smckusick 		panic("syscall: STARTSAVE");
501*49911Smckusick 	if (curproc->p_spare[2])
502*49911Smckusick 		panic("syscall: LOCK COUNT");
50349817Smckusick #endif
50442370Skarels 	if (error == ERESTART)
50542370Skarels 		frame.f_pc = opc;
50642370Skarels 	else if (error != EJUSTRETURN) {
50742370Skarels 		if (error) {
50841475Smckusick #ifdef HPUXCOMPAT
50942370Skarels 			if (p->p_flag & SHPUX)
51042370Skarels 				error = bsdtohpuxerrno(error);
51141475Smckusick #endif
51249362Skarels 			frame.f_regs[D0] = error;
51342370Skarels 			frame.f_sr |= PSL_C;	/* carry bit */
51441475Smckusick 		} else {
51543641Skarels 			frame.f_regs[D0] = rval[0];
51643641Skarels 			frame.f_regs[D1] = rval[1];
51741475Smckusick 			frame.f_sr &= ~PSL_C;
51841475Smckusick 		}
51942370Skarels 	}
52042370Skarels 	/* else if (error == EJUSTRETURN) */
52141475Smckusick 		/* nothing to do */
52242370Skarels 
52341475Smckusick done:
52441475Smckusick 	/*
52542370Skarels 	 * Reinitialize proc pointer `p' as it may be different
52642370Skarels 	 * if this is a child returning from fork syscall.
52742370Skarels 	 */
52848465Skarels 	p = curproc;
52949317Shibler 	while (i = CURSIG(p))
53049317Shibler 		psig(i);
53141475Smckusick 	p->p_pri = p->p_usrpri;
53248465Skarels 	if (want_resched) {
53341475Smckusick 		/*
53448465Skarels 		 * Since we are curproc, clock will normally just change
53541475Smckusick 		 * our priority without moving us from one queue to another
53641475Smckusick 		 * (since the running process is not on a queue.)
53741475Smckusick 		 * If that happened after we setrq ourselves but before we
53841475Smckusick 		 * swtch()'ed, we might not be on the queue indicated by
53941475Smckusick 		 * our priority.
54041475Smckusick 		 */
54141475Smckusick 		(void) splclock();
54241475Smckusick 		setrq(p);
54348465Skarels 		p->p_stats->p_ru.ru_nivcsw++;
54441475Smckusick 		swtch();
54549317Shibler 		while (i = CURSIG(p))
54649317Shibler 			psig(i);
54741475Smckusick 	}
54848465Skarels 	if (p->p_stats->p_prof.pr_scale) {
54941475Smckusick 		int ticks;
55048465Skarels 		struct timeval *tv = &p->p_stime;
55141475Smckusick 
55241475Smckusick 		ticks = ((tv->tv_sec - syst.tv_sec) * 1000 +
55341475Smckusick 			(tv->tv_usec - syst.tv_usec) / 1000) / (tick / 1000);
55441475Smckusick 		if (ticks) {
55541475Smckusick #ifdef PROFTIMER
55641475Smckusick 			extern int profscale;
55748465Skarels 			addupc(frame.f_pc, &p->p_stats->p_prof,
55848465Skarels 			    ticks * profscale);
55941475Smckusick #else
56048465Skarels 			addupc(frame.f_pc, &p->p_stats->p_prof, ticks);
56141475Smckusick #endif
56241475Smckusick 		}
56341475Smckusick 	}
56441475Smckusick 	curpri = p->p_pri;
56541475Smckusick #ifdef KTRACE
56643641Skarels 	if (KTRPOINT(p, KTR_SYSRET))
56743641Skarels 		ktrsysret(p->p_tracep, code, error, rval[0]);
56841475Smckusick #endif
56941475Smckusick }
570