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