xref: /csrg-svn/sys/hp300/hp300/trap.c (revision 45751)
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  *
1241475Smckusick  * from: Utah $Hdr: trap.c 1.28 89/09/25$
1341475Smckusick  *
14*45751Smckusick  *	@(#)trap.c	7.8 (Berkeley) 12/05/90
1541475Smckusick  */
1641475Smckusick 
1741475Smckusick #include "cpu.h"
1841475Smckusick #include "psl.h"
1941475Smckusick #include "reg.h"
2041475Smckusick #include "mtpr.h"
2141475Smckusick 
2241475Smckusick #include "param.h"
2341475Smckusick #include "systm.h"
2441475Smckusick #include "user.h"
2541475Smckusick #include "proc.h"
2641475Smckusick #include "seg.h"
2741475Smckusick #include "trap.h"
2841475Smckusick #include "acct.h"
2941475Smckusick #include "kernel.h"
3041475Smckusick #include "syslog.h"
3141475Smckusick #ifdef KTRACE
3241475Smckusick #include "ktrace.h"
3341475Smckusick #endif
3441475Smckusick 
35*45751Smckusick #include "../vm/vm_param.h"
36*45751Smckusick #include "../vm/pmap.h"
37*45751Smckusick #include "../vm/vm_map.h"
38*45751Smckusick #include "vmmeter.h"
39*45751Smckusick 
4041475Smckusick #ifdef HPUXCOMPAT
4141475Smckusick #include "../hpux/hpux.h"
4241475Smckusick #endif
4341475Smckusick 
4441475Smckusick #define	USER	040		/* user-mode flag added to type */
4541475Smckusick 
4641475Smckusick struct	sysent	sysent[];
4741475Smckusick int	nsysent;
4841475Smckusick 
4941475Smckusick char	*trap_type[] = {
5041475Smckusick 	"Bus error",
5141475Smckusick 	"Address error",
5241475Smckusick 	"Illegal instruction",
5341475Smckusick 	"Zero divide",
5441475Smckusick 	"CHK instruction",
5541475Smckusick 	"TRAPV instruction",
5641475Smckusick 	"Privilege violation",
5741475Smckusick 	"Trace trap",
5841475Smckusick 	"MMU fault",
5941475Smckusick 	"SSIR trap",
6041475Smckusick 	"Format error",
6141475Smckusick 	"68881 exception",
6241475Smckusick 	"Coprocessor violation",
6341475Smckusick 	"Async system trap"
6441475Smckusick };
6541475Smckusick #define	TRAP_TYPES	(sizeof trap_type / sizeof trap_type[0])
6641475Smckusick 
6741475Smckusick #ifdef DEBUG
6841475Smckusick int mmudebug = 0;
6941475Smckusick #endif
7041475Smckusick 
7141475Smckusick /*
7241475Smckusick  * Called from the trap handler when a processor trap occurs.
7341475Smckusick  */
7441475Smckusick /*ARGSUSED*/
7541475Smckusick trap(type, code, v, frame)
7641475Smckusick 	int type;
7741475Smckusick 	unsigned code;
7841475Smckusick 	register unsigned v;
7941475Smckusick 	struct frame frame;
8041475Smckusick {
8141475Smckusick 	register int i;
8241475Smckusick 	unsigned ucode = 0;
8341475Smckusick 	register struct proc *p = u.u_procp;
8441475Smckusick 	struct timeval syst;
8541475Smckusick 	unsigned ncode;
8641475Smckusick 
8741475Smckusick 	cnt.v_trap++;
8841475Smckusick 	syst = u.u_ru.ru_stime;
8941475Smckusick 	if (USERMODE(frame.f_sr)) {
9041475Smckusick 		type |= USER;
9141475Smckusick 		u.u_ar0 = frame.f_regs;
9241475Smckusick 	}
9341475Smckusick 	switch (type) {
9441475Smckusick 
9541475Smckusick 	default:
9641475Smckusick dopanic:
9741475Smckusick #ifdef KGDB
9841475Smckusick 		if (!panicstr && kgdb_trap(type, code, v, &frame))
9941475Smckusick 			return;
10041475Smckusick #endif
10141475Smckusick 		printf("trap type %d, code = %x, v = %x\n", type, code, v);
10241475Smckusick 		regdump(frame.f_regs, 128);
10341475Smckusick 		type &= ~USER;
10441475Smckusick 		if ((unsigned)type < TRAP_TYPES)
10541475Smckusick 			panic(trap_type[type]);
10641475Smckusick 		panic("trap");
10741475Smckusick 
10841475Smckusick 	case T_BUSERR:		/* kernel bus error */
10941475Smckusick 		if (!u.u_pcb.pcb_onfault)
11041475Smckusick 			goto dopanic;
11141475Smckusick 		/*
11241475Smckusick 		 * If we have arranged to catch this fault in any of the
11341475Smckusick 		 * copy to/from user space routines, set PC to return to
11441475Smckusick 		 * indicated location and set flag informing buserror code
11541475Smckusick 		 * that it may need to clean up stack frame.
11641475Smckusick 		 */
11741475Smckusick copyfault:
11841475Smckusick 		frame.f_pc = (int) u.u_pcb.pcb_onfault;
11941475Smckusick 		frame.f_stackadj = -1;
12041475Smckusick 		return;
12141475Smckusick 
12241475Smckusick 	case T_BUSERR+USER:	/* bus error */
12341475Smckusick 	case T_ADDRERR+USER:	/* address error */
12441475Smckusick 		i = SIGBUS;
12541475Smckusick 		break;
12641475Smckusick 
12741475Smckusick #ifdef FPCOPROC
12841475Smckusick 	case T_COPERR:		/* kernel coprocessor violation */
12941475Smckusick #endif
13041475Smckusick 	case T_FMTERR:		/* kernel format error */
13141475Smckusick 	/*
13241475Smckusick 	 * The user has most likely trashed the RTE or FP state info
13341475Smckusick 	 * in the stack frame of a signal handler.
13441475Smckusick 	 */
13542370Skarels 		type |= USER;
13641475Smckusick 		printf("pid %d: kernel %s exception\n", u.u_procp->p_pid,
13741475Smckusick 		       type==T_COPERR ? "coprocessor" : "format");
13841475Smckusick 		u.u_signal[SIGILL] = SIG_DFL;
13941475Smckusick 		i = sigmask(SIGILL);
14041475Smckusick 		p->p_sigignore &= ~i;
14141475Smckusick 		p->p_sigcatch &= ~i;
14241475Smckusick 		p->p_sigmask &= ~i;
14342370Skarels 		i = SIGILL;
14441475Smckusick 		ucode = frame.f_format;	/* XXX was ILL_RESAD_FAULT */
14542370Skarels 		break;
14641475Smckusick 
14741475Smckusick #ifdef FPCOPROC
14841475Smckusick 	case T_COPERR+USER:	/* user coprocessor violation */
14941475Smckusick 	/* What is a proper response here? */
15041475Smckusick 		ucode = 0;
15141475Smckusick 		i = SIGFPE;
15241475Smckusick 		break;
15341475Smckusick 
15441475Smckusick 	case T_FPERR+USER:		/* 68881 exceptions */
15541475Smckusick 	/*
15641475Smckusick 	 * We pass along the 68881 status register which locore stashed
15741475Smckusick 	 * in code for us.  Note that there is a possibility that the
15841475Smckusick 	 * bit pattern of this register will conflict with one of the
15941475Smckusick 	 * FPE_* codes defined in signal.h.  Fortunately for us, the
16041475Smckusick 	 * only such codes we use are all in the range 1-7 and the low
16141475Smckusick 	 * 3 bits of the status register are defined as 0 so there is
16241475Smckusick 	 * no clash.
16341475Smckusick 	 */
16441475Smckusick 		ucode = code;
16541475Smckusick 		i = SIGFPE;
16641475Smckusick 		break;
16741475Smckusick #endif
16841475Smckusick 
16941475Smckusick 	case T_ILLINST+USER:	/* illegal instruction fault */
17041475Smckusick #ifdef HPUXCOMPAT
17141475Smckusick 		if (u.u_procp->p_flag & SHPUX) {
17241475Smckusick 			ucode = HPUX_ILL_ILLINST_TRAP;
17341475Smckusick 			i = SIGILL;
17441475Smckusick 			break;
17541475Smckusick 		}
17641475Smckusick 		/* fall through */
17741475Smckusick #endif
17841475Smckusick 	case T_PRIVINST+USER:	/* privileged instruction fault */
17941475Smckusick #ifdef HPUXCOMPAT
18041475Smckusick 		if (u.u_procp->p_flag & SHPUX)
18141475Smckusick 			ucode = HPUX_ILL_PRIV_TRAP;
18241475Smckusick 		else
18341475Smckusick #endif
18441475Smckusick 		ucode = frame.f_format;	/* XXX was ILL_PRIVIN_FAULT */
18541475Smckusick 		i = SIGILL;
18641475Smckusick 		break;
18741475Smckusick 
18841475Smckusick 	case T_ZERODIV+USER:	/* Divide by zero */
18941475Smckusick #ifdef HPUXCOMPAT
19041475Smckusick 		if (u.u_procp->p_flag & SHPUX)
19141475Smckusick 			ucode = HPUX_FPE_INTDIV_TRAP;
19241475Smckusick 		else
19341475Smckusick #endif
19441475Smckusick 		ucode = frame.f_format;	/* XXX was FPE_INTDIV_TRAP */
19541475Smckusick 		i = SIGFPE;
19641475Smckusick 		break;
19741475Smckusick 
19841475Smckusick 	case T_CHKINST+USER:	/* CHK instruction trap */
19941475Smckusick #ifdef HPUXCOMPAT
20041475Smckusick 		if (u.u_procp->p_flag & SHPUX) {
20141475Smckusick 			/* handled differently under hp-ux */
20241475Smckusick 			i = SIGILL;
20341475Smckusick 			ucode = HPUX_ILL_CHK_TRAP;
20441475Smckusick 			break;
20541475Smckusick 		}
20641475Smckusick #endif
20741475Smckusick 		ucode = frame.f_format;	/* XXX was FPE_SUBRNG_TRAP */
20841475Smckusick 		i = SIGFPE;
20941475Smckusick 		break;
21041475Smckusick 
21141475Smckusick 	case T_TRAPVINST+USER:	/* TRAPV instruction trap */
21241475Smckusick #ifdef HPUXCOMPAT
21341475Smckusick 		if (u.u_procp->p_flag & SHPUX) {
21441475Smckusick 			/* handled differently under hp-ux */
21541475Smckusick 			i = SIGILL;
21641475Smckusick 			ucode = HPUX_ILL_TRAPV_TRAP;
21741475Smckusick 			break;
21841475Smckusick 		}
21941475Smckusick #endif
22041475Smckusick 		ucode = frame.f_format;	/* XXX was FPE_INTOVF_TRAP */
22141475Smckusick 		i = SIGFPE;
22241475Smckusick 		break;
22341475Smckusick 
22441475Smckusick 	/*
22541475Smckusick 	 * XXX: Trace traps are a nightmare.
22641475Smckusick 	 *
22741475Smckusick 	 *	HP-UX uses trap #1 for breakpoints,
22841475Smckusick 	 *	HPBSD uses trap #2,
22941475Smckusick 	 *	SUN 3.x uses trap #15,
23041475Smckusick 	 *	KGDB uses trap #15 (for kernel breakpoints).
23141475Smckusick 	 *
23241475Smckusick 	 * HPBSD and HP-UX traps both get mapped by locore.s into T_TRACE.
23341475Smckusick 	 * SUN 3.x traps get passed through as T_TRAP15 and are not really
23441475Smckusick 	 * supported yet.  KGDB traps are also passed through as T_TRAP15
23541475Smckusick 	 * and are not used yet.
23641475Smckusick 	 */
23741475Smckusick 	case T_TRACE:		/* kernel trace trap */
23841475Smckusick 	case T_TRAP15:		/* SUN (or KGDB) kernel trace trap */
23941475Smckusick #ifdef KGDB
24041475Smckusick 		if (kgdb_trap(type, code, v, &frame))
24141475Smckusick 			return;
24241475Smckusick #endif
24341475Smckusick 		frame.f_sr &= ~PSL_T;
24441475Smckusick 		i = SIGTRAP;
24541475Smckusick 		break;
24641475Smckusick 
24741475Smckusick 	case T_TRACE+USER:	/* user trace trap */
24841475Smckusick 	case T_TRAP15+USER:	/* SUN user trace trap */
24941475Smckusick 		frame.f_sr &= ~PSL_T;
25041475Smckusick 		i = SIGTRAP;
25141475Smckusick 		break;
25241475Smckusick 
25343413Shibler 	case T_ASTFLT:		/* system async trap, cannot happen */
25441475Smckusick 		goto dopanic;
25541475Smckusick 
25643413Shibler 	case T_ASTFLT+USER:	/* user async trap */
25741475Smckusick 		astoff();
25841475Smckusick 		/*
25941475Smckusick 		 * We check for software interrupts first.  This is because
26041475Smckusick 		 * they are at a higher level than ASTs, and on a VAX would
26141475Smckusick 		 * interrupt the AST.  We assume that if we are processing
26241475Smckusick 		 * an AST that we must be at IPL0 so we don't bother to
26341475Smckusick 		 * check.  Note that we ensure that we are at least at SIR
26441475Smckusick 		 * IPL while processing the SIR.
26541475Smckusick 		 */
26641475Smckusick 		spl1();
26741475Smckusick 		/* fall into... */
26841475Smckusick 
26941475Smckusick 	case T_SSIR:		/* software interrupt */
27041475Smckusick 	case T_SSIR+USER:
27141475Smckusick 		if (ssir & SIR_NET) {
27241475Smckusick 			siroff(SIR_NET);
27341475Smckusick 			cnt.v_soft++;
27441475Smckusick 			netintr();
27541475Smckusick 		}
27641475Smckusick 		if (ssir & SIR_CLOCK) {
27741475Smckusick 			siroff(SIR_CLOCK);
27841475Smckusick 			cnt.v_soft++;
27941475Smckusick 			softclock((caddr_t)frame.f_pc, (int)frame.f_sr);
28041475Smckusick 		}
28141475Smckusick 		/*
28241475Smckusick 		 * If this was not an AST trap, we are all done.
28341475Smckusick 		 */
28443413Shibler 		if (type != T_ASTFLT+USER) {
28541475Smckusick 			cnt.v_trap--;
28641475Smckusick 			return;
28741475Smckusick 		}
28841475Smckusick 		spl0();
28941475Smckusick #ifndef PROFTIMER
29041475Smckusick 		if ((u.u_procp->p_flag&SOWEUPC) && u.u_prof.pr_scale) {
29141475Smckusick 			addupc(frame.f_pc, &u.u_prof, 1);
29241475Smckusick 			u.u_procp->p_flag &= ~SOWEUPC;
29341475Smckusick 		}
29441475Smckusick #endif
29541475Smckusick 		goto out;
29641475Smckusick 
29741475Smckusick 	case T_MMUFLT:		/* kernel mode page fault */
29841475Smckusick 		/* fall into ... */
29941475Smckusick 
30041475Smckusick 	case T_MMUFLT+USER:	/* page fault */
301*45751Smckusick 	    {
302*45751Smckusick 		register vm_offset_t va;
303*45751Smckusick 		register vm_map_t map;
304*45751Smckusick 		int rv;
305*45751Smckusick 		vm_prot_t ftype;
306*45751Smckusick 		extern vm_map_t kernel_map;
307*45751Smckusick 		unsigned nss;
308*45751Smckusick 
30941475Smckusick 		/*
310*45751Smckusick 		 * It is only a kernel address space fault iff:
311*45751Smckusick 		 * 	1. (type & USER) == 0  and
312*45751Smckusick 		 * 	2. pcb_onfault not set or
313*45751Smckusick 		 *	3. pcb_onfault set but supervisor space data fault
314*45751Smckusick 		 * The last can occur during an exec() copyin where the
315*45751Smckusick 		 * argument space is lazy-allocated.
31641475Smckusick 		 */
317*45751Smckusick 		if (type == T_MMUFLT &&
318*45751Smckusick 		    (!u.u_pcb.pcb_onfault ||
319*45751Smckusick 		     (code & (SSW_DF|FC_SUPERD)) == (SSW_DF|FC_SUPERD)))
320*45751Smckusick 			map = kernel_map;
321*45751Smckusick 		else
322*45751Smckusick 			map = u.u_procp->p_map;
323*45751Smckusick 		if ((code & (SSW_DF|SSW_RW)) == SSW_DF)	/* what about RMW? */
324*45751Smckusick 			ftype = VM_PROT_READ | VM_PROT_WRITE;
325*45751Smckusick 		else
326*45751Smckusick 			ftype = VM_PROT_READ;
327*45751Smckusick 		va = trunc_page((vm_offset_t)v);
32841475Smckusick #ifdef DEBUG
329*45751Smckusick 		if (map == kernel_map && va == 0) {
330*45751Smckusick 			printf("trap: bad kernel access at %x\n", v);
33141475Smckusick 			goto dopanic;
33241475Smckusick 		}
33341475Smckusick #endif
33441475Smckusick 		/*
335*45751Smckusick 		 * XXX: rude hack to make stack limits "work"
33641475Smckusick 		 */
337*45751Smckusick 		nss = 0;
338*45751Smckusick 		if ((caddr_t)va >= u.u_maxsaddr && map != kernel_map) {
339*45751Smckusick 			nss = clrnd(btoc(USRSTACK-(unsigned)va));
340*45751Smckusick 			if (nss > btoc(u.u_rlimit[RLIMIT_STACK].rlim_cur)) {
341*45751Smckusick 				rv = KERN_FAILURE;
342*45751Smckusick 				goto nogo;
34341475Smckusick 			}
34441475Smckusick 		}
345*45751Smckusick 		rv = vm_fault(map, va, ftype, FALSE);
346*45751Smckusick 		if (rv == KERN_SUCCESS) {
347*45751Smckusick 			/*
348*45751Smckusick 			 * XXX: continuation of rude stack hack
349*45751Smckusick 			 */
350*45751Smckusick 			if (nss > u.u_ssize)
351*45751Smckusick 				u.u_ssize = nss;
35241475Smckusick 			if (type == T_MMUFLT)
35341475Smckusick 				return;
35441475Smckusick 			goto out;
35541475Smckusick 		}
356*45751Smckusick nogo:
357*45751Smckusick 		if (type == T_MMUFLT) {
358*45751Smckusick 			if (u.u_pcb.pcb_onfault)
359*45751Smckusick 				goto copyfault;
360*45751Smckusick 			printf("vm_fault(%x, %x, %x, 0) -> %x\n",
361*45751Smckusick 			       map, va, ftype, rv);
362*45751Smckusick 			printf("  type %x, code [mmu,,ssw]: %x\n",
363*45751Smckusick 			       type, code);
364*45751Smckusick 			goto dopanic;
365*45751Smckusick 		}
366*45751Smckusick 		i = (rv == KERN_PROTECTION_FAILURE) ? SIGBUS : SIGSEGV;
367*45751Smckusick 		break;
368*45751Smckusick 	    }
36941475Smckusick 	}
37041475Smckusick 	trapsignal(i, ucode);
37141475Smckusick 	if ((type & USER) == 0)
37241475Smckusick 		return;
37341475Smckusick out:
37441475Smckusick 	p = u.u_procp;
37542370Skarels 	if (i = CURSIG(p))
37642370Skarels 		psig(i);
37741475Smckusick 	p->p_pri = p->p_usrpri;
37841475Smckusick 	if (runrun) {
37941475Smckusick 		/*
38041475Smckusick 		 * Since we are u.u_procp, clock will normally just change
38141475Smckusick 		 * our priority without moving us from one queue to another
38241475Smckusick 		 * (since the running process is not on a queue.)
38341475Smckusick 		 * If that happened after we setrq ourselves but before we
38441475Smckusick 		 * swtch()'ed, we might not be on the queue indicated by
38541475Smckusick 		 * our priority.
38641475Smckusick 		 */
38741475Smckusick 		(void) splclock();
38841475Smckusick 		setrq(p);
38941475Smckusick 		u.u_ru.ru_nivcsw++;
39041475Smckusick 		swtch();
39142370Skarels 		if (i = CURSIG(p))
39242370Skarels 			psig(i);
39341475Smckusick 	}
39441475Smckusick 	if (u.u_prof.pr_scale) {
39541475Smckusick 		int ticks;
39641475Smckusick 		struct timeval *tv = &u.u_ru.ru_stime;
39741475Smckusick 
39841475Smckusick 		ticks = ((tv->tv_sec - syst.tv_sec) * 1000 +
39941475Smckusick 			(tv->tv_usec - syst.tv_usec) / 1000) / (tick / 1000);
40041475Smckusick 		if (ticks) {
40141475Smckusick #ifdef PROFTIMER
40241475Smckusick 			extern int profscale;
40341475Smckusick 			addupc(frame.f_pc, &u.u_prof, ticks * profscale);
40441475Smckusick #else
40541475Smckusick 			addupc(frame.f_pc, &u.u_prof, ticks);
40641475Smckusick #endif
40741475Smckusick 		}
40841475Smckusick 	}
40941475Smckusick 	curpri = p->p_pri;
41041475Smckusick }
41141475Smckusick 
41241475Smckusick /*
41341475Smckusick  * Called from the trap handler when a system call occurs
41441475Smckusick  */
41541475Smckusick /*ARGSUSED*/
41641475Smckusick syscall(code, frame)
41741475Smckusick 	volatile int code;
41841475Smckusick 	struct frame frame;
41941475Smckusick {
42041475Smckusick 	register caddr_t params;
42141475Smckusick 	register int i;
42241475Smckusick 	register struct sysent *callp;
42342370Skarels 	register struct proc *p = u.u_procp;
42442370Skarels 	int error, opc, numsys;
42544018Skarels 	struct args {
42644018Skarels 		int i[8];
42744018Skarels 	} args;
42844018Skarels 	int rval[2];
42941475Smckusick 	struct timeval syst;
43041475Smckusick 	struct sysent *systab;
43141475Smckusick #ifdef HPUXCOMPAT
43241475Smckusick 	extern struct sysent hpuxsysent[];
43341475Smckusick 	extern int hpuxnsysent, notimp();
43441475Smckusick #endif
43541475Smckusick 
43641475Smckusick 	cnt.v_syscall++;
43742371Smckusick 	syst = u.u_ru.ru_stime;
43841475Smckusick 	if (!USERMODE(frame.f_sr))
43941475Smckusick 		panic("syscall");
44042371Smckusick 	u.u_ar0 = frame.f_regs;
44141475Smckusick 	opc = frame.f_pc - 2;
44241475Smckusick 	systab = sysent;
44341475Smckusick 	numsys = nsysent;
44441475Smckusick #ifdef HPUXCOMPAT
44542370Skarels 	if (p->p_flag & SHPUX) {
44641475Smckusick 		systab = hpuxsysent;
44741475Smckusick 		numsys = hpuxnsysent;
44841475Smckusick 	}
44941475Smckusick #endif
45041475Smckusick 	params = (caddr_t)frame.f_regs[SP] + NBPW;
45142370Skarels 	if (code == 0) {			/* indir */
45242370Skarels 		code = fuword(params);
45341475Smckusick 		params += NBPW;
45442370Skarels 	}
45542370Skarels 	if (code >= numsys)
45642370Skarels 		callp = &systab[0];		/* indir (illegal) */
45742370Skarels 	else
45842370Skarels 		callp = &systab[code];
45941475Smckusick 	if ((i = callp->sy_narg * sizeof (int)) &&
46044018Skarels 	    (error = copyin(params, (caddr_t)&args, (u_int)i))) {
46141475Smckusick #ifdef HPUXCOMPAT
46241475Smckusick 		if (p->p_flag & SHPUX)
46342370Skarels 			error = bsdtohpuxerrno(error);
46441475Smckusick #endif
46542370Skarels 		frame.f_regs[D0] = (u_char) error;
46641475Smckusick 		frame.f_sr |= PSL_C;	/* carry bit */
46741475Smckusick #ifdef KTRACE
46843641Skarels 		if (KTRPOINT(p, KTR_SYSCALL))
46944018Skarels 			ktrsyscall(p->p_tracep, code, callp->sy_narg, args.i);
47041475Smckusick #endif
47141475Smckusick 		goto done;
47241475Smckusick 	}
47341475Smckusick #ifdef KTRACE
47443641Skarels 	if (KTRPOINT(p, KTR_SYSCALL))
47544018Skarels 		ktrsyscall(p->p_tracep, code, callp->sy_narg, args.i);
47641475Smckusick #endif
47743641Skarels 	rval[0] = 0;
47843641Skarels 	rval[1] = frame.f_regs[D1];
47941475Smckusick #ifdef HPUXCOMPAT
48042370Skarels 	/* debug kludge */
48142370Skarels 	if (callp->sy_call == notimp)
48244018Skarels 		error = notimp(u.u_procp, args.i, rval, code, callp->sy_narg);
48342370Skarels 	else
48441475Smckusick #endif
48544018Skarels 	error = (*callp->sy_call)(u.u_procp, &args, rval);
48642370Skarels 	if (error == ERESTART)
48742370Skarels 		frame.f_pc = opc;
48842370Skarels 	else if (error != EJUSTRETURN) {
48942370Skarels 		if (error) {
49041475Smckusick #ifdef HPUXCOMPAT
49142370Skarels 			if (p->p_flag & SHPUX)
49242370Skarels 				error = bsdtohpuxerrno(error);
49341475Smckusick #endif
49442370Skarels 			frame.f_regs[D0] = (u_char) error;
49542370Skarels 			frame.f_sr |= PSL_C;	/* carry bit */
49641475Smckusick 		} else {
49743641Skarels 			frame.f_regs[D0] = rval[0];
49843641Skarels 			frame.f_regs[D1] = rval[1];
49941475Smckusick 			frame.f_sr &= ~PSL_C;
50041475Smckusick 		}
50142370Skarels 	}
50242370Skarels 	/* else if (error == EJUSTRETURN) */
50341475Smckusick 		/* nothing to do */
50442370Skarels 
50541475Smckusick done:
50641475Smckusick 	/*
50742370Skarels 	 * Reinitialize proc pointer `p' as it may be different
50842370Skarels 	 * if this is a child returning from fork syscall.
50942370Skarels 	 */
51042371Smckusick 	p = u.u_procp;
51142370Skarels 	/*
51242371Smckusick 	 * XXX the check for sigreturn ensures that we don't
51341475Smckusick 	 * attempt to set up a call to a signal handler (sendsig) before
51441475Smckusick 	 * we have cleaned up the stack from the last call (sigreturn).
51541475Smckusick 	 * Allowing this seems to lock up the machine in certain scenarios.
51641475Smckusick 	 * What should really be done is to clean up the signal handling
51741475Smckusick 	 * so that this is not a problem.
51841475Smckusick 	 */
51942371Smckusick #include "syscall.h"
52042371Smckusick 	if (code != SYS_sigreturn && (i = CURSIG(p)))
52142370Skarels 		psig(i);
52241475Smckusick 	p->p_pri = p->p_usrpri;
52341475Smckusick 	if (runrun) {
52441475Smckusick 		/*
52541475Smckusick 		 * Since we are u.u_procp, clock will normally just change
52641475Smckusick 		 * our priority without moving us from one queue to another
52741475Smckusick 		 * (since the running process is not on a queue.)
52841475Smckusick 		 * If that happened after we setrq ourselves but before we
52941475Smckusick 		 * swtch()'ed, we might not be on the queue indicated by
53041475Smckusick 		 * our priority.
53141475Smckusick 		 */
53241475Smckusick 		(void) splclock();
53341475Smckusick 		setrq(p);
53442371Smckusick 		u.u_ru.ru_nivcsw++;
53541475Smckusick 		swtch();
53643413Shibler 		if (code != SYS_sigreturn && (i = CURSIG(p)))
53742370Skarels 			psig(i);
53841475Smckusick 	}
53942371Smckusick 	if (u.u_prof.pr_scale) {
54041475Smckusick 		int ticks;
54142371Smckusick 		struct timeval *tv = &u.u_ru.ru_stime;
54241475Smckusick 
54341475Smckusick 		ticks = ((tv->tv_sec - syst.tv_sec) * 1000 +
54441475Smckusick 			(tv->tv_usec - syst.tv_usec) / 1000) / (tick / 1000);
54541475Smckusick 		if (ticks) {
54641475Smckusick #ifdef PROFTIMER
54741475Smckusick 			extern int profscale;
54842371Smckusick 			addupc(frame.f_pc, &u.u_prof, ticks * profscale);
54941475Smckusick #else
55042371Smckusick 			addupc(frame.f_pc, &u.u_prof, ticks);
55141475Smckusick #endif
55241475Smckusick 		}
55341475Smckusick 	}
55441475Smckusick 	curpri = p->p_pri;
55541475Smckusick #ifdef KTRACE
55643641Skarels 	if (KTRPOINT(p, KTR_SYSRET))
55743641Skarels 		ktrsysret(p->p_tracep, code, error, rval[0]);
55841475Smckusick #endif
55941475Smckusick }
560