|
|
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 "ureg.h" ! 7: #include "io.h" ! 8: #include "../port/error.h" ! 9: ! 10: void noted(Ureg*, ulong); ! 11: void rfnote(Ureg*); ! 12: ! 13: char *regname[]={ ! 14: "R0", ! 15: "R1", ! 16: "R2", ! 17: "R3", ! 18: "R4", ! 19: "R5", ! 20: "R6", ! 21: "R7", ! 22: "A0", ! 23: "A1", ! 24: "A2", ! 25: "A3", ! 26: "A4", ! 27: "A5", ! 28: "A6", ! 29: "A7", ! 30: }; ! 31: ! 32: long ticks; ! 33: ! 34: char *trapname[]={ ! 35: "reset isp", ! 36: "reset ipc", ! 37: "bus error", ! 38: "address error", ! 39: "illegal instruction", ! 40: "zero divide", ! 41: "chk, chk2 instruction", ! 42: "trapcc instruction", ! 43: "privilege violation", ! 44: "trace", ! 45: "line 1010 emulator", ! 46: "line 1111 emulator", ! 47: "reserved", ! 48: "coprocessor protocol violation", ! 49: "format error", ! 50: "uninitialized interrupt", ! 51: "unassigned 0x40", ! 52: "unassigned 0x44", ! 53: "unassigned 0x48", ! 54: "unassigned 0x4C", ! 55: "unassigned 0x50", ! 56: "unassigned 0x54", ! 57: "unassigned 0x58", ! 58: "unassigned 0x5C", ! 59: "spurious interrupt", ! 60: "level 1 autovector (tac)", ! 61: "level 2 autovector (port)", ! 62: "level 3 autovector (incon)", ! 63: "level 4 autovector (mouse)", ! 64: "level 5 autovector (uart)", ! 65: "level 6 autovector (sync)", ! 66: "level 7 autovector", ! 67: }; ! 68: ! 69: char *fptrapname[]={ ! 70: [49-49] "inexact result", ! 71: [50-49] "divide by zero", ! 72: [51-49] "underflow", ! 73: [52-49] "operand error", ! 74: [53-49] "overflow", ! 75: [54-49] "signaling NaN", ! 76: }; ! 77: ! 78: char* ! 79: excname(unsigned vo, ulong pc) ! 80: { ! 81: static char buf[32]; /* BUG: not reentrant! */ ! 82: ulong fppc; ! 83: ! 84: vo &= 0x0FFF; ! 85: vo >>= 2; ! 86: if(vo < sizeof trapname/sizeof(char*)){ ! 87: /* special case, and pc will be o.k. */ ! 88: if(vo==4 && *(ushort*)pc==0x4848) ! 89: return "breakpoint"; ! 90: sprint(buf, "trap: %s", trapname[vo]); ! 91: return buf; ! 92: } ! 93: if(49<=vo && vo<=54){ ! 94: fppc = 0; ! 95: if(u) ! 96: fppc = *(ulong*)(u->fpsave.reg+8); ! 97: sprint(buf, "fp: %s fppc=0x%lux", fptrapname[vo-49], fppc); ! 98: return buf; ! 99: } ! 100: sprint(buf, "offset 0x%ux", vo<<2); ! 101: return buf; ! 102: } ! 103: ! 104: void ! 105: trap(Ureg *ur) ! 106: { ! 107: int user; ! 108: char buf[64]; ! 109: ! 110: user = !(ur->sr&SUPER); ! 111: ! 112: if(u) ! 113: u->dbgreg = ur; ! 114: ! 115: if(user){ ! 116: splhi(); ! 117: procsave(u->p); ! 118: spllo(); ! 119: sprint(buf, "sys: %s", excname(ur->vo, ur->pc)); ! 120: postnote(u->p, 1, buf, NDebug); ! 121: }else{ ! 122: print("kernel trap %s pc=0x%lux\n", excname(ur->vo, ur->pc), ur->pc); ! 123: dumpregs(ur); ! 124: exit(1); ! 125: } ! 126: ! 127: if(user) ! 128: notify(ur); ! 129: } ! 130: ! 131: void ! 132: dumpstack(void) ! 133: { ! 134: ulong l, v, i; ! 135: extern ulong etext; ! 136: ! 137: if(u==0) ! 138: return; ! 139: ! 140: i = 0; ! 141: for(l=(ulong)&l; l<USERADDR+BY2PG; l+=4){ ! 142: v = *(ulong*)l; ! 143: if(KTZERO < v && v < (ulong)&etext){ ! 144: print("%lux\t", v); ! 145: if(++i == 4){ ! 146: i = 0; ! 147: print("\n"); ! 148: } ! 149: } ! 150: } ! 151: print("\n"); ! 152: } ! 153: ! 154: void ! 155: dumpregs(Ureg *ur) ! 156: { ! 157: int i; ! 158: ulong *l; ! 159: ! 160: if(u) ! 161: print("registers for %s %d\n", u->p->text, u->p->pid); ! 162: else ! 163: print("registers for kernel\n"); ! 164: print("SR=%ux PC=%lux VO=%lux, USP=%lux\n", ur->sr, ur->pc, ur->vo, ur->usp); ! 165: l = &ur->r0; ! 166: for(i=0; i<sizeof regname/sizeof(char*); i+=2, l+=2) ! 167: print("%s\t%.8lux\t%s\t%.8lux\n", regname[i], l[0], regname[i+1], l[1]); ! 168: } ! 169: ! 170: /* ! 171: * Call user, if necessary, with note ! 172: */ ! 173: int ! 174: notify(Ureg *ur) ! 175: { ! 176: int l; ! 177: ulong s, sp; ! 178: Note *n; ! 179: ! 180: if(u->p->procctl) ! 181: procctl(u->p); ! 182: if(u->nnote == 0) ! 183: return 0; ! 184: ! 185: s = spllo(); ! 186: qlock(&u->p->debug); ! 187: u->p->notepending = 0; ! 188: n = &u->note[0]; ! 189: if(strncmp(n->msg, "sys:", 4) == 0){ ! 190: l = strlen(n->msg); ! 191: if(l > ERRLEN-15) /* " pc=0x12345678\0" */ ! 192: l = ERRLEN-15; ! 193: sprint(n->msg+l, " pc=0x%lux", ur->pc); ! 194: } ! 195: if(n->flag!=NUser && (u->notified || u->notify==0)){ ! 196: if(n->flag == NDebug){ ! 197: qunlock(&u->p->debug); ! 198: pprint("suicide: %s\n", n->msg); ! 199: }else ! 200: qunlock(&u->p->debug); ! 201: pexit(n->msg, n->flag!=NDebug); ! 202: } ! 203: ! 204: if(u->notified){ ! 205: qunlock(&u->p->debug); ! 206: splx(s); ! 207: return 0; ! 208: } ! 209: ! 210: if(!u->notify){ ! 211: qunlock(&u->p->debug); ! 212: pexit(n->msg, n->flag!=NDebug); ! 213: } ! 214: ! 215: sp = ur->usp - sizeof(Ureg); ! 216: ! 217: if(!okaddr((ulong)u->notify, BY2WD, 0) ! 218: || !okaddr(sp-ERRLEN-4*BY2WD, sizeof(Ureg)+ERRLEN+4*BY2WD, 1)){ ! 219: qunlock(&u->p->debug); ! 220: pprint("suicide: bad address in notify\n"); ! 221: pexit("Suicide", 0); ! 222: } ! 223: ! 224: memmove((Ureg*)sp, ur, sizeof(Ureg)); ! 225: *(Ureg**)(sp-BY2WD) = u->ureg; /* word under Ureg is old u->ureg */ ! 226: u->ureg = (void*)sp; ! 227: sp -= BY2WD+ERRLEN; ! 228: memmove((char*)sp, u->note[0].msg, ERRLEN); ! 229: sp -= 3*BY2WD; ! 230: *(ulong*)(sp+2*BY2WD) = sp+3*BY2WD; /* arg 2 is string */ ! 231: *(ulong*)(sp+1*BY2WD) = (ulong)u->ureg; /* arg 1 is ureg* */ ! 232: *(ulong*)(sp+0*BY2WD) = 0; /* arg 0 is pc */ ! 233: ur->usp = sp; ! 234: ur->pc = (ulong)u->notify; ! 235: ur->vo = 0x0080; /* pretend we're returning from syscall */ ! 236: u->notified = 1; ! 237: u->nnote--; ! 238: memmove(&u->lastnote, &u->note[0], sizeof(Note)); ! 239: memmove(&u->note[0], &u->note[1], u->nnote*sizeof(Note)); ! 240: qunlock(&u->p->debug); ! 241: splx(s); ! 242: return 1; ! 243: } ! 244: ! 245: /* ! 246: * Check that sr and vo are OK to return from note. ! 247: */ ! 248: int ! 249: validstatus(ushort usr, ushort uvo) ! 250: { ! 251: ushort fmt, vector; ! 252: static char okfmt[] = { 1, 1, 1, 0, 0, 0, 0, 0, 0, 1, 1, 1, 0, 0, 0, 0 }; ! 253: ! 254: fmt = uvo>>12; ! 255: if(!okfmt[fmt]) ! 256: return 0; ! 257: if(uvo & 3) /* offset must be even */ ! 258: return 0; ! 259: vector = (uvo & 0xFFF) >> 2; ! 260: if(vector<2 || vector >58) /* <2 is reset; greater than 58 is undefined */ ! 261: return 0; ! 262: if(usr & 0xFF00) /* system byte must be clear */ ! 263: return 0; ! 264: return 1; ! 265: } ! 266: ! 267: /* ! 268: * Return user to state before notify() ! 269: */ ! 270: void ! 271: noted(Ureg *ur, ulong arg0) ! 272: { ! 273: Ureg *nur; ! 274: ulong oureg, sp; ! 275: ! 276: qlock(&u->p->debug); ! 277: if(arg0!=NRSTR && !u->notified){ ! 278: qunlock(&u->p->debug); ! 279: pprint("call to noted() when not notified\n"); ! 280: pexit("Suicide", 0); ! 281: } ! 282: u->notified = 0; ! 283: ! 284: nur = u->ureg; ! 285: ! 286: oureg = (ulong)nur; ! 287: if((oureg & (BY2WD-1)) ! 288: || !okaddr((ulong)oureg-BY2WD, BY2WD+sizeof(Ureg), 0)){ ! 289: qunlock(&u->p->debug); ! 290: pprint("bad ureg in noted or call to noted() when not notified\n"); ! 291: pexit("Suicide", 0); ! 292: } ! 293: ! 294: if(!validstatus(nur->sr, nur->vo)){ ! 295: qunlock(&u->p->debug); ! 296: pprint("bad noted ureg sr %ux vo %ux\n", nur->sr, nur->vo); ! 297: pexit("Suicide", 0); ! 298: } ! 299: ! 300: memmove(ur, u->ureg, sizeof(Ureg)); ! 301: switch(arg0){ ! 302: case NCONT: ! 303: case NRSTR: ! 304: if(!okaddr(nur->pc, 2, 0) || !okaddr(nur->usp, BY2WD, 0)){ ! 305: qunlock(&u->p->debug); ! 306: pprint("suicide: trap in noted\n"); ! 307: pexit("Suicide", 0); ! 308: } ! 309: u->ureg = (Ureg*)(*(ulong*)(oureg-BY2WD)); ! 310: qunlock(&u->p->debug); ! 311: splhi(); ! 312: rfnote(ur); ! 313: break; ! 314: /* never returns */ ! 315: ! 316: case NSAVE: ! 317: if(!okaddr(nur->pc, 2, 0) || !okaddr(nur->usp, BY2WD, 0)){ ! 318: qunlock(&u->p->debug); ! 319: pprint("suicide: trap in noted\n"); ! 320: pexit("Suicide", 0); ! 321: } ! 322: qunlock(&u->p->debug); ! 323: sp = oureg-4*BY2WD-ERRLEN; ! 324: splhi(); ! 325: ur->vo = 0x0080; /* we're returning from syscall */ ! 326: ur->usp = sp; ! 327: ((ulong*)sp)[1] = oureg; /* arg 1 0(FP) is ureg* */ ! 328: ((ulong*)sp)[0] = 0; /* arg 0 is pc */ ! 329: rfnote(ur); ! 330: break; ! 331: ! 332: default: ! 333: u->lastnote.flag = NDebug; ! 334: qunlock(&u->p->debug); ! 335: pprint("unknown noted arg 0x%lux\n", arg0); ! 336: pprint("suicide: %s\n", u->lastnote.msg); ! 337: pexit(u->lastnote.msg, 0); ! 338: ! 339: case NDFLT: ! 340: if(u->lastnote.flag == NDebug){ ! 341: qunlock(&u->p->debug); ! 342: pprint("suicide: %s\n", u->lastnote.msg); ! 343: }else ! 344: qunlock(&u->p->debug); ! 345: pexit(u->lastnote.msg, u->lastnote.flag!=NDebug); ! 346: } ! 347: } ! 348: ! 349: #include "../port/systab.h" ! 350: ! 351: long ! 352: syscall(Ureg *aur) ! 353: { ! 354: long ret; ! 355: ulong sp; ! 356: Ureg *ur; ! 357: ! 358: u->p->insyscall = 1; ! 359: ur = aur; ! 360: u->dbgreg = aur; ! 361: u->p->pc = ur->pc; ! 362: if(ur->sr & SUPER) ! 363: panic("recursive system call"); ! 364: ! 365: /* must save FP registers before fork */ ! 366: if(u->p->fpstate==FPactive && ur->r0==RFORK){ ! 367: splhi(); ! 368: procsave(u->p); ! 369: spllo(); ! 370: } ! 371: ! 372: if(u->p->procctl) ! 373: procctl(u->p); ! 374: ! 375: u->scallnr = ur->r0; ! 376: sp = ur->usp; ! 377: ! 378: u->nerrlab = 0; ! 379: ret = -1; ! 380: if(!waserror()){ ! 381: if(u->scallnr >= sizeof systab/sizeof systab[0]){ ! 382: pprint("bad sys call number %d pc %lux\n", u->scallnr, ur->pc); ! 383: postnote(u->p, 1, "sys: bad sys call", NDebug); ! 384: error(Ebadarg); ! 385: } ! 386: ! 387: if(sp & (BY2WD-1)){ ! 388: pprint("odd sp in sys call pc %lux sp %lux\n", ur->pc, ur->sp); ! 389: postnote(u->p, 1, "sys: odd stack", NDebug); ! 390: error(Ebadarg); ! 391: } ! 392: ! 393: if(sp<(USTKTOP-BY2PG) || sp>(USTKTOP-sizeof(Sargs))) ! 394: validaddr(sp, sizeof(Sargs), 0); ! 395: ! 396: u->s = *((Sargs*)(sp+1*BY2WD)); ! 397: u->p->psstate = sysctab[u->scallnr]; ! 398: ! 399: ret = (*systab[u->scallnr])(u->s.args); ! 400: poperror(); ! 401: } ! 402: ! 403: u->nerrlab = 0; ! 404: u->p->insyscall = 0; ! 405: u->p->psstate = 0; ! 406: ! 407: if(u->scallnr == NOTED) /* ugly hack */ ! 408: noted(aur, *(ulong*)(sp+BY2WD)); /* doesn't return */ ! 409: splhi(); ! 410: if(u->scallnr!=RFORK && (u->p->procctl || u->nnote)){ ! 411: ur->r0 = ret; ! 412: notify(ur); ! 413: } ! 414: return ret; ! 415: } ! 416: ! 417: long ! 418: execregs(ulong entry, ulong ssize, ulong nargs) ! 419: { ! 420: ulong *sp; ! 421: ! 422: sp = (ulong*)(USTKTOP - ssize); ! 423: *--sp = nargs; ! 424: ((Ureg*)UREGADDR)->usp = (ulong)sp; ! 425: ((Ureg*)UREGADDR)->pc = entry; ! 426: return USTKTOP-BY2WD; /* address of user-level clock */ ! 427: } ! 428: ! 429: ulong ! 430: userpc(void) ! 431: { ! 432: return ((Ureg*)UREGADDR)->pc; ! 433: } ! 434: ! 435: /* This routine must save the values of registers the user is not permitted to write ! 436: * from devproc and the restore the saved values before returning ! 437: */ ! 438: void ! 439: setregisters(Ureg *xp, char *pureg, char *uva, int n) ! 440: { ! 441: ushort sr; ! 442: ulong magic; ! 443: ushort vo; ! 444: char microstate[UREGVARSZ]; ! 445: ! 446: sr = xp->sr; ! 447: vo = xp->vo; ! 448: magic = xp->magic; ! 449: memmove(microstate, xp->microstate, UREGVARSZ); ! 450: ! 451: memmove(pureg, uva, n); ! 452: ! 453: xp->sr = (sr&0xff00) |(xp->sr&0xff); ! 454: xp->vo = vo; ! 455: xp->magic = magic; ! 456: memmove(xp->microstate, microstate, UREGVARSZ); ! 457: }
This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.