3 #include "../port/lib.h"
8 #include "../port/error.h"
12 _dumpstack(Ureg *ureg)
14 uintptr l, v, i, estack;
19 if((s = getconf("*nodumpstack")) != nil && strcmp(s, "0") != 0){
20 iprint("dumpstack disabled\n");
23 iprint("cpu%d: dumpstack\n", m->machno);
26 x += iprint("ktrace /arm/9zynq %.8lux %.8lux %.8lux <<EOF\n", ureg->pc, ureg->sp, ureg->r14);
29 && (uintptr)&l >= (uintptr)up->kstack
30 && (uintptr)&l <= (uintptr)up->kstack+KSTACK)
31 estack = (uintptr)up->kstack+KSTACK;
32 else if((uintptr)&l >= (uintptr)m->stack
33 && (uintptr)&l <= (uintptr)m+MACHSIZE)
34 estack = (uintptr)m+MACHSIZE;
37 x += iprint("estackx %p\n", estack);
39 for(l = (uintptr)&l; l < estack; l += sizeof(uintptr)){
41 if((KTZERO < v && v < (uintptr)&etext) || estack-l < 32){
42 x += iprint("%.8p=%.8p ", l, v);
57 [0x01] "alignement fault",
59 [0x04] "fault on instruction cache maintenance",
60 [0x08] "synchronous external abort",
61 [0x0C] "synchronous external abort on translation table walk L1",
62 [0x0E] "synchronous external abort on translation table walk L2",
63 [0x10] "tlb conflict abort",
64 [0x16] "asynchronous external abort",
65 [0x19] "synchronous parity error on memory access",
66 [0x1C] "synchronous parity error on translation table walk L1",
67 [0x1E] "synchronous parity error on translation table walk L2",
71 faultarm(Ureg *ureg, ulong fsr, uintptr addr)
73 int user, insyscall, read;
74 static char buf[ERRMAX];
77 read = (fsr & (1<<11)) == 0;
78 user = userureg(ureg);
80 if(addr >= USTKTOP || up == nil)
83 panic("kernel fault: bad address pc=%#.8lux addr=%#.8lux fsr=%#.8lux", ureg->pc, addr, fsr);
85 panic("kernel fault: no user process pc=%#.8lux addr=%#.8lux fsr=%#.8lux", ureg->pc, addr, fsr);
88 panic("user fault: up=nil pc=%#.8lux addr=%#.8lux fsr=%#.8lux", ureg->pc, addr, fsr);
90 insyscall = up->insyscall;
93 case 0x05: /* translation fault L1 */
94 case 0x07: /* translation fault L2 */
95 case 0x03: /* access flag fault L1 */
96 case 0x06: /* access flag fault L2 */
97 case 0x09: /* domain fault L1 */
98 case 0x0B: /* domain fault L2 */
99 case 0x0D: /* permission fault L1 */
100 case 0x0F: /* permission fault L2 */
101 if(fault(addr, ureg->pc, read) == 0)
105 err = faulterr[fsr & 0x1F];
111 panic("kernel %s: pc=%#.8lux addr=%#.8lux fsr=%#.8lux", err, ureg->pc, addr, fsr);
113 sprint(buf, "sys: trap: %s %s addr=%#.8lux", err, read ? "read" : "write", addr);
114 postnote(up, 1, buf, NDebug);
116 up->insyscall = insyscall;
120 mathtrap(Ureg *, ulong)
124 if((up->fpstate & FPillegal) != 0){
125 postnote(up, 1, "sys: floating point in note handler", NDebug);
132 up->fpstate = FPactive;
137 fprestore(up->fpsave);
138 up->fpstate = FPactive;
142 postnote(up, 1, "sys: floating point error", NDebug);
159 if(okaddr(ureg->pc, 4, 0)){
160 opc = *(ulong*)ureg->pc;
161 if((opc & 0x0f000000) == 0x0e000000 || (opc & 0x0e000000) == 0x0c000000){
163 if(cp == 10 || cp == 11){
169 postnote(up, 1, "sys: trap: invalid opcode", NDebug);
173 panic("invalid opcode at pc=%#.8lux lr=%#.8lux", ureg->pc, ureg->r14);
177 faultarm(ureg, getifsr(), getifar());
181 faultarm(ureg, getdfsr(), getdfar());
188 iprint("cpu%d: unknown trap type %ulx\n", m->machno, ureg->type);
192 if(up->procctl || up->nnote)
198 #include "../port/systab.h"
208 vlong startns, stopns;
211 panic("syscall: pc=%#.8lux", ureg->pc);
218 up->scallnr = scallnr = ureg->r0;
225 if(sp < USTKTOP - BY2PG || sp > USTKTOP - sizeof(Sargs) - BY2WD){
226 validaddr(sp, sizeof(Sargs)+BY2WD, 0);
229 up->s = *((Sargs*) (sp + BY2WD));
231 if(up->procctl == Proc_tracesyscall){
232 syscallfmt(scallnr, ureg->pc, (va_list) up->s.args);
234 up->procctl = Proc_stopme;
237 startns = todget(nil);
240 if(scallnr >= nsyscall || systab[scallnr] == 0){
241 pprint("bad sys call number %lud pc %lux", scallnr, ureg->pc);
242 postnote(up, 1, "sys: bad sys call", NDebug);
245 up->psstate = sysctab[scallnr];
246 ret = systab[scallnr]((va_list)up->s.args);
250 up->syserrstr = up->errstr;
254 print("bad errstack [%lud]: %d extra\n", scallnr, up->nerrlab);
255 for(i = 0; i < NERR; i++)
256 print("sp=%lux pc=%lux\n", up->errlab[i].sp, up->errlab[i].pc);
257 panic("error stack");
261 if(up->procctl == Proc_tracesyscall){
262 stopns = todget(nil);
263 sysretfmt(scallnr, (va_list) up->s.args, ret, startns, stopns);
265 up->procctl = Proc_stopme;
273 noted(ureg, *((ulong *) up->s.args));
275 if(scallnr != RFORK && (up->procctl || up->nnote)){
297 if(up->fpstate == FPactive){
299 up->fpstate = FPinactive;
301 up->fpstate |= FPillegal;
307 if(strncmp(n->msg, "sys:", 4) == 0){
309 if(l > ERRMAX-15) /* " pc=0x12345678\0" */
311 sprint(n->msg+l, " pc=0x%.8lux", ureg->pc);
314 if(n->flag!=NUser && (up->notified || up->notify==0)){
316 if(n->flag == NDebug)
317 pprint("suicide: %s\n", n->msg);
318 pexit(n->msg, n->flag!=NDebug);
329 pexit(n->msg, n->flag!=NDebug);
332 sp -= 256; /* debugging: preserve context causing problem */
335 if(!okaddr((uintptr)up->notify, 1, 0)
336 || !okaddr(sp-ERRMAX-4*BY2WD, sizeof(Ureg)+ERRMAX+4*BY2WD, 1)
337 || ((uintptr) up->notify & 3) != 0
340 pprint("suicide: bad address in notify\n");
344 memmove((Ureg*)sp, ureg, sizeof(Ureg));
345 *(Ureg**)(sp-BY2WD) = up->ureg; /* word under Ureg is old up->ureg */
346 up->ureg = (void*)sp;
348 memmove((char*)sp, up->note[0].msg, ERRMAX);
350 *(ulong*)(sp+2*BY2WD) = sp+3*BY2WD;
351 *(ulong*)(sp+1*BY2WD) = (ulong)up->ureg;
352 ureg->r0 = (uintptr) up->ureg;
354 ureg->pc = (uintptr) up->notify;
358 memmove(&up->lastnote, &up->note[0], sizeof(Note));
359 memmove(&up->note[0], &up->note[1], up->nnote*sizeof(Note));
367 noted(Ureg *ureg, ulong arg0)
373 if(arg0 != NRSTR && !up->notified){
375 pprint("call to noted() when not notified\n");
381 up->fpstate &= ~FPillegal;
383 oureg = (ulong) nureg;
384 if(!okaddr(oureg - BY2WD, BY2WD + sizeof(Ureg), 0) || (oureg & 3) != 0){
386 pprint("bad ureg in noted or call to noted when not notified\n");
390 nureg->psr = nureg->psr & 0xf80f0000 | ureg->psr & 0x07f0ffff;
392 memmove(ureg, nureg, sizeof(Ureg));
395 case NCONT: case NRSTR:
396 if(!okaddr(nureg->pc, BY2WD, 0) || !okaddr(nureg->sp, BY2WD, 0) ||
397 (nureg->pc & 3) != 0 || (nureg->sp & 3) != 0){
399 pprint("suicide: trap in noted\n");
402 up->ureg = (Ureg *) (*(ulong *) (oureg - BY2WD));
407 if(!okaddr(nureg->pc, BY2WD, 0) || !okaddr(nureg->sp, BY2WD, 0) ||
408 (nureg->pc & 3) != 0 || (nureg->sp & 3) != 0){
410 pprint("suicide: trap in noted\n");
414 sp = oureg - 4 * BY2WD - ERRMAX;
417 ureg->r0 = (uintptr) oureg;
418 ((ulong *) sp)[1] = oureg;
419 ((ulong *) sp)[0] = 0;
423 up->lastnote.flag = NDebug;
427 if(up->lastnote.flag == NDebug)
428 pprint("suicide: %s\n", up->lastnote.msg);
429 pexit(up->lastnote.msg, up->lastnote.flag != NDebug);
437 callwithureg(_dumpstack);
443 iprint("trap: %lux psr %8.8lux type %2.2lux pc %8.8lux link %8.8lux\n",
444 ureg->type, ureg->psr, ureg->type, ureg->pc, ureg->link);
445 iprint("R14 %8.8lux R13 %8.8lux R12 %8.8lux R11 %8.8lux R10 %8.8lux\n",
446 ureg->r14, ureg->r13, ureg->r12, ureg->r11, ureg->r10);
447 iprint("R9 %8.8lux R8 %8.8lux R7 %8.8lux R6 %8.8lux R5 %8.8lux\n",
448 ureg->r9, ureg->r8, ureg->r7, ureg->r6, ureg->r5);
449 iprint("R4 %8.8lux R3 %8.8lux R2 %8.8lux R1 %8.8lux R0 %8.8lux\n",
450 ureg->r4, ureg->r3, ureg->r2, ureg->r1, ureg->r0);
451 iprint("pc %#lux link %#lux\n", ureg->pc, ureg->link);
455 setkernur(Ureg *ureg, Proc *p)
457 ureg->pc = p->sched.pc;
458 ureg->sp = p->sched.sp + 4;
459 ureg->r14 = (uintptr) sched;
463 setregisters(Ureg* ureg, char* pureg, char* uva, int n)
468 memmove(pureg, uva, n);
469 ureg->psr = ureg->psr & 0xf80f0000 | v & 0x07f0ffff;
473 callwithureg(void (*f) (Ureg *))
477 u.pc = getcallerpc(&f);
478 u.sp = (uintptr) &f - 4;
505 if(p->fpstate == FPactive){
506 if(p->state == Moribund)
510 p->fpstate = FPinactive;
521 kprocchild(Proc *p, void (*entry)(void))
523 p->sched.pc = (uintptr) entry;
524 p->sched.sp = (uintptr) p->kstack + KSTACK;
528 forkchild(Proc *p, Ureg *ureg)
532 p->sched.pc = (uintptr) forkret;
533 p->sched.sp = (uintptr) p->kstack + KSTACK - sizeof(Ureg);
535 cureg = (Ureg*) p->sched.sp;
536 memmove(cureg, ureg, sizeof(Ureg));
541 execregs(uintptr entry, ulong ssize, ulong nargs)
546 sp = (ulong*)(USTKTOP - ssize);
550 ureg->sp = (uintptr) sp;
553 return USTKTOP-sizeof(Tos);