xref: /csrg-svn/sys/hp300/hp300/trap.c (revision 49125)
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*49125Skarels  *	@(#)trap.c	7.11 (Berkeley) 05/04/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 
31*49125Skarels #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 
6841475Smckusick #ifdef DEBUG
6941475Smckusick int mmudebug = 0;
7041475Smckusick #endif
7141475Smckusick 
7241475Smckusick /*
7341475Smckusick  * Called from the trap handler when a processor trap occurs.
7441475Smckusick  */
7541475Smckusick /*ARGSUSED*/
7641475Smckusick trap(type, code, v, frame)
7741475Smckusick 	int type;
7841475Smckusick 	unsigned code;
7941475Smckusick 	register unsigned v;
8041475Smckusick 	struct frame frame;
8141475Smckusick {
8241475Smckusick 	register int i;
8341475Smckusick 	unsigned ucode = 0;
8448465Skarels 	register struct proc *p = curproc;
8541475Smckusick 	struct timeval syst;
8641475Smckusick 	unsigned ncode;
8741475Smckusick 
8841475Smckusick 	cnt.v_trap++;
8948465Skarels 	syst = p->p_stime;
9041475Smckusick 	if (USERMODE(frame.f_sr)) {
9141475Smckusick 		type |= USER;
9248465Skarels 		p->p_regs = frame.f_regs;
9341475Smckusick 	}
9441475Smckusick 	switch (type) {
9541475Smckusick 
9641475Smckusick 	default:
9741475Smckusick dopanic:
9841475Smckusick 		printf("trap type %d, code = %x, v = %x\n", type, code, v);
9941475Smckusick 		regdump(frame.f_regs, 128);
10041475Smckusick 		type &= ~USER;
10141475Smckusick 		if ((unsigned)type < TRAP_TYPES)
10241475Smckusick 			panic(trap_type[type]);
10341475Smckusick 		panic("trap");
10441475Smckusick 
10541475Smckusick 	case T_BUSERR:		/* kernel bus error */
106*49125Skarels 		if (!p->p_addr->u_pcb.pcb_onfault)
10741475Smckusick 			goto dopanic;
10841475Smckusick 		/*
10941475Smckusick 		 * If we have arranged to catch this fault in any of the
11041475Smckusick 		 * copy to/from user space routines, set PC to return to
11141475Smckusick 		 * indicated location and set flag informing buserror code
11241475Smckusick 		 * that it may need to clean up stack frame.
11341475Smckusick 		 */
11441475Smckusick copyfault:
115*49125Skarels 		frame.f_pc = (int) p->p_addr->u_pcb.pcb_onfault;
11641475Smckusick 		frame.f_stackadj = -1;
11741475Smckusick 		return;
11841475Smckusick 
11941475Smckusick 	case T_BUSERR+USER:	/* bus error */
12041475Smckusick 	case T_ADDRERR+USER:	/* address error */
12141475Smckusick 		i = SIGBUS;
12241475Smckusick 		break;
12341475Smckusick 
12441475Smckusick #ifdef FPCOPROC
12541475Smckusick 	case T_COPERR:		/* kernel coprocessor violation */
12641475Smckusick #endif
12741475Smckusick 	case T_FMTERR:		/* kernel format error */
12841475Smckusick 	/*
12941475Smckusick 	 * The user has most likely trashed the RTE or FP state info
13041475Smckusick 	 * in the stack frame of a signal handler.
13141475Smckusick 	 */
13242370Skarels 		type |= USER;
13348465Skarels 		printf("pid %d: kernel %s exception\n", p->p_pid,
13441475Smckusick 		       type==T_COPERR ? "coprocessor" : "format");
13548465Skarels 		p->p_sigacts->ps_sigact[SIGILL] = SIG_DFL;
13641475Smckusick 		i = sigmask(SIGILL);
13741475Smckusick 		p->p_sigignore &= ~i;
13841475Smckusick 		p->p_sigcatch &= ~i;
13941475Smckusick 		p->p_sigmask &= ~i;
14042370Skarels 		i = SIGILL;
14141475Smckusick 		ucode = frame.f_format;	/* XXX was ILL_RESAD_FAULT */
14242370Skarels 		break;
14341475Smckusick 
14441475Smckusick #ifdef FPCOPROC
14541475Smckusick 	case T_COPERR+USER:	/* user coprocessor violation */
14641475Smckusick 	/* What is a proper response here? */
14741475Smckusick 		ucode = 0;
14841475Smckusick 		i = SIGFPE;
14941475Smckusick 		break;
15041475Smckusick 
15141475Smckusick 	case T_FPERR+USER:		/* 68881 exceptions */
15241475Smckusick 	/*
15341475Smckusick 	 * We pass along the 68881 status register which locore stashed
15441475Smckusick 	 * in code for us.  Note that there is a possibility that the
15541475Smckusick 	 * bit pattern of this register will conflict with one of the
15641475Smckusick 	 * FPE_* codes defined in signal.h.  Fortunately for us, the
15741475Smckusick 	 * only such codes we use are all in the range 1-7 and the low
15841475Smckusick 	 * 3 bits of the status register are defined as 0 so there is
15941475Smckusick 	 * no clash.
16041475Smckusick 	 */
16141475Smckusick 		ucode = code;
16241475Smckusick 		i = SIGFPE;
16341475Smckusick 		break;
16441475Smckusick #endif
16541475Smckusick 
16641475Smckusick 	case T_ILLINST+USER:	/* illegal instruction fault */
16741475Smckusick #ifdef HPUXCOMPAT
16848465Skarels 		if (p->p_flag & SHPUX) {
16941475Smckusick 			ucode = HPUX_ILL_ILLINST_TRAP;
17041475Smckusick 			i = SIGILL;
17141475Smckusick 			break;
17241475Smckusick 		}
17341475Smckusick 		/* fall through */
17441475Smckusick #endif
17541475Smckusick 	case T_PRIVINST+USER:	/* privileged instruction fault */
17641475Smckusick #ifdef HPUXCOMPAT
17748465Skarels 		if (p->p_flag & SHPUX)
17841475Smckusick 			ucode = HPUX_ILL_PRIV_TRAP;
17941475Smckusick 		else
18041475Smckusick #endif
18141475Smckusick 		ucode = frame.f_format;	/* XXX was ILL_PRIVIN_FAULT */
18241475Smckusick 		i = SIGILL;
18341475Smckusick 		break;
18441475Smckusick 
18541475Smckusick 	case T_ZERODIV+USER:	/* Divide by zero */
18641475Smckusick #ifdef HPUXCOMPAT
18748465Skarels 		if (p->p_flag & SHPUX)
18841475Smckusick 			ucode = HPUX_FPE_INTDIV_TRAP;
18941475Smckusick 		else
19041475Smckusick #endif
19141475Smckusick 		ucode = frame.f_format;	/* XXX was FPE_INTDIV_TRAP */
19241475Smckusick 		i = SIGFPE;
19341475Smckusick 		break;
19441475Smckusick 
19541475Smckusick 	case T_CHKINST+USER:	/* CHK instruction trap */
19641475Smckusick #ifdef HPUXCOMPAT
19748465Skarels 		if (p->p_flag & SHPUX) {
19841475Smckusick 			/* handled differently under hp-ux */
19941475Smckusick 			i = SIGILL;
20041475Smckusick 			ucode = HPUX_ILL_CHK_TRAP;
20141475Smckusick 			break;
20241475Smckusick 		}
20341475Smckusick #endif
20441475Smckusick 		ucode = frame.f_format;	/* XXX was FPE_SUBRNG_TRAP */
20541475Smckusick 		i = SIGFPE;
20641475Smckusick 		break;
20741475Smckusick 
20841475Smckusick 	case T_TRAPVINST+USER:	/* TRAPV instruction trap */
20941475Smckusick #ifdef HPUXCOMPAT
21048465Skarels 		if (p->p_flag & SHPUX) {
21141475Smckusick 			/* handled differently under hp-ux */
21241475Smckusick 			i = SIGILL;
21341475Smckusick 			ucode = HPUX_ILL_TRAPV_TRAP;
21441475Smckusick 			break;
21541475Smckusick 		}
21641475Smckusick #endif
21741475Smckusick 		ucode = frame.f_format;	/* XXX was FPE_INTOVF_TRAP */
21841475Smckusick 		i = SIGFPE;
21941475Smckusick 		break;
22041475Smckusick 
22141475Smckusick 	/*
22241475Smckusick 	 * XXX: Trace traps are a nightmare.
22341475Smckusick 	 *
22441475Smckusick 	 *	HP-UX uses trap #1 for breakpoints,
22541475Smckusick 	 *	HPBSD uses trap #2,
22641475Smckusick 	 *	SUN 3.x uses trap #15,
22748465Skarels 	 *	KGDB uses trap #15 (for kernel breakpoints; handled elsewhere).
22841475Smckusick 	 *
22941475Smckusick 	 * HPBSD and HP-UX traps both get mapped by locore.s into T_TRACE.
23041475Smckusick 	 * SUN 3.x traps get passed through as T_TRAP15 and are not really
23148465Skarels 	 * supported yet.
23241475Smckusick 	 */
23341475Smckusick 	case T_TRACE:		/* kernel trace trap */
23448465Skarels 	case T_TRAP15:		/* SUN trace trap */
23541475Smckusick 		frame.f_sr &= ~PSL_T;
23641475Smckusick 		i = SIGTRAP;
23741475Smckusick 		break;
23841475Smckusick 
23941475Smckusick 	case T_TRACE+USER:	/* user trace trap */
24041475Smckusick 	case T_TRAP15+USER:	/* SUN user trace trap */
24141475Smckusick 		frame.f_sr &= ~PSL_T;
24241475Smckusick 		i = SIGTRAP;
24341475Smckusick 		break;
24441475Smckusick 
24543413Shibler 	case T_ASTFLT:		/* system async trap, cannot happen */
24641475Smckusick 		goto dopanic;
24741475Smckusick 
24843413Shibler 	case T_ASTFLT+USER:	/* user async trap */
249*49125Skarels 		astpending = 0;
25041475Smckusick 		/*
25141475Smckusick 		 * We check for software interrupts first.  This is because
25241475Smckusick 		 * they are at a higher level than ASTs, and on a VAX would
25341475Smckusick 		 * interrupt the AST.  We assume that if we are processing
25441475Smckusick 		 * an AST that we must be at IPL0 so we don't bother to
25541475Smckusick 		 * check.  Note that we ensure that we are at least at SIR
25641475Smckusick 		 * IPL while processing the SIR.
25741475Smckusick 		 */
25841475Smckusick 		spl1();
25941475Smckusick 		/* fall into... */
26041475Smckusick 
26141475Smckusick 	case T_SSIR:		/* software interrupt */
26241475Smckusick 	case T_SSIR+USER:
26341475Smckusick 		if (ssir & SIR_NET) {
26441475Smckusick 			siroff(SIR_NET);
26541475Smckusick 			cnt.v_soft++;
26641475Smckusick 			netintr();
26741475Smckusick 		}
26841475Smckusick 		if (ssir & SIR_CLOCK) {
26941475Smckusick 			siroff(SIR_CLOCK);
27041475Smckusick 			cnt.v_soft++;
27141475Smckusick 			softclock((caddr_t)frame.f_pc, (int)frame.f_sr);
27241475Smckusick 		}
27341475Smckusick 		/*
27441475Smckusick 		 * If this was not an AST trap, we are all done.
27541475Smckusick 		 */
27643413Shibler 		if (type != T_ASTFLT+USER) {
27741475Smckusick 			cnt.v_trap--;
27841475Smckusick 			return;
27941475Smckusick 		}
28041475Smckusick 		spl0();
28141475Smckusick #ifndef PROFTIMER
28248465Skarels 		if ((p->p_flag&SOWEUPC) && p->p_stats->p_prof.pr_scale) {
28348465Skarels 			addupc(frame.f_pc, &p->p_stats->p_prof, 1);
28448465Skarels 			p->p_flag &= ~SOWEUPC;
28541475Smckusick 		}
28641475Smckusick #endif
28741475Smckusick 		goto out;
28841475Smckusick 
28941475Smckusick 	case T_MMUFLT:		/* kernel mode page fault */
29041475Smckusick 		/* fall into ... */
29141475Smckusick 
29241475Smckusick 	case T_MMUFLT+USER:	/* page fault */
29345751Smckusick 	    {
29445751Smckusick 		register vm_offset_t va;
29548465Skarels 		register struct vmspace *vm = p->p_vmspace;
29645751Smckusick 		register vm_map_t map;
29745751Smckusick 		int rv;
29845751Smckusick 		vm_prot_t ftype;
29945751Smckusick 		extern vm_map_t kernel_map;
30045751Smckusick 		unsigned nss;
30145751Smckusick 
30241475Smckusick 		/*
30345751Smckusick 		 * It is only a kernel address space fault iff:
30445751Smckusick 		 * 	1. (type & USER) == 0  and
30545751Smckusick 		 * 	2. pcb_onfault not set or
30645751Smckusick 		 *	3. pcb_onfault set but supervisor space data fault
30745751Smckusick 		 * The last can occur during an exec() copyin where the
30845751Smckusick 		 * argument space is lazy-allocated.
30941475Smckusick 		 */
31045751Smckusick 		if (type == T_MMUFLT &&
311*49125Skarels 		    (!p->p_addr->u_pcb.pcb_onfault ||
31245751Smckusick 		     (code & (SSW_DF|FC_SUPERD)) == (SSW_DF|FC_SUPERD)))
31345751Smckusick 			map = kernel_map;
31445751Smckusick 		else
31548465Skarels 			map = &vm->vm_map;
31645751Smckusick 		if ((code & (SSW_DF|SSW_RW)) == SSW_DF)	/* what about RMW? */
31745751Smckusick 			ftype = VM_PROT_READ | VM_PROT_WRITE;
31845751Smckusick 		else
31945751Smckusick 			ftype = VM_PROT_READ;
32045751Smckusick 		va = trunc_page((vm_offset_t)v);
32141475Smckusick #ifdef DEBUG
32245751Smckusick 		if (map == kernel_map && va == 0) {
32345751Smckusick 			printf("trap: bad kernel access at %x\n", v);
32441475Smckusick 			goto dopanic;
32541475Smckusick 		}
32641475Smckusick #endif
32741475Smckusick 		/*
32845751Smckusick 		 * XXX: rude hack to make stack limits "work"
32941475Smckusick 		 */
33045751Smckusick 		nss = 0;
33148465Skarels 		if ((caddr_t)va >= vm->vm_maxsaddr && map != kernel_map) {
33245751Smckusick 			nss = clrnd(btoc(USRSTACK-(unsigned)va));
33348465Skarels 			if (nss > btoc(p->p_rlimit[RLIMIT_STACK].rlim_cur)) {
33445751Smckusick 				rv = KERN_FAILURE;
33545751Smckusick 				goto nogo;
33641475Smckusick 			}
33741475Smckusick 		}
33845751Smckusick 		rv = vm_fault(map, va, ftype, FALSE);
33945751Smckusick 		if (rv == KERN_SUCCESS) {
34045751Smckusick 			/*
34145751Smckusick 			 * XXX: continuation of rude stack hack
34245751Smckusick 			 */
34348465Skarels 			if (nss > vm->vm_ssize)
34448465Skarels 				vm->vm_ssize = nss;
34541475Smckusick 			if (type == T_MMUFLT)
34641475Smckusick 				return;
34741475Smckusick 			goto out;
34841475Smckusick 		}
34945751Smckusick nogo:
35045751Smckusick 		if (type == T_MMUFLT) {
351*49125Skarels 			if (p->p_addr->u_pcb.pcb_onfault)
35245751Smckusick 				goto copyfault;
35345751Smckusick 			printf("vm_fault(%x, %x, %x, 0) -> %x\n",
35445751Smckusick 			       map, va, ftype, rv);
35545751Smckusick 			printf("  type %x, code [mmu,,ssw]: %x\n",
35645751Smckusick 			       type, code);
35745751Smckusick 			goto dopanic;
35845751Smckusick 		}
35948465Skarels 		ucode = v;
36045751Smckusick 		i = (rv == KERN_PROTECTION_FAILURE) ? SIGBUS : SIGSEGV;
36145751Smckusick 		break;
36245751Smckusick 	    }
36341475Smckusick 	}
36448465Skarels 	trapsignal(p, i, ucode);
36541475Smckusick 	if ((type & USER) == 0)
36641475Smckusick 		return;
36741475Smckusick out:
36848465Skarels 	while (i = CURSIG(p))
36942370Skarels 		psig(i);
37041475Smckusick 	p->p_pri = p->p_usrpri;
37148465Skarels 	if (want_resched) {
37241475Smckusick 		/*
37348465Skarels 		 * Since we are curproc, clock will normally just change
37441475Smckusick 		 * our priority without moving us from one queue to another
37541475Smckusick 		 * (since the running process is not on a queue.)
37641475Smckusick 		 * If that happened after we setrq ourselves but before we
37741475Smckusick 		 * swtch()'ed, we might not be on the queue indicated by
37841475Smckusick 		 * our priority.
37941475Smckusick 		 */
38041475Smckusick 		(void) splclock();
38141475Smckusick 		setrq(p);
38248465Skarels 		p->p_stats->p_ru.ru_nivcsw++;
38341475Smckusick 		swtch();
38448465Skarels 		while (i = CURSIG(p))
38542370Skarels 			psig(i);
38641475Smckusick 	}
38748465Skarels 	if (p->p_stats->p_prof.pr_scale) {
38841475Smckusick 		int ticks;
38948465Skarels 		struct timeval *tv = &p->p_stime;
39041475Smckusick 
39141475Smckusick 		ticks = ((tv->tv_sec - syst.tv_sec) * 1000 +
39241475Smckusick 			(tv->tv_usec - syst.tv_usec) / 1000) / (tick / 1000);
39341475Smckusick 		if (ticks) {
39441475Smckusick #ifdef PROFTIMER
39541475Smckusick 			extern int profscale;
39648465Skarels 			addupc(frame.f_pc, &p->p_stats->p_prof,
39748465Skarels 			    ticks * profscale);
39841475Smckusick #else
39948465Skarels 			addupc(frame.f_pc, &p->p_stats->p_prof, ticks);
40041475Smckusick #endif
40141475Smckusick 		}
40241475Smckusick 	}
40341475Smckusick 	curpri = p->p_pri;
40441475Smckusick }
40541475Smckusick 
40641475Smckusick /*
40741475Smckusick  * Called from the trap handler when a system call occurs
40841475Smckusick  */
40941475Smckusick /*ARGSUSED*/
41041475Smckusick syscall(code, frame)
41141475Smckusick 	volatile int code;
41241475Smckusick 	struct frame frame;
41341475Smckusick {
41441475Smckusick 	register caddr_t params;
41541475Smckusick 	register int i;
41641475Smckusick 	register struct sysent *callp;
41748465Skarels 	register struct proc *p = curproc;
41842370Skarels 	int error, opc, numsys;
41944018Skarels 	struct args {
42044018Skarels 		int i[8];
42144018Skarels 	} args;
42244018Skarels 	int rval[2];
42341475Smckusick 	struct timeval syst;
42441475Smckusick 	struct sysent *systab;
42541475Smckusick #ifdef HPUXCOMPAT
42641475Smckusick 	extern struct sysent hpuxsysent[];
42741475Smckusick 	extern int hpuxnsysent, notimp();
42841475Smckusick #endif
42941475Smckusick 
43041475Smckusick 	cnt.v_syscall++;
43148465Skarels 	syst = p->p_stime;
43241475Smckusick 	if (!USERMODE(frame.f_sr))
43341475Smckusick 		panic("syscall");
43448465Skarels 	p->p_regs = frame.f_regs;
43541475Smckusick 	opc = frame.f_pc - 2;
43641475Smckusick 	systab = sysent;
43741475Smckusick 	numsys = nsysent;
43841475Smckusick #ifdef HPUXCOMPAT
43942370Skarels 	if (p->p_flag & SHPUX) {
44041475Smckusick 		systab = hpuxsysent;
44141475Smckusick 		numsys = hpuxnsysent;
44241475Smckusick 	}
44341475Smckusick #endif
44441475Smckusick 	params = (caddr_t)frame.f_regs[SP] + NBPW;
44542370Skarels 	if (code == 0) {			/* indir */
44642370Skarels 		code = fuword(params);
44741475Smckusick 		params += NBPW;
44842370Skarels 	}
44942370Skarels 	if (code >= numsys)
45042370Skarels 		callp = &systab[0];		/* indir (illegal) */
45142370Skarels 	else
45242370Skarels 		callp = &systab[code];
45341475Smckusick 	if ((i = callp->sy_narg * sizeof (int)) &&
45444018Skarels 	    (error = copyin(params, (caddr_t)&args, (u_int)i))) {
45541475Smckusick #ifdef HPUXCOMPAT
45641475Smckusick 		if (p->p_flag & SHPUX)
45742370Skarels 			error = bsdtohpuxerrno(error);
45841475Smckusick #endif
45942370Skarels 		frame.f_regs[D0] = (u_char) error;
46041475Smckusick 		frame.f_sr |= PSL_C;	/* carry bit */
46141475Smckusick #ifdef KTRACE
46243641Skarels 		if (KTRPOINT(p, KTR_SYSCALL))
46344018Skarels 			ktrsyscall(p->p_tracep, code, callp->sy_narg, args.i);
46441475Smckusick #endif
46541475Smckusick 		goto done;
46641475Smckusick 	}
46741475Smckusick #ifdef KTRACE
46843641Skarels 	if (KTRPOINT(p, KTR_SYSCALL))
46944018Skarels 		ktrsyscall(p->p_tracep, code, callp->sy_narg, args.i);
47041475Smckusick #endif
47143641Skarels 	rval[0] = 0;
47243641Skarels 	rval[1] = frame.f_regs[D1];
47341475Smckusick #ifdef HPUXCOMPAT
47442370Skarels 	/* debug kludge */
47542370Skarels 	if (callp->sy_call == notimp)
47648465Skarels 		error = notimp(p, args.i, rval, code, callp->sy_narg);
47742370Skarels 	else
47841475Smckusick #endif
47948465Skarels 	error = (*callp->sy_call)(p, &args, rval);
48042370Skarels 	if (error == ERESTART)
48142370Skarels 		frame.f_pc = opc;
48242370Skarels 	else if (error != EJUSTRETURN) {
48342370Skarels 		if (error) {
48441475Smckusick #ifdef HPUXCOMPAT
48542370Skarels 			if (p->p_flag & SHPUX)
48642370Skarels 				error = bsdtohpuxerrno(error);
48741475Smckusick #endif
48842370Skarels 			frame.f_regs[D0] = (u_char) error;
48942370Skarels 			frame.f_sr |= PSL_C;	/* carry bit */
49041475Smckusick 		} else {
49143641Skarels 			frame.f_regs[D0] = rval[0];
49243641Skarels 			frame.f_regs[D1] = rval[1];
49341475Smckusick 			frame.f_sr &= ~PSL_C;
49441475Smckusick 		}
49542370Skarels 	}
49642370Skarels 	/* else if (error == EJUSTRETURN) */
49741475Smckusick 		/* nothing to do */
49842370Skarels 
49941475Smckusick done:
50041475Smckusick 	/*
50142370Skarels 	 * Reinitialize proc pointer `p' as it may be different
50242370Skarels 	 * if this is a child returning from fork syscall.
50342370Skarels 	 */
50448465Skarels 	p = curproc;
50542370Skarels 	/*
50642371Smckusick 	 * XXX the check for sigreturn ensures that we don't
50741475Smckusick 	 * attempt to set up a call to a signal handler (sendsig) before
50841475Smckusick 	 * we have cleaned up the stack from the last call (sigreturn).
50941475Smckusick 	 * Allowing this seems to lock up the machine in certain scenarios.
51041475Smckusick 	 * What should really be done is to clean up the signal handling
51141475Smckusick 	 * so that this is not a problem.
51241475Smckusick 	 */
51345788Sbostic #include "sys/syscall.h"
51448465Skarels 	if (code != SYS_sigreturn)
51548465Skarels 		while (i = CURSIG(p))
51648465Skarels 			psig(i);
51741475Smckusick 	p->p_pri = p->p_usrpri;
51848465Skarels 	if (want_resched) {
51941475Smckusick 		/*
52048465Skarels 		 * Since we are curproc, clock will normally just change
52141475Smckusick 		 * our priority without moving us from one queue to another
52241475Smckusick 		 * (since the running process is not on a queue.)
52341475Smckusick 		 * If that happened after we setrq ourselves but before we
52441475Smckusick 		 * swtch()'ed, we might not be on the queue indicated by
52541475Smckusick 		 * our priority.
52641475Smckusick 		 */
52741475Smckusick 		(void) splclock();
52841475Smckusick 		setrq(p);
52948465Skarels 		p->p_stats->p_ru.ru_nivcsw++;
53041475Smckusick 		swtch();
53148465Skarels 		if (code != SYS_sigreturn)
53248465Skarels 			while (i = CURSIG(p))
53348465Skarels 				psig(i);
53441475Smckusick 	}
53548465Skarels 	if (p->p_stats->p_prof.pr_scale) {
53641475Smckusick 		int ticks;
53748465Skarels 		struct timeval *tv = &p->p_stime;
53841475Smckusick 
53941475Smckusick 		ticks = ((tv->tv_sec - syst.tv_sec) * 1000 +
54041475Smckusick 			(tv->tv_usec - syst.tv_usec) / 1000) / (tick / 1000);
54141475Smckusick 		if (ticks) {
54241475Smckusick #ifdef PROFTIMER
54341475Smckusick 			extern int profscale;
54448465Skarels 			addupc(frame.f_pc, &p->p_stats->p_prof,
54548465Skarels 			    ticks * profscale);
54641475Smckusick #else
54748465Skarels 			addupc(frame.f_pc, &p->p_stats->p_prof, ticks);
54841475Smckusick #endif
54941475Smckusick 		}
55041475Smckusick 	}
55141475Smckusick 	curpri = p->p_pri;
55241475Smckusick #ifdef KTRACE
55343641Skarels 	if (KTRPOINT(p, KTR_SYSRET))
55443641Skarels 		ktrsysret(p->p_tracep, code, error, rval[0]);
55541475Smckusick #endif
55641475Smckusick }
557