FreeBSD/Linux Kernel Cross Reference
sys/ppc/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 "ureg.h"
7 #include "../port/error.h"
8 #include "tos.h"
9 #include <trace.h>
10
11 static Lock vctllock;
12 Vctl *vctl[256];
13
14 void
15 intrenable(int irq, void (*f)(Ureg*, void*), void* a, char *name)
16 {
17 int vno;
18 Vctl *v;
19
20 if(f == nil){
21 print("intrenable: nil handler for %d for %s\n",
22 irq, name);
23 return;
24 }
25
26 v = xalloc(sizeof(Vctl));
27 v->isintr = 1;
28 v->irq = irq;
29 v->f = f;
30 v->a = a;
31 strncpy(v->name, name, KNAMELEN-1);
32 v->name[KNAMELEN-1] = 0;
33
34 ilock(&vctllock);
35 vno = vectorenable(v);
36 if(vno == -1){
37 iunlock(&vctllock);
38 print("intrenable: couldn't enable irq %d for %s\n",
39 irq, v->name);
40 xfree(v);
41 return;
42 }
43 v->next = vctl[vno];
44 vctl[vno] = v;
45 iunlock(&vctllock);
46 }
47
48 void
49 intrdisable(int irq, void (*f)(Ureg *, void *), void *a, char *name)
50 {
51 Vctl **pv, *v;
52
53 ilock(&vctllock);
54 pv = &vctl[irq];
55 while (*pv &&
56 ((*pv)->irq != irq || (*pv)->f != f || (*pv)->a != a ||
57 strcmp((*pv)->name, name)))
58 pv = &((*pv)->next);
59
60 if(*pv == nil){
61 print("intrdisable: irq %d not found\n", irq);
62 iunlock(&vctllock);
63 return;
64 }
65
66 v = *pv;
67 *pv = (*pv)->next; /* Link out the entry */
68
69 if(vctl[irq] == nil)
70 vectordisable(v);
71 iunlock(&vctllock);
72 xfree(v);
73 }
74
75 void syscall(Ureg*);
76 void noted(Ureg*, ulong);
77 static void _dumpstack(Ureg*);
78
79 char *excname[] =
80 {
81 "reserved 0",
82 "system reset",
83 "machine check",
84 "data access",
85 "instruction access",
86 "external interrupt",
87 "alignment",
88 "program exception",
89 "floating-point unavailable",
90 "decrementer",
91 "reserved A",
92 "reserved B",
93 "system call",
94 "trace trap",
95 "floating point assist",
96 "reserved F",
97 "reserved 10",
98 "data load translation miss",
99 "data store translation miss",
100 "instruction address breakpoint",
101 "system management interrupt",
102 };
103
104 char *fpcause[] =
105 {
106 "inexact operation",
107 "division by zero",
108 "underflow",
109 "overflow",
110 "invalid operation",
111 };
112 char *fpexcname(Ureg*, ulong, char*);
113 #define FPEXPMASK 0xfff80300 /* Floating exception bits in fpscr */
114
115
116 char *regname[]={
117 "CAUSE", "SRR1",
118 "PC", "GOK",
119 "LR", "CR",
120 "XER", "CTR",
121 "R0", "R1",
122 "R2", "R3",
123 "R4", "R5",
124 "R6", "R7",
125 "R8", "R9",
126 "R10", "R11",
127 "R12", "R13",
128 "R14", "R15",
129 "R16", "R17",
130 "R18", "R19",
131 "R20", "R21",
132 "R22", "R23",
133 "R24", "R25",
134 "R26", "R27",
135 "R28", "R29",
136 "R30", "R31",
137 "DCMP", "ICMP",
138 "DMISS", "IMISS",
139 "HASH1", "HASH2",
140 "DAR", "DSISR",
141 };
142
143 void
144 kexit(Ureg*)
145 {
146 uvlong t;
147 Tos *tos;
148
149 /* precise time accounting, kernel exit */
150 tos = (Tos*)(USTKTOP-sizeof(Tos));
151 cycles(&t);
152 tos->kcycles += t - up->kentry;
153 tos->pcycles = up->pcycles;
154 tos->pid = up->pid;
155 }
156
157 void
158 trap(Ureg *ureg)
159 {
160 int ecode, user;
161 char buf[ERRMAX], *s;
162 extern FPsave initfp;
163
164 ecode = (ureg->cause >> 8) & 0xff;
165 user = (ureg->srr1 & MSR_PR) != 0;
166 if(user){
167 cycles(&up->kentry);
168 up->dbgreg = ureg;
169 }
170 if(ureg->status & MSR_RI == 0)
171 print("double fault?: ecode = %d\n", ecode);
172
173 switch(ecode) {
174 case CEI:
175 m->intr++;
176 intr(ureg);
177 break;
178 case CDEC:
179 clockintr(ureg);
180 break;
181 case CDSI:
182 m->pfault++;
183 if (up == nil){
184 dumpregs(ureg);
185 panic("kernel fault");
186 }
187 up->mmureg = ureg;
188 faultpower(ureg, ureg->dar, (ureg->dsisr & BIT(6)) == 0);
189 break;
190 case CISI:
191 m->pfault++;
192 if (up == nil){
193 dumpregs(ureg);
194 panic("kernel fault");
195 }
196 up->mmureg = ureg;
197 faultpower(ureg, ureg->pc, 1);
198 break;
199 case CIMISS: /* instruction miss */
200 if (up == nil){
201 dumpregs(ureg);
202 panic("kernel fault");
203 }
204 up->mmureg = ureg;
205 faultpower(ureg, ureg->imiss, 1);
206 break;
207 case CLMISS: /* data load miss */
208 if (up == nil){
209 dumpregs(ureg);
210 panic("kernel fault");
211 }
212 up->mmureg = ureg;
213 faultpower(ureg, ureg->dmiss, 1);
214 break;
215 case CSMISS: /* data store miss */
216 if (up == nil){
217 dumpregs(ureg);
218 panic("kernel fault");
219 }
220 up->mmureg = ureg;
221 faultpower(ureg, ureg->dmiss, 0);
222 break;
223
224 case CSYSCALL:
225 if(!user)
226 panic("syscall in kernel: srr1 0x%4.4luX\n", ureg->srr1);
227 syscall(ureg);
228 if (up->delaysched){
229 sched();
230 splhi();
231 }
232 kexit(ureg);
233 return; /* syscall() calls notify itself, don't do it again */
234
235 case CFPU:
236 if(!user || up == nil) {
237 dumpregs(ureg);
238 panic("floating point in kernel");
239 }
240 switch(up->fpstate){
241 case FPinit:
242 fprestore(&initfp);
243 up->fpstate = FPactive;
244 break;
245 case FPinactive:
246 fprestore(&up->fpsave);
247 up->fpstate = FPactive;
248 break;
249 case FPactive:
250 print("up->fpstate %d\n", up->fpstate);
251 delay(100);
252 dumpregs(ureg);
253 delay(200);
254 panic("fpstate");
255 break;
256 default:
257 if(user){
258 spllo();
259 sprint(buf, "sys: floating point in note handler:");
260 postnote(up, 1, buf, NDebug);
261 break;
262 }
263 panic("kernel fpstate illegal");
264 }
265 ureg->srr1 |= MSR_FP;
266 break;
267 case CPROG:
268 if(ureg->status & (1<<19))
269 s = "floating point exception";
270 else if(ureg->status & (1<<18))
271 s = "illegal instruction";
272 else if(ureg->status & (1<<17))
273 s = "privileged instruction";
274 else
275 s = "undefined program exception";
276 if(user){
277 spllo();
278 sprint(buf, "sys: trap: %s", s);
279 postnote(up, 1, buf, NDebug);
280 break;
281 }
282 dumpregs(ureg);
283 panic(s);
284 break;
285 default:
286 if(ecode < nelem(excname) && user){
287 spllo();
288 sprint(buf, "sys: trap: %s", excname[ecode]);
289 postnote(up, 1, buf, NDebug);
290 break;
291 }
292 dumpregs(ureg);
293 if(ecode < nelem(excname))
294 panic("%s", excname[ecode]);
295 panic("unknown trap/intr: %d\n", ecode);
296 }
297
298 /* restoreureg must execute at high IPL */
299 splhi();
300
301 /* delaysched set because we held a lock or because our quantum ended */
302 if(up && up->delaysched && ecode == CDEC){
303 sched();
304 splhi();
305 }
306
307 if(user) {
308 if (up->fpstate == FPactive && (ureg->srr1 & MSR_FP) == 0){
309 postnote(up, 1, buf, NDebug);
310 }
311 notify(ureg);
312 if(up->fpstate != FPactive)
313 ureg->srr1 &= ~MSR_FP;
314 kexit(ureg);
315 }
316 }
317
318 void
319 faultpower(Ureg *ureg, ulong addr, int read)
320 {
321 int user, insyscall, n;
322 char buf[ERRMAX];
323
324 user = (ureg->srr1 & MSR_PR) != 0;
325 insyscall = up->insyscall;
326 up->insyscall = 1;
327 n = fault(addr, read);
328 if(n < 0){
329 if(!user){
330 dumpregs(ureg);
331 panic("fault: 0x%lux", addr);
332 }
333 sprint(buf, "sys: trap: fault %s addr=0x%lux", read? "read" : "write", addr);
334 postnote(up, 1, buf, NDebug);
335 }
336 up->insyscall = insyscall;
337 }
338
339 void
340 sethvec(int v, void (*r)(void))
341 {
342 ulong *vp, pa, o;
343
344 vp = KADDR(v);
345 vp[0] = 0x7c1043a6; /* MOVW R0, SPR(SPRG0) */
346 vp[1] = 0x7c0802a6; /* MOVW LR, R0 */
347 vp[2] = 0x7c1243a6; /* MOVW R0, SPR(SPRG2) */
348 pa = PADDR(r);
349 o = pa >> 25;
350 if(o != 0 && o != 0x7F){
351 /* a branch too far */
352 vp[3] = (15<<26)|(pa>>16); /* MOVW $r&~0xFFFF, R0 */
353 vp[4] = (24<<26)|(pa&0xFFFF); /* OR $r&0xFFFF, R0 */
354 vp[5] = 0x7c0803a6; /* MOVW R0, LR */
355 vp[6] = 0x4e800021; /* BL (LR) */
356 }else
357 vp[3] = (18<<26)|(pa&0x3FFFFFC)|3; /* bla */
358 }
359
360 void
361 setmvec(int v, void (*r)(void), void (*t)(void))
362 {
363 ulong *vp, pa, o, n;
364
365 vp = KADDR(v);
366 n = 0;
367 vp[n++] = 0x7c1043a6; /* MOVW R0, SPR(SPRG0) */
368 vp[n++] = 0x7c0802a6; /* MOVW LR, R0 */
369 vp[n++] = 0x7c1243a6; /* MOVW R0, SPR(SPRG2) */
370 pa = PADDR(r);
371 o = pa >> 25;
372 if(o != 0 && o != 0x7F){
373 /* a branch too far */
374 vp[n++] = (15<<26)|(pa>>16); /* MOVW $r&~0xFFFF, R0 */
375 vp[n++] = (24<<26)|(pa&0xFFFF); /* OR $r&0xFFFF, R0 */
376 vp[n++] = 0x7c0803a6; /* MOVW R0, LR */
377 vp[n++] = 0x4e800021; /* BL (LR) */
378 }else
379 vp[n++] = (18<<26)|(pa&0x3FFFFFC)|3; /* bla */
380 pa = PADDR(t);
381 o = pa >> 25;
382 if(o != 0 && o != 0x7F){
383 /* a branch too far */
384 vp[n++] = (15<<26)|(pa>>16); /* MOVW $r&~0xFFFF, R0 */
385 vp[n++] = (24<<26)|(pa&0xFFFF); /* OR $r&0xFFFF, R0 */
386 vp[n++] = 0x7c0803a6; /* MOVW R0, LR */
387 vp[n] = 0x4e800021; /* BL (LR) */
388 }else
389 vp[n] = (18<<26)|(pa&0x3FFFFFC)|3; /* bla */
390 }
391
392 char*
393 fpexcname(Ureg *ur, ulong fpscr, char *buf)
394 {
395 int i;
396 char *s;
397 ulong fppc;
398
399 fppc = ur->pc;
400 s = 0;
401 fpscr >>= 3; /* trap enable bits */
402 fpscr &= (fpscr>>22); /* anded with exceptions */
403 for(i=0; i<5; i++)
404 if(fpscr & (1<<i))
405 s = fpcause[i];
406 if(s == 0)
407 return "no floating point exception";
408 sprint(buf, "%s fppc=0x%lux", s, fppc);
409 return buf;
410 }
411
412 /*
413 * Fill in enough of Ureg to get a stack trace, and call a function.
414 * Used by debugging interface rdb.
415 */
416
417 static void
418 getpcsp(ulong *pc, ulong *sp)
419 {
420 *pc = getcallerpc(&pc);
421 *sp = (ulong)&pc-4;
422 }
423
424 void
425 callwithureg(void (*fn)(Ureg*))
426 {
427 Ureg ureg;
428
429 getpcsp((ulong*)&ureg.pc, (ulong*)&ureg.sp);
430 ureg.lr = getcallerpc(&fn);
431 fn(&ureg);
432 }
433
434 static void
435 _dumpstack(Ureg *ureg)
436 {
437 ulong l, sl, el, v;
438 int i;
439
440 l = (ulong)&l;
441 if(up == 0){
442 el = (ulong)m+BY2PG;
443 sl = el-KSTACK;
444 }
445 else{
446 sl = (ulong)up->kstack;
447 el = sl + KSTACK;
448 }
449 if(l > el || l < sl){
450 el = (ulong)m+BY2PG;
451 sl = el-KSTACK;
452 }
453 if(l > el || l < sl)
454 return;
455 print("ktrace /kernel/path %.8lux %.8lux %.8lux\n", ureg->pc, ureg->sp, ureg->lr);
456 i = 0;
457 for(; l < el; l += 4){
458 v = *(ulong*)l;
459 if(KTZERO < v && v < (ulong)etext){
460 print("%.8lux=%.8lux ", l, v);
461 if(i++ == 4){
462 print("\n");
463 i = 0;
464 }
465 }
466 }
467 }
468
469 void
470 dumpstack(void)
471 {
472 callwithureg(_dumpstack);
473 }
474
475 void
476 dumpregs(Ureg *ur)
477 {
478 int i;
479 ulong *l;
480
481 if(up) {
482 print("registers for %s %ld\n", up->text, up->pid);
483 if(ur->srr1 & MSR_PR == 0)
484 if(ur->usp < (ulong)up->kstack || ur->usp > (ulong)up->kstack+KSTACK)
485 print("invalid stack ptr\n");
486 }
487 else
488 print("registers for kernel\n");
489
490 for(i=0; i<16; i+=2)
491 print("sr[%x]\t0x%.8lux\tsr[%x]\t0x%.8lux\n", i, getsr(i<<28), i+1, getsr((i+1)<<28));
492 l = &ur->cause;
493 for(i=0; i<sizeof regname/sizeof(char*); i+=2, l+=2)
494 print("%s\t0x%.8lux\t%s\t0x%.8lux\n", regname[i], l[0], regname[i+1], l[1]);
495 delay(500);
496 }
497
498 static void
499 linkproc(void)
500 {
501 spllo();
502 (*up->kpfun)(up->kparg);
503 pexit("", 0);
504 }
505
506 void
507 kprocchild(Proc *p, void (*func)(void*), void *arg)
508 {
509 p->sched.pc = (ulong)linkproc;
510 p->sched.sp = (ulong)p->kstack+KSTACK;
511
512 p->kpfun = func;
513 p->kparg = arg;
514 }
515
516 /*
517 * called in sysfile.c
518 */
519 void
520 evenaddr(ulong addr)
521 {
522 if(addr & 3){
523 postnote(up, 1, "sys: odd address", NDebug);
524 error(Ebadarg);
525 }
526 }
527
528 long
529 execregs(ulong entry, ulong ssize, ulong nargs)
530 {
531 ulong *sp;
532 Ureg *ureg;
533
534 sp = (ulong*)(USTKTOP - ssize);
535 *--sp = nargs;
536
537 ureg = up->dbgreg;
538 ureg->usp = (ulong)sp;
539 ureg->pc = entry;
540 ureg->srr1 &= ~MSR_FP; /* disable floating point */
541 up->fpstate = FPinit;
542 return USTKTOP-sizeof(Tos); /* address of kernel/user shared data */
543 }
544
545 void
546 forkchild(Proc *p, Ureg *ur)
547 {
548 Ureg *cur;
549
550 p->sched.sp = (ulong)p->kstack+KSTACK-UREGSIZE;
551 p->sched.pc = (ulong)forkret;
552
553 cur = (Ureg*)(p->sched.sp+2*BY2WD);
554 memmove(cur, ur, sizeof(Ureg));
555 cur->r3 = 0;
556
557 /* Things from bottom of syscall we never got to execute */
558 p->psstate = 0;
559 p->insyscall = 0;
560 }
561
562 ulong
563 userpc(void)
564 {
565 Ureg *ureg;
566
567 ureg = (Ureg*)up->dbgreg;
568 return ureg->pc;
569 }
570
571
572 /* This routine must save the values of registers the user is not
573 * permitted to write from devproc and then restore the saved values
574 * before returning
575 */
576 void
577 setregisters(Ureg *xp, char *pureg, char *uva, int n)
578 {
579 ulong status;
580
581 status = xp->status;
582 memmove(pureg, uva, n);
583 xp->status = status;
584 }
585
586 /* Give enough context in the ureg to produce a kernel stack for
587 * a sleeping process
588 */
589 void
590 setkernur(Ureg* ureg, Proc* p)
591 {
592 ureg->pc = p->sched.pc;
593 ureg->sp = p->sched.sp+4;
594 }
595
596 ulong
597 dbgpc(Proc *p)
598 {
599 Ureg *ureg;
600
601 ureg = p->dbgreg;
602 if(ureg == 0)
603 return 0;
604
605 return ureg->pc;
606 }
607
608 /*
609 * system calls
610 */
611 #include "../port/systab.h"
612
613 /* TODO: make this trap a separate asm entry point, like on other RISC architectures */
614 void
615 syscall(Ureg* ureg)
616 {
617 int i;
618 char *e;
619 long ret;
620 ulong sp, scallnr;
621
622 m->syscall++;
623 up->insyscall = 1;
624 up->pc = ureg->pc;
625 up->dbgreg = ureg;
626
627 if (up->fpstate == FPactive && (ureg->srr1 & MSR_FP) == 0){
628 print("fpstate check, entry syscall\n");
629 delay(200);
630 dumpregs(ureg);
631 print("fpstate check, entry syscall\n");
632 }
633
634 scallnr = ureg->r3;
635 up->scallnr = ureg->r3;
636 if(scallnr == RFORK && up->fpstate == FPactive){
637 fpsave(&up->fpsave);
638 up->fpstate = FPinactive;
639 }
640 spllo();
641
642 sp = ureg->usp;
643 up->nerrlab = 0;
644 ret = -1;
645 if(!waserror()){
646 if(scallnr >= nsyscall || systab[scallnr] == nil){
647 pprint("bad sys call number %d pc %lux\n", scallnr, ureg->pc);
648 postnote(up, 1, "sys: bad sys call", NDebug);
649 error(Ebadarg);
650 }
651
652 if(sp<(USTKTOP-BY2PG) || sp>(USTKTOP-sizeof(Sargs)-BY2WD))
653 validaddr(sp, sizeof(Sargs)+BY2WD, 0);
654
655 up->s = *((Sargs*)(sp+BY2WD));
656 up->psstate = sysctab[scallnr];
657
658 ret = systab[scallnr](up->s.args);
659 poperror();
660 }else{
661 /* failure: save the error buffer for errstr */
662 e = up->syserrstr;
663 up->syserrstr = up->errstr;
664 up->errstr = e;
665 }
666 if(up->nerrlab){
667 print("bad errstack [%uld]: %d extra\n", scallnr, up->nerrlab);
668 print("scall %s lr =%lux\n", sysctab[scallnr], ureg->lr);
669 for(i = 0; i < NERR; i++)
670 print("sp=%lux pc=%lux\n", up->errlab[i].sp, up->errlab[i].pc);
671 panic("error stack");
672 }
673
674 up->insyscall = 0;
675 up->psstate = 0;
676
677 /*
678 * Put return value in frame. On the x86 the syscall is
679 * just another trap and the return value from syscall is
680 * ignored. On other machines the return value is put into
681 * the results register by caller of syscall.
682 */
683 ureg->r3 = ret;
684
685 if(scallnr == NOTED)
686 noted(ureg, *(ulong*)(sp+BY2WD));
687
688 /* restoreureg must execute at high IPL */
689 splhi();
690 if(scallnr!=RFORK)
691 notify(ureg);
692
693 if (up->fpstate == FPactive && (ureg->srr1 & MSR_FP) == 0){
694 print("fpstate check, exit syscall nr %lud, pid %lud\n", scallnr, up->pid);
695 dumpregs(ureg);
696 }
697 if(up->fpstate != FPactive)
698 ureg->srr1 &= ~MSR_FP;
699 }
700
701 /*
702 * Call user, if necessary, with note.
703 * Pass user the Ureg struct and the note on his stack.
704 */
705 int
706 notify(Ureg* ur)
707 {
708 int l;
709 ulong s, sp;
710 Note *n;
711
712 if(up->procctl)
713 procctl(up);
714 if(up->nnote == 0)
715 return 0;
716
717 s = spllo();
718 qlock(&up->debug);
719 up->notepending = 0;
720 n = &up->note[0];
721 if(strncmp(n->msg, "sys:", 4) == 0){
722 l = strlen(n->msg);
723 if(l > ERRMAX-15) /* " pc=0x12345678\0" */
724 l = ERRMAX-15;
725 sprint(n->msg+l, " pc=0x%.8lux", ur->pc);
726 }
727
728 if(n->flag!=NUser && (up->notified || up->notify==0)){
729 if(n->flag == NDebug)
730 pprint("suicide: %s\n", n->msg);
731 qunlock(&up->debug);
732 pexit(n->msg, n->flag!=NDebug);
733 }
734
735 if(up->notified) {
736 qunlock(&up->debug);
737 splhi();
738 return 0;
739 }
740
741 if(!up->notify) {
742 qunlock(&up->debug);
743 pexit(n->msg, n->flag!=NDebug);
744 }
745
746 if(up->fpstate == FPactive){
747 fpsave(&up->fpsave);
748 up->fpstate = FPinactive;
749 }
750 up->fpstate |= FPillegal;
751
752 sp = ur->usp & ~(BY2V-1);
753 sp -= sizeof(Ureg);
754
755 if(!okaddr((ulong)up->notify, BY2WD, 0) ||
756 !okaddr(sp-ERRMAX-4*BY2WD, sizeof(Ureg)+ERRMAX+4*BY2WD, 1)) {
757 pprint("suicide: bad address or sp in notify\n");
758 qunlock(&up->debug);
759 pexit("Suicide", 0);
760 }
761
762 memmove((Ureg*)sp, ur, sizeof(Ureg));
763 *(Ureg**)(sp-BY2WD) = up->ureg; /* word under Ureg is old up->ureg */
764 up->ureg = (void*)sp;
765 sp -= BY2WD+ERRMAX;
766 memmove((char*)sp, up->note[0].msg, ERRMAX);
767 sp -= 3*BY2WD;
768 *(ulong*)(sp+2*BY2WD) = sp+3*BY2WD; /* arg 2 is string */
769 ur->r1 = (long)up->ureg; /* arg 1 is ureg* */
770 ((ulong*)sp)[1] = (ulong)up->ureg; /* arg 1 0(FP) is ureg* */
771 ((ulong*)sp)[0] = 0; /* arg 0 is pc */
772 ur->usp = sp;
773 ur->pc = (ulong)up->notify;
774 up->notified = 1;
775 up->nnote--;
776 memmove(&up->lastnote, &up->note[0], sizeof(Note));
777 memmove(&up->note[0], &up->note[1], up->nnote*sizeof(Note));
778
779 qunlock(&up->debug);
780 splx(s);
781 return 1;
782 }
783
784
785 /*
786 * Return user to state before notify()
787 */
788 void
789 noted(Ureg* ureg, ulong arg0)
790 {
791 Ureg *nureg;
792 ulong oureg, sp;
793
794 qlock(&up->debug);
795 if(arg0!=NRSTR && !up->notified) {
796 qunlock(&up->debug);
797 pprint("call to noted() when not notified\n");
798 pexit("Suicide", 0);
799 }
800 up->notified = 0;
801
802 nureg = up->ureg; /* pointer to user returned Ureg struct */
803
804 /* sanity clause */
805 oureg = (ulong)nureg;
806 if(!okaddr((ulong)oureg-BY2WD, BY2WD+sizeof(Ureg), 0)){
807 pprint("bad ureg in noted or call to noted when not notified\n");
808 qunlock(&up->debug);
809 pexit("Suicide", 0);
810 }
811
812 memmove(ureg, nureg, sizeof(Ureg));
813
814 switch(arg0){
815 case NCONT:
816 case NRSTR:
817 if(!okaddr(nureg->pc, 1, 0) || !okaddr(nureg->usp, BY2WD, 0)){
818 pprint("suicide: trap in noted\n");
819 qunlock(&up->debug);
820 pexit("Suicide", 0);
821 }
822 up->ureg = (Ureg*)(*(ulong*)(oureg-BY2WD));
823 qunlock(&up->debug);
824 break;
825
826 case NSAVE:
827 if(!okaddr(nureg->pc, BY2WD, 0)
828 || !okaddr(nureg->usp, BY2WD, 0)){
829 pprint("suicide: trap in noted\n");
830 qunlock(&up->debug);
831 pexit("Suicide", 0);
832 }
833 qunlock(&up->debug);
834 sp = oureg-4*BY2WD-ERRMAX;
835 splhi();
836 ureg->sp = sp;
837 ((ulong*)sp)[1] = oureg; /* arg 1 0(FP) is ureg* */
838 ((ulong*)sp)[0] = 0; /* arg 0 is pc */
839 break;
840
841 default:
842 pprint("unknown noted arg 0x%lux\n", arg0);
843 up->lastnote.flag = NDebug;
844 /* fall through */
845
846 case NDFLT:
847 if(up->lastnote.flag == NDebug)
848 pprint("suicide: %s\n", up->lastnote.msg);
849 qunlock(&up->debug);
850 pexit(up->lastnote.msg, up->lastnote.flag!=NDebug);
851 }
852 up->fpstate &= ~FPillegal;
853 if (up->fpstate == FPactive)
854 ureg->srr1 |= MSR_FP;
855 else
856 ureg->srr1 &= ~MSR_FP;
857 }
Cache object: d2a965dac1ed8b00152eef6859afbf35
|