trap.c revision 1.32.2.2 1 1.32.2.2 elad /* $NetBSD: trap.c,v 1.32.2.2 2006/04/19 02:32:44 elad Exp $ */
2 1.32.2.2 elad
3 1.32.2.2 elad /*-
4 1.32.2.2 elad * Copyright (c) 2001, 2002 The NetBSD Foundation, Inc.
5 1.32.2.2 elad * All rights reserved.
6 1.32.2.2 elad *
7 1.32.2.2 elad * This code is derived from software contributed to The NetBSD Foundation
8 1.32.2.2 elad * by Matthew Fredette.
9 1.32.2.2 elad *
10 1.32.2.2 elad * Redistribution and use in source and binary forms, with or without
11 1.32.2.2 elad * modification, are permitted provided that the following conditions
12 1.32.2.2 elad * are met:
13 1.32.2.2 elad * 1. Redistributions of source code must retain the above copyright
14 1.32.2.2 elad * notice, this list of conditions and the following disclaimer.
15 1.32.2.2 elad * 2. Redistributions in binary form must reproduce the above copyright
16 1.32.2.2 elad * notice, this list of conditions and the following disclaimer in the
17 1.32.2.2 elad * documentation and/or other materials provided with the distribution.
18 1.32.2.2 elad * 3. All advertising materials mentioning features or use of this software
19 1.32.2.2 elad * must display the following acknowledgement:
20 1.32.2.2 elad * This product includes software developed by the NetBSD
21 1.32.2.2 elad * Foundation, Inc. and its contributors.
22 1.32.2.2 elad * 4. Neither the name of The NetBSD Foundation nor the names of its
23 1.32.2.2 elad * contributors may be used to endorse or promote products derived
24 1.32.2.2 elad * from this software without specific prior written permission.
25 1.32.2.2 elad *
26 1.32.2.2 elad * THIS SOFTWARE IS PROVIDED BY THE NETBSD FOUNDATION, INC. AND CONTRIBUTORS
27 1.32.2.2 elad * ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED
28 1.32.2.2 elad * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
29 1.32.2.2 elad * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE FOUNDATION OR CONTRIBUTORS
30 1.32.2.2 elad * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
31 1.32.2.2 elad * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
32 1.32.2.2 elad * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
33 1.32.2.2 elad * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
34 1.32.2.2 elad * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
35 1.32.2.2 elad * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
36 1.32.2.2 elad * POSSIBILITY OF SUCH DAMAGE.
37 1.32.2.2 elad */
38 1.32.2.2 elad
39 1.32.2.2 elad /* $OpenBSD: trap.c,v 1.30 2001/09/19 20:50:56 mickey Exp $ */
40 1.32.2.2 elad
41 1.32.2.2 elad /*
42 1.32.2.2 elad * Copyright (c) 1998-2000 Michael Shalayeff
43 1.32.2.2 elad * All rights reserved.
44 1.32.2.2 elad *
45 1.32.2.2 elad * Redistribution and use in source and binary forms, with or without
46 1.32.2.2 elad * modification, are permitted provided that the following conditions
47 1.32.2.2 elad * are met:
48 1.32.2.2 elad * 1. Redistributions of source code must retain the above copyright
49 1.32.2.2 elad * notice, this list of conditions and the following disclaimer.
50 1.32.2.2 elad * 2. Redistributions in binary form must reproduce the above copyright
51 1.32.2.2 elad * notice, this list of conditions and the following disclaimer in the
52 1.32.2.2 elad * documentation and/or other materials provided with the distribution.
53 1.32.2.2 elad * 3. All advertising materials mentioning features or use of this software
54 1.32.2.2 elad * must display the following acknowledgement:
55 1.32.2.2 elad * This product includes software developed by Michael Shalayeff.
56 1.32.2.2 elad * 4. The name of the author may not be used to endorse or promote products
57 1.32.2.2 elad * derived from this software without specific prior written permission.
58 1.32.2.2 elad *
59 1.32.2.2 elad * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
60 1.32.2.2 elad * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
61 1.32.2.2 elad * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
62 1.32.2.2 elad * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
63 1.32.2.2 elad * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
64 1.32.2.2 elad * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
65 1.32.2.2 elad * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
66 1.32.2.2 elad * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
67 1.32.2.2 elad * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
68 1.32.2.2 elad * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
69 1.32.2.2 elad */
70 1.32.2.2 elad
71 1.32.2.2 elad #include <sys/cdefs.h>
72 1.32.2.2 elad __KERNEL_RCSID(0, "$NetBSD: trap.c,v 1.32.2.2 2006/04/19 02:32:44 elad Exp $");
73 1.32.2.2 elad
74 1.32.2.2 elad /* #define INTRDEBUG */
75 1.32.2.2 elad /* #define TRAPDEBUG */
76 1.32.2.2 elad /* #define USERTRACE */
77 1.32.2.2 elad
78 1.32.2.2 elad #include "opt_kgdb.h"
79 1.32.2.2 elad #include "opt_ktrace.h"
80 1.32.2.2 elad
81 1.32.2.2 elad #include <sys/param.h>
82 1.32.2.2 elad #include <sys/systm.h>
83 1.32.2.2 elad #include <sys/kernel.h>
84 1.32.2.2 elad #include <sys/syscall.h>
85 1.32.2.2 elad #include <sys/sa.h>
86 1.32.2.2 elad #include <sys/savar.h>
87 1.32.2.2 elad #ifdef KTRACE
88 1.32.2.2 elad #include <sys/ktrace.h>
89 1.32.2.2 elad #endif
90 1.32.2.2 elad #include <sys/proc.h>
91 1.32.2.2 elad #include <sys/signalvar.h>
92 1.32.2.2 elad #include <sys/user.h>
93 1.32.2.2 elad #include <sys/acct.h>
94 1.32.2.2 elad #include <sys/signal.h>
95 1.32.2.2 elad #include <sys/device.h>
96 1.32.2.2 elad #include <sys/pool.h>
97 1.32.2.2 elad #include <sys/userret.h>
98 1.32.2.2 elad
99 1.32.2.2 elad #include <net/netisr.h>
100 1.32.2.2 elad
101 1.32.2.2 elad #ifdef KGDB
102 1.32.2.2 elad #include <sys/kgdb.h>
103 1.32.2.2 elad #endif
104 1.32.2.2 elad
105 1.32.2.2 elad #include <uvm/uvm.h>
106 1.32.2.2 elad
107 1.32.2.2 elad #include <machine/iomod.h>
108 1.32.2.2 elad #include <machine/cpufunc.h>
109 1.32.2.2 elad #include <machine/reg.h>
110 1.32.2.2 elad #include <machine/autoconf.h>
111 1.32.2.2 elad
112 1.32.2.2 elad #include <machine/db_machdep.h>
113 1.32.2.2 elad
114 1.32.2.2 elad #include <hppa/hppa/machdep.h>
115 1.32.2.2 elad
116 1.32.2.2 elad #include <ddb/db_output.h>
117 1.32.2.2 elad #include <ddb/db_interface.h>
118 1.32.2.2 elad
119 1.32.2.2 elad #if defined(DEBUG) || defined(DIAGNOSTIC)
120 1.32.2.2 elad /*
121 1.32.2.2 elad * 0x6fc1000 is a stwm r1, d(sr0, sp), which is the last
122 1.32.2.2 elad * instruction in the function prologue that gcc -O0 uses.
123 1.32.2.2 elad * When we have this instruction we know the relationship
124 1.32.2.2 elad * between the stack pointer and the gcc -O0 frame pointer
125 1.32.2.2 elad * (in r3, loaded with the initial sp) for the body of a
126 1.32.2.2 elad * function.
127 1.32.2.2 elad *
128 1.32.2.2 elad * If the given instruction is a stwm r1, d(sr0, sp) where
129 1.32.2.2 elad * d > 0, we evaluate to d, else we evaluate to zero.
130 1.32.2.2 elad */
131 1.32.2.2 elad #define STWM_R1_D_SR0_SP(inst) \
132 1.32.2.2 elad (((inst) & 0xffffc001) == 0x6fc10000 ? (((inst) & 0x00003ff) >> 1) : 0)
133 1.32.2.2 elad #endif /* DEBUG || DIAGNOSTIC */
134 1.32.2.2 elad
135 1.32.2.2 elad const char *trap_type[] = {
136 1.32.2.2 elad "invalid",
137 1.32.2.2 elad "HPMC",
138 1.32.2.2 elad "power failure",
139 1.32.2.2 elad "recovery counter",
140 1.32.2.2 elad "external interrupt",
141 1.32.2.2 elad "LPMC",
142 1.32.2.2 elad "ITLB miss fault",
143 1.32.2.2 elad "instruction protection",
144 1.32.2.2 elad "Illegal instruction",
145 1.32.2.2 elad "break instruction",
146 1.32.2.2 elad "privileged operation",
147 1.32.2.2 elad "privileged register",
148 1.32.2.2 elad "overflow",
149 1.32.2.2 elad "conditional",
150 1.32.2.2 elad "assist exception",
151 1.32.2.2 elad "DTLB miss",
152 1.32.2.2 elad "ITLB non-access miss",
153 1.32.2.2 elad "DTLB non-access miss",
154 1.32.2.2 elad "data protection/rights/alignment",
155 1.32.2.2 elad "data break",
156 1.32.2.2 elad "TLB dirty",
157 1.32.2.2 elad "page reference",
158 1.32.2.2 elad "assist emulation",
159 1.32.2.2 elad "higher-priv transfer",
160 1.32.2.2 elad "lower-priv transfer",
161 1.32.2.2 elad "taken branch",
162 1.32.2.2 elad "data access rights",
163 1.32.2.2 elad "data protection",
164 1.32.2.2 elad "unaligned data ref",
165 1.32.2.2 elad };
166 1.32.2.2 elad int trap_types = sizeof(trap_type)/sizeof(trap_type[0]);
167 1.32.2.2 elad
168 1.32.2.2 elad uint8_t fpopmap[] = {
169 1.32.2.2 elad 0x00, 0x00, 0x00, 0x06, 0x00, 0x00, 0x00, 0x00,
170 1.32.2.2 elad 0x00, 0x0c, 0x00, 0x0e, 0x00, 0x00, 0x00, 0x00,
171 1.32.2.2 elad 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
172 1.32.2.2 elad 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
173 1.32.2.2 elad 0x00, 0x00, 0x00, 0x26, 0x00, 0x00, 0x00, 0x00,
174 1.32.2.2 elad 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
175 1.32.2.2 elad 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
176 1.32.2.2 elad 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
177 1.32.2.2 elad };
178 1.32.2.2 elad
179 1.32.2.2 elad int want_resched;
180 1.32.2.2 elad volatile int astpending;
181 1.32.2.2 elad
182 1.32.2.2 elad void pmap_hptdump(void);
183 1.32.2.2 elad void syscall(struct trapframe *, int *);
184 1.32.2.2 elad
185 1.32.2.2 elad #ifdef USERTRACE
186 1.32.2.2 elad /*
187 1.32.2.2 elad * USERTRACE is a crude facility that traces the PC of
188 1.32.2.2 elad * a single user process. This tracing is normally
189 1.32.2.2 elad * activated by the dispatching of a certain syscall
190 1.32.2.2 elad * with certain arguments - see the activation code in
191 1.32.2.2 elad * syscall().
192 1.32.2.2 elad */
193 1.32.2.2 elad u_int rctr_next_iioq;
194 1.32.2.2 elad #endif
195 1.32.2.2 elad
196 1.32.2.2 elad static inline void
197 1.32.2.2 elad userret(struct lwp *l, register_t pc, u_quad_t oticks)
198 1.32.2.2 elad {
199 1.32.2.2 elad struct proc *p = l->l_proc;
200 1.32.2.2 elad
201 1.32.2.2 elad l->l_priority = l->l_usrpri;
202 1.32.2.2 elad if (want_resched) {
203 1.32.2.2 elad preempt(0);
204 1.32.2.2 elad }
205 1.32.2.2 elad
206 1.32.2.2 elad mi_userret(l);
207 1.32.2.2 elad
208 1.32.2.2 elad /*
209 1.32.2.2 elad * If profiling, charge recent system time to the trapped pc.
210 1.32.2.2 elad */
211 1.32.2.2 elad if (l->l_flag & P_PROFIL) {
212 1.32.2.2 elad extern int psratio;
213 1.32.2.2 elad
214 1.32.2.2 elad addupc_task(p, pc, (int)(p->p_sticks - oticks) * psratio);
215 1.32.2.2 elad }
216 1.32.2.2 elad
217 1.32.2.2 elad curcpu()->ci_schedstate.spc_curpriority = l->l_priority;
218 1.32.2.2 elad }
219 1.32.2.2 elad
220 1.32.2.2 elad /*
221 1.32.2.2 elad * This handles some messy kernel debugger details.
222 1.32.2.2 elad * It dispatches into either kgdb or DDB, and knows
223 1.32.2.2 elad * about some special things to do, like skipping over
224 1.32.2.2 elad * break instructions and how to really set up for
225 1.32.2.2 elad * a single-step.
226 1.32.2.2 elad */
227 1.32.2.2 elad #if defined(KGDB) || defined(DDB)
228 1.32.2.2 elad static int
229 1.32.2.2 elad trap_kdebug(int type, int code, struct trapframe *frame)
230 1.32.2.2 elad {
231 1.32.2.2 elad int handled;
232 1.32.2.2 elad u_int tf_iioq_head_old;
233 1.32.2.2 elad u_int tf_iioq_tail_old;
234 1.32.2.2 elad
235 1.32.2.2 elad for(;;) {
236 1.32.2.2 elad
237 1.32.2.2 elad /* This trap has not been handled. */
238 1.32.2.2 elad handled = 0;
239 1.32.2.2 elad
240 1.32.2.2 elad /* Remember the instruction offset queue. */
241 1.32.2.2 elad tf_iioq_head_old = frame->tf_iioq_head;
242 1.32.2.2 elad tf_iioq_tail_old = frame->tf_iioq_tail;
243 1.32.2.2 elad
244 1.32.2.2 elad #ifdef KGDB
245 1.32.2.2 elad /* Let KGDB handle it (if connected) */
246 1.32.2.2 elad if (!handled)
247 1.32.2.2 elad handled = kgdb_trap(type, frame);
248 1.32.2.2 elad #endif
249 1.32.2.2 elad #ifdef DDB
250 1.32.2.2 elad /* Let DDB handle it. */
251 1.32.2.2 elad if (!handled)
252 1.32.2.2 elad handled = kdb_trap(type, code, frame);
253 1.32.2.2 elad #endif
254 1.32.2.2 elad
255 1.32.2.2 elad /* If this trap wasn't handled, return now. */
256 1.32.2.2 elad if (!handled)
257 1.32.2.2 elad return(0);
258 1.32.2.2 elad
259 1.32.2.2 elad /*
260 1.32.2.2 elad * If the instruction offset queue head changed,
261 1.32.2.2 elad * but the offset queue tail didn't, assume that
262 1.32.2.2 elad * the user wants to jump to the head offset, and
263 1.32.2.2 elad * adjust the tail accordingly. This should fix
264 1.32.2.2 elad * the kgdb `jump' command, and can help DDB users
265 1.32.2.2 elad * who `set' the offset head but forget the tail.
266 1.32.2.2 elad */
267 1.32.2.2 elad if (frame->tf_iioq_head != tf_iioq_head_old &&
268 1.32.2.2 elad frame->tf_iioq_tail == tf_iioq_tail_old)
269 1.32.2.2 elad frame->tf_iioq_tail = frame->tf_iioq_head + 4;
270 1.32.2.2 elad
271 1.32.2.2 elad /*
272 1.32.2.2 elad * This is some single-stepping support.
273 1.32.2.2 elad * If we're trying to step through a nullified
274 1.32.2.2 elad * instruction, just advance by hand and trap
275 1.32.2.2 elad * again. Otherwise, load the recovery counter
276 1.32.2.2 elad * with zero.
277 1.32.2.2 elad */
278 1.32.2.2 elad if (frame->tf_ipsw & PSW_R) {
279 1.32.2.2 elad #ifdef TRAPDEBUG
280 1.32.2.2 elad printf("(single stepping at head 0x%x tail 0x%x)\n", frame->tf_iioq_head, frame->tf_iioq_tail);
281 1.32.2.2 elad #endif
282 1.32.2.2 elad if (frame->tf_ipsw & PSW_N) {
283 1.32.2.2 elad #ifdef TRAPDEBUG
284 1.32.2.2 elad printf("(single stepping past nullified)\n");
285 1.32.2.2 elad #endif
286 1.32.2.2 elad
287 1.32.2.2 elad /* Advance the program counter. */
288 1.32.2.2 elad frame->tf_iioq_head = frame->tf_iioq_tail;
289 1.32.2.2 elad frame->tf_iioq_tail = frame->tf_iioq_head + 4;
290 1.32.2.2 elad
291 1.32.2.2 elad /* Clear flags. */
292 1.32.2.2 elad frame->tf_ipsw &= ~(PSW_N|PSW_X|PSW_Y|PSW_Z|PSW_B|PSW_T|PSW_H|PSW_L);
293 1.32.2.2 elad
294 1.32.2.2 elad /* Simulate another trap. */
295 1.32.2.2 elad type = T_RECOVERY;
296 1.32.2.2 elad continue;
297 1.32.2.2 elad }
298 1.32.2.2 elad frame->tf_rctr = 0;
299 1.32.2.2 elad }
300 1.32.2.2 elad
301 1.32.2.2 elad /* We handled this trap. */
302 1.32.2.2 elad return (1);
303 1.32.2.2 elad }
304 1.32.2.2 elad /* NOTREACHED */
305 1.32.2.2 elad }
306 1.32.2.2 elad #else /* !KGDB && !DDB */
307 1.32.2.2 elad #define trap_kdebug(t, c, f) (0)
308 1.32.2.2 elad #endif /* !KGDB && !DDB */
309 1.32.2.2 elad
310 1.32.2.2 elad #if defined(DEBUG) || defined(USERTRACE)
311 1.32.2.2 elad /*
312 1.32.2.2 elad * These functions give a crude usermode backtrace. They
313 1.32.2.2 elad * really only work when code has been compiled without
314 1.32.2.2 elad * optimization, as they assume a certain function prologue
315 1.32.2.2 elad * sets up a frame pointer and stores the return pointer
316 1.32.2.2 elad * and arguments in it.
317 1.32.2.2 elad */
318 1.32.2.2 elad static void user_backtrace_raw(u_int, u_int);
319 1.32.2.2 elad static void
320 1.32.2.2 elad user_backtrace_raw(u_int pc, u_int fp)
321 1.32.2.2 elad {
322 1.32.2.2 elad int frame_number;
323 1.32.2.2 elad int arg_number;
324 1.32.2.2 elad
325 1.32.2.2 elad for (frame_number = 0;
326 1.32.2.2 elad frame_number < 100 && pc > HPPA_PC_PRIV_MASK && fp;
327 1.32.2.2 elad frame_number++) {
328 1.32.2.2 elad
329 1.32.2.2 elad printf("%3d: pc=%08x%s fp=0x%08x", frame_number,
330 1.32.2.2 elad pc & ~HPPA_PC_PRIV_MASK, USERMODE(pc) ? "" : "**", fp);
331 1.32.2.2 elad for(arg_number = 0; arg_number < 4; arg_number++)
332 1.32.2.2 elad printf(" arg%d=0x%08x", arg_number,
333 1.32.2.2 elad (int) fuword(HPPA_FRAME_CARG(arg_number, fp)));
334 1.32.2.2 elad printf("\n");
335 1.32.2.2 elad pc = fuword(((register_t *) fp) - 5); /* fetch rp */
336 1.32.2.2 elad if (pc == -1) {
337 1.32.2.2 elad printf(" fuword for pc failed\n");
338 1.32.2.2 elad break;
339 1.32.2.2 elad }
340 1.32.2.2 elad fp = fuword(((register_t *) fp) + 0); /* fetch previous fp */
341 1.32.2.2 elad if (fp == -1) {
342 1.32.2.2 elad printf(" fuword for fp failed\n");
343 1.32.2.2 elad break;
344 1.32.2.2 elad }
345 1.32.2.2 elad }
346 1.32.2.2 elad printf(" backtrace stopped with pc %08x fp 0x%08x\n", pc, fp);
347 1.32.2.2 elad }
348 1.32.2.2 elad
349 1.32.2.2 elad static void user_backtrace(struct trapframe *, struct lwp *, int);
350 1.32.2.2 elad static void
351 1.32.2.2 elad user_backtrace(struct trapframe *tf, struct lwp *l, int type)
352 1.32.2.2 elad {
353 1.32.2.2 elad struct proc *p = l->l_proc;
354 1.32.2.2 elad u_int pc, fp, inst;
355 1.32.2.2 elad
356 1.32.2.2 elad /*
357 1.32.2.2 elad * Display any trap type that we have.
358 1.32.2.2 elad */
359 1.32.2.2 elad if (type >= 0)
360 1.32.2.2 elad printf("pid %d (%s) trap #%d\n",
361 1.32.2.2 elad p->p_pid, p->p_comm, type & ~T_USER);
362 1.32.2.2 elad
363 1.32.2.2 elad /*
364 1.32.2.2 elad * Assuming that the frame pointer in r3 is valid,
365 1.32.2.2 elad * dump out a stack trace.
366 1.32.2.2 elad */
367 1.32.2.2 elad fp = tf->tf_r3;
368 1.32.2.2 elad printf("pid %d (%s) backtrace, starting with fp 0x%08x\n",
369 1.32.2.2 elad p->p_pid, p->p_comm, fp);
370 1.32.2.2 elad user_backtrace_raw(tf->tf_iioq_head, fp);
371 1.32.2.2 elad
372 1.32.2.2 elad /*
373 1.32.2.2 elad * In case the frame pointer in r3 is not valid,
374 1.32.2.2 elad * assuming the stack pointer is valid and the
375 1.32.2.2 elad * faulting function is a non-leaf, if we can
376 1.32.2.2 elad * find its prologue we can recover its frame
377 1.32.2.2 elad * pointer.
378 1.32.2.2 elad */
379 1.32.2.2 elad pc = tf->tf_iioq_head;
380 1.32.2.2 elad fp = tf->tf_sp - HPPA_FRAME_SIZE;
381 1.32.2.2 elad printf("pid %d (%s) backtrace, starting with sp 0x%08x pc 0x%08x\n",
382 1.32.2.2 elad p->p_pid, p->p_comm, tf->tf_sp, pc);
383 1.32.2.2 elad for(pc &= ~HPPA_PC_PRIV_MASK; pc > 0; pc -= sizeof(inst)) {
384 1.32.2.2 elad inst = fuword((register_t *) pc);
385 1.32.2.2 elad if (inst == -1) {
386 1.32.2.2 elad printf(" fuword for inst at pc %08x failed\n", pc);
387 1.32.2.2 elad break;
388 1.32.2.2 elad }
389 1.32.2.2 elad /* Check for the prologue instruction that sets sp. */
390 1.32.2.2 elad if (STWM_R1_D_SR0_SP(inst)) {
391 1.32.2.2 elad fp = tf->tf_sp - STWM_R1_D_SR0_SP(inst);
392 1.32.2.2 elad printf(" sp from fp at pc %08x: %08x\n", pc, inst);
393 1.32.2.2 elad break;
394 1.32.2.2 elad }
395 1.32.2.2 elad }
396 1.32.2.2 elad user_backtrace_raw(tf->tf_iioq_head, fp);
397 1.32.2.2 elad }
398 1.32.2.2 elad #endif /* DEBUG || USERTRACE */
399 1.32.2.2 elad
400 1.32.2.2 elad #ifdef DEBUG
401 1.32.2.2 elad /*
402 1.32.2.2 elad * This sanity-checks a trapframe. It is full of various
403 1.32.2.2 elad * assumptions about what a healthy CPU state should be,
404 1.32.2.2 elad * with some documented elsewhere, some not.
405 1.32.2.2 elad */
406 1.32.2.2 elad struct trapframe *sanity_frame;
407 1.32.2.2 elad struct lwp *sanity_lwp;
408 1.32.2.2 elad int sanity_checked = 0;
409 1.32.2.2 elad void frame_sanity_check(int, int, struct trapframe *, struct lwp *);
410 1.32.2.2 elad void
411 1.32.2.2 elad frame_sanity_check(int where, int type, struct trapframe *tf, struct lwp *l)
412 1.32.2.2 elad {
413 1.32.2.2 elad extern int kernel_text;
414 1.32.2.2 elad extern int etext;
415 1.32.2.2 elad extern register_t kpsw;
416 1.32.2.2 elad extern vaddr_t hpt_base;
417 1.32.2.2 elad extern vsize_t hpt_mask;
418 1.32.2.2 elad vsize_t uspace_size;
419 1.32.2.2 elad #define SANITY(e) \
420 1.32.2.2 elad do { \
421 1.32.2.2 elad if (sanity_frame == NULL && !(e)) { \
422 1.32.2.2 elad sanity_frame = tf; \
423 1.32.2.2 elad sanity_lwp = l; \
424 1.32.2.2 elad sanity_checked = __LINE__; \
425 1.32.2.2 elad } \
426 1.32.2.2 elad } while (/* CONSTCOND */ 0)
427 1.32.2.2 elad
428 1.32.2.2 elad SANITY((tf->tf_ipsw & kpsw) == kpsw);
429 1.32.2.2 elad SANITY(tf->tf_hptm == hpt_mask && tf->tf_vtop == hpt_base);
430 1.32.2.2 elad SANITY((kpsw & PSW_I) == 0 || tf->tf_eiem != 0);
431 1.32.2.2 elad if (tf->tf_iisq_head == HPPA_SID_KERNEL) {
432 1.32.2.2 elad /*
433 1.32.2.2 elad * If the trap happened in the gateway
434 1.32.2.2 elad * page, we take the easy way out and
435 1.32.2.2 elad * assume that the trapframe is okay.
436 1.32.2.2 elad */
437 1.32.2.2 elad if ((tf->tf_iioq_head & ~PAGE_MASK) != SYSCALLGATE) {
438 1.32.2.2 elad SANITY(!USERMODE(tf->tf_iioq_head));
439 1.32.2.2 elad SANITY(!USERMODE(tf->tf_iioq_tail));
440 1.32.2.2 elad SANITY(tf->tf_iioq_head >= (u_int) &kernel_text);
441 1.32.2.2 elad SANITY(tf->tf_iioq_head < (u_int) &etext);
442 1.32.2.2 elad SANITY(tf->tf_iioq_tail >= (u_int) &kernel_text);
443 1.32.2.2 elad SANITY(tf->tf_iioq_tail < (u_int) &etext);
444 1.32.2.2 elad #ifdef HPPA_REDZONE
445 1.32.2.2 elad uspace_size = HPPA_REDZONE;
446 1.32.2.2 elad #else
447 1.32.2.2 elad uspace_size = USPACE;
448 1.32.2.2 elad #endif
449 1.32.2.2 elad SANITY(l == NULL ||
450 1.32.2.2 elad ((tf->tf_sp >= (u_int)(l->l_addr) + PAGE_SIZE &&
451 1.32.2.2 elad tf->tf_sp < (u_int)(l->l_addr) + uspace_size)));
452 1.32.2.2 elad }
453 1.32.2.2 elad } else {
454 1.32.2.2 elad SANITY(USERMODE(tf->tf_iioq_head));
455 1.32.2.2 elad SANITY(USERMODE(tf->tf_iioq_tail));
456 1.32.2.2 elad SANITY(l != NULL && tf->tf_cr30 == kvtop((caddr_t)l->l_addr));
457 1.32.2.2 elad }
458 1.32.2.2 elad #undef SANITY
459 1.32.2.2 elad if (sanity_frame == tf) {
460 1.32.2.2 elad printf("insanity: where 0x%x type 0x%x tf %p lwp %p line %d "
461 1.32.2.2 elad "sp 0x%x pc 0x%x\n",
462 1.32.2.2 elad where, type, sanity_frame, sanity_lwp, sanity_checked,
463 1.32.2.2 elad tf->tf_sp, tf->tf_iioq_head);
464 1.32.2.2 elad (void) trap_kdebug(T_IBREAK, 0, tf);
465 1.32.2.2 elad sanity_frame = NULL;
466 1.32.2.2 elad sanity_lwp = NULL;
467 1.32.2.2 elad sanity_checked = 0;
468 1.32.2.2 elad }
469 1.32.2.2 elad }
470 1.32.2.2 elad #endif /* DEBUG */
471 1.32.2.2 elad
472 1.32.2.2 elad void
473 1.32.2.2 elad trap(int type, struct trapframe *frame)
474 1.32.2.2 elad {
475 1.32.2.2 elad struct lwp *l;
476 1.32.2.2 elad struct proc *p;
477 1.32.2.2 elad struct pcb *pcbp;
478 1.32.2.2 elad vaddr_t va;
479 1.32.2.2 elad struct vm_map *map;
480 1.32.2.2 elad struct vmspace *vm;
481 1.32.2.2 elad vm_prot_t vftype;
482 1.32.2.2 elad pa_space_t space;
483 1.32.2.2 elad ksiginfo_t ksi;
484 1.32.2.2 elad u_int opcode, onfault;
485 1.32.2.2 elad int ret;
486 1.32.2.2 elad const char *tts;
487 1.32.2.2 elad int type_raw;
488 1.32.2.2 elad #ifdef DIAGNOSTIC
489 1.32.2.2 elad extern int emergency_stack_start, emergency_stack_end;
490 1.32.2.2 elad #endif
491 1.32.2.2 elad
492 1.32.2.2 elad type_raw = type & ~T_USER;
493 1.32.2.2 elad opcode = frame->tf_iir;
494 1.32.2.2 elad if (type_raw == T_ITLBMISS || type_raw == T_ITLBMISSNA) {
495 1.32.2.2 elad va = frame->tf_iioq_head;
496 1.32.2.2 elad space = frame->tf_iisq_head;
497 1.32.2.2 elad vftype = VM_PROT_EXECUTE;
498 1.32.2.2 elad } else {
499 1.32.2.2 elad va = frame->tf_ior;
500 1.32.2.2 elad space = frame->tf_isr;
501 1.32.2.2 elad vftype = inst_store(opcode) ? VM_PROT_WRITE : VM_PROT_READ;
502 1.32.2.2 elad }
503 1.32.2.2 elad
504 1.32.2.2 elad l = curlwp;
505 1.32.2.2 elad p = l ? l->l_proc : NULL;
506 1.32.2.2 elad
507 1.32.2.2 elad tts = (type & ~T_USER) > trap_types ? "reserved" :
508 1.32.2.2 elad trap_type[type & ~T_USER];
509 1.32.2.2 elad
510 1.32.2.2 elad #ifdef DIAGNOSTIC
511 1.32.2.2 elad /*
512 1.32.2.2 elad * If we are on the emergency stack, then we either got
513 1.32.2.2 elad * a fault on the kernel stack, or we're just handling
514 1.32.2.2 elad * a trap for the machine check handler (which also
515 1.32.2.2 elad * runs on the emergency stack).
516 1.32.2.2 elad *
517 1.32.2.2 elad * We *very crudely* differentiate between the two cases
518 1.32.2.2 elad * by checking the faulting instruction: if it is the
519 1.32.2.2 elad * function prologue instruction that stores the old
520 1.32.2.2 elad * frame pointer and updates the stack pointer, we assume
521 1.32.2.2 elad * that we faulted on the kernel stack.
522 1.32.2.2 elad *
523 1.32.2.2 elad * In this case, not completing that instruction will
524 1.32.2.2 elad * probably confuse backtraces in kgdb/ddb. Completing
525 1.32.2.2 elad * it would be difficult, because we already faulted on
526 1.32.2.2 elad * that part of the stack, so instead we fix up the
527 1.32.2.2 elad * frame as if the function called has just returned.
528 1.32.2.2 elad * This has peculiar knowledge about what values are in
529 1.32.2.2 elad * what registers during the "normal gcc -g" prologue.
530 1.32.2.2 elad */
531 1.32.2.2 elad if (&type >= &emergency_stack_start &&
532 1.32.2.2 elad &type < &emergency_stack_end &&
533 1.32.2.2 elad type != T_IBREAK && STWM_R1_D_SR0_SP(opcode)) {
534 1.32.2.2 elad /* Restore the caller's frame pointer. */
535 1.32.2.2 elad frame->tf_r3 = frame->tf_r1;
536 1.32.2.2 elad /* Restore the caller's instruction offsets. */
537 1.32.2.2 elad frame->tf_iioq_head = frame->tf_rp;
538 1.32.2.2 elad frame->tf_iioq_tail = frame->tf_iioq_head + 4;
539 1.32.2.2 elad goto dead_end;
540 1.32.2.2 elad }
541 1.32.2.2 elad #endif /* DIAGNOSTIC */
542 1.32.2.2 elad
543 1.32.2.2 elad #ifdef DEBUG
544 1.32.2.2 elad frame_sanity_check(0xdead01, type, frame, l);
545 1.32.2.2 elad #endif /* DEBUG */
546 1.32.2.2 elad
547 1.32.2.2 elad /* If this is a trap, not an interrupt, reenable interrupts. */
548 1.32.2.2 elad if (type_raw != T_INTERRUPT)
549 1.32.2.2 elad mtctl(frame->tf_eiem, CR_EIEM);
550 1.32.2.2 elad
551 1.32.2.2 elad if (frame->tf_flags & TFF_LAST)
552 1.32.2.2 elad l->l_md.md_regs = frame;
553 1.32.2.2 elad
554 1.32.2.2 elad #ifdef TRAPDEBUG
555 1.32.2.2 elad if (type_raw != T_INTERRUPT && type_raw != T_IBREAK)
556 1.32.2.2 elad printf("trap: %d, %s for %x:%x at %x:%x, fp=%p, rp=%x\n",
557 1.32.2.2 elad type, tts, space, (u_int)va, frame->tf_iisq_head,
558 1.32.2.2 elad frame->tf_iioq_head, frame, frame->tf_rp);
559 1.32.2.2 elad else if (type_raw == T_IBREAK)
560 1.32.2.2 elad printf("trap: break instruction %x:%x at %x:%x, fp=%p\n",
561 1.32.2.2 elad break5(opcode), break13(opcode),
562 1.32.2.2 elad frame->tf_iisq_head, frame->tf_iioq_head, frame);
563 1.32.2.2 elad
564 1.32.2.2 elad {
565 1.32.2.2 elad extern int etext;
566 1.32.2.2 elad if (frame < (struct trapframe *)&etext) {
567 1.32.2.2 elad printf("trap: bogus frame ptr %p\n", frame);
568 1.32.2.2 elad goto dead_end;
569 1.32.2.2 elad }
570 1.32.2.2 elad }
571 1.32.2.2 elad #endif
572 1.32.2.2 elad switch (type) {
573 1.32.2.2 elad case T_NONEXIST:
574 1.32.2.2 elad case T_NONEXIST|T_USER:
575 1.32.2.2 elad #if !defined(DDB) && !defined(KGDB)
576 1.32.2.2 elad /* we've got screwed up by the central scrutinizer */
577 1.32.2.2 elad panic ("trap: elvis has just left the building!");
578 1.32.2.2 elad break;
579 1.32.2.2 elad #else
580 1.32.2.2 elad goto dead_end;
581 1.32.2.2 elad #endif
582 1.32.2.2 elad case T_RECOVERY|T_USER:
583 1.32.2.2 elad #ifdef USERTRACE
584 1.32.2.2 elad for(;;) {
585 1.32.2.2 elad if (frame->tf_iioq_head != rctr_next_iioq)
586 1.32.2.2 elad printf("-%08x\nr %08x",
587 1.32.2.2 elad rctr_next_iioq - 4,
588 1.32.2.2 elad frame->tf_iioq_head);
589 1.32.2.2 elad rctr_next_iioq = frame->tf_iioq_head + 4;
590 1.32.2.2 elad if (frame->tf_ipsw & PSW_N) {
591 1.32.2.2 elad /* Advance the program counter. */
592 1.32.2.2 elad frame->tf_iioq_head = frame->tf_iioq_tail;
593 1.32.2.2 elad frame->tf_iioq_tail = frame->tf_iioq_head + 4;
594 1.32.2.2 elad /* Clear flags. */
595 1.32.2.2 elad frame->tf_ipsw &= ~(PSW_N|PSW_X|PSW_Y|PSW_Z|PSW_B|PSW_T|PSW_H|PSW_L);
596 1.32.2.2 elad /* Simulate another trap. */
597 1.32.2.2 elad continue;
598 1.32.2.2 elad }
599 1.32.2.2 elad break;
600 1.32.2.2 elad }
601 1.32.2.2 elad frame->tf_rctr = 0;
602 1.32.2.2 elad break;
603 1.32.2.2 elad #endif /* USERTRACE */
604 1.32.2.2 elad case T_RECOVERY:
605 1.32.2.2 elad #if !defined(DDB) && !defined(KGDB)
606 1.32.2.2 elad /* XXX will implement later */
607 1.32.2.2 elad printf ("trap: handicapped");
608 1.32.2.2 elad break;
609 1.32.2.2 elad #else
610 1.32.2.2 elad goto dead_end;
611 1.32.2.2 elad #endif
612 1.32.2.2 elad
613 1.32.2.2 elad case T_EMULATION | T_USER:
614 1.32.2.2 elad #ifdef FPEMUL
615 1.32.2.2 elad hppa_fpu_emulate(frame, l, opcode);
616 1.32.2.2 elad #else /* !FPEMUL */
617 1.32.2.2 elad /*
618 1.32.2.2 elad * We don't have FPU emulation, so signal the
619 1.32.2.2 elad * process with a SIGFPE.
620 1.32.2.2 elad */
621 1.32.2.2 elad
622 1.32.2.2 elad KSI_INIT_TRAP(&ksi);
623 1.32.2.2 elad ksi.ksi_signo = SIGFPE;
624 1.32.2.2 elad ksi.ksi_code = SI_NOINFO;
625 1.32.2.2 elad ksi.ksi_trap = type;
626 1.32.2.2 elad ksi.ksi_addr = (void *)frame->tf_iioq_head;
627 1.32.2.2 elad trapsignal(l, &ksi);
628 1.32.2.2 elad #endif /* !FPEMUL */
629 1.32.2.2 elad break;
630 1.32.2.2 elad
631 1.32.2.2 elad case T_DATALIGN:
632 1.32.2.2 elad if (l->l_addr->u_pcb.pcb_onfault) {
633 1.32.2.2 elad do_onfault:
634 1.32.2.2 elad pcbp = &l->l_addr->u_pcb;
635 1.32.2.2 elad frame->tf_iioq_tail = 4 +
636 1.32.2.2 elad (frame->tf_iioq_head =
637 1.32.2.2 elad pcbp->pcb_onfault);
638 1.32.2.2 elad pcbp->pcb_onfault = 0;
639 1.32.2.2 elad break;
640 1.32.2.2 elad }
641 1.32.2.2 elad /*FALLTHROUGH*/
642 1.32.2.2 elad
643 1.32.2.2 elad #ifdef DIAGNOSTIC
644 1.32.2.2 elad /* these just can't happen ever */
645 1.32.2.2 elad case T_PRIV_OP:
646 1.32.2.2 elad case T_PRIV_REG:
647 1.32.2.2 elad /* these just can't make it to the trap() ever */
648 1.32.2.2 elad case T_HPMC:
649 1.32.2.2 elad case T_HPMC | T_USER:
650 1.32.2.2 elad case T_EMULATION:
651 1.32.2.2 elad case T_EXCEPTION:
652 1.32.2.2 elad #endif
653 1.32.2.2 elad case T_IBREAK:
654 1.32.2.2 elad case T_DBREAK:
655 1.32.2.2 elad dead_end:
656 1.32.2.2 elad if (type & T_USER) {
657 1.32.2.2 elad #ifdef DEBUG
658 1.32.2.2 elad user_backtrace(frame, l, type);
659 1.32.2.2 elad #endif
660 1.32.2.2 elad KSI_INIT_TRAP(&ksi);
661 1.32.2.2 elad ksi.ksi_signo = SIGILL;
662 1.32.2.2 elad ksi.ksi_code = ILL_ILLTRP;
663 1.32.2.2 elad ksi.ksi_trap = type;
664 1.32.2.2 elad ksi.ksi_addr = (void *)frame->tf_iioq_head;
665 1.32.2.2 elad trapsignal(l, &ksi);
666 1.32.2.2 elad break;
667 1.32.2.2 elad }
668 1.32.2.2 elad if (trap_kdebug(type, va, frame))
669 1.32.2.2 elad return;
670 1.32.2.2 elad else if (type == T_DATALIGN)
671 1.32.2.2 elad panic ("trap: %s at 0x%x", tts, (u_int) va);
672 1.32.2.2 elad else
673 1.32.2.2 elad panic ("trap: no debugger for \"%s\" (%d)", tts, type);
674 1.32.2.2 elad break;
675 1.32.2.2 elad
676 1.32.2.2 elad case T_IBREAK | T_USER:
677 1.32.2.2 elad case T_DBREAK | T_USER:
678 1.32.2.2 elad /* pass to user debugger */
679 1.32.2.2 elad break;
680 1.32.2.2 elad
681 1.32.2.2 elad case T_EXCEPTION | T_USER: { /* co-proc assist trap */
682 1.32.2.2 elad uint64_t *fpp;
683 1.32.2.2 elad uint32_t *pex, ex, inst;
684 1.32.2.2 elad int i;
685 1.32.2.2 elad
686 1.32.2.2 elad hppa_fpu_flush(l);
687 1.32.2.2 elad fpp = l->l_addr->u_pcb.pcb_fpregs;
688 1.32.2.2 elad pex = (uint32_t *)&fpp[1];
689 1.32.2.2 elad for (i = 1; i < 8 && !*pex; i++, pex++)
690 1.32.2.2 elad ;
691 1.32.2.2 elad KASSERT(i < 8);
692 1.32.2.2 elad ex = *pex;
693 1.32.2.2 elad *pex = 0;
694 1.32.2.2 elad
695 1.32.2.2 elad /* reset the trap flag, as if there was none */
696 1.32.2.2 elad fpp[0] &= ~(((uint64_t)HPPA_FPU_T) << 32);
697 1.32.2.2 elad
698 1.32.2.2 elad /* emulate the instruction */
699 1.32.2.2 elad inst = ((uint32_t)fpopmap[ex >> 26] << 26) | (ex & 0x03ffffff);
700 1.32.2.2 elad hppa_fpu_emulate(frame, l, inst);
701 1.32.2.2 elad }
702 1.32.2.2 elad break;
703 1.32.2.2 elad
704 1.32.2.2 elad case T_OVERFLOW | T_USER:
705 1.32.2.2 elad KSI_INIT_TRAP(&ksi);
706 1.32.2.2 elad ksi.ksi_signo = SIGFPE;
707 1.32.2.2 elad ksi.ksi_code = SI_NOINFO;
708 1.32.2.2 elad ksi.ksi_trap = type;
709 1.32.2.2 elad ksi.ksi_addr = (void *)va;
710 1.32.2.2 elad trapsignal(l, &ksi);
711 1.32.2.2 elad break;
712 1.32.2.2 elad
713 1.32.2.2 elad case T_CONDITION | T_USER:
714 1.32.2.2 elad KSI_INIT_TRAP(&ksi);
715 1.32.2.2 elad ksi.ksi_signo = SIGFPE;
716 1.32.2.2 elad ksi.ksi_code = FPE_INTDIV;
717 1.32.2.2 elad ksi.ksi_trap = type;
718 1.32.2.2 elad ksi.ksi_addr = (void *)va;
719 1.32.2.2 elad trapsignal(l, &ksi);
720 1.32.2.2 elad break;
721 1.32.2.2 elad
722 1.32.2.2 elad case T_ILLEGAL | T_USER:
723 1.32.2.2 elad #ifdef DEBUG
724 1.32.2.2 elad user_backtrace(frame, l, type);
725 1.32.2.2 elad #endif
726 1.32.2.2 elad KSI_INIT_TRAP(&ksi);
727 1.32.2.2 elad ksi.ksi_signo = SIGILL;
728 1.32.2.2 elad ksi.ksi_code = ILL_ILLOPC;
729 1.32.2.2 elad ksi.ksi_trap = type;
730 1.32.2.2 elad ksi.ksi_addr = (void *)va;
731 1.32.2.2 elad trapsignal(l, &ksi);
732 1.32.2.2 elad break;
733 1.32.2.2 elad
734 1.32.2.2 elad case T_PRIV_OP | T_USER:
735 1.32.2.2 elad #ifdef DEBUG
736 1.32.2.2 elad user_backtrace(frame, l, type);
737 1.32.2.2 elad #endif
738 1.32.2.2 elad KSI_INIT_TRAP(&ksi);
739 1.32.2.2 elad ksi.ksi_signo = SIGILL;
740 1.32.2.2 elad ksi.ksi_code = ILL_PRVOPC;
741 1.32.2.2 elad ksi.ksi_trap = type;
742 1.32.2.2 elad ksi.ksi_addr = (void *)va;
743 1.32.2.2 elad trapsignal(l, &ksi);
744 1.32.2.2 elad break;
745 1.32.2.2 elad
746 1.32.2.2 elad case T_PRIV_REG | T_USER:
747 1.32.2.2 elad #ifdef DEBUG
748 1.32.2.2 elad user_backtrace(frame, l, type);
749 1.32.2.2 elad #endif
750 1.32.2.2 elad KSI_INIT_TRAP(&ksi);
751 1.32.2.2 elad ksi.ksi_signo = SIGILL;
752 1.32.2.2 elad ksi.ksi_code = ILL_PRVREG;
753 1.32.2.2 elad ksi.ksi_trap = type;
754 1.32.2.2 elad ksi.ksi_addr = (void *)va;
755 1.32.2.2 elad trapsignal(l, &ksi);
756 1.32.2.2 elad break;
757 1.32.2.2 elad
758 1.32.2.2 elad /* these should never got here */
759 1.32.2.2 elad case T_HIGHERPL | T_USER:
760 1.32.2.2 elad case T_LOWERPL | T_USER:
761 1.32.2.2 elad KSI_INIT_TRAP(&ksi);
762 1.32.2.2 elad ksi.ksi_signo = SIGSEGV;
763 1.32.2.2 elad ksi.ksi_code = SEGV_ACCERR;
764 1.32.2.2 elad ksi.ksi_trap = type;
765 1.32.2.2 elad ksi.ksi_addr = (void *)va;
766 1.32.2.2 elad trapsignal(l, &ksi);
767 1.32.2.2 elad break;
768 1.32.2.2 elad
769 1.32.2.2 elad case T_IPROT | T_USER:
770 1.32.2.2 elad case T_DPROT | T_USER:
771 1.32.2.2 elad KSI_INIT_TRAP(&ksi);
772 1.32.2.2 elad ksi.ksi_signo = SIGSEGV;
773 1.32.2.2 elad ksi.ksi_code = SEGV_ACCERR;
774 1.32.2.2 elad ksi.ksi_trap = type;
775 1.32.2.2 elad ksi.ksi_addr = (void *)va;
776 1.32.2.2 elad trapsignal(l, &ksi);
777 1.32.2.2 elad break;
778 1.32.2.2 elad
779 1.32.2.2 elad case T_DATACC: case T_USER | T_DATACC:
780 1.32.2.2 elad case T_ITLBMISS: case T_USER | T_ITLBMISS:
781 1.32.2.2 elad case T_DTLBMISS: case T_USER | T_DTLBMISS:
782 1.32.2.2 elad case T_ITLBMISSNA: case T_USER | T_ITLBMISSNA:
783 1.32.2.2 elad case T_DTLBMISSNA: case T_USER | T_DTLBMISSNA:
784 1.32.2.2 elad case T_TLB_DIRTY: case T_USER | T_TLB_DIRTY:
785 1.32.2.2 elad vm = p->p_vmspace;
786 1.32.2.2 elad
787 1.32.2.2 elad if (!vm) {
788 1.32.2.2 elad #ifdef TRAPDEBUG
789 1.32.2.2 elad printf("trap: no vm, p=%p\n", p);
790 1.32.2.2 elad #endif
791 1.32.2.2 elad goto dead_end;
792 1.32.2.2 elad }
793 1.32.2.2 elad
794 1.32.2.2 elad /*
795 1.32.2.2 elad * it could be a kernel map for exec_map faults
796 1.32.2.2 elad */
797 1.32.2.2 elad if (!(type & T_USER) && space == HPPA_SID_KERNEL)
798 1.32.2.2 elad map = kernel_map;
799 1.32.2.2 elad else {
800 1.32.2.2 elad map = &vm->vm_map;
801 1.32.2.2 elad if (l->l_flag & L_SA) {
802 1.32.2.2 elad l->l_savp->savp_faultaddr = va;
803 1.32.2.2 elad l->l_flag |= L_SA_PAGEFAULT;
804 1.32.2.2 elad }
805 1.32.2.2 elad }
806 1.32.2.2 elad
807 1.32.2.2 elad va = hppa_trunc_page(va);
808 1.32.2.2 elad
809 1.32.2.2 elad if (map->pmap->pmap_space != space) {
810 1.32.2.2 elad #ifdef TRAPDEBUG
811 1.32.2.2 elad printf("trap: space missmatch %d != %d\n",
812 1.32.2.2 elad space, map->pmap->pmap_space);
813 1.32.2.2 elad #endif
814 1.32.2.2 elad /* actually dump the user, crap the kernel */
815 1.32.2.2 elad goto dead_end;
816 1.32.2.2 elad }
817 1.32.2.2 elad
818 1.32.2.2 elad /* Never call uvm_fault in interrupt context. */
819 1.32.2.2 elad KASSERT(hppa_intr_depth == 0);
820 1.32.2.2 elad
821 1.32.2.2 elad onfault = l->l_addr->u_pcb.pcb_onfault;
822 1.32.2.2 elad l->l_addr->u_pcb.pcb_onfault = 0;
823 1.32.2.2 elad ret = uvm_fault(map, va, vftype);
824 1.32.2.2 elad l->l_addr->u_pcb.pcb_onfault = onfault;
825 1.32.2.2 elad
826 1.32.2.2 elad #ifdef TRAPDEBUG
827 1.32.2.2 elad printf("uvm_fault(%p, %x, %d)=%d\n",
828 1.32.2.2 elad map, (u_int)va, vftype, ret);
829 1.32.2.2 elad #endif
830 1.32.2.2 elad
831 1.32.2.2 elad if (map != kernel_map)
832 1.32.2.2 elad l->l_flag &= ~L_SA_PAGEFAULT;
833 1.32.2.2 elad
834 1.32.2.2 elad /*
835 1.32.2.2 elad * If this was a stack access we keep track of the maximum
836 1.32.2.2 elad * accessed stack size. Also, if uvm_fault gets a protection
837 1.32.2.2 elad * failure it is due to accessing the stack region outside
838 1.32.2.2 elad * the current limit and we need to reflect that as an access
839 1.32.2.2 elad * error.
840 1.32.2.2 elad */
841 1.32.2.2 elad if (va >= (vaddr_t)vm->vm_maxsaddr + vm->vm_ssize) {
842 1.32.2.2 elad if (ret == 0) {
843 1.32.2.2 elad vsize_t nss = btoc(va - USRSTACK + PAGE_SIZE);
844 1.32.2.2 elad if (nss > vm->vm_ssize)
845 1.32.2.2 elad vm->vm_ssize = nss;
846 1.32.2.2 elad } else if (ret == EACCES)
847 1.32.2.2 elad ret = EFAULT;
848 1.32.2.2 elad }
849 1.32.2.2 elad
850 1.32.2.2 elad if (ret != 0) {
851 1.32.2.2 elad if (type & T_USER) {
852 1.32.2.2 elad #ifdef DEBUG
853 1.32.2.2 elad user_backtrace(frame, l, type);
854 1.32.2.2 elad #endif
855 1.32.2.2 elad KSI_INIT_TRAP(&ksi);
856 1.32.2.2 elad ksi.ksi_signo = SIGSEGV;
857 1.32.2.2 elad ksi.ksi_code = (ret == EACCES ?
858 1.32.2.2 elad SEGV_ACCERR : SEGV_MAPERR);
859 1.32.2.2 elad ksi.ksi_trap = type;
860 1.32.2.2 elad ksi.ksi_addr = (void *)va;
861 1.32.2.2 elad trapsignal(l, &ksi);
862 1.32.2.2 elad } else {
863 1.32.2.2 elad if (l->l_addr->u_pcb.pcb_onfault) {
864 1.32.2.2 elad goto do_onfault;
865 1.32.2.2 elad }
866 1.32.2.2 elad panic("trap: uvm_fault(%p, %lx, %d): %d",
867 1.32.2.2 elad map, va, vftype, ret);
868 1.32.2.2 elad }
869 1.32.2.2 elad }
870 1.32.2.2 elad break;
871 1.32.2.2 elad
872 1.32.2.2 elad case T_DATALIGN | T_USER:
873 1.32.2.2 elad #ifdef DEBUG
874 1.32.2.2 elad user_backtrace(frame, l, type);
875 1.32.2.2 elad #endif
876 1.32.2.2 elad KSI_INIT_TRAP(&ksi);
877 1.32.2.2 elad ksi.ksi_signo = SIGBUS;
878 1.32.2.2 elad ksi.ksi_code = BUS_ADRALN;
879 1.32.2.2 elad ksi.ksi_trap = type;
880 1.32.2.2 elad ksi.ksi_addr = (void *)va;
881 1.32.2.2 elad trapsignal(l, &ksi);
882 1.32.2.2 elad break;
883 1.32.2.2 elad
884 1.32.2.2 elad case T_INTERRUPT:
885 1.32.2.2 elad case T_INTERRUPT|T_USER:
886 1.32.2.2 elad hppa_intr(frame);
887 1.32.2.2 elad mtctl(frame->tf_eiem, CR_EIEM);
888 1.32.2.2 elad break;
889 1.32.2.2 elad
890 1.32.2.2 elad case T_LOWERPL:
891 1.32.2.2 elad case T_DPROT:
892 1.32.2.2 elad case T_IPROT:
893 1.32.2.2 elad case T_OVERFLOW:
894 1.32.2.2 elad case T_CONDITION:
895 1.32.2.2 elad case T_ILLEGAL:
896 1.32.2.2 elad case T_HIGHERPL:
897 1.32.2.2 elad case T_TAKENBR:
898 1.32.2.2 elad case T_POWERFAIL:
899 1.32.2.2 elad case T_LPMC:
900 1.32.2.2 elad case T_PAGEREF:
901 1.32.2.2 elad case T_DATAPID: case T_DATAPID | T_USER:
902 1.32.2.2 elad if (0 /* T-chip */) {
903 1.32.2.2 elad break;
904 1.32.2.2 elad }
905 1.32.2.2 elad /* FALLTHROUGH to unimplemented */
906 1.32.2.2 elad default:
907 1.32.2.2 elad panic ("trap: unimplemented \'%s\' (%d)", tts, type);
908 1.32.2.2 elad }
909 1.32.2.2 elad
910 1.32.2.2 elad if (type & T_USER)
911 1.32.2.2 elad userret(l, l->l_md.md_regs->tf_iioq_head, 0);
912 1.32.2.2 elad
913 1.32.2.2 elad #ifdef DEBUG
914 1.32.2.2 elad frame_sanity_check(0xdead02, type, frame, l);
915 1.32.2.2 elad if (frame->tf_flags & TFF_LAST && curlwp != NULL)
916 1.32.2.2 elad frame_sanity_check(0xdead03, type, curlwp->l_md.md_regs,
917 1.32.2.2 elad curlwp);
918 1.32.2.2 elad #endif /* DEBUG */
919 1.32.2.2 elad }
920 1.32.2.2 elad
921 1.32.2.2 elad void
922 1.32.2.2 elad child_return(void *arg)
923 1.32.2.2 elad {
924 1.32.2.2 elad struct lwp *l = arg;
925 1.32.2.2 elad struct proc *p = l->l_proc;
926 1.32.2.2 elad
927 1.32.2.2 elad userret(l, l->l_md.md_regs->tf_iioq_head, 0);
928 1.32.2.2 elad #ifdef KTRACE
929 1.32.2.2 elad if (KTRPOINT(p, KTR_SYSRET))
930 1.32.2.2 elad ktrsysret(l, SYS_fork, 0, 0);
931 1.32.2.2 elad #endif
932 1.32.2.2 elad #ifdef DEBUG
933 1.32.2.2 elad frame_sanity_check(0xdead04, 0, l->l_md.md_regs, l);
934 1.32.2.2 elad #endif /* DEBUG */
935 1.32.2.2 elad }
936 1.32.2.2 elad
937 1.32.2.2 elad /*
938 1.32.2.2 elad * call actual syscall routine
939 1.32.2.2 elad * from the low-level syscall handler:
940 1.32.2.2 elad * - all HPPA_FRAME_NARGS syscall's arguments supposed to be copied onto
941 1.32.2.2 elad * our stack, this wins compared to copyin just needed amount anyway
942 1.32.2.2 elad * - register args are copied onto stack too
943 1.32.2.2 elad */
944 1.32.2.2 elad void
945 1.32.2.2 elad syscall(struct trapframe *frame, int *args)
946 1.32.2.2 elad {
947 1.32.2.2 elad struct lwp *l;
948 1.32.2.2 elad struct proc *p;
949 1.32.2.2 elad const struct sysent *callp;
950 1.32.2.2 elad int nsys, code, argsize, error;
951 1.32.2.2 elad int tmp;
952 1.32.2.2 elad int rval[2];
953 1.32.2.2 elad
954 1.32.2.2 elad uvmexp.syscalls++;
955 1.32.2.2 elad
956 1.32.2.2 elad #ifdef DEBUG
957 1.32.2.2 elad frame_sanity_check(0xdead04, 0, frame, curlwp);
958 1.32.2.2 elad #endif /* DEBUG */
959 1.32.2.2 elad
960 1.32.2.2 elad if (!USERMODE(frame->tf_iioq_head))
961 1.32.2.2 elad panic("syscall");
962 1.32.2.2 elad
963 1.32.2.2 elad l = curlwp;
964 1.32.2.2 elad p = l->l_proc;
965 1.32.2.2 elad l->l_md.md_regs = frame;
966 1.32.2.2 elad nsys = p->p_emul->e_nsysent;
967 1.32.2.2 elad callp = p->p_emul->e_sysent;
968 1.32.2.2 elad code = frame->tf_t1;
969 1.32.2.2 elad
970 1.32.2.2 elad /*
971 1.32.2.2 elad * Restarting a system call is touchy on the HPPA,
972 1.32.2.2 elad * because syscall arguments are passed in registers
973 1.32.2.2 elad * and the program counter of the syscall "point"
974 1.32.2.2 elad * isn't easily divined.
975 1.32.2.2 elad *
976 1.32.2.2 elad * We handle the first problem by assuming that we
977 1.32.2.2 elad * will have to restart this system call, so we
978 1.32.2.2 elad * stuff the first four words of the original arguments
979 1.32.2.2 elad * back into the frame as arg0...arg3, which is where
980 1.32.2.2 elad * we found them in the first place. Any further
981 1.32.2.2 elad * arguments are (still) on the user's stack and the
982 1.32.2.2 elad * syscall code will fetch them from there (again).
983 1.32.2.2 elad *
984 1.32.2.2 elad * The program counter problem is addressed below.
985 1.32.2.2 elad */
986 1.32.2.2 elad frame->tf_arg0 = args[0];
987 1.32.2.2 elad frame->tf_arg1 = args[1];
988 1.32.2.2 elad frame->tf_arg2 = args[2];
989 1.32.2.2 elad frame->tf_arg3 = args[3];
990 1.32.2.2 elad
991 1.32.2.2 elad /*
992 1.32.2.2 elad * Some special handling for the syscall(2) and
993 1.32.2.2 elad * __syscall(2) system calls.
994 1.32.2.2 elad */
995 1.32.2.2 elad switch (code) {
996 1.32.2.2 elad case SYS_syscall:
997 1.32.2.2 elad code = *args;
998 1.32.2.2 elad args += 1;
999 1.32.2.2 elad break;
1000 1.32.2.2 elad case SYS___syscall:
1001 1.32.2.2 elad if (callp != sysent)
1002 1.32.2.2 elad break;
1003 1.32.2.2 elad /*
1004 1.32.2.2 elad * NB: even though __syscall(2) takes a quad_t
1005 1.32.2.2 elad * containing the system call number, because
1006 1.32.2.2 elad * our argument copying word-swaps 64-bit arguments,
1007 1.32.2.2 elad * the least significant word of that quad_t
1008 1.32.2.2 elad * is the first word in the argument array.
1009 1.32.2.2 elad */
1010 1.32.2.2 elad code = *args;
1011 1.32.2.2 elad args += 2;
1012 1.32.2.2 elad }
1013 1.32.2.2 elad
1014 1.32.2.2 elad /*
1015 1.32.2.2 elad * Stacks growing from lower addresses to higher
1016 1.32.2.2 elad * addresses are not really such a good idea, because
1017 1.32.2.2 elad * it makes it impossible to overlay a struct on top
1018 1.32.2.2 elad * of C stack arguments (the arguments appear in
1019 1.32.2.2 elad * reversed order).
1020 1.32.2.2 elad *
1021 1.32.2.2 elad * You can do the obvious thing (as locore.S does) and
1022 1.32.2.2 elad * copy argument words one by one, laying them out in
1023 1.32.2.2 elad * the "right" order in the destination buffer, but this
1024 1.32.2.2 elad * ends up word-swapping multi-word arguments (like off_t).
1025 1.32.2.2 elad *
1026 1.32.2.2 elad * To compensate, we have some automatically-generated
1027 1.32.2.2 elad * code that word-swaps these multi-word arguments.
1028 1.32.2.2 elad * Right now the script that generates this code is
1029 1.32.2.2 elad * in Perl, because I don't know awk.
1030 1.32.2.2 elad *
1031 1.32.2.2 elad * FIXME - this works only on native binaries and
1032 1.32.2.2 elad * will probably screw up any and all emulation.
1033 1.32.2.2 elad */
1034 1.32.2.2 elad switch (code) {
1035 1.32.2.2 elad /*
1036 1.32.2.2 elad * BEGIN automatically generated
1037 1.32.2.2 elad * by /home/fredette/project/hppa/makescargfix.pl
1038 1.32.2.2 elad * do not edit!
1039 1.32.2.2 elad */
1040 1.32.2.2 elad case SYS_pread:
1041 1.32.2.2 elad /*
1042 1.32.2.2 elad * syscallarg(int) fd;
1043 1.32.2.2 elad * syscallarg(void *) buf;
1044 1.32.2.2 elad * syscallarg(size_t) nbyte;
1045 1.32.2.2 elad * syscallarg(int) pad;
1046 1.32.2.2 elad * syscallarg(off_t) offset;
1047 1.32.2.2 elad */
1048 1.32.2.2 elad tmp = args[4];
1049 1.32.2.2 elad args[4] = args[4 + 1];
1050 1.32.2.2 elad args[4 + 1] = tmp;
1051 1.32.2.2 elad break;
1052 1.32.2.2 elad case SYS_pwrite:
1053 1.32.2.2 elad /*
1054 1.32.2.2 elad * syscallarg(int) fd;
1055 1.32.2.2 elad * syscallarg(const void *) buf;
1056 1.32.2.2 elad * syscallarg(size_t) nbyte;
1057 1.32.2.2 elad * syscallarg(int) pad;
1058 1.32.2.2 elad * syscallarg(off_t) offset;
1059 1.32.2.2 elad */
1060 1.32.2.2 elad tmp = args[4];
1061 1.32.2.2 elad args[4] = args[4 + 1];
1062 1.32.2.2 elad args[4 + 1] = tmp;
1063 1.32.2.2 elad break;
1064 1.32.2.2 elad case SYS_mmap:
1065 1.32.2.2 elad /*
1066 1.32.2.2 elad * syscallarg(void *) addr;
1067 1.32.2.2 elad * syscallarg(size_t) len;
1068 1.32.2.2 elad * syscallarg(int) prot;
1069 1.32.2.2 elad * syscallarg(int) flags;
1070 1.32.2.2 elad * syscallarg(int) fd;
1071 1.32.2.2 elad * syscallarg(long) pad;
1072 1.32.2.2 elad * syscallarg(off_t) pos;
1073 1.32.2.2 elad */
1074 1.32.2.2 elad tmp = args[6];
1075 1.32.2.2 elad args[6] = args[6 + 1];
1076 1.32.2.2 elad args[6 + 1] = tmp;
1077 1.32.2.2 elad break;
1078 1.32.2.2 elad case SYS_lseek:
1079 1.32.2.2 elad /*
1080 1.32.2.2 elad * syscallarg(int) fd;
1081 1.32.2.2 elad * syscallarg(int) pad;
1082 1.32.2.2 elad * syscallarg(off_t) offset;
1083 1.32.2.2 elad */
1084 1.32.2.2 elad tmp = args[2];
1085 1.32.2.2 elad args[2] = args[2 + 1];
1086 1.32.2.2 elad args[2 + 1] = tmp;
1087 1.32.2.2 elad break;
1088 1.32.2.2 elad case SYS_truncate:
1089 1.32.2.2 elad /*
1090 1.32.2.2 elad * syscallarg(const char *) path;
1091 1.32.2.2 elad * syscallarg(int) pad;
1092 1.32.2.2 elad * syscallarg(off_t) length;
1093 1.32.2.2 elad */
1094 1.32.2.2 elad tmp = args[2];
1095 1.32.2.2 elad args[2] = args[2 + 1];
1096 1.32.2.2 elad args[2 + 1] = tmp;
1097 1.32.2.2 elad break;
1098 1.32.2.2 elad case SYS_ftruncate:
1099 1.32.2.2 elad /*
1100 1.32.2.2 elad * syscallarg(int) fd;
1101 1.32.2.2 elad * syscallarg(int) pad;
1102 1.32.2.2 elad * syscallarg(off_t) length;
1103 1.32.2.2 elad */
1104 1.32.2.2 elad tmp = args[2];
1105 1.32.2.2 elad args[2] = args[2 + 1];
1106 1.32.2.2 elad args[2 + 1] = tmp;
1107 1.32.2.2 elad break;
1108 1.32.2.2 elad case SYS_preadv:
1109 1.32.2.2 elad /*
1110 1.32.2.2 elad * syscallarg(int) fd;
1111 1.32.2.2 elad * syscallarg(const struct iovec *) iovp;
1112 1.32.2.2 elad * syscallarg(int) iovcnt;
1113 1.32.2.2 elad * syscallarg(int) pad;
1114 1.32.2.2 elad * syscallarg(off_t) offset;
1115 1.32.2.2 elad */
1116 1.32.2.2 elad tmp = args[4];
1117 1.32.2.2 elad args[4] = args[4 + 1];
1118 1.32.2.2 elad args[4 + 1] = tmp;
1119 1.32.2.2 elad break;
1120 1.32.2.2 elad case SYS_pwritev:
1121 1.32.2.2 elad /*
1122 1.32.2.2 elad * syscallarg(int) fd;
1123 1.32.2.2 elad * syscallarg(const struct iovec *) iovp;
1124 1.32.2.2 elad * syscallarg(int) iovcnt;
1125 1.32.2.2 elad * syscallarg(int) pad;
1126 1.32.2.2 elad * syscallarg(off_t) offset;
1127 1.32.2.2 elad */
1128 1.32.2.2 elad tmp = args[4];
1129 1.32.2.2 elad args[4] = args[4 + 1];
1130 1.32.2.2 elad args[4 + 1] = tmp;
1131 1.32.2.2 elad break;
1132 1.32.2.2 elad default:
1133 1.32.2.2 elad break;
1134 1.32.2.2 elad /*
1135 1.32.2.2 elad * END automatically generated
1136 1.32.2.2 elad * by /home/fredette/project/hppa/makescargfix.pl
1137 1.32.2.2 elad * do not edit!
1138 1.32.2.2 elad */
1139 1.32.2.2 elad }
1140 1.32.2.2 elad
1141 1.32.2.2 elad #ifdef USERTRACE
1142 1.32.2.2 elad if (0) {
1143 1.32.2.2 elad user_backtrace(frame, p, -1);
1144 1.32.2.2 elad frame->tf_ipsw |= PSW_R;
1145 1.32.2.2 elad frame->tf_rctr = 0;
1146 1.32.2.2 elad printf("r %08x", frame->tf_iioq_head);
1147 1.32.2.2 elad rctr_next_iioq = frame->tf_iioq_head + 4;
1148 1.32.2.2 elad }
1149 1.32.2.2 elad #endif
1150 1.32.2.2 elad
1151 1.32.2.2 elad if (code < 0 || code >= nsys)
1152 1.32.2.2 elad callp += p->p_emul->e_nosys; /* bad syscall # */
1153 1.32.2.2 elad else
1154 1.32.2.2 elad callp += code;
1155 1.32.2.2 elad argsize = callp->sy_argsize;
1156 1.32.2.2 elad
1157 1.32.2.2 elad if ((error = trace_enter(l, code, code, NULL, args)) != 0)
1158 1.32.2.2 elad goto out;
1159 1.32.2.2 elad
1160 1.32.2.2 elad rval[0] = 0;
1161 1.32.2.2 elad rval[1] = 0;
1162 1.32.2.2 elad error = (*callp->sy_call)(l, args, rval);
1163 1.32.2.2 elad out:
1164 1.32.2.2 elad switch (error) {
1165 1.32.2.2 elad case 0:
1166 1.32.2.2 elad l = curlwp; /* changes on exec() */
1167 1.32.2.2 elad frame = l->l_md.md_regs;
1168 1.32.2.2 elad frame->tf_ret0 = rval[0];
1169 1.32.2.2 elad frame->tf_ret1 = rval[1];
1170 1.32.2.2 elad frame->tf_t1 = 0;
1171 1.32.2.2 elad break;
1172 1.32.2.2 elad case ERESTART:
1173 1.32.2.2 elad /*
1174 1.32.2.2 elad * Now we have to wind back the instruction
1175 1.32.2.2 elad * offset queue to the point where the system
1176 1.32.2.2 elad * call will be made again. This is inherently
1177 1.32.2.2 elad * tied to the SYSCALL macro.
1178 1.32.2.2 elad *
1179 1.32.2.2 elad * Currently, the part of the SYSCALL macro
1180 1.32.2.2 elad * that we want to rerun reads as:
1181 1.32.2.2 elad *
1182 1.32.2.2 elad * ldil L%SYSCALLGATE, r1
1183 1.32.2.2 elad * ble 4(sr7, r1)
1184 1.32.2.2 elad * ldi __CONCAT(SYS_,x), t1
1185 1.32.2.2 elad * ldw HPPA_FRAME_ERP(sr0,sp), rp
1186 1.32.2.2 elad *
1187 1.32.2.2 elad * And our offset queue head points to the
1188 1.32.2.2 elad * final ldw instruction. So we need to
1189 1.32.2.2 elad * subtract twelve to reach the ldil.
1190 1.32.2.2 elad */
1191 1.32.2.2 elad frame->tf_iioq_head -= 12;
1192 1.32.2.2 elad frame->tf_iioq_tail = frame->tf_iioq_head + 4;
1193 1.32.2.2 elad break;
1194 1.32.2.2 elad case EJUSTRETURN:
1195 1.32.2.2 elad p = curproc;
1196 1.32.2.2 elad break;
1197 1.32.2.2 elad default:
1198 1.32.2.2 elad if (p->p_emul->e_errno)
1199 1.32.2.2 elad error = p->p_emul->e_errno[error];
1200 1.32.2.2 elad frame->tf_t1 = error;
1201 1.32.2.2 elad break;
1202 1.32.2.2 elad }
1203 1.32.2.2 elad
1204 1.32.2.2 elad trace_exit(l, code, args, rval, error);
1205 1.32.2.2 elad
1206 1.32.2.2 elad userret(l, frame->tf_iioq_head, 0);
1207 1.32.2.2 elad #ifdef DEBUG
1208 1.32.2.2 elad frame_sanity_check(0xdead05, 0, frame, l);
1209 1.32.2.2 elad #endif /* DEBUG */
1210 1.32.2.2 elad }
1211 1.32.2.2 elad
1212 1.32.2.2 elad /*
1213 1.32.2.2 elad * Start a new LWP
1214 1.32.2.2 elad */
1215 1.32.2.2 elad void
1216 1.32.2.2 elad startlwp(void *arg)
1217 1.32.2.2 elad {
1218 1.32.2.2 elad int err;
1219 1.32.2.2 elad ucontext_t *uc = arg;
1220 1.32.2.2 elad struct lwp *l = curlwp;
1221 1.32.2.2 elad
1222 1.32.2.2 elad err = cpu_setmcontext(l, &uc->uc_mcontext, uc->uc_flags);
1223 1.32.2.2 elad #if DIAGNOSTIC
1224 1.32.2.2 elad if (err) {
1225 1.32.2.2 elad printf("Error %d from cpu_setmcontext.", err);
1226 1.32.2.2 elad }
1227 1.32.2.2 elad #endif
1228 1.32.2.2 elad pool_put(&lwp_uc_pool, uc);
1229 1.32.2.2 elad
1230 1.32.2.2 elad userret(l, l->l_md.md_regs->tf_iioq_head, 0);
1231 1.32.2.2 elad }
1232 1.32.2.2 elad
1233 1.32.2.2 elad /*
1234 1.32.2.2 elad * XXX This is a terrible name.
1235 1.32.2.2 elad */
1236 1.32.2.2 elad void
1237 1.32.2.2 elad upcallret(struct lwp *l)
1238 1.32.2.2 elad {
1239 1.32.2.2 elad userret(l, l->l_md.md_regs->tf_iioq_head, 0);
1240 1.32.2.2 elad }
1241