trap.c revision 1.2 1 /* $NetBSD: trap.c,v 1.2 2006/04/08 14:52:09 cherry Exp $ */
2
3 /*-
4 * Copyright (c) 2005 Marcel Moolenaar
5 * All rights reserved.
6 *
7 * Redistribution and use in source and binary forms, with or without
8 * modification, are permitted provided that the following conditions
9 * are met:
10 *
11 * 1. Redistributions of source code must retain the above copyright
12 * notice, this list of conditions and the following disclaimer.
13 * 2. Redistributions in binary form must reproduce the above copyright
14 * notice, this list of conditions and the following disclaimer in the
15 * documentation and/or other materials provided with the distribution.
16 *
17 * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
18 * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
19 * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
20 * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
21 * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
22 * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
23 * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
24 * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
25 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
26 * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
27 */
28
29 /*-
30 * Copyright (c) 2000, 2001 The NetBSD Foundation, Inc.
31 * All rights reserved.
32 *
33 * This code is derived from software contributed to The NetBSD Foundation
34 * by Jason R. Thorpe of the Numerical Aerospace Simulation Facility,
35 * NASA Ames Research Center, by Charles M. Hannum, and by Ross Harvey.
36 *
37 * Redistribution and use in source and binary forms, with or without
38 * modification, are permitted provided that the following conditions
39 * are met:
40 * 1. Redistributions of source code must retain the above copyright
41 * notice, this list of conditions and the following disclaimer.
42 * 2. Redistributions in binary form must reproduce the above copyright
43 * notice, this list of conditions and the following disclaimer in the
44 * documentation and/or other materials provided with the distribution.
45 * 3. All advertising materials mentioning features or use of this software
46 * must display the following acknowledgement:
47 * This product includes software developed by the NetBSD
48 * Foundation, Inc. and its contributors.
49 * 4. Neither the name of The NetBSD Foundation nor the names of its
50 * contributors may be used to endorse or promote products derived
51 * from this software without specific prior written permission.
52 *
53 * THIS SOFTWARE IS PROVIDED BY THE NETBSD FOUNDATION, INC. AND CONTRIBUTORS
54 * ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED
55 * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
56 * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE FOUNDATION OR CONTRIBUTORS
57 * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
58 * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
59 * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
60 * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
61 * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
62 * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
63 * POSSIBILITY OF SUCH DAMAGE.
64 */
65
66
67 #include "opt_ddb.h"
68
69 #include <sys/cdefs.h> /* RCS ID & Copyright macro defns */
70
71 __KERNEL_RCSID(0, "$NetBSD: trap.c,v 1.2 2006/04/08 14:52:09 cherry Exp $");
72
73 #include <sys/param.h>
74 #include <sys/systm.h>
75 #include <sys/proc.h>
76 #include <sys/sa.h>
77 #include <sys/savar.h>
78
79 #include <sys/userret.h>
80
81 #include <uvm/uvm_extern.h>
82
83 #include <machine/frame.h>
84 #include <machine/md_var.h>
85 #include <machine/cpu.h>
86 #include <machine/ia64_cpu.h>
87 #include <machine/fpu.h>
88 #ifdef DDB
89 #include <machine/db_machdep.h>
90 #include <ddb/db_extern.h>
91 #endif
92
93 #include <ia64/disasm/disasm.h>
94
95
96 static const char *ia64_vector_names[] = {
97 "VHPT Translation", /* 0 */
98 "Instruction TLB", /* 1 */
99 "Data TLB", /* 2 */
100 "Alternate Instruction TLB", /* 3 */
101 "Alternate Data TLB", /* 4 */
102 "Data Nested TLB", /* 5 */
103 "Instruction Key Miss", /* 6 */
104 "Data Key Miss", /* 7 */
105 "Dirty-Bit", /* 8 */
106 "Instruction Access-Bit", /* 9 */
107 "Data Access-Bit", /* 10 */
108 "Break Instruction", /* 11 */
109 "External Interrupt", /* 12 */
110 "Reserved 13", /* 13 */
111 "Reserved 14", /* 14 */
112 "Reserved 15", /* 15 */
113 "Reserved 16", /* 16 */
114 "Reserved 17", /* 17 */
115 "Reserved 18", /* 18 */
116 "Reserved 19", /* 19 */
117 "Page Not Present", /* 20 */
118 "Key Permission", /* 21 */
119 "Instruction Access Rights", /* 22 */
120 "Data Access Rights", /* 23 */
121 "General Exception", /* 24 */
122 "Disabled FP-Register", /* 25 */
123 "NaT Consumption", /* 26 */
124 "Speculation", /* 27 */
125 "Reserved 28", /* 28 */
126 "Debug", /* 29 */
127 "Unaligned Reference", /* 30 */
128 "Unsupported Data Reference", /* 31 */
129 "Floating-point Fault", /* 32 */
130 "Floating-point Trap", /* 33 */
131 "Lower-Privilege Transfer Trap", /* 34 */
132 "Taken Branch Trap", /* 35 */
133 "Single Step Trap", /* 36 */
134 "Reserved 37", /* 37 */
135 "Reserved 38", /* 38 */
136 "Reserved 39", /* 39 */
137 "Reserved 40", /* 40 */
138 "Reserved 41", /* 41 */
139 "Reserved 42", /* 42 */
140 "Reserved 43", /* 43 */
141 "Reserved 44", /* 44 */
142 "IA-32 Exception", /* 45 */
143 "IA-32 Intercept", /* 46 */
144 "IA-32 Interrupt", /* 47 */
145 "Reserved 48", /* 48 */
146 "Reserved 49", /* 49 */
147 "Reserved 50", /* 50 */
148 "Reserved 51", /* 51 */
149 "Reserved 52", /* 52 */
150 "Reserved 53", /* 53 */
151 "Reserved 54", /* 54 */
152 "Reserved 55", /* 55 */
153 "Reserved 56", /* 56 */
154 "Reserved 57", /* 57 */
155 "Reserved 58", /* 58 */
156 "Reserved 59", /* 59 */
157 "Reserved 60", /* 60 */
158 "Reserved 61", /* 61 */
159 "Reserved 62", /* 62 */
160 "Reserved 63", /* 63 */
161 "Reserved 64", /* 64 */
162 "Reserved 65", /* 65 */
163 "Reserved 66", /* 66 */
164 "Reserved 67", /* 67 */
165 };
166
167 struct bitname {
168 uint64_t mask;
169 const char* name;
170 };
171
172 static void
173 printbits(uint64_t mask, struct bitname *bn, int count)
174 {
175 int i, first = 1;
176 uint64_t bit;
177
178 for (i = 0; i < count; i++) {
179 /*
180 * Handle fields wider than one bit.
181 */
182 bit = bn[i].mask & ~(bn[i].mask - 1);
183 if (bn[i].mask > bit) {
184 if (first)
185 first = 0;
186 else
187 printf(",");
188 printf("%s=%ld", bn[i].name,
189 (mask & bn[i].mask) / bit);
190 } else if (mask & bit) {
191 if (first)
192 first = 0;
193 else
194 printf(",");
195 printf("%s", bn[i].name);
196 }
197 }
198 }
199
200 struct bitname psr_bits[] = {
201 {IA64_PSR_BE, "be"},
202 {IA64_PSR_UP, "up"},
203 {IA64_PSR_AC, "ac"},
204 {IA64_PSR_MFL, "mfl"},
205 {IA64_PSR_MFH, "mfh"},
206 {IA64_PSR_IC, "ic"},
207 {IA64_PSR_I, "i"},
208 {IA64_PSR_PK, "pk"},
209 {IA64_PSR_DT, "dt"},
210 {IA64_PSR_DFL, "dfl"},
211 {IA64_PSR_DFH, "dfh"},
212 {IA64_PSR_SP, "sp"},
213 {IA64_PSR_PP, "pp"},
214 {IA64_PSR_DI, "di"},
215 {IA64_PSR_SI, "si"},
216 {IA64_PSR_DB, "db"},
217 {IA64_PSR_LP, "lp"},
218 {IA64_PSR_TB, "tb"},
219 {IA64_PSR_RT, "rt"},
220 {IA64_PSR_CPL, "cpl"},
221 {IA64_PSR_IS, "is"},
222 {IA64_PSR_MC, "mc"},
223 {IA64_PSR_IT, "it"},
224 {IA64_PSR_ID, "id"},
225 {IA64_PSR_DA, "da"},
226 {IA64_PSR_DD, "dd"},
227 {IA64_PSR_SS, "ss"},
228 {IA64_PSR_RI, "ri"},
229 {IA64_PSR_ED, "ed"},
230 {IA64_PSR_BN, "bn"},
231 {IA64_PSR_IA, "ia"},
232 };
233
234 static void
235 printpsr(uint64_t psr)
236 {
237 printbits(psr, psr_bits, sizeof(psr_bits)/sizeof(psr_bits[0]));
238 }
239
240 struct bitname isr_bits[] = {
241 {IA64_ISR_CODE, "code"},
242 {IA64_ISR_VECTOR, "vector"},
243 {IA64_ISR_X, "x"},
244 {IA64_ISR_W, "w"},
245 {IA64_ISR_R, "r"},
246 {IA64_ISR_NA, "na"},
247 {IA64_ISR_SP, "sp"},
248 {IA64_ISR_RS, "rs"},
249 {IA64_ISR_IR, "ir"},
250 {IA64_ISR_NI, "ni"},
251 {IA64_ISR_SO, "so"},
252 {IA64_ISR_EI, "ei"},
253 {IA64_ISR_ED, "ed"},
254 };
255
256 static void printisr(uint64_t isr)
257 {
258 printbits(isr, isr_bits, sizeof(isr_bits)/sizeof(isr_bits[0]));
259 }
260
261 static void
262 printtrap(int vector, struct trapframe *tf, int isfatal, int user)
263 {
264
265 printf("\n");
266 printf("%s %s trap (cpu %lu):\n", isfatal? "fatal" : "handled",
267 user ? "user" : "kernel", curcpu()->ci_cpuid);
268 printf("\n");
269 printf(" trap vector = 0x%x (%s)\n",
270 vector, ia64_vector_names[vector]);
271 printf(" cr.iip = 0x%lx\n", tf->tf_special.iip);
272 printf(" cr.ipsr = 0x%lx (", tf->tf_special.psr);
273 printpsr(tf->tf_special.psr);
274 printf(")\n");
275 printf(" cr.isr = 0x%lx (", tf->tf_special.isr);
276 printisr(tf->tf_special.isr);
277 printf(")\n");
278 printf(" cr.ifa = 0x%lx\n", tf->tf_special.ifa);
279 if (tf->tf_special.psr & IA64_PSR_IS) {
280 printf(" ar.cflg = 0x%lx\n", ia64_get_cflg());
281 printf(" ar.csd = 0x%lx\n", ia64_get_csd());
282 printf(" ar.ssd = 0x%lx\n", ia64_get_ssd());
283 }
284 printf(" curlwp = %p\n", curlwp);
285 if (curproc != NULL)
286 printf(" pid = %d, comm = %s\n",
287 curproc->p_pid, curproc->p_comm);
288 printf("\n");
289 }
290
291 /*
292 * We got a trap caused by a break instruction and the immediate was 0.
293 * This indicates that we may have a break.b with some non-zero immediate.
294 * The break.b doesn't cause the immediate to be put in cr.iim. Hence,
295 * we need to disassemble the bundle and return the immediate found there.
296 * This may be a 0 value anyway. Return 0 for any error condition. This
297 * will result in a SIGILL, which is pretty much the best thing to do.
298 */
299 static uint64_t
300 trap_decode_break(struct trapframe *tf)
301 {
302 struct asm_bundle bundle;
303 struct asm_inst *inst;
304 int slot;
305
306 if (!asm_decode(tf->tf_special.iip, &bundle))
307 return (0);
308
309 slot = ((tf->tf_special.psr & IA64_PSR_RI) == IA64_PSR_RI_0) ? 0 :
310 ((tf->tf_special.psr & IA64_PSR_RI) == IA64_PSR_RI_1) ? 1 : 2;
311 inst = bundle.b_inst + slot;
312
313 /*
314 * Sanity checking: It must be a break instruction and the operand
315 * that has the break value must be an immediate.
316 */
317 if (inst->i_op != ASM_OP_BREAK ||
318 inst->i_oper[1].o_type != ASM_OPER_IMM)
319 return (0);
320
321 return (inst->i_oper[1].o_value);
322 }
323
324
325 /*
326 * Start a new LWP
327 */
328 void
329 startlwp(arg)
330 void *arg;
331 {
332 return;
333 }
334
335 void
336 upcallret(struct lwp *l)
337 {
338 return;
339 }
340
341 #ifdef DDB
342 int call_debugger = 1;
343
344 /*
345 * Enter the debugger due to a trap.
346 */
347
348 int
349 ia64_trap(int type, int code, db_regs_t *regs)
350 {
351
352 /* XXX: Switch stacks ? */
353
354 /* Debugger is not re-entrant. */
355
356 ddb_regp = regs;
357 db_trap(type, code);
358 return 1; /* XXX: Always handled ??? */
359
360 }
361
362 #endif
363
364 void
365 trap_panic(int vector, struct trapframe *tf)
366 {
367
368 printtrap(vector, tf, 1, TRAPF_USERMODE(tf));
369
370 #ifdef DDB
371 if (ia64_trap(vector, 0, tf)) return;
372 #endif
373 panic("trap");
374
375 return;
376 }
377
378 /*
379 *
380 */
381 int
382 do_ast(struct trapframe *tf)
383 {
384 return 0;
385 }
386
387 /*
388 * Trap is called from exception.s to handle most types of processor traps.
389 */
390 /*ARGSUSED*/
391 void
392 trap(int vector, struct trapframe *tf)
393 {
394
395 struct proc *p;
396 struct lwp *l;
397 uint64_t ucode;
398 int sig, user;
399 u_int sticks;
400 ksiginfo_t ksi;
401
402 user = TRAPF_USERMODE(tf) ? 1 : 0;
403
404 l = curlwp;
405
406 ucode = 0;
407
408 #if 0
409 printtrap(vector, tf, 0, TRAPF_USERMODE(tf));
410 #endif
411 if (user) {
412 ia64_set_fpsr(IA64_FPSR_DEFAULT);
413 sticks = p->p_sticks;
414 l->l_md.md_tf = tf;
415 p = l->l_proc;
416 } else {
417 sticks = 0; /* XXX bogus -Wuninitialized warning */
418 p = NULL;
419 }
420 sig = 0;
421 switch (vector) {
422 case IA64_VEC_VHPT:
423 /*
424 * This one is tricky. We should hardwire the VHPT, but
425 * don't at this time. I think we're mostly lucky that
426 * the VHPT is mapped.
427 */
428 trap_panic(vector, tf);
429 break;
430 case IA64_VEC_ITLB:
431 case IA64_VEC_DTLB:
432 case IA64_VEC_EXT_INTR:
433 /* We never call trap() with these vectors. */
434 trap_panic(vector, tf);
435 break;
436
437 case IA64_VEC_ALT_ITLB:
438 case IA64_VEC_ALT_DTLB:
439 /*
440 * These should never happen, because regions 0-4 use the
441 * VHPT. If we get one of these it means we didn't program
442 * the region registers correctly.
443 */
444 trap_panic(vector, tf);
445 break;
446
447 case IA64_VEC_NESTED_DTLB:
448 /*
449 * We never call trap() with this vector. We may want to
450 * do that in the future in case the nested TLB handler
451 * could not find the translation it needs. In that case
452 * we could switch to a special (hardwired) stack and
453 * come here to produce a nice panic().
454 */
455 trap_panic(vector, tf);
456 break;
457
458 case IA64_VEC_IKEY_MISS:
459 case IA64_VEC_DKEY_MISS:
460 case IA64_VEC_KEY_PERMISSION:
461 /*
462 * We don't use protection keys, so we should never get
463 * these faults.
464 */
465 trap_panic(vector, tf);
466 break;
467
468 case IA64_VEC_DIRTY_BIT:
469 case IA64_VEC_INST_ACCESS:
470 case IA64_VEC_DATA_ACCESS:
471 /*
472 * We get here if we read or write to a page of which the
473 * PTE does not have the access bit or dirty bit set and
474 * we can not find the PTE in our datastructures. This
475 * either means we have a stale PTE in the TLB, or we lost
476 * the PTE in our datastructures.
477 */
478 trap_panic(vector, tf);
479 break;
480
481 case IA64_VEC_BREAK:
482 if (user) {
483 ucode = (int)tf->tf_special.ifa & 0x1FFFFF;
484 if (ucode == 0) {
485 /*
486 * A break.b doesn't cause the immediate to be
487 * stored in cr.iim (and saved in the TF in
488 * tf_special.ifa). We need to decode the
489 * instruction to find out what the immediate
490 * was. Note that if the break instruction
491 * didn't happen to be a break.b, but any
492 * other break with an immediate of 0, we
493 * will do unnecessary work to get the value
494 * we already had. Not an issue, because a
495 * break 0 is invalid.
496 */
497 ucode = trap_decode_break(tf);
498 }
499 if (ucode < 0x80000) {
500 /* Software interrupts. */
501 switch (ucode) {
502 case 0: /* Unknown error. */
503 sig = SIGILL;
504 break;
505 case 1: /* Integer divide by zero. */
506 sig = SIGFPE;
507 ucode = FPE_INTDIV;
508 break;
509 case 2: /* Integer overflow. */
510 sig = SIGFPE;
511 ucode = FPE_INTOVF;
512 break;
513 case 3: /* Range check/bounds check. */
514 sig = SIGFPE;
515 ucode = FPE_FLTSUB;
516 break;
517 case 6: /* Decimal overflow. */
518 case 7: /* Decimal divide by zero. */
519 case 8: /* Packed decimal error. */
520 case 9: /* Invalid ASCII digit. */
521 case 10: /* Invalid decimal digit. */
522 sig = SIGFPE;
523 ucode = FPE_FLTINV;
524 break;
525 case 4: /* Null pointer dereference. */
526 case 5: /* Misaligned data. */
527 case 11: /* Paragraph stack overflow. */
528 sig = SIGSEGV;
529 break;
530 default:
531 sig = SIGILL;
532 break;
533 }
534 } else if (ucode < 0x100000) {
535 /* Debugger breakpoint. */
536 tf->tf_special.psr &= ~IA64_PSR_SS;
537 sig = SIGTRAP;
538 #if 0
539 } else if (ucode == 0x100000) {
540 break_syscall(tf);
541 return; /* do_ast() already called. */
542
543 } else if (ucode == 0x180000) {
544 mcontext_t mc;
545
546 error = copyin((void*)tf->tf_scratch.gr8,
547 &mc, sizeof(mc));
548 if (!error) {
549 set_mcontext(td, &mc);
550 return; /* Don't call do_ast()!!! */
551 }
552 sig = SIGSEGV;
553 ucode = tf->tf_scratch.gr8;
554 #endif
555 } else
556 sig = SIGILL;
557 } else {
558 trap_panic(vector, tf);
559 goto out;
560 }
561 break;
562
563 /* XXX: Fill in the rest */
564
565 case IA64_VEC_DEBUG:
566 case IA64_VEC_SINGLE_STEP_TRAP:
567 tf->tf_special.psr &= ~IA64_PSR_SS;
568 if (!user) {
569 trap_panic(vector, tf);
570 goto out;
571 }
572 sig = SIGTRAP;
573 break;
574
575
576
577 default:
578 /* Reserved vectors get here. Should never happen of course. */
579 trap_panic(vector, tf);
580 break;
581 }
582
583 printf("sig = %d", sig);
584 KASSERT(sig != 0);
585
586 KSI_INIT(&ksi);
587 ksi.ksi_signo = sig;
588 ksi.ksi_code = ucode;
589 trapsignal(l, &ksi);
590
591 #if 1
592 out:
593 #endif
594
595 if (user) {
596 mi_userret(l);
597 }
598
599
600 return;
601 }
602