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