|
|
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.