]> git.lizzy.rs Git - plan9front.git/blob - sys/src/9/bitsy/trap.c
merge
[plan9front.git] / sys / src / 9 / bitsy / 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        "io.h"
7 #include        "ureg.h"
8 #include        "../port/error.h"
9 #include        "tos.h"
10
11 Intrregs *intrregs;
12
13 typedef struct Vctl {
14         Vctl*   next;                   /* handlers on this vector */
15         char    *name;          /* of driver, xallocated */
16         void    (*f)(Ureg*, void*);     /* handler to call */
17         void*   a;                      /* argument to call it with */
18 } Vctl;
19
20 static Lock     vctllock;
21 static Vctl     *vctl[32];
22 static Vctl     *gpiovctl[27];
23 static int      gpioirqref[12];
24
25 /*
26  *   Layout at virtual address 0.
27  */
28 typedef struct Vpage0 {
29         void    (*vectors[8])(void);
30         ulong   vtable[8];
31 } Vpage0;
32 Vpage0 *vpage0;
33
34 static int      irq(Ureg*);
35 static void     gpiointr(Ureg*, void*);
36
37 /* recover state after power suspend
38  * NB: to help debugging bad suspend code,
39  *     I changed some prints below to iprints,
40  *     to avoid deadlocks when a panic is being
41  *     issued during the suspend/resume handler.
42  */
43 void
44 trapresume(void)
45 {
46         vpage0 = (Vpage0*)EVECTORS;
47         memmove(vpage0->vectors, vectors, sizeof(vpage0->vectors));
48         memmove(vpage0->vtable, vtable, sizeof(vpage0->vtable));
49         wbflush();
50         mappedIvecEnable();
51 }
52
53 /*
54  *  set up for exceptions
55  */
56 void
57 trapinit(void)
58 {
59         /* set up the exception vectors */
60         vpage0 = (Vpage0*)EVECTORS;
61         memmove(vpage0->vectors, vectors, sizeof(vpage0->vectors));
62         memmove(vpage0->vtable, vtable, sizeof(vpage0->vtable));
63
64         wbflush();
65
66         /* use exception vectors at 0xFFFF0000 */
67         mappedIvecEnable();
68
69         /* set up the stacks for the interrupt modes */
70         setr13(PsrMfiq, m->sfiq);
71         setr13(PsrMirq, m->sirq);
72         setr13(PsrMabt, m->sabt);
73         setr13(PsrMund, m->sund);
74
75         /* map in interrupt registers */
76         intrregs = mapspecial(INTRREGS, sizeof(*intrregs));
77
78         /* make all interrupts IRQ (i.e. not FIQ) and disable all interrupts */
79         intrregs->iclr = 0;
80         intrregs->icmr = 0;
81
82         /* turn off all gpio interrupts */
83         gpioregs->rising = 0;
84         gpioregs->falling = 0;
85         gpioregs->edgestatus = gpioregs->edgestatus;
86
87         /* allow all enabled interrupts to take processor out of sleep mode */
88         intrregs->iccr = 0;
89 }
90
91 void
92 trapdump(char *tag)
93 {
94         iprint("%s: icip %lux icmr %lux iclr %lux iccr %lux icfp %lux\n",
95                 tag, intrregs->icip, intrregs->icmr, intrregs->iclr,
96                 intrregs->iccr, intrregs->icfp);
97 }
98
99 void
100 warnregs(Ureg *ur, char *tag)
101 {
102         char buf[1024];
103         char *e = buf+sizeof(buf);
104         char *p;
105
106         p = seprint(buf, e, "%s:\n", tag);
107         p = seprint(p, e, "type 0x%.8lux psr 0x%.8lux pc 0x%.8lux\n",
108                 ur->type, ur->psr, ur->pc);
109         p = seprint(p, e, "r0  0x%.8lux r1  0x%.8lux r2  0x%.8lux r3  0x%.8lux\n",
110                 ur->r0, ur->r1, ur->r2, ur->r3);
111         p = seprint(p, e, "r4  0x%.8lux r5  0x%.8lux r6  0x%.8lux r7  0x%.8lux\n",
112                 ur->r4, ur->r5, ur->r6, ur->r7);
113         p = seprint(p, e, "r8  0x%.8lux r9  0x%.8lux r10 0x%.8lux r11 0x%.8lux\n",
114                 ur->r8, ur->r9, ur->r10, ur->r11);
115         seprint(p, e, "r12 0x%.8lux r13 0x%.8lux r14 0x%.8lux\n",
116                 ur->r12, ur->r13, ur->r14);
117         iprint("%s", buf);
118 }
119
120 /*
121  *  enable an irq interrupt
122  */
123 static void
124 irqenable(int irq, IntrHandler *f, void* a, char *name)
125 {
126         Vctl *v;
127
128         if(irq >= nelem(vctl) || irq < 0)
129                 panic("intrenable");
130
131         v = malloc(sizeof(Vctl));
132         v->f = f;
133         v->a = a;
134         v->name = xalloc(strlen(name)+1);
135         strcpy(v->name, name);
136
137         lock(&vctllock);
138         v->next = vctl[irq];
139         vctl[irq] = v;
140         intrregs->icmr |= 1<<irq;
141         unlock(&vctllock);
142 }
143
144 /*
145  *  disable an irq interrupt
146  */
147 static void
148 irqdisable(int irq, IntrHandler *f, void* a, char *name)
149 {
150         Vctl **vp, *v;
151
152         if(irq >= nelem(vctl) || irq < 0)
153                 panic("intrdisable");
154
155         lock(&vctllock);
156         for(vp = &vctl[irq]; v = *vp; vp = &v->next)
157                 if (v->f == f && v->a == a && strcmp(v->name, name) == 0){
158                         print("irqdisable: remove %s\n", name);
159                         *vp = v->next;
160                         free(v);
161                         break;
162                 }
163         if (v == nil)
164                 print("irqdisable: irq %d, name %s not enabled\n", irq, name);
165         if (vctl[irq] == nil){
166                 print("irqdisable: clear icmr bit %d\n", irq);
167                 intrregs->icmr &= ~(1<<irq);
168         }
169         unlock(&vctllock);
170 }
171
172 /*
173  *  enable an interrupt
174  */
175 void
176 intrenable(int type, int which, IntrHandler *f, void* a, char *name)
177 {
178         int irq;
179         Vctl *v;
180
181         if(type == IRQ){
182                 irqenable(which, f, a, name);
183                 return;
184         }
185
186         /* from here down, it must be a GPIO edge interrupt */
187         irq = which;
188         if(which >= nelem(gpiovctl) || which < 0)
189                 panic("intrenable");
190         if(which > 11)
191                 irq = 11;
192
193         /* the pin had better be configured as input */
194         if((1<<which) & gpioregs->direction)
195                 panic("intrenable of output pin %d", which);
196
197         /* create a second level vctl for the gpio edge interrupt */
198         v = malloc(sizeof(Vctl));
199         v->f = f;
200         v->a = a;
201         v->name = xalloc(strlen(name)+1);
202         strcpy(v->name, name);
203
204         lock(&vctllock);
205         v->next = gpiovctl[which];
206         gpiovctl[which] = v;
207
208         /* set edge register to enable interrupt */
209         switch(type){
210         case GPIOboth:
211                 gpioregs->rising |= 1<<which;
212                 gpioregs->falling |= 1<<which;
213                 break;
214         case GPIOfalling:
215                 gpioregs->falling |= 1<<which;
216                 break;
217         case GPIOrising:
218                 gpioregs->rising |= 1<<which;
219                 break;
220         }
221         unlock(&vctllock);
222         /* point the irq to the gpio interrupt handler */
223         if(gpioirqref[irq]++ == 0)
224                 irqenable(irq, gpiointr, nil, "gpio edge");
225 }
226
227 /*
228  *  disable an interrupt
229  */
230 void
231 intrdisable(int type, int which, IntrHandler *f, void* a, char *name)
232 {
233         int irq;
234         Vctl **vp, *v;
235
236
237         if(type == IRQ){
238                 irqdisable(which, f, a, name);
239                 return;
240         }
241
242         /* from here down, it must be a GPIO edge interrupt */
243         irq = which;
244         if(which >= nelem(gpiovctl) || which < 0)
245                 panic("intrdisable");
246         if(which > 11)
247                 irq = 11;
248
249         lock(&vctllock);
250         for(vp = &gpiovctl[which]; v = *vp; vp = &v->next)
251                 if (v->f == f && v->a == a && strcmp(v->name, name) == 0){
252                         break;
253                 }
254         if (gpiovctl[which] == nil){
255                 /* set edge register to enable interrupt */
256                 switch(type){
257                 case GPIOboth:
258                         print("intrdisable: gpio-rising+falling clear bit %d\n", which);
259                         gpioregs->rising &= ~(1<<which);
260                         gpioregs->falling &= ~(1<<which);
261                         break;
262                 case GPIOfalling:
263                         print("intrdisable: gpio-falling clear bit %d\n", which);
264                         gpioregs->falling &= ~(1<<which);
265                         break;
266                 case GPIOrising:
267                         print("intrdisable: gpio-rising clear bit %d\n", which);
268                         gpioregs->rising &= ~(1<<which);
269                         break;
270                 }
271         
272         }
273         if (v) {
274                 print("intrdisable: removing %s\n", name);
275                 *vp = v->next;
276         }else
277                 print("intrdisable: which %d, name %s not enabled\n", which, name);
278         unlock(&vctllock);
279         /* disable the gpio interrupt handler if necessary */
280         if(--gpioirqref[irq] == 0){
281                 print("intrdisable: inrqdisable gpiointr\n");
282                 irqdisable(irq, gpiointr, nil, "gpio edge");
283         }
284         free(v);
285 }
286
287 /*
288  *  called by trap to handle access faults
289  */
290 static void
291 faultarm(Ureg *ureg, ulong va, int user, int read)
292 {
293         int n, insyscall;
294         char buf[ERRMAX];
295
296         if (up == nil) {
297                 warnregs(ureg, "kernel fault");
298                 panic("fault: nil up in faultarm, accessing 0x%lux", va);
299         }
300         insyscall = up->insyscall;
301         up->insyscall = 1;
302         n = fault(va, read);
303         if(n < 0){
304                 if(!user){
305                         warnregs(ureg, "kernel fault");
306                         panic("fault: kernel accessing 0x%lux", va);
307                 }
308 //              warnregs(ureg, "user fault");
309                 sprint(buf, "sys: trap: fault %s va=0x%lux", read ? "read" : "write", va);
310                 postnote(up, 1, buf, NDebug);
311         }
312         up->insyscall = insyscall;
313 }
314
315 /*
316  *  returns 1 if the instruction writes memory, 0 otherwise
317  */
318 int
319 writetomem(ulong inst)
320 {
321         /* swap always write memory */
322         if((inst & 0x0FC00000) == 0x01000000)
323                 return 1;
324
325         /* loads and stores are distinguished by bit 20 */
326         if(inst & (1<<20))
327                 return 0;
328
329         return 1;
330 }
331
332
333 /*
334  *  here on all exceptions other than syscall (SWI)
335  */
336 void
337 trap(Ureg *ureg)
338 {
339         ulong inst;
340         int clockintr, user, x, rv;
341         ulong va, fsr;
342         char buf[ERRMAX];
343         int rem;
344
345         if(up != nil)
346                 rem = ((char*)ureg)-up->kstack;
347         else
348                 rem = ((char*)ureg)-((char*)(MACHADDR+sizeof(Mach)));
349         if(rem < 256) {
350                 dumpstack();
351                 panic("trap %d bytes remaining, up = %#p, ureg = %#p, at pc 0x%lux",
352                         rem, up, ureg, ureg->pc);
353         }
354
355         user = (ureg->psr & PsrMask) == PsrMusr;
356
357         /*
358          * All interrupts/exceptions should be resumed at ureg->pc-4,
359          * except for Data Abort which resumes at ureg->pc-8.
360          */
361         if(ureg->type == (PsrMabt+1))
362                 ureg->pc -= 8;
363         else
364                 ureg->pc -= 4;
365
366         clockintr = 0;
367         switch(ureg->type){
368         default:
369                 panic("unknown trap");
370                 break;
371         case PsrMirq:
372                 clockintr = irq(ureg);
373                 break;
374         case PsrMabt:   /* prefetch fault */
375                 faultarm(ureg, ureg->pc, user, 1);
376                 break;
377         case PsrMabt+1: /* data fault */
378                 va = getfar();
379                 inst = *(ulong*)(ureg->pc);
380                 fsr = getfsr() & 0xf;
381                 switch(fsr){
382                 case 0x0:
383                         panic("vector exception at %lux", ureg->pc);
384                         break;
385                 case 0x1:
386                 case 0x3:
387                         if(user){
388                                 snprint(buf, sizeof(buf), "sys: alignment: pc 0x%lux va 0x%lux\n",
389                                         ureg->pc, va);
390                                 postnote(up, 1, buf, NDebug);
391                         } else
392                                 panic("kernel alignment: pc 0x%lux va 0x%lux", ureg->pc, va);
393                         break;
394                 case 0x2:
395                         panic("terminal exception at %lux", ureg->pc);
396                         break;
397                 case 0x4:
398                 case 0x6:
399                 case 0x8:
400                 case 0xa:
401                 case 0xc:
402                 case 0xe:
403                         panic("external abort 0x%lux pc 0x%lux addr 0x%lux", fsr, ureg->pc, va);
404                         break;
405                 case 0x5:
406                 case 0x7:
407                         /* translation fault, i.e., no pte entry */
408                         faultarm(ureg, va, user, !writetomem(inst));
409                         break;
410                 case 0x9:
411                 case 0xb:
412                         /* domain fault, accessing something we shouldn't */
413                         if(user){
414                                 sprint(buf, "sys: access violation: pc 0x%lux va 0x%lux\n",
415                                         ureg->pc, va);
416                                 postnote(up, 1, buf, NDebug);
417                         } else
418                                 panic("kernel access violation: pc 0x%lux va 0x%lux",
419                                         ureg->pc, va);
420                         break;
421                 case 0xd:
422                 case 0xf:
423                         /* permission error, copy on write or real permission error */
424                         faultarm(ureg, va, user, !writetomem(inst));
425                         break;
426                 }
427                 break;
428         case PsrMund:   /* undefined instruction */
429                 if (user) {
430                         /* look for floating point instructions to interpret */
431                         x = spllo();
432                         rv = fpiarm(ureg);
433                         splx(x);
434                         if (rv == 0) {
435                                 sprint(buf, "undefined instruction: pc 0x%lux\n", ureg->pc);
436                                 postnote(up, 1, buf, NDebug);
437                         }
438                 }else{
439                         iprint("undefined instruction: pc=0x%lux, inst=0x%lux, 0x%lux, 0x%lux, 0x%lux, 0x%lux\n", ureg->pc, ((ulong*)ureg->pc)[-2], ((ulong*)ureg->pc)[-1], ((ulong*)ureg->pc)[0], ((ulong*)ureg->pc)[1], ((ulong*)ureg->pc)[2]);
440                         panic("undefined instruction");
441                 }
442                 break;
443         }
444         splhi();
445
446         /* delaysched set because we held a lock or because our quantum ended */
447         if(up && up->delaysched && clockintr){
448                 sched();
449                 splhi();
450         }
451
452         if(user){
453                 if(up->procctl || up->nnote)
454                         notify(ureg);
455                 kexit(ureg);
456         }
457 }
458
459 /*
460  *  here on irq's
461  */
462 static int
463 irq(Ureg *ur)
464 {
465         ulong va;
466         int clockintr, i;
467         Vctl *v;
468
469         va = intrregs->icip;
470
471         if(va & (1<<IRQtimer0))
472                 clockintr = 1;
473         else
474                 clockintr = 0;
475         for(i = 0; i < 32; i++){
476                 if(((1<<i) & va) == 0)
477                         continue;
478                 for(v = vctl[i]; v != nil; v = v->next){
479                         v->f(ur, v->a);
480                         va &= ~(1<<i);
481                 }
482         }
483         if(va)
484                 print("unknown interrupt: %lux\n", va);
485
486         return clockintr;
487 }
488
489 /*
490  *  here on gpio interrupts
491  */
492 static void
493 gpiointr(Ureg *ur, void*)
494 {
495         ulong va;
496         int i;
497         Vctl *v;
498
499         va = gpioregs->edgestatus;
500         gpioregs->edgestatus = va;
501
502         for(i = 0; i < 27; i++){
503                 if(((1<<i) & va) == 0)
504                         continue;
505                 for(v = gpiovctl[i]; v != nil; v = v->next){
506                         v->f(ur, v->a);
507                         va &= ~(1<<i);
508                 }
509         }
510         if(va)
511                 print("unknown gpio interrupt: %lux\n", va);
512 }
513
514 /*
515  *  system calls
516  */
517 #include "../port/systab.h"
518
519 /*
520  *  Syscall is called directly from assembler without going through trap().
521  */
522 void
523 syscall(Ureg* ureg)
524 {
525         char *e;
526         ulong   sp;
527         long    ret;
528         int     i, scallnr;
529
530         if((ureg->psr & PsrMask) != PsrMusr) {
531                 panic("syscall: pc 0x%lux r14 0x%lux cs 0x%lux", ureg->pc, ureg->r14, ureg->psr);
532         }
533
534         m->syscall++;
535         up->insyscall = 1;
536         up->pc = ureg->pc;
537         up->dbgreg = ureg;
538
539         scallnr = ureg->r0;
540         up->scallnr = scallnr;
541         spllo();
542
543         sp = ureg->sp;
544         up->nerrlab = 0;
545         ret = -1;
546         if(!waserror()){
547                 if(scallnr >= nsyscall){
548                         pprint("bad sys call number %d pc %lux\n",
549                                 scallnr, ureg->pc);
550                         postnote(up, 1, "sys: bad sys call", NDebug);
551                         error(Ebadarg);
552                 }
553
554                 if(sp<(USTKTOP-BY2PG) || sp>(USTKTOP-sizeof(Sargs)-BY2WD))
555                         validaddr(sp, sizeof(Sargs)+BY2WD, 0);
556
557                 up->s = *((Sargs*)(sp+BY2WD));
558                 up->psstate = sysctab[scallnr];
559
560                 ret = systab[scallnr](up->s.args);
561                 poperror();
562         }else{
563                 /* failure: save the error buffer for errstr */
564                 e = up->syserrstr;
565                 up->syserrstr = up->errstr;
566                 up->errstr = e;
567         }
568         if(up->nerrlab){
569                 print("bad errstack [%d]: %d extra\n", scallnr, up->nerrlab);
570                 for(i = 0; i < NERR; i++)
571                         print("sp=%lux pc=%lux\n",
572                                 up->errlab[i].sp, up->errlab[i].pc);
573                 panic("error stack");
574         }
575
576         up->insyscall = 0;
577         up->psstate = 0;
578
579         /*
580          *  Put return value in frame.  On the x86 the syscall is
581          *  just another trap and the return value from syscall is
582          *  ignored.  On other machines the return value is put into
583          *  the results register by caller of syscall.
584          */
585         ureg->r0 = ret;
586
587         if(scallnr == NOTED)
588                 noted(ureg, *(ulong*)(sp+BY2WD));
589
590         if(up->delaysched)
591                 sched();
592
593         splhi();
594         if(scallnr != RFORK && (up->procctl || up->nnote))
595                 notify(ureg);
596 }
597
598 /*
599  *   Return user to state before notify()
600  */
601 void
602 noted(Ureg* ureg, ulong arg0)
603 {
604         Ureg *nureg;
605         ulong oureg, sp;
606
607         qlock(&up->debug);
608         if(arg0!=NRSTR && !up->notified) {
609                 qunlock(&up->debug);
610                 pprint("call to noted() when not notified\n");
611                 pexit("Suicide", 0);
612         }
613         up->notified = 0;
614
615         nureg = up->ureg;       /* pointer to user returned Ureg struct */
616
617         /* sanity clause */
618         oureg = (ulong)nureg;
619         if(!okaddr((ulong)oureg-BY2WD, BY2WD+sizeof(Ureg), 0)){
620                 pprint("bad ureg in noted or call to noted when not notified\n");
621                 qunlock(&up->debug);
622                 pexit("Suicide", 0);
623         }
624
625         /* don't let user change system flags */
626         nureg->psr = (ureg->psr & ~(PsrMask|PsrDfiq|PsrDirq)) |
627                         (nureg->psr & (PsrMask|PsrDfiq|PsrDirq));
628
629         memmove(ureg, nureg, sizeof(Ureg));
630
631         switch(arg0){
632         case NCONT:
633         case NRSTR:
634                 if(!okaddr(nureg->pc, 1, 0) || !okaddr(nureg->sp, BY2WD, 0)){
635                         qunlock(&up->debug);
636                         pprint("suicide: trap in noted\n");
637                         pexit("Suicide", 0);
638                 }
639                 up->ureg = (Ureg*)(*(ulong*)(oureg-BY2WD));
640                 qunlock(&up->debug);
641                 break;
642
643         case NSAVE:
644                 if(!okaddr(nureg->pc, BY2WD, 0)
645                 || !okaddr(nureg->sp, BY2WD, 0)){
646                         qunlock(&up->debug);
647                         pprint("suicide: trap in noted\n");
648                         pexit("Suicide", 0);
649                 }
650                 qunlock(&up->debug);
651                 sp = oureg-4*BY2WD-ERRMAX;
652                 splhi();
653                 ureg->sp = sp;
654                 ((ulong*)sp)[1] = oureg;        /* arg 1 0(FP) is ureg* */
655                 ((ulong*)sp)[0] = 0;            /* arg 0 is pc */
656                 break;
657
658         default:
659                 pprint("unknown noted arg 0x%lux\n", arg0);
660                 up->lastnote.flag = NDebug;
661                 /* fall through */
662                 
663         case NDFLT:
664                 if(up->lastnote.flag == NDebug){ 
665                         qunlock(&up->debug);
666                         pprint("suicide: %s\n", up->lastnote.msg);
667                 } else
668                         qunlock(&up->debug);
669                 pexit(up->lastnote.msg, up->lastnote.flag!=NDebug);
670         }
671 }
672
673 /*
674  *  Call user, if necessary, with note.
675  *  Pass user the Ureg struct and the note on his stack.
676  */
677 int
678 notify(Ureg* ureg)
679 {
680         int l;
681         ulong s, sp;
682         Note *n;
683
684         if(up->procctl)
685                 procctl(up);
686         if(up->nnote == 0)
687                 return 0;
688
689         s = spllo();
690         qlock(&up->debug);
691         up->notepending = 0;
692         n = &up->note[0];
693         if(strncmp(n->msg, "sys:", 4) == 0){
694                 l = strlen(n->msg);
695                 if(l > ERRMAX-15)       /* " pc=0x12345678\0" */
696                         l = ERRMAX-15;
697                 sprint(n->msg+l, " pc=0x%.8lux", ureg->pc);
698         }
699
700         if(n->flag!=NUser && (up->notified || up->notify==0)){
701                 if(n->flag == NDebug)
702                         pprint("suicide: %s\n", n->msg);
703                 qunlock(&up->debug);
704                 pexit(n->msg, n->flag!=NDebug);
705         }
706
707         if(up->notified) {
708                 qunlock(&up->debug);
709                 splhi();
710                 return 0;
711         }
712                 
713         if(!up->notify){
714                 qunlock(&up->debug);
715                 pexit(n->msg, n->flag!=NDebug);
716         }
717         sp = ureg->sp;
718         sp -= sizeof(Ureg);
719
720         if(!okaddr((ulong)up->notify, 1, 0)
721         || !okaddr(sp-ERRMAX-4*BY2WD, sizeof(Ureg)+ERRMAX+4*BY2WD, 1)){
722                 pprint("suicide: bad address in notify\n");
723                 qunlock(&up->debug);
724                 pexit("Suicide", 0);
725         }
726
727         up->ureg = (void*)sp;
728         memmove((Ureg*)sp, ureg, sizeof(Ureg));
729         *(Ureg**)(sp-BY2WD) = up->ureg; /* word under Ureg is old up->ureg */
730         up->ureg = (void*)sp;
731         sp -= BY2WD+ERRMAX;
732         memmove((char*)sp, up->note[0].msg, ERRMAX);
733         sp -= 3*BY2WD;
734         *(ulong*)(sp+2*BY2WD) = sp+3*BY2WD;     /* arg 2 is string */
735         *(ulong*)(sp+1*BY2WD) = (ulong)up->ureg;        /* arg 1 is ureg* */
736         *(ulong*)(sp+0*BY2WD) = 0;              /* arg 0 is pc */
737         ureg->sp = sp;
738         ureg->pc = (ulong)up->notify;
739         up->notified = 1;
740         up->nnote--;
741         memmove(&up->lastnote, &up->note[0], sizeof(Note));
742         memmove(&up->note[0], &up->note[1], up->nnote*sizeof(Note));
743
744         qunlock(&up->debug);
745         splx(s);
746         return 1;
747 }
748
749 /* Give enough context in the ureg to produce a kernel stack for
750  * a sleeping process
751  */
752 void
753 setkernur(Ureg *ureg, Proc *p)
754 {
755         ureg->pc = p->sched.pc;
756         ureg->sp = p->sched.sp+4;
757         ureg->r14 = (ulong)sched;
758 }
759
760 /*
761  *  return the userpc the last exception happened at
762  */
763 ulong
764 userpc(void)
765 {
766         Ureg *ureg;
767
768         ureg = (Ureg*)up->dbgreg;
769         return ureg->pc;
770 }
771
772 /* This routine must save the values of registers the user is not permitted
773  * to write from devproc and then restore the saved values before returning.
774  */
775 void
776 setregisters(Ureg* ureg, char* pureg, char* uva, int n)
777 {
778         USED(ureg, pureg, uva, n);
779 }
780
781 /*
782  *  this is the body for all kproc's
783  */
784 static void
785 linkproc(void)
786 {
787         spllo();
788         up->kpfun(up->kparg);
789         pexit("kproc exiting", 0);
790 }
791
792 /*
793  *  setup stack and initial PC for a new kernel proc.  This is architecture
794  *  dependent because of the starting stack location
795  */
796 void
797 kprocchild(Proc *p, void (*func)(void*), void *arg)
798 {
799         p->sched.pc = (ulong)linkproc;
800         p->sched.sp = (ulong)p->kstack+KSTACK;
801
802         p->kpfun = func;
803         p->kparg = arg;
804 }
805
806
807 /* 
808  *  Craft a return frame which will cause the child to pop out of
809  *  the scheduler in user mode with the return register zero.  Set
810  *  pc to point to a l.s return function.
811  */
812 void
813 forkchild(Proc *p, Ureg *ureg)
814 {
815         Ureg *cureg;
816
817 //print("%lud setting up for forking child %lud\n", up->pid, p->pid);
818         p->sched.sp = (ulong)p->kstack+KSTACK-sizeof(Ureg);
819         p->sched.pc = (ulong)forkret;
820
821         cureg = (Ureg*)(p->sched.sp);
822         memmove(cureg, ureg, sizeof(Ureg));
823
824         /* syscall returns 0 for child */
825         cureg->r0 = 0;
826
827         /* Things from bottom of syscall which were never executed */
828         p->psstate = 0;
829         p->insyscall = 0;
830 }
831
832 /*
833  *  setup stack, initial PC, and any arch dependent regs for an execing user proc.
834  */
835 long
836 execregs(ulong entry, ulong ssize, ulong nargs)
837 {
838         ulong *sp;
839         Ureg *ureg;
840
841         sp = (ulong*)(USTKTOP - ssize);
842         *--sp = nargs;
843
844         ureg = up->dbgreg;
845         memset(ureg, 0, 15*sizeof(ulong));
846         ureg->r13 = (ulong)sp;
847         ureg->pc = entry;
848 //print("%lud: EXECREGS pc 0x%lux sp 0x%lux\n", up->pid, ureg->pc, ureg->r13);
849         return USTKTOP-sizeof(Tos);             /* address of kernel/user shared data */
850 }
851
852 /*
853  * Fill in enough of Ureg to get a stack trace, and call a function.
854  * Used by debugging interface rdb.
855  */
856 void
857 callwithureg(void (*fn)(Ureg*))
858 {
859         Ureg ureg;
860         ureg.pc = getcallerpc(&fn);
861         ureg.sp = (ulong)&fn;
862         fn(&ureg);
863 }
864
865 static void
866 _dumpstack(Ureg *ureg)
867 {
868         ulong l, v, i;
869         ulong *p;
870         extern ulong etext;
871
872         if(up == 0){
873                 iprint("no current proc\n");
874                 return;
875         }
876
877         iprint("ktrace /kernel/path %.8lux %.8lux %.8lux\n", ureg->pc, ureg->sp, ureg->r14);
878         i = 0;
879         for(l=(ulong)&l; l<(ulong)(up->kstack+KSTACK); l+=4){
880                 v = *(ulong*)l;
881                 if(KTZERO < v && v < (ulong)&etext && (v&3)==0){
882                         v -= 4;
883                         p = (ulong*)v;
884                         if((*p & 0x0f000000) == 0x0b000000){
885                                 iprint("%.8lux=%.8lux ", l, v);
886                                 i++;
887                         }
888                 }
889                 if(i == 4){
890                         i = 0;
891                         iprint("\n");
892                 }
893         }
894         if(i)
895                 iprint("\n");
896 }
897
898 void
899 dumpstack(void)
900 {
901         callwithureg(_dumpstack);
902 }
903
904 /*
905  *  pc output by ps
906  */
907 ulong
908 dbgpc(Proc *p)
909 {
910         Ureg *ureg;
911
912         ureg = p->dbgreg;
913         if(ureg == 0)
914                 return 0;
915
916         return ureg->pc;
917 }
918
919 /*
920  * called in sysfile.c
921  */
922 void
923 evenaddr(ulong addr)
924 {
925         if(addr & 3){
926                 postnote(up, 1, "sys: odd address", NDebug);
927                 error(Ebadarg);
928         }
929 }