FreeBSD/Linux Kernel Cross Reference
sys/alphapc/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 "io.h"
8 #include "../port/error.h"
9
10 void noted(Ureg*, Ureg**, ulong);
11 void rfnote(Ureg**);
12 void kernfault(Ureg*, int);
13 void illegal(Ureg *);
14 void fen(Ureg *);
15
16 char *regname[]={
17 "type", "a0", "a1",
18 "a2", "R0", "R1",
19 "R2", "R3", "R4",
20 "R5", "R6", "R7",
21 "R8", "R9", "R10",
22 "R11", "R12", "R13",
23 "R14", "R15", "R19",
24 "R20", "R21", "R22",
25 "R23", "R24", "R25",
26 "R26", "R27", "R28",
27 "R30", "status", "PC",
28 "R29", "R16", "R17",
29 "R18",
30 };
31
32 static Lock vctllock;
33 static Vctl *vctl[256];
34
35 void
36 intrenable(int irq, void (*f)(Ureg*, void*), void* a, int tbdf, char *name)
37 {
38 int vno;
39 Vctl *v;
40
41 if(f == nil){
42 print("intrenable: nil handler for %d, tbdf 0x%uX for %s\n",
43 irq, tbdf, name);
44 return;
45 }
46
47 v = xalloc(sizeof(Vctl));
48 v->isintr = 1;
49 v->irq = irq;
50 v->tbdf = tbdf;
51 v->f = f;
52 v->a = a;
53 strncpy(v->name, name, KNAMELEN-1);
54 v->name[KNAMELEN-1] = 0;
55
56 ilock(&vctllock);
57 vno = arch->intrenable(v);
58 if(vno == -1){
59 iunlock(&vctllock);
60 print("intrenable: couldn't enable irq %d, tbdf 0x%uX for %s\n",
61 irq, tbdf, v->name);
62 xfree(v);
63 return;
64 }
65 if(vctl[vno]){
66 if(vctl[vno]->isr != v->isr || vctl[vno]->eoi != v->eoi)
67 panic("intrenable: handler: %s %s %#p %#p %#p %#p",
68 vctl[vno]->name, v->name,
69 vctl[vno]->isr, v->isr, vctl[vno]->eoi, v->eoi);
70 v->next = vctl[vno];
71 }
72 vctl[vno] = v;
73 iunlock(&vctllock);
74 }
75
76 int
77 intrdisable(int irq, void (*f)(Ureg *, void *), void *a, int tbdf, char *name)
78 {
79 Vctl **pv, *v;
80 int vno;
81
82 /*
83 * For now, none of this will work with the APIC code,
84 * there is no mapping between irq and vector as the IRQ
85 * is pretty meaningless.
86 */
87 if(arch->intrvecno == nil)
88 return -1;
89 vno = arch->intrvecno(irq);
90 ilock(&vctllock);
91 for(pv = &vctl[vno]; *pv != nil; pv = &((*pv)->next)){
92 if((*pv)->irq != irq)
93 continue;
94 if((*pv)->tbdf != tbdf)
95 continue;
96 if((*pv)->f != f)
97 continue;
98 if((*pv)->a != a)
99 continue;
100 if(strcmp((*pv)->name, name) != 0)
101 continue;
102 break;
103 }
104 assert(*pv != nil);
105
106 v = *pv;
107 *pv = (*pv)->next; /* Link out the entry */
108
109 if (vctl[vno] == nil && arch->intrdisable != nil)
110 arch->intrdisable(irq);
111 iunlock(&vctllock);
112 xfree(v);
113 return 0;
114 }
115
116 int
117 irqallocread(char *buf, long n, vlong offset)
118 {
119 int vno;
120 Vctl *v;
121 long oldn;
122 char str[11+1+KNAMELEN+1], *p;
123 int m;
124
125 if(n < 0 || offset < 0)
126 error(Ebadarg);
127
128 oldn = n;
129 for(vno=0; vno<nelem(vctl); vno++){
130 for(v=vctl[vno]; v; v=v->next){
131 m = snprint(str, sizeof str, "%11d %11d %.*s\n", vno, v->irq, KNAMELEN, v->name);
132 if(m <= offset) /* if do not want this, skip entry */
133 offset -= m;
134 else{
135 /* skip offset bytes */
136 m -= offset;
137 p = str+offset;
138 offset = 0;
139
140 /* write at most max(n,m) bytes */
141 if(m > n)
142 m = n;
143 memmove(buf, p, m);
144 n -= m;
145 buf += m;
146
147 if(n == 0)
148 return oldn;
149 }
150 }
151 }
152 return oldn - n;
153 }
154
155 typedef struct Mcheck Mcheck;
156 struct Mcheck
157 {
158 ulong len;
159 ulong inprogress;
160 ulong procoff;
161 ulong sysoff;
162 ulong code;
163 };
164
165 static char *
166 smcheck(ulong code)
167 {
168 switch (code) {
169 case 0x80: return "tag parity error";
170 case 0x82: return "tag control parity error";
171 case 0x84: return "generic hard error";
172 case 0x86: return "correctable ECC error";
173 case 0x88: return "uncorrectable ECC error";
174 case 0x8a: return "OS-specific PAL bugcheck";
175 case 0x90: return "callsys in kernel mode";
176 case 0x96: return "i-cache read retryable error";
177 case 0x98: return "processor detected hard error";
178
179 case 0x203: return "system detected uncorrectable ECC error";
180 case 0x205: return "parity error detected by CIA";
181 case 0x207: return "non-existent memory error";
182 case 0x209: return "PCI SERR detected";
183 case 0x20b: return "PCI data parity error detected";
184 case 0x20d: return "PCI address parity error detected";
185 case 0x20f: return "PCI master abort error";
186 case 0x211: return "PCI target abort error";
187 case 0x213: return "scatter/gather PTE invalid error";
188 case 0x215: return "flash ROM write error";
189 case 0x217: return "IOA timeout detected";
190 case 0x219: return "IOCHK#, EISA add-in board parity or other catastrophic error";
191 case 0x21b: return "EISA fail-safe timer timeout";
192 case 0x21d: return "EISA bus time-out";
193 case 0x21f: return "EISA software generated NMI";
194 case 0x221: return "unexpected ev5 IRQ[3] interrupt";
195 default: return "unknown mcheck";
196 }
197 }
198
199 void
200 mcheck(Ureg *ur, void *x)
201 {
202 Mcheck *m;
203 uvlong *data;
204 int i, col;
205
206 m = x;
207 data = x;
208 iprint("panic: Machine Check @%#p: %s (%lux) len %lud\n",
209 m, smcheck(m->code), m->code, m->len);
210 iprint("proc offset %lux sys offset %lux\n", m->procoff, m->sysoff);
211 for (i = 0, col = 0; i < m->len/8; i++) {
212 iprint("%.3x: %.16llux%s", 8*i, data[i], (col == 2) ? "\n" : " ");
213 if (col++ == 2)
214 col = 0;
215 }
216 if(col != 2)
217 print("\n");
218 print("\n");
219 dumpregs(ur);
220 prflush();
221 firmware();
222 }
223
224 void
225 intr(Ureg *ur)
226 {
227 int i, vno;
228 Vctl *ctl, *v;
229 Mach *mach;
230
231 vno = (ulong)ur->a1>>4;
232 vno -= 0x80;
233 if(vno < nelem(vctl) && (ctl = vctl[vno])){
234 if(ctl->isintr){
235 m->intr++;
236 if(vno >= VectorPIC && vno <= MaxVectorPIC)
237 m->lastintr = vno-VectorPIC;
238 }
239
240 if(ctl->isr)
241 ctl->isr(vno);
242 for(v = ctl; v != nil; v = v->next) {
243 if(v->f)
244 v->f(ur, v->a);
245 }
246
247 if(ctl->eoi)
248 ctl->eoi(vno);
249
250 if(ctl->isintr && up)
251 preempted();
252 }
253 else if(vno >= VectorPIC && vno <= MaxVectorPIC){
254 /*
255 * An unknown interrupt.
256 * Check for a default IRQ7. This can happen when
257 * the IRQ input goes away before the acknowledge.
258 * In this case, a 'default IRQ7' is generated, but
259 * the corresponding bit in the ISR isn't set.
260 * In fact, just ignore all such interrupts.
261 */
262 iprint("cpu%d: spurious interrupt %d, last %d",
263 m->machno, vno-VectorPIC, m->lastintr);
264 for(i = 0; i < 32; i++){
265 if(!(active.machs & (1<<i)))
266 continue;
267 mach = MACHP(i);
268 if(m->machno == mach->machno)
269 continue;
270 iprint(": cpu%d: last %d", mach->machno, mach->lastintr);
271 }
272 iprint("\n");
273 m->spuriousintr++;
274 return;
275 }
276 else{
277 dumpregs(ur);
278 print("unknown intr: %d\n", vno); /* */
279 }
280 }
281
282 void
283 trap(Ureg *ur)
284 {
285 char buf[ERRMAX];
286 int clockintr, user, x;
287
288 user = ur->status&UMODE;
289
290 if(user){
291 up = m->proc;
292 up->dbgreg = ur;
293 }
294 clockintr = 0;
295 switch ((int)ur->type) {
296 case 1: /* arith */
297 fptrap(ur);
298 break;
299 case 2: /* bad instr or FEN */
300 illegal(ur);
301 break;
302
303 case 3: /* intr */
304 m->intr++;
305 switch ((int)ur->a0) {
306 case 0: /* interprocessor */
307 panic("interprocessor intr");
308 break;
309 case 1: /* clock */
310 clockintr = 1;
311 clock(ur);
312 break;
313 case 2: /* machine check */
314 mcheck(ur, (void*)(KZERO|(ulong)ur->a2));
315 break;
316 case 3: /* device */
317 intr(ur);
318 break;
319 case 4: /* perf counter */
320 panic("perf count");
321 break;
322 default:
323 panic("bad intr");
324 break;
325 }
326 break;
327
328 case 4: /* memory fault */
329 if(up == 0)
330 kernfault(ur, (ulong)ur->a1);
331
332 x = up->insyscall;
333 up->insyscall = 1;
334 spllo();
335 faultalpha(ur);
336 up->insyscall = x;
337 break;
338 case 6: /* alignment fault */
339 ur->pc -= 4;
340 sprint(buf, "trap: unaligned addr 0x%lux", (ulong)ur->a0);
341 fataltrap(ur, buf);
342 break;
343 default: /* cannot happen */
344 panic("bad trap type %d", (int)ur->type);
345 break;
346 }
347
348 splhi();
349
350 /* delaysched set because we held a lock or because our quantum ended */
351 if(up && up->delaysched && clockintr){
352 sched();
353 splhi();
354 }
355
356 if(user){
357 if(up->procctl || up->nnote)
358 notify(ur);
359 kexit(ur);
360 }
361 }
362
363 void
364 trapinit(void)
365 {
366 splhi();
367 wrent(0, intr0);
368 wrent(1, arith);
369 wrent(2, fault0);
370 wrent(3, illegal0);
371 wrent(4, unaligned);
372 wrent(5, syscall0);
373 }
374
375 void
376 fataltrap(Ureg *ur, char *reason)
377 {
378 char buf[ERRMAX];
379
380 if(ur->status&UMODE) {
381 spllo();
382 sprint(buf, "sys: %s", reason);
383 postnote(up, 1, buf, NDebug);
384 return;
385 }
386 print("kernel %s pc=%lux\n", reason, (ulong)ur->pc);
387 dumpregs(ur);
388 dumpstack();
389 if(m->machno == 0)
390 spllo();
391 exit(1);
392 }
393
394 void
395 kernfault(Ureg *ur, int code)
396 {
397 Label l;
398 char *s;
399
400 splhi();
401 if (code == 0)
402 s = "read";
403 else if (code == 1)
404 s = "write";
405 else
406 s = "ifetch";
407 print("panic: kfault %s VA=0x%lux\n", s, (ulong)ur->a0);
408 print("u=%#p status=0x%lux pc=0x%lux sp=0x%lux\n",
409 up, (ulong)ur->status, (ulong)ur->pc, (ulong)ur->sp);
410 dumpregs(ur);
411 l.sp = ur->sp;
412 l.pc = ur->pc;
413 dumpstack();
414 exit(1);
415 }
416
417 void
418 dumpregs(Ureg *ur)
419 {
420 int i, col;
421 uvlong *l;
422
423 if(up)
424 print("registers for %s %ld\n", up->text, up->pid);
425 else
426 print("registers for kernel\n");
427
428 l = &ur->type;
429 col = 0;
430 for (i = 0; i < sizeof regname/sizeof(char*); i++, l++) {
431 print("%-7s%.16llux%s", regname[i], *l, col == 2 ? "\n" : " ");
432 if (col++ == 2)
433 col = 0;
434 }
435 print("\n");
436 }
437
438
439 /*
440 * Fill in enough of Ureg to get a stack trace, and call a function.
441 * Used by debugging interface rdb.
442 */
443 static void
444 getpcsp(ulong *pc, ulong *sp)
445 {
446 *pc = getcallerpc(&pc);
447 *sp = (ulong)&pc-8;
448 }
449
450 void
451 callwithureg(void (*fn)(Ureg*))
452 {
453 Ureg ureg;
454
455 getpcsp((ulong*)&ureg.pc, (ulong*)&ureg.sp);
456 ureg.r26 = getcallerpc(&fn);
457 fn(&ureg);
458 }
459
460 void
461 _dumpstack(Ureg *ureg)
462 {
463 ulong l, sl, el, v, i, instr, op;
464 extern ulong etext;
465
466 l=(ulong)&l;
467 if(l&4)
468 l += 4;
469 if(up == 0){
470 el = (ulong)m+BY2PG;
471 sl = el-KSTACK;
472 }
473 else{
474 sl = (ulong)up->kstack;
475 el = sl + KSTACK;
476 }
477 if(l > el || l < sl){
478 el = (ulong)m+BY2PG;
479 sl = el-KSTACK;
480 }
481 if(l > el || l < sl)
482 return;
483 print("ktrace /kernel/path %.8lux %.8lux %.8lux\n", (ulong)ureg->pc, (ulong)ureg->sp, (ulong)ureg->r26);
484
485 i = 0;
486 for(; l<el; l+=8){
487 v = *(ulong*)l - 4;
488 if(KTZERO < v && v < (ulong)&etext && (v&3) == 0){
489 /*
490 * Check for JSR/BSR
491 */
492 instr = *(ulong*)v;
493 op = (instr>>26);
494 if(op == 26 || op == 52){
495 print("%lux=%lux ", l, v);
496 i++;
497 }
498 }
499 if(i == 4){
500 i = 0;
501 print("\n");
502 }
503 }
504 if(i)
505 print("\n");
506 }
507
508 void
509 dumpstack(void)
510 {
511 callwithureg(_dumpstack);
512 }
513
514 int
515 notify(Ureg *ur)
516 {
517 int l;
518 ulong sp;
519 Note *n;
520
521 if(up->procctl)
522 procctl(up);
523 if(up->nnote == 0)
524 return 0;
525
526 spllo();
527 qlock(&up->debug);
528 up->notepending = 0;
529
530 if(up->fpstate == FPactive){
531 savefpregs(&up->fpsave);
532 up->fpstate = FPinactive;
533 }
534 up->fpstate |= FPillegal;
535
536 n = &up->note[0];
537 if(strncmp(n->msg, "sys:", 4) == 0) {
538 l = strlen(n->msg);
539 if(l > ERRMAX-15) /* " pc=0x12345678\0" */
540 l = ERRMAX-15;
541
542 sprint(n->msg+l, " pc=0x%lux", (ulong)ur->pc);
543 }
544
545 if(n->flag != NUser && (up->notified || up->notify==0)) {
546 if(n->flag == NDebug)
547 pprint("suicide: %s\n", n->msg);
548 qunlock(&up->debug);
549 pexit(n->msg, n->flag!=NDebug);
550 }
551
552 if(up->notified) {
553 qunlock(&up->debug);
554 splhi();
555 return 0;
556 }
557
558 if(!up->notify) {
559 qunlock(&up->debug);
560 pexit(n->msg, n->flag!=NDebug);
561 }
562 sp = ur->usp & ~(BY2V-1);
563 sp -= sizeof(Ureg);
564
565 if(!okaddr((ulong)up->notify, BY2WD, 0)
566 || !okaddr(sp-ERRMAX-6*BY2WD, sizeof(Ureg)+ERRMAX-6*BY2WD, 1)) {
567 pprint("suicide: bad address or sp in notify\n");
568 print("suicide: bad address or sp in notify\n");
569 qunlock(&up->debug);
570 pexit("Suicide", 0);
571 }
572
573 memmove((Ureg*)sp, ur, sizeof(Ureg));
574 *(Ureg**)(sp-BY2WD) = up->ureg; /* word under Ureg is old up->ureg */
575 up->ureg = (void*)sp;
576 sp -= 2*BY2WD+ERRMAX;
577 memmove((char*)sp, up->note[0].msg, ERRMAX);
578 sp -= 4*BY2WD;
579 *(ulong*)(sp+3*BY2WD) = sp+4*BY2WD; /* arg 2 is string */
580 ur->r0 = (ulong)up->ureg; /* arg 1 (R0) is ureg* */
581 *(ulong*)(sp+2*BY2WD) = (ulong)up->ureg; /* arg 1 0(FP) is ureg* */
582 *(ulong*)(sp+0*BY2WD) = 0; /* arg 0 is pc */
583 ur->usp = sp;
584 ur->pc = (ulong)up->notify;
585 up->notified = 1;
586 up->nnote--;
587 memmove(&up->lastnote, &up->note[0], sizeof(Note));
588 memmove(&up->note[0], &up->note[1], up->nnote*sizeof(Note));
589
590 qunlock(&up->debug);
591 splhi();
592 return 1;
593 }
594
595 /*
596 * Check that status is OK to return from note.
597 */
598 int
599 validstatus(ulong kstatus, ulong ustatus)
600 {
601 if((kstatus & 7) != (ustatus & 7))
602 return 0;
603 if((ustatus&UMODE) != UMODE)
604 return 0;
605 return 1;
606 }
607
608 /*
609 * Return user to state before notify()
610 */
611 void
612 noted(Ureg *kur, Ureg **urp, ulong arg0)
613 {
614 Ureg *nur;
615 ulong oureg, sp;
616
617 qlock(&up->debug);
618 if(arg0!=NRSTR && !up->notified) {
619 qunlock(&up->debug);
620 pprint("call to noted() when not notified\n");
621 print("call to noted() when not notified\n");
622 pexit("Suicide", 0);
623 }
624 up->notified = 0;
625
626 up->fpstate &= ~FPillegal;
627
628 nur = up->ureg;
629
630 oureg = (ulong)nur;
631 if((oureg & (BY2V-1))
632 || !okaddr((ulong)oureg-BY2WD, BY2WD+sizeof(Ureg), 0)){
633 pprint("bad ureg in noted or call to noted() when not notified\n");
634 print("bad ureg in noted or call to noted() when not notified\n");
635 qunlock(&up->debug);
636 pexit("Suicide", 0);
637 }
638
639 if(!validstatus(kur->status, nur->status)) {
640 qunlock(&up->debug);
641 pprint("bad noted ureg status %lux\n", (ulong)nur->status);
642 print("bad noted ureg status %lux\n", (ulong)nur->status);
643 pexit("Suicide", 0);
644 }
645
646 memmove(*urp, up->ureg, sizeof(Ureg));
647 switch(arg0) {
648 case NCONT:
649 case NRSTR:
650 if(!okaddr(nur->pc, BY2WD, 0) || !okaddr(nur->usp, BY2WD, 0)){
651 pprint("suicide: trap in noted\n");
652 print("suicide: trap in noted\n");
653 qunlock(&up->debug);
654 pexit("Suicide", 0);
655 }
656 up->ureg = (Ureg*)(*(ulong*)(oureg-BY2WD));
657 qunlock(&up->debug);
658 splhi();
659 rfnote(urp);
660 break;
661
662 case NSAVE:
663 if(!okaddr(nur->pc, BY2WD, 0) || !okaddr(nur->usp, BY2WD, 0)){
664 pprint("suicide: trap in noted\n");
665 print("suicide: trap in noted\n");
666 qunlock(&up->debug);
667 pexit("Suicide", 0);
668 }
669 qunlock(&up->debug);
670 sp = oureg-4*BY2WD-ERRMAX;
671 splhi();
672 (*urp)->sp = sp;
673 ((ulong*)sp)[1] = oureg; /* arg 1 0(FP) is ureg* */
674 ((ulong*)sp)[0] = 0; /* arg 0 is pc */
675 (*urp)->r0 = oureg; /* arg 1 is ureg* */
676 rfnote(urp);
677 break;
678
679 default:
680 pprint("unknown noted arg 0x%lux\n", arg0);
681 print("unknown noted arg 0x%lux\n", arg0);
682 up->lastnote.flag = NDebug;
683 /* fall through */
684
685 case NDFLT:
686 if(up->lastnote.flag == NDebug)
687 pprint("suicide: %s\n", up->lastnote.msg);
688 qunlock(&up->debug);
689 pexit(up->lastnote.msg, up->lastnote.flag!=NDebug);
690 }
691 }
692
693 #include "../port/systab.h"
694
695 long
696 syscall(Ureg *aur)
697 {
698 int i;
699 char *e;
700 long ret;
701 ulong sp;
702 Ureg *ur;
703 ulong scallnr;
704
705 m->syscall++;
706 up = m->proc;
707 up->insyscall = 1;
708 ur = aur;
709 up->pc = ur->pc;
710 up->dbgreg = aur;
711 ur->type = 5; /* for debugging */
712
713 scallnr = ur->r0;
714 up->scallnr = ur->r0;
715
716 if(scallnr == RFORK && up->fpstate == FPactive){
717 savefpregs(&up->fpsave);
718 up->fpstate = FPinactive;
719 //print("SR=%lux+", up->fpsave.fpstatus);
720 }
721 spllo();
722
723 sp = ur->sp;
724 up->nerrlab = 0;
725 ret = -1;
726 if(!waserror()) {
727 if(scallnr >= nsyscall || systab[scallnr] == nil){
728 pprint("bad sys call %d pc %lux\n", up->scallnr, (ulong)ur->pc);
729 postnote(up, 1, "sys: bad sys call", NDebug);
730 error(Ebadarg);
731 }
732
733 if(sp & (BY2WD-1)){ /* XXX too weak? */
734 pprint("odd sp in sys call pc %lux sp %lux\n",
735 (ulong)ur->pc, (ulong)ur->sp);
736 postnote(up, 1, "sys: odd stack", NDebug);
737 error(Ebadarg);
738 }
739
740 if(sp<(USTKTOP-BY2PG) || sp>(USTKTOP-sizeof(Sargs)))
741 validaddr(sp, sizeof(Sargs), 0);
742
743 up->s = *((Sargs*)(sp+2*BY2WD));
744 up->psstate = sysctab[scallnr];
745 ret = systab[scallnr](up->s.args);
746 poperror();
747 }else{
748 /* failure: save the error buffer for errstr */
749 e = up->syserrstr;
750 up->syserrstr = up->errstr;
751 up->errstr = e;
752 }
753 if(up->nerrlab){
754 print("bad errstack [%uld]: %d extra\n", scallnr, up->nerrlab);
755 for(i = 0; i < NERR; i++)
756 print("sp=%lux pc=%lux\n",
757 up->errlab[i].sp, up->errlab[i].pc);
758 panic("error stack");
759 }
760
761 up->nerrlab = 0;
762 up->psstate = 0;
763 up->insyscall = 0;
764 if(scallnr == NOTED) /* ugly hack */
765 noted(ur, &aur, *(ulong*)(sp+2*BY2WD)); /* doesn't return */
766
767 if(scallnr!=RFORK && (up->procctl || up->nnote)){
768 ur->r0 = ret; /* load up for noted() */
769 if(notify(ur))
770 return ur->r0;
771 }
772
773 return ret;
774 }
775
776 void
777 forkchild(Proc *p, Ureg *ur)
778 {
779 Ureg *cur;
780
781 p->sched.sp = (ulong)p->kstack+KSTACK-(4*BY2WD+sizeof(Ureg));
782 p->sched.pc = (ulong)forkret;
783
784 cur = (Ureg*)(p->sched.sp+4*BY2WD);
785 memmove(cur, ur, sizeof(Ureg));
786
787 /* Things from bottom of syscall we never got to execute */
788 p->psstate = 0;
789 p->insyscall = 0;
790 }
791
792 static
793 void
794 linkproc(void)
795 {
796 spllo();
797 up->kpfun(up->kparg);
798 pexit("kproc exiting", 0);
799 }
800
801 void
802 kprocchild(Proc *p, void (*func)(void*), void *arg)
803 {
804 p->sched.pc = (ulong)linkproc;
805 p->sched.sp = (ulong)p->kstack+KSTACK;
806
807 p->kpfun = func;
808 p->kparg = arg;
809 }
810
811 long
812 execregs(ulong entry, ulong ssize, ulong nargs)
813 {
814 Ureg *ur;
815 ulong *sp;
816
817 sp = (ulong*)(USTKTOP - ssize);
818 *--sp = nargs;
819
820 ur = (Ureg*)up->dbgreg;
821 ur->usp = (ulong)sp;
822 ur->pc = entry;
823 return USTKTOP-BY2WD; /* address of user-level clock */
824 }
825
826 ulong
827 userpc(void)
828 {
829 Ureg *ur;
830
831 ur = (Ureg*)up->dbgreg;
832 return ur->pc;
833 }
834
835 /* This routine must save the values of registers the user is not permitted to write
836 * from devproc and then restore the saved values before returning
837 */
838 void
839 setregisters(Ureg *xp, char *pureg, char *uva, int n)
840 {
841 ulong status;
842
843 status = xp->status;
844 memmove(pureg, uva, n);
845 xp->status = status;
846 }
847
848 /* Give enough context in the ureg to produce a kernel stack for
849 * a sleeping process
850 */
851 void
852 setkernur(Ureg *xp, Proc *p)
853 {
854 xp->pc = p->sched.pc;
855 xp->sp = p->sched.sp;
856 xp->r26 = (ulong)sched;
857 }
858
859 ulong
860 dbgpc(Proc *p)
861 {
862 Ureg *ur;
863
864 ur = p->dbgreg;
865 if(ur == 0)
866 return 0;
867
868 return ur->pc;
869 }
870
871 void
872 illegal(Ureg *ur)
873 {
874 switch ((int)ur->a0) {
875 case 0: /* breakpoint */
876 ur->pc -= 4;
877 fataltrap(ur, "breakpoint");
878 break;
879 case 1: /* bugchk */
880 fataltrap(ur, "trap: bugchk");
881 break;
882 case 2: /* gentrap */
883 fataltrap(ur, "trap: gentrap");
884 break;
885 case 3: /* FEN */
886 fen(ur);
887 break;
888 case 4: /* opDEC */
889 fataltrap(ur, "trap: illegal instruction");
890 break;
891 default:
892 panic("illegal illegal %d", (int)ur->a0);
893 break;
894 }
895 }
896
897 void
898 fen(Ureg *ur)
899 {
900 if(up){
901 switch(up->fpstate){
902 case FPinit:
903 restfpregs(&initfp);
904 up->fpstate = FPactive;
905 //print("EI=%lux+", initfp.fpstatus);
906 return;
907
908 case FPinactive:
909 restfpregs(&up->fpsave);
910 up->fpstate = FPactive;
911 //print("EIA=%lux+", up->fpsave.fpstatus);
912 return;
913 }
914 }
915 fataltrap(ur, "trap: floating enable"); /* should never happen */
916 }
Cache object: e8e2aacad23e441dd8cf341502558223
|