Annotation of lucent/sys/src/9/gnot/trap.c, revision 1.1.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.