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);
153 user = userureg(ureg);
156 panic("user trap: up=nil");
165 if(okaddr(ureg->pc, 4, 0)){
166 opc = *(ulong*)ureg->pc;
167 if((opc & 0x0f000000) == 0x0e000000 || (opc & 0x0e000000) == 0x0c000000){
169 if(cp == 10 || cp == 11){
175 postnote(up, 1, "sys: trap: invalid opcode", NDebug);
179 panic("invalid opcode at pc=%#.8lux lr=%#.8lux", ureg->pc, ureg->r14);
183 faultarm(ureg, getifsr(), getifar());
187 faultarm(ureg, getdfsr(), getdfar());
194 iprint("cpu%d: unknown trap type %ulx\n", m->machno, ureg->type);
198 if(up->procctl || up->nnote)
204 #include "../port/systab.h"
214 vlong startns, stopns;
217 panic("syscall: pc=%#.8lux", ureg->pc);
227 up->scallnr = scallnr = ureg->r0;
234 if(sp < USTKTOP - BY2PG || sp > USTKTOP - sizeof(Sargs) - BY2WD){
235 validaddr(sp, sizeof(Sargs)+BY2WD, 0);
238 up->s = *((Sargs*) (sp + BY2WD));
240 if(up->procctl == Proc_tracesyscall){
241 syscallfmt(scallnr, ureg->pc, (va_list) up->s.args);
243 up->procctl = Proc_stopme;
246 startns = todget(nil);
249 if(scallnr >= nsyscall || systab[scallnr] == 0){
250 pprint("bad sys call number %lud pc %lux", scallnr, ureg->pc);
251 postnote(up, 1, "sys: bad sys call", NDebug);
254 up->psstate = sysctab[scallnr];
255 ret = systab[scallnr]((va_list)up->s.args);
259 up->syserrstr = up->errstr;
263 print("bad errstack [%lud]: %d extra\n", scallnr, up->nerrlab);
264 for(i = 0; i < NERR; i++)
265 print("sp=%lux pc=%lux\n", up->errlab[i].sp, up->errlab[i].pc);
266 panic("error stack");
270 if(up->procctl == Proc_tracesyscall){
271 stopns = todget(nil);
272 sysretfmt(scallnr, (va_list) up->s.args, ret, startns, stopns);
274 up->procctl = Proc_stopme;
282 noted(ureg, *((ulong *) up->s.args));
284 if(scallnr != RFORK && (up->procctl || up->nnote)){
306 if(up->fpstate == FPactive){
308 up->fpstate = FPinactive;
310 up->fpstate |= FPillegal;
316 if(strncmp(n->msg, "sys:", 4) == 0){
318 if(l > ERRMAX-15) /* " pc=0x12345678\0" */
320 sprint(n->msg+l, " pc=0x%.8lux", ureg->pc);
323 if(n->flag!=NUser && (up->notified || up->notify==0)){
325 if(n->flag == NDebug)
326 pprint("suicide: %s\n", n->msg);
327 pexit(n->msg, n->flag!=NDebug);
338 pexit(n->msg, n->flag!=NDebug);
341 sp -= 256; /* debugging: preserve context causing problem */
344 if(!okaddr((uintptr)up->notify, 1, 0)
345 || !okaddr(sp-ERRMAX-4*BY2WD, sizeof(Ureg)+ERRMAX+4*BY2WD, 1)
346 || ((uintptr) up->notify & 3) != 0
349 pprint("suicide: bad address in notify\n");
353 memmove((Ureg*)sp, ureg, sizeof(Ureg));
354 *(Ureg**)(sp-BY2WD) = up->ureg; /* word under Ureg is old up->ureg */
355 up->ureg = (void*)sp;
357 memmove((char*)sp, up->note[0].msg, ERRMAX);
359 *(ulong*)(sp+2*BY2WD) = sp+3*BY2WD;
360 *(ulong*)(sp+1*BY2WD) = (ulong)up->ureg;
361 ureg->r0 = (uintptr) up->ureg;
363 ureg->pc = (uintptr) up->notify;
367 memmove(&up->lastnote, &up->note[0], sizeof(Note));
368 memmove(&up->note[0], &up->note[1], up->nnote*sizeof(Note));
376 noted(Ureg *ureg, ulong arg0)
382 if(arg0 != NRSTR && !up->notified){
384 pprint("call to noted() when not notified\n");
390 up->fpstate &= ~FPillegal;
392 oureg = (ulong) nureg;
393 if(!okaddr(oureg - BY2WD, BY2WD + sizeof(Ureg), 0) || (oureg & 3) != 0){
395 pprint("bad ureg in noted or call to noted when not notified\n");
399 nureg->psr = nureg->psr & 0xf80f0000 | ureg->psr & 0x07f0ffff;
401 memmove(ureg, nureg, sizeof(Ureg));
404 case NCONT: case NRSTR:
405 if(!okaddr(nureg->pc, BY2WD, 0) || !okaddr(nureg->sp, BY2WD, 0) ||
406 (nureg->pc & 3) != 0 || (nureg->sp & 3) != 0){
408 pprint("suicide: trap in noted\n");
411 up->ureg = (Ureg *) (*(ulong *) (oureg - BY2WD));
416 if(!okaddr(nureg->pc, BY2WD, 0) || !okaddr(nureg->sp, BY2WD, 0) ||
417 (nureg->pc & 3) != 0 || (nureg->sp & 3) != 0){
419 pprint("suicide: trap in noted\n");
423 sp = oureg - 4 * BY2WD - ERRMAX;
426 ureg->r0 = (uintptr) oureg;
427 ((ulong *) sp)[1] = oureg;
428 ((ulong *) sp)[0] = 0;
432 up->lastnote.flag = NDebug;
436 if(up->lastnote.flag == NDebug)
437 pprint("suicide: %s\n", up->lastnote.msg);
438 pexit(up->lastnote.msg, up->lastnote.flag != NDebug);
446 callwithureg(_dumpstack);
452 iprint("trap: %lux psr %8.8lux type %2.2lux pc %8.8lux link %8.8lux\n",
453 ureg->type, ureg->psr, ureg->type, ureg->pc, ureg->link);
454 iprint("R14 %8.8lux R13 %8.8lux R12 %8.8lux R11 %8.8lux R10 %8.8lux\n",
455 ureg->r14, ureg->r13, ureg->r12, ureg->r11, ureg->r10);
456 iprint("R9 %8.8lux R8 %8.8lux R7 %8.8lux R6 %8.8lux R5 %8.8lux\n",
457 ureg->r9, ureg->r8, ureg->r7, ureg->r6, ureg->r5);
458 iprint("R4 %8.8lux R3 %8.8lux R2 %8.8lux R1 %8.8lux R0 %8.8lux\n",
459 ureg->r4, ureg->r3, ureg->r2, ureg->r1, ureg->r0);
460 iprint("pc %#lux link %#lux\n", ureg->pc, ureg->link);
464 setkernur(Ureg *ureg, Proc *p)
466 ureg->pc = p->sched.pc;
467 ureg->sp = p->sched.sp + 4;
468 ureg->r14 = (uintptr) sched;
472 setregisters(Ureg* ureg, char* pureg, char* uva, int n)
477 memmove(pureg, uva, n);
478 ureg->psr = ureg->psr & 0xf80f0000 | v & 0x07f0ffff;
482 callwithureg(void (*f) (Ureg *))
486 u.pc = getcallerpc(&f);
487 u.sp = (uintptr) &f - 4;
516 if(p->fpstate == FPactive){
517 if(p->state == Moribund)
521 p->fpstate = FPinactive;
547 up->kpfun(up->kparg);
548 pexit("kproc dying", 0);
552 kprocchild(Proc* p, void (*func)(void*), void* arg)
554 p->sched.pc = (uintptr) linkproc;
555 p->sched.sp = (uintptr) p->kstack + KSTACK;
562 forkchild(Proc *p, Ureg *ureg)
566 p->sched.pc = (uintptr) forkret;
567 p->sched.sp = (uintptr) p->kstack + KSTACK - sizeof(Ureg);
569 cureg = (Ureg*) p->sched.sp;
570 memmove(cureg, ureg, sizeof(Ureg));
575 execregs(uintptr entry, ulong ssize, ulong nargs)
580 sp = (ulong*)(USTKTOP - ssize);
584 ureg->sp = (uintptr) sp;
587 return USTKTOP-sizeof(Tos);