]> git.lizzy.rs Git - plan9front.git/blob - sys/src/9/bcm64/trap.c
bcm64: use exclusive monitor on nrdy to wake up idlehands()
[plan9front.git] / sys / src / 9 / bcm64 / trap.c
1 #include "u.h"
2 #include "../port/lib.h"
3 #include "mem.h"
4 #include "dat.h"
5 #include "fns.h"
6 #include "../port/error.h"
7 #include "../port/systab.h"
8
9 #include <tos.h>
10 #include "ureg.h"
11 #include "sysreg.h"
12
13 /* SPSR bits user can modify */
14 #define USPSRMASK       (0xFULL<<28)
15
16 static void
17 setupvector(u32int *v, void (*t)(void), void (*f)(void))
18 {
19         int i;
20
21         for(i = 0; i < 0x80/4; i++){
22                 v[i] = ((u32int*)t)[i];
23                 if(v[i] == 0x14000000){
24                         v[i] |= ((u32int*)f - &v[i]) & 0x3ffffff;
25                         return;
26                 }
27         }
28         panic("bug in vector code");
29 }
30
31 void
32 trapinit(void)
33 {
34         extern void vsys(void);
35         extern void vtrap(void);
36         extern void virq(void);
37         extern void vfiq(void);
38         extern void vserr(void);
39
40         extern void vsys0(void);
41         extern void vtrap0(void);
42         extern void vtrap1(void);
43
44         static u32int *v;
45
46         intrcpushutdown();
47         if(v == nil){
48                 /* disable everything */
49                 intrsoff();
50
51                 v = mallocalign(0x80*4*4, 1<<11, 0, 0);
52                 if(v == nil)
53                         panic("no memory for vector table");
54
55                 setupvector(&v[0x000/4], vtrap, vtrap0);
56                 setupvector(&v[0x080/4], virq,  vtrap0);
57                 setupvector(&v[0x100/4], vfiq,  vtrap0);
58                 setupvector(&v[0x180/4], vserr, vtrap0);
59
60                 setupvector(&v[0x200/4], vtrap, vtrap1);
61                 setupvector(&v[0x280/4], virq,  vtrap1);
62                 setupvector(&v[0x300/4], vfiq,  vtrap1);
63                 setupvector(&v[0x380/4], vserr, vtrap1);
64
65                 setupvector(&v[0x400/4], vsys,  vsys0);
66                 setupvector(&v[0x480/4], virq,  vtrap0);
67                 setupvector(&v[0x500/4], vfiq,  vtrap0);
68                 setupvector(&v[0x580/4], vserr, vtrap0);
69
70                 setupvector(&v[0x600/4], vtrap, vtrap0);
71                 setupvector(&v[0x680/4], virq,  vtrap0);
72                 setupvector(&v[0x700/4], vfiq,  vtrap0);
73                 setupvector(&v[0x780/4], vserr, vtrap0);
74
75                 cacheduwbse(v, 0x80*4*4);
76         }
77         cacheiinvse(v, 0x80*4*4);
78         syswr(VBAR_EL1, (uintptr)v);
79         splx(0x3<<6);   // unmask serr and debug
80 }
81
82 void
83 kexit(Ureg*)
84 {
85         Tos *tos;
86         uvlong t;
87
88         t = cycles();
89
90         tos = (Tos*)(USTKTOP-sizeof(Tos));
91         tos->kcycles += t - up->kentry;
92         tos->pcycles = t + up->pcycles;
93         tos->pid = up->pid;
94 }
95
96 static char *traps[64] = {
97         [0x00]  "sys: trap: unknown",
98         [0x01]  "sys: trap: WFI or WFE instruction execution",
99         [0x0E]  "sys: trap: illegal execution state",
100         [0x18]  "sys: trap: illegal MSR/MRS access",
101         [0x22]  "sys: trap: misaligned pc",
102         [0x26]  "sys: trap: stack pointer misaligned",
103         [0x30]  "sys: trap: breakpoint",
104         [0x32]  "sys: trap: software step",
105         [0x34]  "sys: trap: watchpoint",
106         [0x3C]  "sys: trap: BRK instruction",
107 };
108
109 void
110 trap(Ureg *ureg)
111 {
112         u32int type, intr;
113         
114         intr = ureg->type >> 32;
115         if(intr == 2){
116                 fiq(ureg);
117                 return;
118         }
119         splflo();
120         if(userureg(ureg)){
121                 up->dbgreg = ureg;
122                 up->kentry = cycles();
123         }
124         type = (u32int)ureg->type >> 26;
125         switch(type){
126         case 0x20:      // instruction abort from lower level
127         case 0x21:      // instruction abort from same level
128         case 0x24:      // data abort from lower level
129         case 0x25:      // data abort from same level
130                 faultarm64(ureg);
131                 break;
132         case 0x07:      // SIMD/FP
133         case 0x2C:      // FPU exception (A64 only)
134                 mathtrap(ureg);
135                 break;
136         case 0x00:      // unknown
137                 if(intr == 1){
138                         if(irq(ureg) && up != nil && up->delaysched)
139                                 sched();
140                         break;
141                 }
142                 if(intr == 3){
143         case 0x2F:      // SError interrupt
144                         dumpregs(ureg);
145                         panic("SError interrupt");
146                         break;
147                 }
148                 /* wet floor */
149         case 0x01:      // WFI or WFE instruction execution
150         case 0x03:      // MCR or MRC access to CP15 (A32 only)
151         case 0x04:      // MCRR or MRC access to CP15 (A32 only)
152         case 0x05:      // MCR or MRC access to CP14 (A32 only)
153         case 0x06:      // LDC or STD access to CP14 (A32 only)
154         case 0x08:      // MCR or MRC to CP10 (A32 only)
155         case 0x0C:      // MRC access to CP14 (A32 only)
156         case 0x0E:      // Illegal Execution State
157         case 0x11:      // SVC instruction execution (A32 only)
158         case 0x12:      // HVC instruction execution (A32 only)
159         case 0x13:      // SMC instruction execution (A32 only)
160         case 0x15:      // SVC instruction execution (A64 only)
161         case 0x16:      // HVC instruction execution (A64 only)
162         case 0x17:      // SMC instruction execution (A64 only)
163         case 0x18:      // MSR/MRS (A64)
164         case 0x22:      // misaligned pc
165         case 0x26:      // stack pointer misaligned
166         case 0x28:      // FPU exception (A32 only)
167         case 0x30:      // breakpoint from lower level
168         case 0x31:      // breakpoint from same level
169         case 0x32:      // software step from lower level
170         case 0x33:      // software step from same level
171         case 0x34:      // watchpoint execution from lower level
172         case 0x35:      // watchpoint exception from same level
173         case 0x38:      // breapoint (A32 only)
174         case 0x3A:      // vector catch exception (A32 only)
175         case 0x3C:      // BRK instruction (A64 only)
176         default:
177                 if(!userureg(ureg)){
178                         dumpregs(ureg);
179                         panic("unhandled trap");
180                 }
181                 if(traps[type] == nil) type = 0;        // unknown
182                 postnote(up, 1, traps[type], NDebug);
183                 break;
184         }
185         splhi();
186         if(userureg(ureg)){
187                 if(up->procctl || up->nnote)
188                         notify(ureg);
189                 kexit(ureg);
190         }
191 }
192
193 void
194 syscall(Ureg *ureg)
195 {
196         vlong startns, stopns;
197         uintptr sp, ret;
198         ulong scallnr;
199         int i, s;
200         char *e;
201
202         up->kentry = cycles();
203         
204         m->syscall++;
205         up->insyscall = 1;
206         up->pc = ureg->pc;
207         up->dbgreg = ureg;
208         
209         sp = ureg->sp;
210         up->scallnr = scallnr = ureg->r0;
211
212         spllo();
213         
214         up->nerrlab = 0;
215         startns = 0;
216         ret = -1;
217         if(!waserror()){
218                 if(sp < USTKTOP - BY2PG || sp > USTKTOP - sizeof(Sargs) - BY2WD){
219                         validaddr(sp, sizeof(Sargs)+BY2WD, 0);
220                         evenaddr(sp);
221                 }
222                 up->s = *((Sargs*) (sp + BY2WD));
223
224                 if(up->procctl == Proc_tracesyscall){
225                         syscallfmt(scallnr, ureg->pc, (va_list) up->s.args);
226                         s = splhi();
227                         up->procctl = Proc_stopme;
228                         procctl();
229                         splx(s);
230                         startns = todget(nil);
231                 }
232                 
233                 if(scallnr >= nsyscall || systab[scallnr] == nil){
234                         pprint("bad sys call number %lud pc %#p", scallnr, ureg->pc);
235                         postnote(up, 1, "sys: bad sys call", NDebug);
236                         error(Ebadarg);
237                 }
238                 up->psstate = sysctab[scallnr];
239                 ret = systab[scallnr]((va_list)up->s.args);
240                 poperror();
241         }else{
242                 e = up->syserrstr;
243                 up->syserrstr = up->errstr;
244                 up->errstr = e;
245         }
246         if(up->nerrlab){
247                 print("bad errstack [%lud]: %d extra\n", scallnr, up->nerrlab);
248                 for(i = 0; i < NERR; i++)
249                         print("sp=%#p pc=%#p\n", up->errlab[i].sp, up->errlab[i].pc);
250                 panic("error stack");
251         }
252         ureg->r0 = ret;
253         if(up->procctl == Proc_tracesyscall){
254                 stopns = todget(nil);
255                 sysretfmt(scallnr, (va_list) up->s.args, ret, startns, stopns);
256                 s = splhi();
257                 up->procctl = Proc_stopme;
258                 procctl();
259                 splx(s);
260         }
261         
262         up->insyscall = 0;
263         up->psstate = 0;
264         if(scallnr == NOTED){
265                 noted(ureg, *((ulong*) up->s.args));
266                 /*
267                  * normally, syscall() returns to forkret()
268                  * not restoring general registers when going
269                  * to userspace. to completely restore the
270                  * interrupted context, we have to return thru
271                  * noteret(). we override return pc to jump to
272                  * to it when returning form syscall()
273                  */
274                 returnto(noteret);
275         }
276
277         if(scallnr != RFORK && (up->procctl || up->nnote)){
278                 splhi();
279                 notify(ureg);
280         }
281         if(up->delaysched)
282                 sched();
283         kexit(ureg);
284 }
285
286 int
287 notify(Ureg *ureg)
288 {
289         int l;
290         uintptr s, sp;
291         Note *n;
292
293         if(up->procctl)
294                 procctl();
295         if(up->nnote == 0)
296                 return 0;
297         if(up->fpstate == FPactive){
298                 fpsave(up->fpsave);
299                 up->fpstate = FPinactive;
300         }
301         up->fpstate |= FPillegal;
302
303         s = spllo();
304         qlock(&up->debug);
305         up->notepending = 0;
306         n = &up->note[0];
307         if(strncmp(n->msg, "sys:", 4) == 0){
308                 l = strlen(n->msg);
309                 if(l > ERRMAX-23)       /* " pc=0x0123456789abcdef\0" */
310                         l = ERRMAX-23;
311                 sprint(n->msg+l, " pc=%#p", ureg->pc);
312         }
313
314         if(n->flag!=NUser && (up->notified || up->notify==0)){
315                 qunlock(&up->debug);
316                 if(n->flag == NDebug)
317                         pprint("suicide: %s\n", n->msg);
318                 pexit(n->msg, n->flag!=NDebug);
319         }
320
321         if(up->notified){
322                 qunlock(&up->debug);
323                 splhi();
324                 return 0;
325         }
326
327         if(!up->notify){
328                 qunlock(&up->debug);
329                 pexit(n->msg, n->flag!=NDebug);
330         }
331         sp = ureg->sp;
332         sp -= 256;      /* debugging: preserve context causing problem */
333         sp -= sizeof(Ureg);
334         sp = STACKALIGN(sp);
335
336         if(!okaddr((uintptr)up->notify, 1, 0)
337         || !okaddr(sp-ERRMAX-4*BY2WD, sizeof(Ureg)+ERRMAX+4*BY2WD, 1)
338         || ((uintptr) up->notify & 3) != 0
339         || (sp & 7) != 0){
340                 qunlock(&up->debug);
341                 pprint("suicide: bad address in notify: handler=%#p sp=%#p\n",
342                         up->notify, sp);
343                 pexit("Suicide", 0);
344         }
345
346         memmove((Ureg*)sp, ureg, sizeof(Ureg));
347         *(Ureg**)(sp-BY2WD) = up->ureg; /* word under Ureg is old up->ureg */
348         up->ureg = (void*)sp;
349         sp -= BY2WD+ERRMAX;
350         memmove((char*)sp, up->note[0].msg, ERRMAX);
351         sp -= 3*BY2WD;
352         *(uintptr*)(sp+2*BY2WD) = sp+3*BY2WD;
353         *(uintptr*)(sp+1*BY2WD) = (uintptr)up->ureg;
354         ureg->r0 = (uintptr) up->ureg;
355         ureg->sp = sp;
356         ureg->pc = (uintptr) up->notify;
357         ureg->link = 0;
358         up->notified = 1;
359         up->nnote--;
360         memmove(&up->lastnote, &up->note[0], sizeof(Note));
361         memmove(&up->note[0], &up->note[1], up->nnote*sizeof(Note));
362
363         qunlock(&up->debug);
364         splx(s);
365         return 1;
366 }
367
368 void
369 noted(Ureg *ureg, ulong arg0)
370 {
371         Ureg *nureg;
372         uintptr oureg, sp;
373         
374         qlock(&up->debug);
375         if(arg0 != NRSTR && !up->notified){
376                 qunlock(&up->debug);
377                 pprint("call to noted() when not notified\n");
378                 pexit("Suicide", 0);
379         }
380         up->notified = 0;
381         
382         nureg = up->ureg;
383         up->fpstate &= ~FPillegal;
384         
385         oureg = (uintptr) nureg;
386         if(!okaddr(oureg - BY2WD, BY2WD + sizeof(Ureg), 0) || (oureg & 7) != 0){
387                 qunlock(&up->debug);
388                 pprint("bad ureg in noted or call to noted when not notified\n");
389                 pexit("Suicide", 0);
390         }
391
392         nureg->psr = (nureg->psr & USPSRMASK) | (ureg->psr & ~USPSRMASK);
393         memmove(ureg, nureg, sizeof(Ureg));
394         
395         switch(arg0){
396         case NCONT: case NRSTR:
397                 if(!okaddr(nureg->pc, BY2WD, 0) || !okaddr(nureg->sp, BY2WD, 0) ||
398                                 (nureg->pc & 3) != 0 || (nureg->sp & 7) != 0){
399                         qunlock(&up->debug);
400                         pprint("suicide: trap in noted\n");
401                         pexit("Suicide", 0);
402                 }
403                 up->ureg = (Ureg *) (*(uintptr*) (oureg - BY2WD));
404                 qunlock(&up->debug);
405                 break;
406         
407         case NSAVE:
408                 if(!okaddr(nureg->pc, BY2WD, 0) || !okaddr(nureg->sp, BY2WD, 0) ||
409                                 (nureg->pc & 3) != 0 || (nureg->sp & 7) != 0){
410                         qunlock(&up->debug);
411                         pprint("suicide: trap in noted\n");
412                         pexit("Suicide", 0);
413                 }
414                 qunlock(&up->debug);
415                 sp = oureg - 4 * BY2WD - ERRMAX;
416                 splhi();
417                 ureg->sp = sp;
418                 ureg->r0 = (uintptr) oureg;
419                 ((uintptr *) sp)[1] = oureg;
420                 ((uintptr *) sp)[0] = 0;
421                 break;
422         
423         default:
424                 up->lastnote.flag = NDebug;
425         
426         case NDFLT:
427                 qunlock(&up->debug);
428                 if(up->lastnote.flag == NDebug)
429                         pprint("suicide: %s\n", up->lastnote.msg);
430                 pexit(up->lastnote.msg, up->lastnote.flag != NDebug);
431         }
432 }
433
434 void
435 faultarm64(Ureg *ureg)
436 {
437         extern void checkpages(void);
438         char buf[ERRMAX];
439         int read, insyscall;
440         uintptr addr;
441
442         insyscall = up->insyscall;
443         up->insyscall = 1;
444
445         if(!userureg(ureg) && waserror()){
446                 if(up->nerrlab == 0){
447                         pprint("suicide: sys: %s\n", up->errstr);
448                         pexit(up->errstr, 1);
449                 }
450                 up->insyscall = insyscall;
451                 nexterror();
452         }
453
454         addr = getfar();
455         read = (ureg->type & (1<<6)) == 0;
456
457         switch((u32int)ureg->type & 0x3F){
458         case  4: case  5: case  6: case  7:     // Tanslation fault.
459         case  8: case  9: case 10: case 11:     // Access flag fault.
460         case 12: case 13: case 14: case 15:     // Permission fault.
461         case 48:                                // tlb conflict fault.
462                 if(fault(addr, read) == 0)
463                         break;
464
465                 /* wet floor */
466         case  0: case  1: case  2: case  3:     // Address size fault.
467         case 16:                                // synchronous external abort.
468         case 24:                                // synchronous parity error on a memory access.
469         case 20: case 21: case 22: case 23:     // synchronous external abort on a table walk.
470         case 28: case 29: case 30: case 31:     // synchronous parity error on table walk.
471         case 33:                                // alignment fault.
472         case 52:                                // implementation defined, lockdown abort.
473         case 53:                                // implementation defined, unsuppoted exclusive.
474         case 61:                                // first level domain fault
475         case 62:                                // second level domain fault
476         default:
477                 if(!userureg(ureg)){
478                         dumpregs(ureg);
479                         panic("fault: %s addr=%#p", read ? "read" : "write", addr);
480                 }
481                 checkpages();
482                 sprint(buf, "sys: trap: fault %s addr=%#p", read ? "read" : "write", addr);
483                 postnote(up, 1, buf, NDebug);
484         }
485
486         if(!userureg(ureg))
487                 poperror();
488
489         up->insyscall = insyscall;
490 }
491
492 int
493 userureg(Ureg* ureg)
494 {
495         return (ureg->psr & 15) == 0;
496 }
497
498 uintptr
499 userpc(void)
500 {
501         Ureg *ur = up->dbgreg;
502         return ur->pc;
503 }
504
505 uintptr
506 dbgpc(Proc *)
507 {
508         Ureg *ur = up->dbgreg;
509         if(ur == nil)
510                 return 0;
511         return ur->pc;
512 }
513
514 void
515 procfork(Proc *p)
516 {
517         int s;
518
519         s = splhi();
520         switch(up->fpstate & ~FPillegal){
521         case FPactive:
522                 fpsave(up->fpsave);
523                 up->fpstate = FPinactive;
524         case FPinactive:
525                 memmove(p->fpsave, up->fpsave, sizeof(FPsave));
526                 p->fpstate = FPinactive;
527         }
528         splx(s);
529
530         p->tpidr = up->tpidr;
531
532         p->kentry = up->kentry;
533         p->pcycles = -p->kentry;
534 }
535
536 void
537 procsetup(Proc *p)
538 {
539         p->fpstate = FPinit;
540         fpoff();
541
542         p->tpidr = 0;
543         syswr(TPIDR_EL0, p->tpidr);
544
545         p->kentry = cycles();
546         p->pcycles = -p->kentry;
547 }
548
549 void
550 procsave(Proc *p)
551 {
552         uvlong t;
553
554         if(p->fpstate == FPactive){
555                 if(p->state == Moribund)
556                         fpclear();
557                 else
558                         fpsave(p->fpsave);
559                 p->fpstate = FPinactive;
560         }
561
562         if(p->kp == 0)
563                 p->tpidr = sysrd(TPIDR_EL0);
564
565         putasid(p);     // release asid
566
567         t = cycles();
568         p->kentry -= t;
569         p->pcycles += t;
570 }
571
572 void
573 procrestore(Proc *p)
574 {
575         uvlong t;
576
577         if(p->kp)
578                 return;
579         
580         syswr(TPIDR_EL0, p->tpidr);
581
582         t = cycles();
583         p->kentry += t;
584         p->pcycles -= t;
585 }
586
587 static void
588 linkproc(void)
589 {
590         spllo();
591         up->kpfun(up->kparg);
592         pexit("kproc dying", 0);
593 }
594
595 void
596 kprocchild(Proc* p, void (*func)(void*), void* arg)
597 {
598         p->sched.pc = (uintptr) linkproc;
599         p->sched.sp = (uintptr) p->kstack + KSTACK - 16;
600         *(void**)p->sched.sp = kprocchild;      /* fake */
601
602         p->kpfun = func;
603         p->kparg = arg;
604 }
605
606 void
607 forkchild(Proc *p, Ureg *ureg)
608 {
609         Ureg *cureg;
610
611         p->sched.pc = (uintptr) forkret;
612         p->sched.sp = (uintptr) p->kstack + KSTACK - TRAPFRAMESIZE;
613
614         cureg = (Ureg*) (p->sched.sp + 16);
615         memmove(cureg, ureg, sizeof(Ureg));
616         cureg->r0 = 0;
617
618         p->psstate = 0;
619         p->insyscall = 0;
620 }
621
622 uintptr
623 execregs(uintptr entry, ulong ssize, ulong nargs)
624 {
625         uintptr *sp;
626         Ureg *ureg;
627
628         sp = (uintptr*)(USTKTOP - ssize);
629         *--sp = nargs;
630
631         ureg = up->dbgreg;
632         ureg->sp = (uintptr)sp;
633         ureg->pc = entry;
634         ureg->link = 0;
635         return USTKTOP-sizeof(Tos);
636 }
637
638 void
639 evenaddr(uintptr addr)
640 {
641         if(addr & 3){
642                 postnote(up, 1, "sys: odd address", NDebug);
643                 error(Ebadarg);
644         }
645 }
646
647 void
648 callwithureg(void (*f) (Ureg *))
649 {
650         Ureg u;
651         
652         u.pc = getcallerpc(&f);
653         u.sp = (uintptr) &f;
654         f(&u);
655 }
656
657 void
658 setkernur(Ureg *ureg, Proc *p)
659 {
660         ureg->pc = p->sched.pc;
661         ureg->sp = p->sched.sp;
662         ureg->link = (uintptr)sched;
663 }
664
665 void
666 setupwatchpts(Proc*, Watchpt*, int)
667 {
668 }
669
670 void
671 setregisters(Ureg* ureg, char* pureg, char* uva, int n)
672 {
673         ulong v;
674
675         v = ureg->psr;
676         memmove(pureg, uva, n);
677         ureg->psr = (ureg->psr & USPSRMASK) | (v & ~USPSRMASK);
678 }
679
680 static void
681 dumpstackwithureg(Ureg *ureg)
682 {
683         uintptr v, estack, sp;
684         char *s;
685         int i;
686
687         if((s = getconf("*nodumpstack")) != nil && strcmp(s, "0") != 0){
688                 iprint("dumpstack disabled\n");
689                 return;
690         }
691         iprint("ktrace /kernel/path %#p %#p %#p # pc, sp, link\n",
692                 ureg->pc, ureg->sp, ureg->link);
693         delay(2000);
694
695         sp = ureg->sp;
696         if(sp < KZERO || (sp & 7) != 0)
697                 sp = (uintptr)&ureg;
698
699         estack = (uintptr)m+MACHSIZE;
700         if(up != nil && sp <= (uintptr)up->kstack+KSTACK)
701                 estack = (uintptr)up->kstack+KSTACK;
702
703         if(sp > estack){
704                 if(up != nil)
705                         iprint("&up->kstack %#p sp %#p\n", up->kstack, sp);
706                 else
707                         iprint("&m %#p sp %#p\n", m, sp);
708                 return;
709         }
710
711         i = 0;
712         for(; sp < estack; sp += sizeof(uintptr)){
713                 v = *(uintptr*)sp;
714                 if(KTZERO < v && v < (uintptr)etext && (v & 3) == 0){
715                         iprint("%#8.8lux=%#8.8lux ", (ulong)sp, (ulong)v);
716                         i++;
717                 }
718                 if(i == 4){
719                         i = 0;
720                         iprint("\n");
721                 }
722         }
723         if(i)
724                 iprint("\n");
725 }
726
727 void
728 dumpstack(void)
729 {
730         callwithureg(dumpstackwithureg);
731 }
732
733 void
734 dumpregs(Ureg *ureg)
735 {
736         u64int *r;
737         int i, x;
738
739         x = splhi();
740         if(up != nil)
741                 iprint("cpu%d: dumpregs ureg %#p process %lud: %s\n", m->machno, ureg,
742                         up->pid, up->text);
743         else
744                 iprint("cpu%d: dumpregs ureg %#p\n", m->machno, ureg);
745         r = &ureg->r0;
746         for(i = 0; i < 30; i += 3)
747                 iprint("R%d %.16llux  R%d %.16llux  R%d %.16llux\n", i, r[i], i+1, r[i+1], i+2, r[i+2]);
748         iprint("PC %#p  SP %#p  LR %#p  PSR %llux  TYPE %llux\n",
749                 ureg->pc, ureg->sp, ureg->link,
750                 ureg->psr, ureg->type);
751         splx(x);
752 }