|
|
1.1 root 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:
10: void noted(Ureg*, ulong);
11:
12: void intr0(void), intr1(void), intr2(void), intr3(void);
13: void intr4(void), intr5(void), intr6(void), intr7(void);
14: void intr8(void), intr9(void), intr10(void), intr11(void);
15: void intr12(void), intr13(void), intr14(void), intr15(void);
16: void intr16(void);
17: void intr24(void), intr25(void), intr26(void), intr27(void);
18: void intr28(void), intr29(void), intr30(void), intr31(void);
19: void intr32(void), intr33(void), intr34(void), intr35(void);
20: void intr36(void), intr37(void), intr38(void), intr39(void);
21: void intr64(void);
22: void intrbad(void);
23:
24: int int0mask = 0xff; /* interrupts enabled for first 8259 */
25: int int1mask = 0xff; /* interrupts enabled for second 8259 */
26:
27: /*
28: * trap/interrupt gates
29: */
30: Segdesc ilt[256];
31: int badintr[16];
32:
33: enum
34: {
35: Maxhandler= 128, /* max number of interrupt handlers */
36: };
37:
38: typedef struct Handler Handler;
39: struct Handler
40: {
41: void (*r)(void*, void*);
42: void *arg;
43: Handler *next;
44: };
45:
46: struct
47: {
48: Lock;
49: Handler *ivec[256];
50: Handler h[Maxhandler];
51: int free;
52: } halloc;
53:
54: void
55: sethvec(int v, void (*r)(void), int type, int pri)
56: {
57: ilt[v].d0 = ((ulong)r)&0xFFFF|(KESEL<<16);
58: ilt[v].d1 = ((ulong)r)&0xFFFF0000|SEGP|SEGPL(pri)|type;
59: }
60:
61: void
62: setvec(int v, void (*r)(Ureg*, void*), void *arg)
63: {
64: Handler *h;
65:
66: lock(&halloc);
67: if(halloc.free >= Maxhandler)
68: panic("out of interrupt handlers");
69: h = &halloc.h[halloc.free++];
70: h->next = halloc.ivec[v];
71: h->r = r;
72: h->arg = arg;
73: halloc.ivec[v] = h;
74: unlock(&halloc);
75:
76: /*
77: * enable corresponding interrupt in 8259
78: */
79: if((v&~0x7) == Int0vec){
80: int0mask &= ~(1<<(v&7));
81: outb(Int0aux, int0mask);
82: } else if((v&~0x7) == Int1vec){
83: int1mask &= ~(1<<(v&7));
84: outb(Int1aux, int1mask);
85: }
86: }
87:
88: void
89: debugbpt(Ureg *ur, void *a)
90: {
91: char buf[ERRLEN];
92:
93: USED(a);
94:
95: if(u == 0)
96: panic("kernel bpt");
97: /* restore pc to instruction that caused the trap */
98: ur->pc--;
99: sprint(buf, "sys: breakpoint");
100: postnote(u->p, 1, buf, NDebug);
101: }
102:
103: /*
104: * set up the interrupt/trap gates
105: */
106: void
107: trapinit(void)
108: {
109: int i;
110:
111: /*
112: * set all interrupts to panics
113: */
114: for(i = 0; i < 256; i++)
115: sethvec(i, intrbad, SEGTG, 0);
116:
117: /*
118: * 80386 processor (and coprocessor) traps
119: */
120: sethvec(0, intr0, SEGTG, 0);
121: sethvec(1, intr1, SEGTG, 0);
122: sethvec(2, intr2, SEGTG, 0);
123: sethvec(4, intr4, SEGTG, 0);
124: sethvec(5, intr5, SEGTG, 0);
125: sethvec(6, intr6, SEGTG, 0);
126: sethvec(7, intr7, SEGTG, 0);
127: sethvec(8, intr8, SEGTG, 0);
128: sethvec(9, intr9, SEGTG, 0);
129: sethvec(10, intr10, SEGTG, 0);
130: sethvec(11, intr11, SEGTG, 0);
131: sethvec(12, intr12, SEGTG, 0);
132: sethvec(13, intr13, SEGTG, 0);
133: sethvec(14, intr14, SEGIG, 0); /* page fault, interrupts off */
134: sethvec(15, intr15, SEGTG, 0);
135: sethvec(16, intr16, SEGIG, 0); /* math coprocessor, interrupts off */
136:
137: /*
138: * device interrupts
139: */
140: sethvec(24, intr24, SEGIG, 0);
141: sethvec(25, intr25, SEGIG, 0);
142: sethvec(26, intr26, SEGIG, 0);
143: sethvec(27, intr27, SEGIG, 0);
144: sethvec(28, intr28, SEGIG, 0);
145: sethvec(29, intr29, SEGIG, 0);
146: sethvec(30, intr30, SEGIG, 0);
147: sethvec(31, intr31, SEGIG, 0);
148: sethvec(32, intr32, SEGIG, 0);
149: sethvec(33, intr33, SEGIG, 0);
150: sethvec(34, intr34, SEGIG, 0);
151: sethvec(35, intr35, SEGIG, 0);
152: sethvec(36, intr36, SEGIG, 0);
153: sethvec(37, intr37, SEGIG, 0);
154: sethvec(38, intr38, SEGIG, 0);
155: sethvec(39, intr39, SEGIG, 0);
156:
157: /*
158: * system calls and break points
159: */
160: sethvec(Syscallvec, intr64, SEGTG, 3);
161: setvec(Syscallvec, (void (*)(Ureg*, void*))syscall, 0);
162: sethvec(Bptvec, intr3, SEGTG, 3);
163: setvec(Bptvec, debugbpt, 0);
164:
165: /*
166: * tell the hardware where the table is (and how long)
167: */
168: putidt(ilt, sizeof(ilt));
169:
170: /*
171: * Set up the first 8259 interrupt processor.
172: * Make 8259 interrupts start at CPU vector Int0vec.
173: * Set the 8259 as master with edge triggered
174: * input with fully nested interrupts.
175: */
176: outb(Int0ctl, (1<<4)|(0<<3)|(1<<0)); /* ICW1 - edge triggered, master,
177: ICW4 will be sent */
178: outb(Int0aux, Int0vec); /* ICW2 - interrupt vector offset */
179: outb(Int0aux, 0x04); /* ICW3 - have slave on level 2 */
180: outb(Int0aux, 0x01); /* ICW4 - 8086 mode, not buffered */
181:
182: /*
183: * Set up the second 8259 interrupt processor.
184: * Make 8259 interrupts start at CPU vector Int0vec.
185: * Set the 8259 as master with edge triggered
186: * input with fully nested interrupts.
187: */
188: outb(Int1ctl, (1<<4)|(0<<3)|(1<<0)); /* ICW1 - edge triggered, master,
189: ICW4 will be sent */
190: outb(Int1aux, Int1vec); /* ICW2 - interrupt vector offset */
191: outb(Int1aux, 0x02); /* ICW3 - I am a slave on level 2 */
192: outb(Int1aux, 0x01); /* ICW4 - 8086 mode, not buffered */
193:
194: /*
195: * pass #2 8259 interrupts to #1
196: */
197: int0mask &= ~0x04;
198: outb(Int0aux, int0mask);
199:
200: /*
201: * Set Ocw3 to return the ISR when ctl read.
202: */
203: outb(Int0ctl, Ocw3|0x03);
204: outb(Int1ctl, Ocw3|0x03);
205: }
206:
207: char *excname[] = {
208: [0] "divide error",
209: [1] "debug exception",
210: [2] " nonmaskable interrupt",
211: [3] "breakpoint",
212: [4] "overflow",
213: [5] "bounds check",
214: [6] "invalid opcode",
215: [7] "coprocessor not available",
216: [8] "double fault",
217: [9] "9 (reserved)",
218: [10] "invalid TSS",
219: [11] "segment not present",
220: [12] "stack exception",
221: [13] "general protection violation",
222: [14] "page fault",
223: [15] "15 (reserved)",
224: [16] "coprocessor error",
225: };
226:
227:
228: /*
229: * All traps
230: */
231: void
232: trap(Ureg *ur)
233: {
234: int v, user;
235: int c;
236: char buf[ERRLEN];
237: Handler *h;
238: static ulong intrtime;
239: static int snoozing;
240: static int iret_traps;
241: ushort isr;
242:
243: v = ur->trap;
244:
245: user = ((ur->cs)&0xffff)!=KESEL && v!=Syscallvec;
246: if(user)
247: u->dbgreg = ur;
248: else if(ur->pc >= KTZERO && ur->pc < (ulong)end && *(uchar*)ur->pc == 0xCF) {
249: if(iret_traps++ > 10)
250: panic("iret trap");
251: return;
252: }
253: iret_traps = 0;
254:
255: /*
256: * tell the 8259 that we're done with the
257: * highest level interrupt (interrupts are still
258: * off at this point)
259: */
260: c = v&~0x7;
261: isr = 0;
262: if(c==Int0vec || c==Int1vec){
263: isr = inb(Int0ctl);
264: outb(Int0ctl, EOI);
265: if(c == Int1vec){
266: isr |= inb(Int1ctl)<<8;
267: outb(Int1ctl, EOI);
268: }
269: }
270:
271: if(v>=256 || (h = halloc.ivec[v]) == 0){
272: /* an old 386 generates these fairly often, no idea why */
273: if(v == 13)
274: return;
275:
276: /* a processor or coprocessor error */
277: if(v <= 16){
278: if(user){
279: sprint(buf, "sys: trap: %s", excname[v]);
280: postnote(u->p, 1, buf, NDebug);
281: return;
282: } else {
283: dumpregs(ur);
284: panic("%s pc=0x%lux", excname[v], ur->pc);
285: }
286: }
287:
288: if(v >= Int0vec && v < Int0vec+16){
289: /* an unknown interrupt */
290: v -= Int0vec;
291: /*
292: * Check for a default IRQ7. This can happen when
293: * the IRQ input goes away before the acknowledge.
294: * In this case, a 'default IRQ7' is generated, but
295: * the corresponding bit in the ISR isn't set.
296: * In fact, just ignore all such interrupts.
297: */
298: if((isr & (1<<v)) == 0)
299: return;
300: if(badintr[v]++ == 0 || (badintr[v]%100000) == 0){
301: print("unknown interrupt %d pc=0x%lux: total %d\n", v,
302: ur->pc, badintr[v]);
303: print("isr = 0x%4.4ux\n", isr);
304: }
305: } else {
306: /* unimplemented traps */
307: print("illegal trap %d pc=0x%lux\n", v, ur->pc);
308: }
309: return;
310: }
311:
312: /* there may be multiple handlers on one interrupt level */
313: do {
314: (*h->r)(ur, h->arg);
315: h = h->next;
316: } while(h);
317: splhi();
318:
319: /* power management */
320: if(v == Clockvec){
321: /* allow power sheding on clock ticks */
322: if(arch->snooze)
323: snoozing = (*arch->snooze)(intrtime, 0);
324: } else {
325: /* turn power back on when anything else happens */
326: if(snoozing && arch->snooze)
327: snoozing = (*arch->snooze)(intrtime, 1);
328: intrtime = m->ticks;
329: }
330:
331: /* check user since syscall does its own notifying */
332: if(user && (u->p->procctl || u->nnote))
333: notify(ur);
334: }
335:
336: /*
337: * dump registers
338: */
339: void
340: dumpregs2(Ureg *ur)
341: {
342: if(u)
343: print("registers for %s %d\n", u->p->text, u->p->pid);
344: else
345: print("registers for kernel\n");
346: print("FLAGS=%lux TRAP=%lux ECODE=%lux CS=%lux PC=%lux", ur->flags, ur->trap,
347: ur->ecode, ur->cs&0xff, ur->pc);
348: if(ur == (Ureg*)UREGADDR)
349: print(" SS=%lux USP=%lux\n", ur->ss&0xff, ur->usp);
350: else
351: print("\n");
352: print(" AX %8.8lux BX %8.8lux CX %8.8lux DX %8.8lux\n",
353: ur->ax, ur->bx, ur->cx, ur->dx);
354: print(" SI %8.8lux DI %8.8lux BP %8.8lux\n",
355: ur->si, ur->di, ur->bp);
356: print(" DS %4.4ux ES %4.4ux FS %4.4ux GS %4.4ux\n",
357: ur->ds&0xffff, ur->es&0xffff, ur->fs&0xffff, ur->gs&0xffff);
358:
359: }
360:
361: void
362: dumpregs(Ureg *ur)
363: {
364: dumpregs2(ur);
365: print(" ur %lux\n", ur);
366: }
367:
368: void
369: dumpstack(void)
370: {
371: ulong l, v, i;
372: extern ulong etext;
373:
374: if(u == 0)
375: return;
376:
377: i = 0;
378: for(l=(ulong)&l; l<USERADDR+BY2PG; l+=4){
379: v = *(ulong*)l;
380: if(KTZERO < v && v < (ulong)&etext){
381: print("%lux ", v);
382: i++;
383: }
384: if(i == 4){
385: i = 0;
386: print("\n");
387: }
388: }
389:
390: }
391:
392: long
393: execregs(ulong entry, ulong ssize, ulong nargs)
394: {
395: ulong *sp;
396:
397: sp = (ulong*)(USTKTOP - ssize);
398: *--sp = nargs;
399: ((Ureg*)UREGADDR)->usp = (ulong)sp;
400: ((Ureg*)UREGADDR)->pc = entry;
401: return USTKTOP-BY2WD; /* address of user-level clock */
402: }
403:
404: ulong
405: userpc(void)
406: {
407: return ((Ureg*)UREGADDR)->pc;
408: }
409:
410: /*
411: * system calls
412: */
413: #include "../port/systab.h"
414:
415: /*
416: * syscall is called spllo()
417: */
418: long
419: syscall(Ureg *ur, void *a)
420: {
421: ulong sp;
422: long ret;
423: int i;
424:
425: USED(a);
426:
427: u->p->insyscall = 1;
428: u->p->pc = ur->pc;
429: if((ur->cs)&0xffff == KESEL)
430: panic("recursive system call");
431:
432: u->scallnr = ur->ax;
433: if(u->scallnr == RFORK && u->p->fpstate == FPactive){
434: /*
435: * so that the child starts out with the
436: * same registers as the parent
437: */
438: splhi();
439: if(u->p->fpstate == FPactive){
440: fpsave(&u->fpsave);
441: u->p->fpstate = FPinactive;
442: }
443: spllo();
444: }
445: sp = ur->usp;
446: u->nerrlab = 0;
447: ret = -1;
448: if(!waserror()){
449: if(u->scallnr >= sizeof systab/BY2WD){
450: pprint("bad sys call number %d pc %lux\n", u->scallnr, ur->pc);
451: postnote(u->p, 1, "sys: bad sys call", NDebug);
452: error(Ebadarg);
453: }
454:
455: if(sp<(USTKTOP-BY2PG) || sp>(USTKTOP-(1+MAXSYSARG)*BY2WD))
456: validaddr(sp, (1+MAXSYSARG)*BY2WD, 0);
457:
458: u->s = *((Sargs*)(sp+1*BY2WD));
459: u->p->psstate = sysctab[u->scallnr];
460:
461: ret = (*systab[u->scallnr])(u->s.args);
462: poperror();
463: }
464: if(u->nerrlab){
465: print("bad errstack [%d]: %d extra\n", u->scallnr, u->nerrlab);
466: for(i = 0; i < NERR; i++)
467: print("sp=%lux pc=%lux\n", u->errlab[i].sp, u->errlab[i].pc);
468: panic("error stack");
469: }
470:
471: u->p->insyscall = 0;
472: u->p->psstate = 0;
473:
474: /*
475: * Put return value in frame. On the safari the syscall is
476: * just another trap and the return value from syscall is
477: * ignored. On other machines the return value is put into
478: * the results register by caller of syscall.
479: */
480: ur->ax = ret;
481:
482: if(u->scallnr == NOTED)
483: noted(ur, *(ulong*)(sp+BY2WD));
484:
485: splhi(); /* avoid interrupts during the iret */
486: if(u->scallnr!=RFORK && (u->p->procctl || u->nnote))
487: notify(ur);
488:
489: return ret;
490: }
491:
492: /*
493: * Call user, if necessary, with note.
494: * Pass user the Ureg struct and the note on his stack.
495: */
496: int
497: notify(Ureg *ur)
498: {
499: int l;
500: ulong s, sp;
501: Note *n;
502:
503: if(u->p->procctl)
504: procctl(u->p);
505: if(u->nnote == 0)
506: return 0;
507:
508: s = spllo();
509: qlock(&u->p->debug);
510: u->p->notepending = 0;
511: n = &u->note[0];
512: if(strncmp(n->msg, "sys:", 4) == 0){
513: l = strlen(n->msg);
514: if(l > ERRLEN-15) /* " pc=0x12345678\0" */
515: l = ERRLEN-15;
516: sprint(n->msg+l, " pc=0x%.8lux", ur->pc);
517: }
518:
519: if(n->flag!=NUser && (u->notified || u->notify==0)){
520: if(n->flag == NDebug){
521: qunlock(&u->p->debug);
522: pprint("suicide: %s\n", n->msg);
523: }else
524: qunlock(&u->p->debug);
525: pexit(n->msg, n->flag!=NDebug);
526: }
527:
528: if(u->notified) {
529: qunlock(&u->p->debug);
530: splhi();
531: return 0;
532: }
533:
534: if(!u->notify){
535: qunlock(&u->p->debug);
536: pexit(n->msg, n->flag!=NDebug);
537: }
538: sp = ur->usp;
539: sp -= sizeof(Ureg);
540:
541: if(!okaddr((ulong)u->notify, 1, 0)
542: || !okaddr(sp-ERRLEN-4*BY2WD, sizeof(Ureg)+ERRLEN+4*BY2WD, 1)){
543: qunlock(&u->p->debug);
544: pprint("suicide: bad address in notify\n");
545: pexit("Suicide", 0);
546: }
547:
548: u->ureg = (void*)sp;
549: memmove((Ureg*)sp, ur, sizeof(Ureg));
550: *(Ureg**)(sp-BY2WD) = u->ureg; /* word under Ureg is old u->ureg */
551: u->ureg = (void*)sp;
552: sp -= BY2WD+ERRLEN;
553: memmove((char*)sp, u->note[0].msg, ERRLEN);
554: sp -= 3*BY2WD;
555: *(ulong*)(sp+2*BY2WD) = sp+3*BY2WD; /* arg 2 is string */
556: *(ulong*)(sp+1*BY2WD) = (ulong)u->ureg; /* arg 1 is ureg* */
557: *(ulong*)(sp+0*BY2WD) = 0; /* arg 0 is pc */
558: ur->usp = sp;
559: ur->pc = (ulong)u->notify;
560: u->notified = 1;
561: u->nnote--;
562: memmove(&u->lastnote, &u->note[0], sizeof(Note));
563: memmove(&u->note[0], &u->note[1], u->nnote*sizeof(Note));
564:
565: qunlock(&u->p->debug);
566: splx(s);
567: return 1;
568: }
569:
570: /*
571: * Return user to state before notify()
572: */
573: void
574: noted(Ureg *ur, ulong arg0)
575: {
576: Ureg *nur;
577: ulong oureg, sp;
578:
579: qlock(&u->p->debug);
580: if(arg0!=NRSTR && !u->notified) {
581: qunlock(&u->p->debug);
582: pprint("call to noted() when not notified\n");
583: pexit("Suicide", 0);
584: }
585: u->notified = 0;
586:
587: nur = u->ureg; /* pointer to user returned Ureg struct */
588:
589: /* sanity clause */
590: oureg = (ulong)nur;
591: if(!okaddr((ulong)oureg-BY2WD, BY2WD+sizeof(Ureg), 0)){
592: qunlock(&u->p->debug);
593: pprint("bad u->ureg in noted or call to noted() when not notified\n");
594: pexit("Suicide", 0);
595: }
596:
597: /* don't let user change text or stack segments */
598: nur->cs = ur->cs;
599: nur->ss = ur->ss;
600:
601: /* don't let user change system flags */
602: nur->flags = (ur->flags & ~0xCD5) | (nur->flags & 0xCD5);
603:
604: memmove(ur, nur, sizeof(Ureg));
605:
606: switch(arg0){
607: case NCONT:
608: case NRSTR:
609: if(!okaddr(nur->pc, 1, 0) || !okaddr(nur->usp, BY2WD, 0)){
610: qunlock(&u->p->debug);
611: pprint("suicide: trap in noted\n");
612: pexit("Suicide", 0);
613: }
614: u->ureg = (Ureg*)(*(ulong*)(oureg-BY2WD));
615: qunlock(&u->p->debug);
616: break;
617:
618: case NSAVE:
619: if(!okaddr(nur->pc, BY2WD, 0) || !okaddr(nur->usp, BY2WD, 0)){
620: qunlock(&u->p->debug);
621: pprint("suicide: trap in noted\n");
622: pexit("Suicide", 0);
623: }
624: qunlock(&u->p->debug);
625: sp = oureg-4*BY2WD-ERRLEN;
626: splhi();
627: ur->sp = sp;
628: ((ulong*)sp)[1] = oureg; /* arg 1 0(FP) is ureg* */
629: ((ulong*)sp)[0] = 0; /* arg 0 is pc */
630: break;
631:
632: default:
633: u->lastnote.flag = NDebug;
634: qunlock(&u->p->debug);
635: pprint("unknown noted arg 0x%lux\n", arg0);
636: pprint("suicide: %s\n", u->lastnote.msg);
637: pexit(u->lastnote.msg, 0);
638: break;
639:
640: case NDFLT:
641: if(u->lastnote.flag == NDebug){
642: qunlock(&u->p->debug);
643: pprint("suicide: %s\n", u->lastnote.msg);
644: }else
645: qunlock(&u->p->debug);
646: pexit(u->lastnote.msg, u->lastnote.flag!=NDebug);
647: }
648: }
649:
650: /* This routine must save the values of registers the user is not permitted to write
651: * from devproc and the restore the saved values before returning
652: */
653: void
654: setregisters(Ureg *xp, char *pureg, char *uva, int n)
655: {
656: ulong flags;
657: ulong cs;
658: ulong ss;
659:
660: flags = xp->flags;
661: cs = xp->cs;
662: ss = xp->ss;
663: memmove(pureg, uva, n);
664: xp->flags = (xp->flags & 0xff) | (flags & 0xff00);
665: xp->cs = cs;
666: xp->ss = ss;
667: }
This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.