2 * traps, exceptions, interrupts, system calls.
5 #include "../port/lib.h"
11 #include "../port/error.h"
16 Nvec = 8, /* # of vectors at start of lexception.s */
20 * Layout at virtual address KZERO (double mapped at HVECTORS).
22 typedef struct Vpage0 {
23 void (*vectors[Nvec])(void);
27 static char *trapnames[PsrMask+1] = {
28 [ PsrMusr ] "user mode",
29 [ PsrMfiq ] "fiq interrupt",
30 [ PsrMirq ] "irq interrupt",
31 [ PsrMsvc ] "svc/swi exception",
32 [ PsrMabt ] "prefetch abort/data abort",
33 [ PsrMabt+1 ] "data abort",
34 [ PsrMund ] "undefined instruction",
35 [ PsrMsys ] "sys trap",
38 extern int irq(Ureg*);
39 extern int notify(Ureg*);
42 * set up for exceptions
51 /* disable everything */
53 /* set up the exception vectors */
54 vpage0 = (Vpage0*)HVECTORS;
55 memmove(vpage0->vectors, vectors, sizeof(vpage0->vectors));
56 memmove(vpage0->vtable, vtable, sizeof(vpage0->vtable));
61 /* set up the stacks for the interrupt modes */
62 setr13(PsrMfiq, (u32int*)(FIQSTKTOP));
63 setr13(PsrMirq, m->sirq);
64 setr13(PsrMabt, m->sabt);
65 setr13(PsrMund, m->sund);
66 setr13(PsrMsys, m->ssys);
76 s = trapnames[psr & PsrMask];
78 s = "unknown trap number in psr";
83 * called by trap to handle access faults
86 faultarm(Ureg *ureg, uintptr va, int user, int read)
93 panic("fault: nil up in faultarm, accessing %#p", va);
95 insyscall = up->insyscall;
97 n = fault(va, ureg->pc, read);
101 panic("fault: kernel accessing %#p", va);
103 /* don't dump registers; programs suicide all the time */
104 snprint(buf, sizeof buf, "sys: trap: fault %s va=%#p",
105 read? "read": "write", va);
106 postnote(up, 1, buf, NDebug);
108 up->insyscall = insyscall;
112 * returns 1 if the instruction writes memory, 0 otherwise
115 writetomem(ulong inst)
117 /* swap always write memory */
118 if((inst & 0x0FC00000) == 0x01000000)
121 /* loads and stores are distinguished by bit 20 */
129 * here on all exceptions other than syscall (SWI) and fiq
134 int clockintr, user, x, rv, rem;
141 rem = ((char*)ureg)-up->kstack;
143 rem = ((char*)ureg)-((char*)m+sizeof(Mach));
145 iprint("trap: %d stack bytes left, up %#p ureg %#p at pc %#lux\n",
146 rem, up, ureg, ureg->pc);
149 panic("trap: %d stack bytes left, up %#p ureg %#p at pc %#lux",
150 rem, up, ureg, ureg->pc);
153 user = (ureg->psr & PsrMask) == PsrMusr;
160 * All interrupts/exceptions should be resumed at ureg->pc-4,
161 * except for Data Abort which resumes at ureg->pc-8.
163 if(ureg->type == (PsrMabt+1))
168 clockintr = 0; /* if set, may call sched() before return */
171 panic("unknown trap; type %#lux, psr mode %#lux", ureg->type,
172 ureg->psr & PsrMask);
175 clockintr = irq(ureg);
177 case PsrMabt: /* prefetch fault */
179 fsr = (x>>7) & 0x8 | x & 0x7;
181 case 0x02: /* instruction debug event (BKPT) */
183 snprint(buf, sizeof buf, "sys: breakpoint");
184 postnote(up, 1, buf, NDebug);
186 iprint("kernel bkpt: pc %#lux inst %#ux\n",
187 ureg->pc, *(u32int*)ureg->pc);
188 panic("kernel bkpt");
192 faultarm(ureg, ureg->pc, user, 1);
196 case PsrMabt+1: /* data fault */
198 inst = *(ulong*)(ureg->pc);
199 /* bits 12 and 10 have to be concatenated with status */
201 fsr = (x>>7) & 0x20 | (x>>6) & 0x10 | x & 0xf;
204 case 0xa: /* ? was under external abort */
205 panic("unknown data fault, 6b fsr %#lux", fsr);
208 panic("vector exception at %#lux", ureg->pc);
210 case 0x1: /* alignment fault */
211 case 0x3: /* access flag fault (section) */
213 snprint(buf, sizeof buf,
214 "sys: alignment: pc %#lux va %#p\n",
216 postnote(up, 1, buf, NDebug);
218 panic("kernel alignment: pc %#lux va %#p", ureg->pc, va);
221 panic("terminal exception at %#lux", ureg->pc);
223 case 0x4: /* icache maint fault */
224 case 0x6: /* access flag fault (page) */
225 case 0x8: /* precise external abort, non-xlat'n */
227 case 0xc: /* l1 translation, precise ext. abort */
229 case 0xe: /* l2 translation, precise ext. abort */
231 case 0x16: /* imprecise ext. abort, non-xlt'n */
233 panic("external abort %#lux pc %#lux addr %#p",
236 case 0x1c: /* l1 translation, precise parity err */
237 case 0x1e: /* l2 translation, precise parity err */
238 case 0x18: /* imprecise parity or ecc err */
239 panic("translation parity error %#lux pc %#lux addr %#p",
242 case 0x5: /* translation fault, no section entry */
243 case 0x7: /* translation fault, no page entry */
244 faultarm(ureg, va, user, !writetomem(inst));
248 /* domain fault, accessing something we shouldn't */
250 snprint(buf, sizeof buf,
251 "sys: access violation: pc %#lux va %#p\n",
253 postnote(up, 1, buf, NDebug);
255 panic("kernel access violation: pc %#lux va %#p",
260 /* permission error, copy on write or real permission error */
261 faultarm(ureg, va, user, !writetomem(inst));
265 case PsrMund: /* undefined instruction */
267 if(seg(up, ureg->pc, 0) != nil &&
268 *(u32int*)ureg->pc == 0xD1200070)
269 postnote(up, 1, "sys: breakpoint", NDebug);
271 /* look for floating point instructions to interpret */
274 snprint(buf, sizeof buf,
275 "undefined instruction: pc %#lux\n",
277 postnote(up, 1, buf, NDebug);
282 iprint("rounding fault pc %#lux down to word\n",
286 iprint("undefined instruction: pc %#lux inst %#ux\n",
287 ureg->pc, *(u32int*)ureg->pc);
288 panic("undefined instruction");
294 /* delaysched set because we held a lock or because our quantum ended */
295 if(up && up->delaysched && clockintr){
296 sched(); /* can cause more traps */
301 if(up->procctl || up->nnote)
310 return (uintptr)v >= KZERO;
314 dumplongs(char *msg, ulong *v, int n)
319 iprint("%s at %.8p: ", msg, v);
322 iprint("\n %.8p: ", v);
326 iprint(" %.8lux", *v++);
337 dumpstackwithureg(Ureg *ureg)
339 uintptr l, i, v, estack;
343 if((s = getconf("*nodumpstack")) != nil && strcmp(s, "0") != 0){
344 iprint("dumpstack disabled\n");
347 iprint("ktrace /kernel/path %#.8lux %#.8lux %#.8lux # pc, sp, link\n",
348 ureg->pc, ureg->sp, ureg->r14);
351 if(up != nil && (uintptr)&l <= (uintptr)up->kstack+KSTACK)
352 estack = (uintptr)up->kstack+KSTACK;
353 else if((uintptr)&l >= (uintptr)m->stack
354 && (uintptr)&l <= (uintptr)m+MACHSIZE)
355 estack = (uintptr)m+MACHSIZE;
358 iprint("&up->kstack %#p &l %#p\n", up->kstack, &l);
360 iprint("&m %#p &l %#p\n", m, &l);
363 for(l = (uintptr)&l; l < estack; l += sizeof(uintptr)){
365 if(KTZERO < v && v < (uintptr)etext && !(v & 3)){
366 v -= sizeof(u32int); /* back up an instr */
368 if((*p & 0x0f000000) == 0x0b000000){ /* BL instr? */
369 iprint("%#8.8lux=%#8.8lux ", l, v);
383 * Fill in enough of Ureg to get a stack trace, and call a function.
384 * Used by debugging interface rdb.
387 callwithureg(void (*fn)(Ureg*))
391 ureg.pc = getcallerpc(&fn);
392 ureg.sp = (uintptr)&fn;
399 callwithureg(dumpstackwithureg);
408 iprint("trap: no user process\n");
412 iprint("trap: %s", trapname(ureg->type));
413 if(ureg != nil && (ureg->psr & PsrMask) != PsrMsvc)
414 iprint(" in %s", trapname(ureg->psr));
416 iprint("psr %8.8lux type %2.2lux pc %8.8lux link %8.8lux\n",
417 ureg->psr, ureg->type, ureg->pc, ureg->link);
418 iprint("R14 %8.8lux R13 %8.8lux R12 %8.8lux R11 %8.8lux R10 %8.8lux\n",
419 ureg->r14, ureg->r13, ureg->r12, ureg->r11, ureg->r10);
420 iprint("R9 %8.8lux R8 %8.8lux R7 %8.8lux R6 %8.8lux R5 %8.8lux\n",
421 ureg->r9, ureg->r8, ureg->r7, ureg->r6, ureg->r5);
422 iprint("R4 %8.8lux R3 %8.8lux R2 %8.8lux R1 %8.8lux R0 %8.8lux\n",
423 ureg->r4, ureg->r3, ureg->r2, ureg->r1, ureg->r0);
424 iprint("stack is at %#p\n", ureg);
425 iprint("pc %#lux link %#lux\n", ureg->pc, ureg->link);
428 iprint("user stack: %#p-%#p\n", up->kstack, up->kstack+KSTACK-4);
430 iprint("kernel stack: %8.8lux-%8.8lux\n",
431 (ulong)(m+1), (ulong)m+BY2PG-4);
432 dumplongs("stack", (ulong *)(ureg + 1), 16);