xref: /openbsd/sys/arch/hppa/hppa/trap.c (revision a9d0813c)
1*a9d0813cSmiod /*	$OpenBSD: trap.c,v 1.88 2005/08/14 10:54:15 miod Exp $	*/
2556d2ba7Smickey 
3556d2ba7Smickey /*
4fef2e65fSmickey  * Copyright (c) 1998-2004 Michael Shalayeff
5556d2ba7Smickey  * All rights reserved.
6556d2ba7Smickey  *
7556d2ba7Smickey  * Redistribution and use in source and binary forms, with or without
8556d2ba7Smickey  * modification, are permitted provided that the following conditions
9556d2ba7Smickey  * are met:
10556d2ba7Smickey  * 1. Redistributions of source code must retain the above copyright
11556d2ba7Smickey  *    notice, this list of conditions and the following disclaimer.
12556d2ba7Smickey  * 2. Redistributions in binary form must reproduce the above copyright
13556d2ba7Smickey  *    notice, this list of conditions and the following disclaimer in the
14556d2ba7Smickey  *    documentation and/or other materials provided with the distribution.
15556d2ba7Smickey  *
16556d2ba7Smickey  * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
17556d2ba7Smickey  * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
18556d2ba7Smickey  * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
19fef2e65fSmickey  * IN NO EVENT SHALL THE AUTHOR OR HIS RELATIVES BE LIABLE FOR ANY DIRECT,
20fef2e65fSmickey  * INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
21fef2e65fSmickey  * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
22fef2e65fSmickey  * SERVICES; LOSS OF MIND, USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
23fef2e65fSmickey  * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT,
24fef2e65fSmickey  * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING
25fef2e65fSmickey  * IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF
26fef2e65fSmickey  * THE POSSIBILITY OF SUCH DAMAGE.
27556d2ba7Smickey  */
28556d2ba7Smickey 
29ce94da48Smickey /* #define TRAPDEBUG */
30556d2ba7Smickey 
31556d2ba7Smickey #include <sys/param.h>
32556d2ba7Smickey #include <sys/systm.h>
33b9b95e0dSmickey #include <sys/syscall.h>
34b9b95e0dSmickey #include <sys/ktrace.h>
35d412f1c2Smickey #include <sys/proc.h>
366acb4cb0Sniklas #include <sys/signalvar.h>
37d412f1c2Smickey #include <sys/user.h>
38556d2ba7Smickey 
39af7386c3Smickey #include <net/netisr.h>
40af7386c3Smickey 
4196a1071fSmiod #include "systrace.h"
4296a1071fSmiod #include <dev/systrace.h>
4396a1071fSmiod 
44b9b95e0dSmickey #include <uvm/uvm.h>
45556d2ba7Smickey 
46556d2ba7Smickey #include <machine/autoconf.h>
47556d2ba7Smickey 
483867ea13Smiod #include <machine/db_machdep.h>	/* XXX always needed for inst_store() */
49137d3021Smickey #ifdef DDB
509d159c9dSmickey #ifdef TRAPDEBUG
51137d3021Smickey #include <ddb/db_output.h>
52137d3021Smickey #endif
539d159c9dSmickey #endif
54556d2ba7Smickey 
557bfbef72Skettenis #ifdef PTRACE
567bfbef72Skettenis #include <miscfs/procfs/procfs.h>
577bfbef72Skettenis void ss_clear_breakpoints(struct proc *p);
587bfbef72Skettenis #endif
597bfbef72Skettenis 
607bfbef72Skettenis /* single-step breakpoint */
617bfbef72Skettenis #define SSBREAKPOINT	(HPPA_BREAK_KERNEL | (HPPA_BREAK_SS << 13))
627bfbef72Skettenis 
63556d2ba7Smickey const char *trap_type[] = {
64e494c7cfSmickey 	"invalid",
65e494c7cfSmickey 	"HPMC",
66556d2ba7Smickey 	"power failure",
67137d3021Smickey 	"recovery counter",
68556d2ba7Smickey 	"external interrupt",
69e494c7cfSmickey 	"LPMC",
70e494c7cfSmickey 	"ITLB miss fault",
71137d3021Smickey 	"instruction protection",
72137d3021Smickey 	"Illegal instruction",
73137d3021Smickey 	"break instruction",
74137d3021Smickey 	"privileged operation",
75137d3021Smickey 	"privileged register",
76137d3021Smickey 	"overflow",
77137d3021Smickey 	"conditional",
78137d3021Smickey 	"assist exception",
79e494c7cfSmickey 	"DTLB miss",
80137d3021Smickey 	"ITLB non-access miss",
81137d3021Smickey 	"DTLB non-access miss",
82137d3021Smickey 	"data protection/rights/alignment",
83137d3021Smickey 	"data break",
84e494c7cfSmickey 	"TLB dirty",
85137d3021Smickey 	"page reference",
86137d3021Smickey 	"assist emulation",
87e494c7cfSmickey 	"higher-priv transfer",
88e494c7cfSmickey 	"lower-priv transfer",
89137d3021Smickey 	"taken branch",
90137d3021Smickey 	"data access rights",
91e494c7cfSmickey 	"data protection",
92137d3021Smickey 	"unaligned data ref",
93556d2ba7Smickey };
94556d2ba7Smickey int trap_types = sizeof(trap_type)/sizeof(trap_type[0]);
95556d2ba7Smickey 
96bed2d21eSmickey int want_resched, astpending;
97556d2ba7Smickey 
981aec61b7Smickey #define	frame_regmap(tf,r)	(((u_int *)(tf))[hppa_regmap[(r)]])
991aec61b7Smickey u_char hppa_regmap[32] = {
1001aec61b7Smickey 	offsetof(struct trapframe, tf_pad[0]) / 4,	/* r0 XXX */
1011aec61b7Smickey 	offsetof(struct trapframe, tf_r1) / 4,
1021aec61b7Smickey 	offsetof(struct trapframe, tf_rp) / 4,
1031aec61b7Smickey 	offsetof(struct trapframe, tf_r3) / 4,
1041aec61b7Smickey 	offsetof(struct trapframe, tf_r4) / 4,
1051aec61b7Smickey 	offsetof(struct trapframe, tf_r5) / 4,
1061aec61b7Smickey 	offsetof(struct trapframe, tf_r6) / 4,
1071aec61b7Smickey 	offsetof(struct trapframe, tf_r7) / 4,
1081aec61b7Smickey 	offsetof(struct trapframe, tf_r8) / 4,
1091aec61b7Smickey 	offsetof(struct trapframe, tf_r9) / 4,
1101aec61b7Smickey 	offsetof(struct trapframe, tf_r10) / 4,
1111aec61b7Smickey 	offsetof(struct trapframe, tf_r11) / 4,
1121aec61b7Smickey 	offsetof(struct trapframe, tf_r12) / 4,
1131aec61b7Smickey 	offsetof(struct trapframe, tf_r13) / 4,
1141aec61b7Smickey 	offsetof(struct trapframe, tf_r14) / 4,
1151aec61b7Smickey 	offsetof(struct trapframe, tf_r15) / 4,
1161aec61b7Smickey 	offsetof(struct trapframe, tf_r16) / 4,
1171aec61b7Smickey 	offsetof(struct trapframe, tf_r17) / 4,
1181aec61b7Smickey 	offsetof(struct trapframe, tf_r18) / 4,
1191aec61b7Smickey 	offsetof(struct trapframe, tf_t4) / 4,
1201aec61b7Smickey 	offsetof(struct trapframe, tf_t3) / 4,
1211aec61b7Smickey 	offsetof(struct trapframe, tf_t2) / 4,
1221aec61b7Smickey 	offsetof(struct trapframe, tf_t1) / 4,
1231aec61b7Smickey 	offsetof(struct trapframe, tf_arg3) / 4,
1241aec61b7Smickey 	offsetof(struct trapframe, tf_arg2) / 4,
1251aec61b7Smickey 	offsetof(struct trapframe, tf_arg1) / 4,
1261aec61b7Smickey 	offsetof(struct trapframe, tf_arg0) / 4,
1271aec61b7Smickey 	offsetof(struct trapframe, tf_dp) / 4,
1281aec61b7Smickey 	offsetof(struct trapframe, tf_ret0) / 4,
1291aec61b7Smickey 	offsetof(struct trapframe, tf_ret1) / 4,
1301aec61b7Smickey 	offsetof(struct trapframe, tf_sp) / 4,
1311aec61b7Smickey 	offsetof(struct trapframe, tf_r31) / 4,
1321aec61b7Smickey };
1331aec61b7Smickey 
13470016991Smickey void
135d412f1c2Smickey userret(struct proc *p, register_t pc, u_quad_t oticks)
136d412f1c2Smickey {
137d412f1c2Smickey 	int sig;
138af7386c3Smickey 
139d412f1c2Smickey 	/* take pending signals */
140d412f1c2Smickey 	while ((sig = CURSIG(p)) != 0)
141d412f1c2Smickey 		postsig(sig);
142d412f1c2Smickey 
143d412f1c2Smickey 	p->p_priority = p->p_usrpri;
14470016991Smickey 	if (astpending) {
14570016991Smickey 		astpending = 0;
14670016991Smickey 		if (p->p_flag & P_OWEUPC) {
14770016991Smickey 			p->p_flag &= ~P_OWEUPC;
14870016991Smickey 			ADDUPROF(p);
14970016991Smickey 		}
15070016991Smickey 	}
151d412f1c2Smickey 	if (want_resched) {
152d412f1c2Smickey 		/*
153c81336dcSart 		 * We're being preempted.
154d412f1c2Smickey 		 */
155c81336dcSart 		preempt(NULL);
156d412f1c2Smickey 		while ((sig = CURSIG(p)) != 0)
157d412f1c2Smickey 			postsig(sig);
158d412f1c2Smickey 	}
159d412f1c2Smickey 
160d412f1c2Smickey 	/*
161d412f1c2Smickey 	 * If profiling, charge recent system time to the trapped pc.
162d412f1c2Smickey 	 */
163d412f1c2Smickey 	if (p->p_flag & P_PROFIL) {
164d412f1c2Smickey 		extern int psratio;
165d412f1c2Smickey 
166d412f1c2Smickey 		addupc_task(p, pc, (int)(p->p_sticks - oticks) * psratio);
167d412f1c2Smickey 	}
168d412f1c2Smickey 
169d412f1c2Smickey 	curpriority = p->p_priority;
170d412f1c2Smickey }
171d412f1c2Smickey 
172556d2ba7Smickey void
173556d2ba7Smickey trap(type, frame)
174556d2ba7Smickey 	int type;
175556d2ba7Smickey 	struct trapframe *frame;
176556d2ba7Smickey {
177556d2ba7Smickey 	struct proc *p = curproc;
178ab8e80c5Sart 	vaddr_t va;
179ab8e80c5Sart 	struct vm_map *map;
180f17fa196Smickey 	struct vmspace *vm;
181af7386c3Smickey 	register vm_prot_t vftype;
182556d2ba7Smickey 	register pa_space_t space;
183af7386c3Smickey 	union sigval sv;
184c37e03c6Smickey 	u_int opcode;
18570016991Smickey 	int ret, trapnum;
186137d3021Smickey 	const char *tts;
1876198d067Smickey 	vm_fault_t fault = VM_FAULT_INVALID;
18870016991Smickey #ifdef DIAGNOSTIC
18970016991Smickey 	int oldcpl = cpl;
19070016991Smickey #endif
1910e979e06Smickey 
192c37e03c6Smickey 	trapnum = type & ~T_USER;
193137d3021Smickey 	opcode = frame->tf_iir;
1949b476898Smickey 	if (trapnum <= T_EXCEPTION || trapnum == T_HIGHERPL ||
1959b476898Smickey 	    trapnum == T_LOWERPL || trapnum == T_TAKENBR ||
1969b476898Smickey 	    trapnum == T_IDEBUG || trapnum == T_PERFMON) {
197a24c0b7aSmickey 		va = frame->tf_iioq_head;
198a24c0b7aSmickey 		space = frame->tf_iisq_head;
199e21aaa8cSmickey 		vftype = UVM_PROT_EXEC;
200a24c0b7aSmickey 	} else {
201b9b95e0dSmickey 		va = frame->tf_ior;
202a24c0b7aSmickey 		space = frame->tf_isr;
203a4be06b3Smickey 		if (va == frame->tf_iioq_head)
204e21aaa8cSmickey 			vftype = UVM_PROT_EXEC;
205a4be06b3Smickey 		else if (inst_store(opcode))
206e21aaa8cSmickey 			vftype = UVM_PROT_WRITE;
207a4be06b3Smickey 		else
208e21aaa8cSmickey 			vftype = UVM_PROT_READ;
209556d2ba7Smickey 	}
210137d3021Smickey 
211137d3021Smickey 	if (frame->tf_flags & TFF_LAST)
212137d3021Smickey 		p->p_md.md_regs = frame;
213137d3021Smickey 
214c37e03c6Smickey 	if (trapnum > trap_types)
215137d3021Smickey 		tts = "reserved";
216137d3021Smickey 	else
217c37e03c6Smickey 		tts = trap_type[trapnum];
218137d3021Smickey 
219446209b7Smiod #ifdef TRAPDEBUG
220c37e03c6Smickey 	if (trapnum != T_INTERRUPT && trapnum != T_IBREAK)
221969c5366Smickey 		db_printf("trap: %x, %s for %x:%x at %x:%x, fl=%x, fp=%p\n",
222137d3021Smickey 		    type, tts, space, va, frame->tf_iisq_head,
223137d3021Smickey 		    frame->tf_iioq_head, frame->tf_flags, frame);
224c37e03c6Smickey 	else if (trapnum  == T_IBREAK)
225137d3021Smickey 		db_printf("trap: break instruction %x:%x at %x:%x, fp=%p\n",
226a24c0b7aSmickey 		    break5(opcode), break13(opcode),
227137d3021Smickey 		    frame->tf_iisq_head, frame->tf_iioq_head, frame);
228e494c7cfSmickey 
229e494c7cfSmickey 	{
230e494c7cfSmickey 		extern int etext;
231532740e6Smickey 		if (frame < (struct trapframe *)&etext) {
232532740e6Smickey 			printf("trap: bogus frame ptr %p\n", frame);
233e494c7cfSmickey 			goto dead_end;
234e494c7cfSmickey 		}
235532740e6Smickey 	}
236d412f1c2Smickey #endif
2377d3bf75dSmickey 	if (trapnum != T_INTERRUPT) {
2387d3bf75dSmickey 		uvmexp.traps++;
23970016991Smickey 		mtctl(frame->tf_eiem, CR_EIEM);
240916310a5Smickey 	}
24170016991Smickey 
242556d2ba7Smickey 	switch (type) {
243556d2ba7Smickey 	case T_NONEXIST:
244556d2ba7Smickey 	case T_NONEXIST | T_USER:
245af7386c3Smickey 		/* we've got screwed up by the central scrutinizer */
246b67578d8Smickey 		printf("trap: elvis has just left the building!\n");
247532740e6Smickey 		goto dead_end;
248b67578d8Smickey 
249556d2ba7Smickey 	case T_RECOVERY:
250556d2ba7Smickey 	case T_RECOVERY | T_USER:
251af7386c3Smickey 		/* XXX will implement later */
252556d2ba7Smickey 		printf("trap: handicapped");
253532740e6Smickey 		goto dead_end;
25466d1ab7aSmickey 
25566d1ab7aSmickey #ifdef DIAGNOSTIC
25666d1ab7aSmickey 	case T_EXCEPTION:
25766d1ab7aSmickey 		panic("FPU/SFU emulation botch");
25866d1ab7aSmickey 
25966d1ab7aSmickey 		/* these just can't happen ever */
26066d1ab7aSmickey 	case T_PRIV_OP:
26166d1ab7aSmickey 	case T_PRIV_REG:
26266d1ab7aSmickey 		/* these just can't make it to the trap() ever */
263c6555f83Sderaadt 	case T_HPMC:
264c6555f83Sderaadt 	case T_HPMC | T_USER:
26566d1ab7aSmickey #endif
266f4daacd8Smickey 	case T_IBREAK:
267a24c0b7aSmickey 	case T_DATALIGN:
268a24c0b7aSmickey 	case T_DBREAK:
2698de28e3eSmickey 	dead_end:
270a24c0b7aSmickey #ifdef DDB
271532740e6Smickey 		if (kdb_trap (type, va, frame)) {
272a24c0b7aSmickey 			if (type == T_IBREAK) {
273f4daacd8Smickey 				/* skip break instruction */
2748de28e3eSmickey 				frame->tf_iioq_head = frame->tf_iioq_tail;
275f4daacd8Smickey 				frame->tf_iioq_tail += 4;
276a24c0b7aSmickey 			}
277556d2ba7Smickey 			return;
278a24c0b7aSmickey 		}
279137d3021Smickey #else
280137d3021Smickey 		if (type == T_DATALIGN)
281137d3021Smickey 			panic ("trap: %s at 0x%x", tts, va);
282137d3021Smickey 		else
283137d3021Smickey 			panic ("trap: no debugger for \"%s\" (%d)", tts, type);
284a24c0b7aSmickey #endif
285556d2ba7Smickey 		break;
286556d2ba7Smickey 
287af7386c3Smickey 	case T_IBREAK | T_USER:
2887bfbef72Skettenis 	case T_DBREAK | T_USER: {
2897bfbef72Skettenis 		int code = TRAP_BRKPT;
2907bfbef72Skettenis #ifdef PTRACE
2917bfbef72Skettenis 		ss_clear_breakpoints(p);
2927bfbef72Skettenis 		if (opcode == SSBREAKPOINT)
2937bfbef72Skettenis 			code = TRAP_TRACE;
2947bfbef72Skettenis #endif
295af7386c3Smickey 		/* pass to user debugger */
2967bfbef72Skettenis 		trapsignal(p, SIGTRAP, type &~ T_USER, code, sv);
2977bfbef72Skettenis 		}
298d412f1c2Smickey 		break;
299d412f1c2Smickey 
3007bfbef72Skettenis #ifdef PTRACE
3017bfbef72Skettenis 	case T_TAKENBR | T_USER:
3027bfbef72Skettenis 		ss_clear_breakpoints(p);
3037bfbef72Skettenis 
3047bfbef72Skettenis 		/* pass to user debugger */
3057bfbef72Skettenis 		trapsignal(p, SIGTRAP, type &~ T_USER, TRAP_TRACE, sv);
3067bfbef72Skettenis 		break;
3077bfbef72Skettenis #endif
3087bfbef72Skettenis 
30938575cbdSmickey 	case T_EXCEPTION | T_USER: {
310969eb289Smickey 		u_int64_t *fpp = (u_int64_t *)frame->tf_cr30;
311969eb289Smickey 		u_int32_t *pex;
31238575cbdSmickey 		int i, flt;
31338575cbdSmickey 
314969eb289Smickey 		pex = (u_int32_t *)&fpp[0];
31538575cbdSmickey 		for (i = 0, pex++; i < 7 && !*pex; i++, pex++);
316969eb289Smickey 		flt = 0;
317969eb289Smickey 		if (i < 7) {
318969eb289Smickey 			u_int32_t stat = HPPA_FPU_OP(*pex);
31928496d60Smickey 			if (stat & HPPA_FPU_UNMPL)
320969eb289Smickey 				flt = FPE_FLTINV;
32128496d60Smickey 			else if (stat & (HPPA_FPU_V << 1))
32238575cbdSmickey 				flt = FPE_FLTINV;
32328496d60Smickey 			else if (stat & (HPPA_FPU_Z << 1))
32438575cbdSmickey 				flt = FPE_FLTDIV;
32528496d60Smickey 			else if (stat & (HPPA_FPU_I << 1))
326969eb289Smickey 				flt = FPE_FLTRES;
32728496d60Smickey 			else if (stat & (HPPA_FPU_O << 1))
32838575cbdSmickey 				flt = FPE_FLTOVF;
32928496d60Smickey 			else if (stat & (HPPA_FPU_U << 1))
33038575cbdSmickey 				flt = FPE_FLTUND;
331969eb289Smickey 			/* still left: under/over-flow w/ inexact */
332ded58a29Smickey 
333ded58a29Smickey 			/* cleanup exceptions (XXX deliver all ?) */
334ded58a29Smickey 			while (i++ < 7)
335ded58a29Smickey 				*pex++ = 0;
336969eb289Smickey 		}
337969eb289Smickey 		/* reset the trap flag, as if there was none */
338969eb289Smickey 		fpp[0] &= ~(((u_int64_t)HPPA_FPU_T) << 32);
339969eb289Smickey 		/* flush out, since load is done from phys, only 4 regs */
340969eb289Smickey 		fdcache(HPPA_SID_KERNEL, (vaddr_t)fpp, 8 * 4);
34138575cbdSmickey 
34238575cbdSmickey 		sv.sival_int = va;
34338575cbdSmickey 		trapsignal(p, SIGFPE, type &~ T_USER, flt, sv);
34438575cbdSmickey 		}
34538575cbdSmickey 		break;
34638575cbdSmickey 
347969eb289Smickey 	case T_EMULATION:
348969eb289Smickey 		panic("trap: emulation trap in the kernel");
349969eb289Smickey 		break;
350969eb289Smickey 
351969eb289Smickey 	case T_EMULATION | T_USER:
352137d3021Smickey 		sv.sival_int = va;
35328496d60Smickey 		trapsignal(p, SIGILL, type &~ T_USER, ILL_COPROC, sv);
354d412f1c2Smickey 		break;
355d412f1c2Smickey 
356af7386c3Smickey 	case T_OVERFLOW | T_USER:
357137d3021Smickey 		sv.sival_int = va;
358af7386c3Smickey 		trapsignal(p, SIGFPE, type &~ T_USER, FPE_INTOVF, sv);
359d412f1c2Smickey 		break;
360d412f1c2Smickey 
361af7386c3Smickey 	case T_CONDITION | T_USER:
3628b9bddf0Smickey 		sv.sival_int = va;
3638b9bddf0Smickey 		trapsignal(p, SIGFPE, type &~ T_USER, FPE_INTDIV, sv);
364af7386c3Smickey 		break;
365af7386c3Smickey 
366af7386c3Smickey 	case T_PRIV_OP | T_USER:
367137d3021Smickey 		sv.sival_int = va;
368af7386c3Smickey 		trapsignal(p, SIGILL, type &~ T_USER, ILL_PRVOPC, sv);
369af7386c3Smickey 		break;
370af7386c3Smickey 
371af7386c3Smickey 	case T_PRIV_REG | T_USER:
372137d3021Smickey 		sv.sival_int = va;
373af7386c3Smickey 		trapsignal(p, SIGILL, type &~ T_USER, ILL_PRVREG, sv);
374af7386c3Smickey 		break;
375af7386c3Smickey 
376af7386c3Smickey 		/* these should never got here */
377af7386c3Smickey 	case T_HIGHERPL | T_USER:
378af7386c3Smickey 	case T_LOWERPL | T_USER:
379137d3021Smickey 		sv.sival_int = va;
380a4be06b3Smickey 		trapsignal(p, SIGSEGV, vftype, SEGV_ACCERR, sv);
381af7386c3Smickey 		break;
382af7386c3Smickey 
383af7386c3Smickey 	case T_IPROT | T_USER:
384af7386c3Smickey 	case T_DPROT | T_USER:
385af7386c3Smickey 		sv.sival_int = va;
386af7386c3Smickey 		trapsignal(p, SIGSEGV, vftype, SEGV_ACCERR, sv);
387af7386c3Smickey 		break;
388af7386c3Smickey 
3899208e3abSmickey 	case T_ITLBMISSNA:
3909208e3abSmickey 	case T_ITLBMISSNA | T_USER:
3919208e3abSmickey 	case T_DTLBMISSNA:
3929208e3abSmickey 	case T_DTLBMISSNA | T_USER:
3939208e3abSmickey 		if (space == HPPA_SID_KERNEL)
3949208e3abSmickey 			map = kernel_map;
3959208e3abSmickey 		else {
3969208e3abSmickey 			vm = p->p_vmspace;
3979208e3abSmickey 			map = &vm->vm_map;
3989208e3abSmickey 		}
3999208e3abSmickey 
40098898169Smickey 		if ((opcode & 0xfc003fc0) == 0x04001340) {
40198898169Smickey 			/* lpa failure case */
40298898169Smickey 			frame_regmap(frame, opcode & 0x1f) = 0;
40398898169Smickey 			frame->tf_ipsw |= PSL_N;
40498898169Smickey 		} else if ((opcode & 0xfc001f80) == 0x04001180) {
4059208e3abSmickey 			int pl;
4069208e3abSmickey 
40798898169Smickey 			/* dig probe[rw]i? insns */
4089208e3abSmickey 			if (opcode & 0x2000)
4099208e3abSmickey 				pl = (opcode >> 16) & 3;
4109208e3abSmickey 			else
4119208e3abSmickey 				pl = frame_regmap(frame,
4129208e3abSmickey 				    (opcode >> 16) & 0x1f) & 3;
4139208e3abSmickey 
4149208e3abSmickey 			if ((type & T_USER && space == HPPA_SID_KERNEL) ||
4159208e3abSmickey 			    (frame->tf_iioq_head & 3) != pl ||
4169208e3abSmickey 			    (type & T_USER && va >= VM_MAXUSER_ADDRESS) ||
4179208e3abSmickey 			    uvm_fault(map, hppa_trunc_page(va), fault,
4189208e3abSmickey 			     opcode & 0x40? UVM_PROT_WRITE : UVM_PROT_READ)) {
4199208e3abSmickey 				frame_regmap(frame, opcode & 0x1f) = 0;
4209208e3abSmickey 				frame->tf_ipsw |= PSL_N;
4219208e3abSmickey 			}
4229208e3abSmickey 		} else if (type & T_USER) {
4239208e3abSmickey 			sv.sival_int = va;
4249208e3abSmickey 			trapsignal(p, SIGILL, type & ~T_USER, ILL_ILLTRP, sv);
4259208e3abSmickey 		} else
42662a36cb0Sfgsch 			panic("trap: %s @ 0x%x:0x%x for 0x%x:0x%x irr 0x%08x",
4279208e3abSmickey 			    tts, frame->tf_iisq_head, frame->tf_iioq_head,
4289208e3abSmickey 			    space, va, opcode);
4299208e3abSmickey 		break;
4309208e3abSmickey 
4319208e3abSmickey 	case T_TLB_DIRTY:
4329208e3abSmickey 	case T_TLB_DIRTY | T_USER:
433c6555f83Sderaadt 	case T_DATACC:
434c6555f83Sderaadt 	case T_DATACC | T_USER:
4356198d067Smickey 		fault = VM_FAULT_PROTECT;
436c6555f83Sderaadt 	case T_ITLBMISS:
437c6555f83Sderaadt 	case T_ITLBMISS | T_USER:
438c6555f83Sderaadt 	case T_DTLBMISS:
439c6555f83Sderaadt 	case T_DTLBMISS | T_USER:
4408de28e3eSmickey 		/*
441e494c7cfSmickey 		 * it could be a kernel map for exec_map faults
4428de28e3eSmickey 		 */
44343a91648Smickey 		if (space == HPPA_SID_KERNEL)
4448de28e3eSmickey 			map = kernel_map;
44543a91648Smickey 		else {
44643a91648Smickey 			vm = p->p_vmspace;
447f17fa196Smickey 			map = &vm->vm_map;
44843a91648Smickey 		}
449556d2ba7Smickey 
4509208e3abSmickey 		/*
4519208e3abSmickey 		 * user faults out of user addr space are always a fail,
4529208e3abSmickey 		 * this happens on va >= VM_MAXUSER_ADDRESS, where
4539208e3abSmickey 		 * space id will be zero and therefore cause
4549208e3abSmickey 		 * a misbehave lower in the code.
4559208e3abSmickey 		 *
4569208e3abSmickey 		 * also check that faulted space id matches the curproc.
4579208e3abSmickey 		 */
4589208e3abSmickey 		if ((type & T_USER && va >= VM_MAXUSER_ADDRESS) ||
4599208e3abSmickey 		   (type & T_USER && map->pmap->pm_space != space)) {
460906a25e0Smickey 			sv.sival_int = va;
461906a25e0Smickey 			trapsignal(p, SIGSEGV, vftype, SEGV_MAPERR, sv);
46243a91648Smickey 			break;
463906a25e0Smickey 		}
464532740e6Smickey 
465a4be06b3Smickey 		ret = uvm_fault(map, hppa_trunc_page(va), fault, vftype);
466f17fa196Smickey 
467f17fa196Smickey 		/*
468f17fa196Smickey 		 * If this was a stack access we keep track of the maximum
469f17fa196Smickey 		 * accessed stack size.  Also, if uvm_fault gets a protection
470f17fa196Smickey 		 * failure it is due to accessing the stack region outside
471f17fa196Smickey 		 * the current limit and we need to reflect that as an access
472f17fa196Smickey 		 * error.
473f17fa196Smickey 		 */
47456f69dffSmiod 		if (space != HPPA_SID_KERNEL &&
47562899679Smiod 		    va < (vaddr_t)vm->vm_minsaddr) {
47662899679Smiod 			if (ret == 0)
47762899679Smiod 				uvm_grow(p, va);
47862899679Smiod 			else if (ret == EACCES)
479738a5b4dSart 				ret = EFAULT;
480f17fa196Smickey 		}
481f17fa196Smickey 
482738a5b4dSart 		if (ret != 0) {
483af7386c3Smickey 			if (type & T_USER) {
484a4be06b3Smickey 				sv.sival_int = va;
485a4be06b3Smickey 				trapsignal(p, SIGSEGV, vftype,
486a4be06b3Smickey 				    ret == EACCES? SEGV_ACCERR : SEGV_MAPERR,
487a4be06b3Smickey 				    sv);
488137d3021Smickey 			} else {
4898de28e3eSmickey 				if (p && p->p_addr->u_pcb.pcb_onfault) {
4908de28e3eSmickey 					frame->tf_iioq_tail = 4 +
4918de28e3eSmickey 					    (frame->tf_iioq_head =
49238575cbdSmickey 						p->p_addr->u_pcb.pcb_onfault);
493b04f760fSmickey #ifdef DDB
494b04f760fSmickey 					frame->tf_iir = 0;
495b04f760fSmickey #endif
496db97f33bSmickey 				} else {
497db97f33bSmickey 					panic("trap: "
49856f69dffSmiod 					    "uvm_fault(%p, %lx, %d, %d): %d",
49996415af6Smickey 					    map, va, fault, vftype, ret);
500137d3021Smickey 				}
501137d3021Smickey 			}
502db97f33bSmickey 		}
503556d2ba7Smickey 		break;
504d412f1c2Smickey 
505af7386c3Smickey 	case T_DATALIGN | T_USER:
506137d3021Smickey 		sv.sival_int = va;
507af7386c3Smickey 		trapsignal(p, SIGBUS, vftype, BUS_ADRALN, sv);
508af7386c3Smickey 		break;
509af7386c3Smickey 
510a24c0b7aSmickey 	case T_INTERRUPT:
511a24c0b7aSmickey 	case T_INTERRUPT | T_USER:
512a24c0b7aSmickey 		cpu_intr(frame);
513af7386c3Smickey 		break;
514af7386c3Smickey 
515b7d25a19Smickey 	case T_CONDITION:
516b7d25a19Smickey 		panic("trap: divide by zero in the kernel");
517b7d25a19Smickey 		break;
518b7d25a19Smickey 
5193147f0deSmickey 	case T_ILLEGAL:
5203147f0deSmickey 	case T_ILLEGAL | T_USER:
5213147f0deSmickey 		/* see if it's a SPOP1,,0 */
52296415af6Smickey 		if ((opcode & 0xfffffe00) == 0x10000200) {
52396415af6Smickey 			frame_regmap(frame, opcode & 0x1f) = 0;
5243147f0deSmickey 			frame->tf_ipsw |= PSL_N;
5253147f0deSmickey 			break;
5263147f0deSmickey 		}
5273147f0deSmickey 		if (type & T_USER) {
5283147f0deSmickey 			sv.sival_int = va;
5293147f0deSmickey 			trapsignal(p, SIGILL, type &~ T_USER, ILL_ILLOPC, sv);
5303147f0deSmickey 			break;
5313147f0deSmickey 		}
5323147f0deSmickey 		/* FALLTHROUGH */
5333147f0deSmickey 
53470016991Smickey 	case T_LOWERPL:
5352ef9a47eSmickey 	case T_DPROT:
5362ef9a47eSmickey 	case T_IPROT:
537af7386c3Smickey 	case T_OVERFLOW:
538af7386c3Smickey 	case T_HIGHERPL:
539af7386c3Smickey 	case T_TAKENBR:
540af7386c3Smickey 	case T_POWERFAIL:
541af7386c3Smickey 	case T_LPMC:
542af7386c3Smickey 	case T_PAGEREF:
543c6555f83Sderaadt 	case T_DATAPID:
544c6555f83Sderaadt 	case T_DATAPID | T_USER:
545d412f1c2Smickey 		if (0 /* T-chip */) {
546d412f1c2Smickey 			break;
547556d2ba7Smickey 		}
548d412f1c2Smickey 		/* FALLTHROUGH to unimplemented */
549d412f1c2Smickey 	default:
550a228f8d2Smickey #if 0
551532740e6Smickey if (kdb_trap (type, va, frame))
552137d3021Smickey 	return;
553137d3021Smickey #endif
55470016991Smickey 		panic("trap: unimplemented \'%s\' (%d)", tts, trapnum);
555d412f1c2Smickey 	}
556af7386c3Smickey 
55770016991Smickey #ifdef DIAGNOSTIC
55870016991Smickey 	if (cpl != oldcpl)
55970016991Smickey 		printf("WARNING: SPL (%d) NOT LOWERED ON "
56070016991Smickey 		    "TRAP (%d) EXIT\n", cpl, trapnum);
56170016991Smickey #endif
56270016991Smickey 
56370016991Smickey 	if (trapnum != T_INTERRUPT)
56470016991Smickey 		splx(cpl);	/* process softints */
56570016991Smickey 
566ba42a120Smickey 	/*
567ba42a120Smickey 	 * in case we were interrupted from the syscall gate page
568ba42a120Smickey 	 * treat this as we were not realy running user code no more
569ba42a120Smickey 	 * for weird things start to happen on return to the userland
570ba42a120Smickey 	 * and also see a note in locore.S:TLABEL(all)
571ba42a120Smickey 	 */
572ba42a120Smickey 	if ((type & T_USER) &&
573ba42a120Smickey 	    (frame->tf_iioq_head & ~PAGE_MASK) != SYSCALLGATE)
57470016991Smickey 		userret(p, frame->tf_iioq_head, 0);
575d412f1c2Smickey }
576d412f1c2Smickey 
577d412f1c2Smickey void
578db36253aSmickey child_return(arg)
579db36253aSmickey 	void *arg;
580d412f1c2Smickey {
581db36253aSmickey 	struct proc *p = (struct proc *)arg;
58289afe3e5Smickey 	struct trapframe *tf = p->p_md.md_regs;
58389afe3e5Smickey 
58489afe3e5Smickey 	/*
58589afe3e5Smickey 	 * Set up return value registers as libc:fork() expects
58689afe3e5Smickey 	 */
58789afe3e5Smickey 	tf->tf_ret0 = 0;
58889afe3e5Smickey 	tf->tf_ret1 = 1;	/* ischild */
58989afe3e5Smickey 	tf->tf_t1 = 0;		/* errno */
59089afe3e5Smickey 
59189afe3e5Smickey 	userret(p, tf->tf_iioq_head, 0);
592d412f1c2Smickey #ifdef KTRACE
593d412f1c2Smickey 	if (KTRPOINT(p, KTR_SYSRET))
594a27b30d8Sart 		ktrsysret(p, SYS_fork, 0, 0);
595d412f1c2Smickey #endif
596556d2ba7Smickey }
597556d2ba7Smickey 
5987bfbef72Skettenis #ifdef PTRACE
5997bfbef72Skettenis 
6007bfbef72Skettenis #include <sys/ptrace.h>
6017bfbef72Skettenis 
6027bfbef72Skettenis int
6037bfbef72Skettenis ss_get_value(struct proc *p, vaddr_t addr, u_int *value)
6047bfbef72Skettenis {
6057bfbef72Skettenis 	struct uio uio;
6067bfbef72Skettenis 	struct iovec iov;
6077bfbef72Skettenis 
6087bfbef72Skettenis 	iov.iov_base = (caddr_t)value;
6097bfbef72Skettenis 	iov.iov_len = sizeof(u_int);
6107bfbef72Skettenis 	uio.uio_iov = &iov;
6117bfbef72Skettenis 	uio.uio_iovcnt = 1;
6127bfbef72Skettenis 	uio.uio_offset = (off_t)addr;
6137bfbef72Skettenis 	uio.uio_resid = sizeof(u_int);
6147bfbef72Skettenis 	uio.uio_segflg = UIO_SYSSPACE;
6157bfbef72Skettenis 	uio.uio_rw = UIO_READ;
6167bfbef72Skettenis 	uio.uio_procp = curproc;
6177bfbef72Skettenis 	return (procfs_domem(curproc, p, NULL, &uio));
6187bfbef72Skettenis }
6197bfbef72Skettenis 
6207bfbef72Skettenis int
6217bfbef72Skettenis ss_put_value(struct proc *p, vaddr_t addr, u_int value)
6227bfbef72Skettenis {
6237bfbef72Skettenis 	struct uio uio;
6247bfbef72Skettenis 	struct iovec iov;
6257bfbef72Skettenis 
6267bfbef72Skettenis 	iov.iov_base = (caddr_t)&value;
6277bfbef72Skettenis 	iov.iov_len = sizeof(u_int);
6287bfbef72Skettenis 	uio.uio_iov = &iov;
6297bfbef72Skettenis 	uio.uio_iovcnt = 1;
6307bfbef72Skettenis 	uio.uio_offset = (off_t)addr;
6317bfbef72Skettenis 	uio.uio_resid = sizeof(u_int);
6327bfbef72Skettenis 	uio.uio_segflg = UIO_SYSSPACE;
6337bfbef72Skettenis 	uio.uio_rw = UIO_WRITE;
6347bfbef72Skettenis 	uio.uio_procp = curproc;
6357bfbef72Skettenis 	return (procfs_domem(curproc, p, NULL, &uio));
6367bfbef72Skettenis }
6377bfbef72Skettenis 
6387bfbef72Skettenis void
6397bfbef72Skettenis ss_clear_breakpoints(struct proc *p)
6407bfbef72Skettenis {
6417bfbef72Skettenis 	/* Restore origional instructions. */
6427bfbef72Skettenis 	if (p->p_md.md_bpva != 0) {
6437bfbef72Skettenis 		ss_put_value(p, p->p_md.md_bpva, p->p_md.md_bpsave[0]);
6447bfbef72Skettenis 		ss_put_value(p, p->p_md.md_bpva + 4, p->p_md.md_bpsave[1]);
6457bfbef72Skettenis 		p->p_md.md_bpva = 0;
6467bfbef72Skettenis 	}
6477bfbef72Skettenis }
6487bfbef72Skettenis 
6497bfbef72Skettenis int
6507bfbef72Skettenis process_sstep(struct proc *p, int sstep)
6517bfbef72Skettenis {
6527bfbef72Skettenis 	int error;
6537bfbef72Skettenis 
6547bfbef72Skettenis 	ss_clear_breakpoints(p);
6557bfbef72Skettenis 
6567bfbef72Skettenis 	/* Don't touch the syscall gateway page. */
6577bfbef72Skettenis 	if (sstep == 0 ||
6587bfbef72Skettenis 	    (p->p_md.md_regs->tf_iioq_tail & ~PAGE_MASK) == SYSCALLGATE) {
6597bfbef72Skettenis 		p->p_md.md_regs->tf_ipsw &= ~PSL_T;
6607bfbef72Skettenis 		return (0);
6617bfbef72Skettenis 	}
6627bfbef72Skettenis 
6637bfbef72Skettenis 	p->p_md.md_bpva = p->p_md.md_regs->tf_iioq_tail & ~HPPA_PC_PRIV_MASK;
6647bfbef72Skettenis 
6657bfbef72Skettenis 	/*
6667bfbef72Skettenis 	 * Insert two breakpoint instructions; the first one might be
6677bfbef72Skettenis 	 * nullified.  Of course we need to save two instruction
6687bfbef72Skettenis 	 * first.
6697bfbef72Skettenis 	 */
6707bfbef72Skettenis 
6717bfbef72Skettenis 	error = ss_get_value(p, p->p_md.md_bpva, &p->p_md.md_bpsave[0]);
6727bfbef72Skettenis 	if (error)
6737bfbef72Skettenis 		return (error);
6747bfbef72Skettenis 	error = ss_get_value(p, p->p_md.md_bpva + 4, &p->p_md.md_bpsave[1]);
6757bfbef72Skettenis 	if (error)
6767bfbef72Skettenis 		return (error);
6777bfbef72Skettenis 
6787bfbef72Skettenis 	error = ss_put_value(p, p->p_md.md_bpva, SSBREAKPOINT);
6797bfbef72Skettenis 	if (error)
6807bfbef72Skettenis 		return (error);
6817bfbef72Skettenis 	error = ss_put_value(p, p->p_md.md_bpva + 4, SSBREAKPOINT);
6827bfbef72Skettenis 	if (error)
6837bfbef72Skettenis 		return (error);
6847bfbef72Skettenis 
6857bfbef72Skettenis 	p->p_md.md_regs->tf_ipsw |= PSL_T;
6867bfbef72Skettenis 	return (0);
6877bfbef72Skettenis }
6887bfbef72Skettenis 
6897bfbef72Skettenis #endif	/* PTRACE */
690db97f33bSmickey 
691b9b95e0dSmickey /*
692b9b95e0dSmickey  * call actual syscall routine
693b9b95e0dSmickey  */
694b9b95e0dSmickey void
69570016991Smickey syscall(struct trapframe *frame)
696b9b95e0dSmickey {
697db97f33bSmickey 	register struct proc *p = curproc;
698b9b95e0dSmickey 	register const struct sysent *callp;
699b7d25a19Smickey 	int retq, nsys, code, argsize, argoff, oerror, error;
700b7d25a19Smickey 	register_t args[8], rval[2];
70170016991Smickey #ifdef DIAGNOSTIC
70270016991Smickey 	int oldcpl = cpl;
70370016991Smickey #endif
704b9b95e0dSmickey 
705b9b95e0dSmickey 	uvmexp.syscalls++;
706b9b95e0dSmickey 
707b9b95e0dSmickey 	if (!USERMODE(frame->tf_iioq_head))
708b9b95e0dSmickey 		panic("syscall");
709b9b95e0dSmickey 
710137d3021Smickey 	p->p_md.md_regs = frame;
711b9b95e0dSmickey 	nsys = p->p_emul->e_nsysent;
712b9b95e0dSmickey 	callp = p->p_emul->e_sysent;
713db97f33bSmickey 
714b7d25a19Smickey 	argoff = 4; retq = 0;
715db97f33bSmickey 	switch (code = frame->tf_t1) {
716b9b95e0dSmickey 	case SYS_syscall:
717db97f33bSmickey 		code = frame->tf_arg0;
718db97f33bSmickey 		args[0] = frame->tf_arg1;
719db97f33bSmickey 		args[1] = frame->tf_arg2;
720db97f33bSmickey 		args[2] = frame->tf_arg3;
721db97f33bSmickey 		argoff = 3;
722b9b95e0dSmickey 		break;
723b9b95e0dSmickey 	case SYS___syscall:
724b9b95e0dSmickey 		if (callp != sysent)
725b9b95e0dSmickey 			break;
726db97f33bSmickey 		/*
727db97f33bSmickey 		 * this works, because quads get magically swapped
7287503858eSjfb 		 * due to the args being laid backwards on the stack
729db97f33bSmickey 		 * and then copied in words
730db97f33bSmickey 		 */
731db97f33bSmickey 		code = frame->tf_arg0;
732db97f33bSmickey 		args[0] = frame->tf_arg2;
733db97f33bSmickey 		args[1] = frame->tf_arg3;
734db97f33bSmickey 		argoff = 2;
735b7d25a19Smickey 		retq = 1;
736db97f33bSmickey 		break;
737db97f33bSmickey 	default:
738db97f33bSmickey 		args[0] = frame->tf_arg0;
739db97f33bSmickey 		args[1] = frame->tf_arg1;
740db97f33bSmickey 		args[2] = frame->tf_arg2;
741db97f33bSmickey 		args[3] = frame->tf_arg3;
742db97f33bSmickey 		break;
743b9b95e0dSmickey 	}
744b9b95e0dSmickey 
745b9b95e0dSmickey 	if (code < 0 || code >= nsys)
746b9b95e0dSmickey 		callp += p->p_emul->e_nosys;	/* bad syscall # */
747b9b95e0dSmickey 	else
748b9b95e0dSmickey 		callp += code;
749db97f33bSmickey 
750db97f33bSmickey 	oerror = error = 0;
751db97f33bSmickey 	if ((argsize = callp->sy_argsize)) {
752db97f33bSmickey 		int i;
753db97f33bSmickey 
754db97f33bSmickey 		for (i = 0, argsize -= argoff * 4;
755db97f33bSmickey 		    argsize > 0; i++, argsize -= 4) {
756db97f33bSmickey 			error = copyin((void *)(frame->tf_sp +
757db97f33bSmickey 			    HPPA_FRAME_ARG(i + 4)), args + i + argoff, 4);
758db97f33bSmickey 
759db97f33bSmickey 			if (error)
760db97f33bSmickey 				break;
761db97f33bSmickey 		}
762db97f33bSmickey 
763db97f33bSmickey 		/*
764db97f33bSmickey 		 * coming from syscall() or __syscall we must be
765db97f33bSmickey 		 * having one of those w/ a 64 bit arguments,
766db97f33bSmickey 		 * which needs a word swap due to the order
767db97f33bSmickey 		 * of the arguments on the stack.
768db97f33bSmickey 		 * this assumes that none of 'em are called
769db97f33bSmickey 		 * by their normal syscall number, maybe a regress
770b49f4f07Smiod 		 * test should be used, to watch the behaviour.
771db97f33bSmickey 		 */
772db97f33bSmickey 		if (!error && argoff < 4) {
773db97f33bSmickey 			int t;
774db97f33bSmickey 
775db97f33bSmickey 			i = 0;
776db97f33bSmickey 			switch (code) {
777b7d25a19Smickey 			case SYS_lseek:		retq = 0;
778db97f33bSmickey 			case SYS_truncate:
779db97f33bSmickey 			case SYS_ftruncate:	i = 2;	break;
780db97f33bSmickey 			case SYS_preadv:
781db97f33bSmickey 			case SYS_pwritev:
782db97f33bSmickey 			case SYS_pread:
783db97f33bSmickey 			case SYS_pwrite:	i = 4;	break;
784*a9d0813cSmiod 			case SYS_mquery:
785db97f33bSmickey 			case SYS_mmap:		i = 6;	break;
786db97f33bSmickey 			}
787db97f33bSmickey 
788db97f33bSmickey 			if (i) {
789db97f33bSmickey 				t = args[i];
790db97f33bSmickey 				args[i] = args[i + 1];
791db97f33bSmickey 				args[i + 1] = t;
792db97f33bSmickey 			}
793db97f33bSmickey 		}
794db97f33bSmickey 	}
795b9b95e0dSmickey 
796b9b95e0dSmickey #ifdef SYSCALL_DEBUG
797b9b95e0dSmickey 	scdebug_call(p, code, args);
798b9b95e0dSmickey #endif
799b9b95e0dSmickey #ifdef KTRACE
800b9b95e0dSmickey 	if (KTRPOINT(p, KTR_SYSCALL))
801d970adb6Smickey 		ktrsyscall(p, code, callp->sy_argsize, args);
802b9b95e0dSmickey #endif
803db97f33bSmickey 	if (error)
804db97f33bSmickey 		goto bad;
805b9b95e0dSmickey 
806b9b95e0dSmickey 	rval[0] = 0;
807db97f33bSmickey 	rval[1] = frame->tf_ret1;
80896a1071fSmiod #if NSYSTRACE > 0
80996a1071fSmiod 	if (ISSET(p->p_flag, P_SYSTRACE))
810db97f33bSmickey 		oerror = error = systrace_redirect(code, p, args, rval);
81196a1071fSmiod 	else
81296a1071fSmiod #endif
813db97f33bSmickey 		oerror = error = (*callp->sy_call)(p, args, rval);
8147882195eSmickey 	p = curproc;
8157882195eSmickey 	frame = p->p_md.md_regs;
81696a1071fSmiod 	switch (error) {
817b9b95e0dSmickey 	case 0:
818b9b95e0dSmickey 		frame->tf_ret0 = rval[0];
819b7d25a19Smickey 		frame->tf_ret1 = rval[!retq];
820137d3021Smickey 		frame->tf_t1 = 0;
821b9b95e0dSmickey 		break;
822b9b95e0dSmickey 	case ERESTART:
823c37e03c6Smickey 		frame->tf_iioq_head -= 12;
824c37e03c6Smickey 		frame->tf_iioq_tail -= 12;
825b9b95e0dSmickey 	case EJUSTRETURN:
826b9b95e0dSmickey 		break;
827b9b95e0dSmickey 	default:
828db97f33bSmickey 	bad:
829b9b95e0dSmickey 		if (p->p_emul->e_errno)
830b9b95e0dSmickey 			error = p->p_emul->e_errno[error];
831137d3021Smickey 		frame->tf_t1 = error;
83247df6ae3Smickey 		frame->tf_ret0 = error;
83347df6ae3Smickey 		frame->tf_ret1 = 0;
834b9b95e0dSmickey 		break;
835b9b95e0dSmickey 	}
836b9b95e0dSmickey #ifdef SYSCALL_DEBUG
837db97f33bSmickey 	scdebug_ret(p, code, oerror, rval);
838b9b95e0dSmickey #endif
839532740e6Smickey 	userret(p, frame->tf_iioq_head, 0);
840b9b95e0dSmickey #ifdef KTRACE
841b9b95e0dSmickey 	if (KTRPOINT(p, KTR_SYSRET))
842db97f33bSmickey 		ktrsysret(p, code, oerror, rval[0]);
843b9b95e0dSmickey #endif
84470016991Smickey #ifdef DIAGNOSTIC
84550552582Smickey 	if (cpl != oldcpl) {
84670016991Smickey 		printf("WARNING: SPL (0x%x) NOT LOWERED ON "
84770016991Smickey 		    "syscall(0x%x, 0x%x, 0x%x, 0x%x...) EXIT, PID %d\n",
84870016991Smickey 		    cpl, code, args[0], args[1], args[2], p->p_pid);
84950552582Smickey 		cpl = oldcpl;
85050552582Smickey 	}
85170016991Smickey #endif
85250552582Smickey 	splx(cpl);	/* process softints */
853b9b95e0dSmickey }
854