]> git.lizzy.rs Git - plan9front.git/blob - sys/src/9/ppc/trap.c
devmnt: make sure auth chan is on said conection in mntattach()
[plan9front.git] / sys / src / 9 / 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 = t + 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 uintptr
529 execregs(uintptr 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
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 uintptr
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 uintptr
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         spllo();
637
638         sp = ureg->usp;
639         up->nerrlab = 0;
640         ret = -1;
641         if(!waserror()){
642                 if(scallnr >= nsyscall || systab[scallnr] == nil){
643                         pprint("bad sys call number %d pc %lux\n", scallnr, ureg->pc);
644                         postnote(up, 1, "sys: bad sys call", NDebug);
645                         error(Ebadarg);
646                 }
647
648                 if(sp<(USTKTOP-BY2PG) || sp>(USTKTOP-sizeof(Sargs)-BY2WD))
649                         validaddr(sp, sizeof(Sargs)+BY2WD, 0);
650
651                 up->s = *((Sargs*)(sp+BY2WD));
652                 up->psstate = sysctab[scallnr];
653
654                 ret = systab[scallnr]((va_list)up->s.args);
655                 poperror();
656         }else{
657                 /* failure: save the error buffer for errstr */
658                 e = up->syserrstr;
659                 up->syserrstr = up->errstr;
660                 up->errstr = e;
661         }
662         if(up->nerrlab){
663                 print("bad errstack [%uld]: %d extra\n", scallnr, up->nerrlab);
664                 print("scall %s lr =%lux\n", sysctab[scallnr], ureg->lr);
665                 for(i = 0; i < NERR; i++)
666                         print("sp=%lux pc=%lux\n", up->errlab[i].sp, up->errlab[i].pc);
667                 panic("error stack");
668         }
669
670         up->insyscall = 0;
671         up->psstate = 0;
672
673         /*
674          *  Put return value in frame.  On the x86 the syscall is
675          *  just another trap and the return value from syscall is
676          *  ignored.  On other machines the return value is put into
677          *  the results register by caller of syscall.
678          */
679         ureg->r3 = ret;
680
681         if(scallnr == NOTED)
682                 noted(ureg, *(ulong*)(sp+BY2WD));
683
684         /* restoreureg must execute at high IPL */
685         splhi();
686         if(scallnr!=RFORK)
687                 notify(ureg);
688
689         if (up->fpstate == FPactive && (ureg->srr1 & MSR_FP) == 0){
690                 print("fpstate check, exit syscall nr %lud, pid %lud\n", scallnr, up->pid);
691                 dumpregs(ureg);
692         }
693         if(up->fpstate != FPactive)
694                 ureg->srr1 &= ~MSR_FP;
695 }
696
697 /*
698  *  Call user, if necessary, with note.
699  *  Pass user the Ureg struct and the note on his stack.
700  */
701 int
702 notify(Ureg* ur)
703 {
704         int l;
705         ulong s, sp;
706         Note *n;
707
708         if(up->procctl)
709                 procctl();
710         if(up->nnote == 0)
711                 return 0;
712
713         if(up->fpstate == FPactive){
714                 fpsave(up->fpsave);
715                 up->fpstate = FPinactive;
716         }
717         up->fpstate |= FPillegal;
718
719         s = spllo();
720         qlock(&up->debug);
721         up->notepending = 0;
722         n = &up->note[0];
723         if(strncmp(n->msg, "sys:", 4) == 0){
724                 l = strlen(n->msg);
725                 if(l > ERRMAX-15)       /* " pc=0x12345678\0" */
726                         l = ERRMAX-15;
727                 sprint(n->msg+l, " pc=0x%.8lux", ur->pc);
728         }
729
730         if(n->flag!=NUser && (up->notified || up->notify==0)){
731                 qunlock(&up->debug);
732                 if(n->flag == NDebug)
733                         pprint("suicide: %s\n", n->msg);
734                 pexit(n->msg, n->flag!=NDebug);
735         }
736
737         if(up->notified) {
738                 qunlock(&up->debug);
739                 splhi();
740                 return 0;
741         }
742
743         if(!up->notify) {
744                 qunlock(&up->debug);
745                 pexit(n->msg, n->flag!=NDebug);
746         }
747
748         sp = ur->usp & ~(BY2V-1);
749         sp -= sizeof(Ureg);
750
751         if(!okaddr((uintptr)up->notify, BY2WD, 0) ||
752            !okaddr(sp-ERRMAX-4*BY2WD, sizeof(Ureg)+ERRMAX+4*BY2WD, 1)) {
753                 qunlock(&up->debug);
754                 pprint("suicide: bad address or sp in notify\n");
755                 pexit("Suicide", 0);
756         }
757
758         memmove((Ureg*)sp, ur, sizeof(Ureg));
759         *(Ureg**)(sp-BY2WD) = up->ureg; /* word under Ureg is old up->ureg */
760         up->ureg = (void*)sp;
761         sp -= BY2WD+ERRMAX;
762         memmove((char*)sp, up->note[0].msg, ERRMAX);
763         sp -= 3*BY2WD;
764         *(ulong*)(sp+2*BY2WD) = sp+3*BY2WD;     /* arg 2 is string */
765         ur->r1 = (long)up->ureg;                /* arg 1 is ureg* */
766         ((ulong*)sp)[1] = (ulong)up->ureg;      /* arg 1 0(FP) is ureg* */
767         ((ulong*)sp)[0] = 0;                    /* arg 0 is pc */
768         ur->usp = sp;
769         ur->pc = (ulong)up->notify;
770         up->notified = 1;
771         up->nnote--;
772         memmove(&up->lastnote, &up->note[0], sizeof(Note));
773         memmove(&up->note[0], &up->note[1], up->nnote*sizeof(Note));
774
775         qunlock(&up->debug);
776         splx(s);
777         return 1;
778 }
779
780
781 /*
782  *   Return user to state before notify()
783  */
784 void
785 noted(Ureg* ureg, ulong arg0)
786 {
787         Ureg *nureg;
788         ulong oureg, sp;
789
790         qlock(&up->debug);
791         if(arg0!=NRSTR && !up->notified) {
792                 qunlock(&up->debug);
793                 pprint("call to noted() when not notified\n");
794                 pexit("Suicide", 0);
795         }
796         up->notified = 0;
797
798         nureg = up->ureg;       /* pointer to user returned Ureg struct */
799
800         /* sanity clause */
801         oureg = (ulong)nureg;
802         if(!okaddr(oureg-BY2WD, BY2WD+sizeof(Ureg), 0)){
803                 qunlock(&up->debug);
804                 pprint("bad ureg in noted or call to noted when not notified\n");
805                 pexit("Suicide", 0);
806         }
807
808         memmove(ureg, nureg, sizeof(Ureg));
809
810         switch(arg0){
811         case NCONT:
812         case NRSTR:
813                 if(!okaddr(nureg->pc, 1, 0) || !okaddr(nureg->usp, BY2WD, 0)){
814                         qunlock(&up->debug);
815                         pprint("suicide: trap in noted\n");
816                         pexit("Suicide", 0);
817                 }
818                 up->ureg = (Ureg*)(*(ulong*)(oureg-BY2WD));
819                 qunlock(&up->debug);
820                 break;
821
822         case NSAVE:
823                 if(!okaddr(nureg->pc, BY2WD, 0)
824                 || !okaddr(nureg->usp, BY2WD, 0)){
825                         qunlock(&up->debug);
826                         pprint("suicide: trap in noted\n");
827                         pexit("Suicide", 0);
828                 }
829                 qunlock(&up->debug);
830                 sp = oureg-4*BY2WD-ERRMAX;
831                 splhi();
832                 ureg->sp = sp;
833                 ((ulong*)sp)[1] = oureg;        /* arg 1 0(FP) is ureg* */
834                 ((ulong*)sp)[0] = 0;            /* arg 0 is pc */
835                 break;
836
837         default:
838                 up->lastnote.flag = NDebug;
839                 /* fall through */
840                 
841         case NDFLT:
842                 qunlock(&up->debug);
843                 if(up->lastnote.flag == NDebug)
844                         pprint("suicide: %s\n", up->lastnote.msg);
845                 pexit(up->lastnote.msg, up->lastnote.flag!=NDebug);
846         }
847         up->fpstate &= ~FPillegal;
848         if (up->fpstate == FPactive)
849                 ureg->srr1 |= MSR_FP;
850         else
851                 ureg->srr1 &= ~MSR_FP;
852 }