Annotation of lucent/sys/src/9/gnot/trap.c, revision 1.1

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: }

unix.superglobalmegacorp.com

This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.