Annotation of lucent/sys/src/9/port/fault.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       "../port/error.h"
                      7: 
                      8: void   faulterror(char*);
                      9: 
                     10: int
                     11: fault(ulong addr, int read)
                     12: {
                     13:        Segment *s;
                     14:        char *sps;
                     15: 
                     16:        sps = u->p->psstate;
                     17:        u->p->psstate = "Fault";
                     18:        spllo();
                     19: 
                     20:        m->pfault++;
                     21:        for(;;) {
                     22:                s = seg(u->p, addr, 1);
                     23:                if(s == 0) {
                     24:                        u->p->psstate = sps;
                     25:                        return -1;
                     26:                }
                     27: 
                     28:                if(!read && (s->type&SG_RONLY)) {
                     29:                        qunlock(&s->lk);
                     30:                        u->p->psstate = sps;
                     31:                        return -1;
                     32:                }
                     33: 
                     34:                if(fixfault(s, addr, read, 1) == 0)
                     35:                        break;
                     36:        }
                     37: 
                     38:        u->p->psstate = sps;
                     39:        return 0;
                     40: }
                     41: 
                     42: int
                     43: fixfault(Segment *s, ulong addr, int read, int doputmmu)
                     44: {
                     45:        int type;
                     46:        Pte **p, *etp;
                     47:        ulong mmuphys=0, soff;
                     48:        Page **pg, *lkp, *new;
                     49:        Page *(*fn)(Segment*, ulong);
                     50: 
                     51:        addr &= ~(BY2PG-1);
                     52:        soff = addr-s->base;
                     53:        p = &s->map[soff/PTEMAPMEM];
                     54:        if(*p == 0) 
                     55:                *p = ptealloc();
                     56: 
                     57:        etp = *p;
                     58:        pg = &etp->pages[(soff&(PTEMAPMEM-1))/BY2PG];
                     59:        type = s->type&SG_TYPE;
                     60: 
                     61:        if(pg < etp->first)
                     62:                etp->first = pg;
                     63:        if(pg > etp->last)
                     64:                etp->last = pg;
                     65: 
                     66:        switch(type) {
                     67:        default:
                     68:                panic("fault");
                     69:                break;
                     70: 
                     71:        case SG_TEXT:
                     72:                if(pagedout(*pg))               /* Demand load */
                     73:                        pio(s, addr, soff, pg);
                     74:                
                     75:                mmuphys = PPN((*pg)->pa) | PTERONLY|PTEVALID;
                     76:                (*pg)->modref = PG_REF;
                     77:                break;
                     78: 
                     79:        case SG_SHDATA:                         /* Shared data */
                     80:                if(pagedout(*pg))
                     81:                        pio(s, addr, soff, pg);
                     82: 
                     83:                lkp = *pg;
                     84:                lock(lkp);
                     85:                if(lkp->image)     
                     86:                        duppage(lkp);   
                     87:                unlock(lkp);
                     88:                goto done;
                     89: 
                     90:        case SG_BSS:
                     91:        case SG_SHARED:                         /* Zero fill on demand */
                     92:        case SG_STACK:  
                     93:                if(*pg == 0) {
                     94:                        new = newpage(1, &s, addr);
                     95:                        if(s == 0)
                     96:                                return -1;
                     97: 
                     98:                        *pg = new;
                     99:                }
                    100:                /* NO break */
                    101: 
                    102:        case SG_DATA:                           /* Demand load/pagein/copy on write */
                    103:                if(pagedout(*pg))
                    104:                        pio(s, addr, soff, pg);
                    105: 
                    106:                if(type == SG_SHARED)
                    107:                        goto done;
                    108: 
                    109:                if(read && conf.copymode == 0) {
                    110:                        mmuphys = PPN((*pg)->pa) | PTERONLY|PTEVALID;
                    111:                        (*pg)->modref |= PG_REF;
                    112:                        break;
                    113:                }
                    114: 
                    115:                lkp = *pg;
                    116:                lock(lkp);
                    117:                if(lkp->ref > 1) {
                    118:                        unlock(lkp);
                    119:                        new = newpage(0, &s, addr);
                    120:                        if(s == 0)
                    121:                                return -1;
                    122:                        *pg = new;
                    123:                        copypage(lkp, *pg);
                    124:                        putpage(lkp);
                    125:                }
                    126:                else {
                    127:                        /* put a duplicate of a text page back onto the free list */
                    128:                        if(lkp->image)     
                    129:                                duppage(lkp);   
                    130:                
                    131:                        unlock(lkp);
                    132:                }
                    133:        done:
                    134:                mmuphys = PPN((*pg)->pa) | PTEWRITE|PTEVALID;
                    135:                (*pg)->modref = PG_MOD|PG_REF;
                    136:                break;
                    137: 
                    138:        case SG_PHYSICAL:
                    139:                if(*pg == 0) {
                    140:                        fn = s->pseg->pgalloc;
                    141:                        if(fn)
                    142:                                *pg = (*fn)(s, addr);
                    143:                        else {
                    144:                                new = smalloc(sizeof(Page));
                    145:                                new->va = addr;
                    146:                                new->pa = s->pseg->pa+(addr-s->base);
                    147:                                new->ref = 1;
                    148:                                *pg = new;
                    149:                        }
                    150:                }
                    151: 
                    152:                mmuphys = PPN((*pg)->pa) |PTEWRITE|PTEUNCACHED|PTEVALID;
                    153:                (*pg)->modref = PG_MOD|PG_REF;
                    154: /*             print("v %lux p %lux\n", addr, mmuphys);        /**/
                    155:                break;
                    156:        }
                    157: 
                    158:        if(s->flushme)
                    159:                memset((*pg)->cachectl, PG_TXTFLUSH, sizeof(new->cachectl));
                    160: 
                    161:        qunlock(&s->lk);
                    162: 
                    163:        if(doputmmu)
                    164:                putmmu(addr, mmuphys, *pg);
                    165: 
                    166:        return 0;
                    167: }
                    168: 
                    169: void
                    170: pio(Segment *s, ulong addr, ulong soff, Page **p)
                    171: {
                    172:        Page *new;
                    173:        KMap *k;
                    174:        Chan *c;
                    175:        int n, ask;
                    176:        char *kaddr;
                    177:        ulong daddr;
                    178:        Page *loadrec;
                    179: 
                    180:        loadrec = *p;
                    181:        if(loadrec == 0) {
                    182:                daddr = s->fstart+soff;         /* Compute disc address */
                    183:                new = lookpage(s->image, daddr);
                    184:        }
                    185:        else {
                    186:                daddr = swapaddr(loadrec);
                    187:                new = lookpage(&swapimage, daddr);
                    188:                if(new)
                    189:                        putswap(loadrec);
                    190:        }
                    191: 
                    192:        if(new) {                               /* Page found from cache */
                    193:                *p = new;
                    194:                return;
                    195:        }
                    196: 
                    197:        qunlock(&s->lk);
                    198: 
                    199:        new = newpage(0, 0, addr);
                    200:        k = kmap(new);
                    201:        kaddr = (char*)VA(k);
                    202:        
                    203:        if(loadrec == 0) {                      /* This is demand load */
                    204:                c = s->image->c;
                    205:                while(waserror()) {
                    206:                        if(strcmp(u->error, Eintr) == 0)
                    207:                                continue;
                    208:                        kunmap(k);
                    209:                        putpage(new);
                    210:                        faulterror("sys: demand load I/O error");
                    211:                }
                    212: 
                    213:                ask = s->flen-soff;
                    214:                if(ask > BY2PG)
                    215:                        ask = BY2PG;
                    216: 
                    217:                n = (*devtab[c->type].read)(c, kaddr, ask, daddr);
                    218:                if(n != ask){
                    219:                        print("demand load: %s: %d %d\n", u->error, n, ask);
                    220:                        error(Eioload);
                    221:                }
                    222:                if(ask < BY2PG)
                    223:                        memset(kaddr+ask, 0, BY2PG-ask);
                    224: 
                    225:                poperror();
                    226:                kunmap(k);
                    227:                qlock(&s->lk);
                    228:                if(*p == 0) {           /* Someone may have got there first */
                    229:                        new->daddr = daddr;
                    230:                        cachepage(new, s->image);
                    231:                        *p = new;
                    232:                }
                    233:                else 
                    234:                        putpage(new);
                    235:        }
                    236:        else {                          /* This is paged out */
                    237:                c = swapimage.c;
                    238: 
                    239:                if(waserror()) {
                    240:                        kunmap(k);
                    241:                        putpage(new);
                    242:                        qlock(&s->lk);
                    243:                        qunlock(&s->lk);
                    244:                        faulterror("sys: page in I/O error");
                    245:                }
                    246: 
                    247:                n = (*devtab[c->type].read)(c, kaddr, BY2PG, daddr);
                    248:                if(n != BY2PG){
                    249:                        print("page in: %s: %d %d\n", u->error, n, BY2PG);
                    250:                        error(Eioload);
                    251:                }
                    252: 
                    253:                poperror();
                    254:                kunmap(k);
                    255:                qlock(&s->lk);
                    256: 
                    257:                if(pagedout(*p)) {
                    258:                        new->daddr = daddr;
                    259:                        cachepage(new, &swapimage);
                    260:                        putswap(*p);
                    261:                        *p = new;
                    262:                }
                    263:                else
                    264:                        putpage(new);
                    265:        }
                    266: }
                    267: 
                    268: void
                    269: faulterror(char *s)
                    270: {
                    271:        if(u->nerrlab) {
                    272:                postnote(u->p, 1, s, NUser);
                    273:                error(s);
                    274:        }
                    275:        pexit(s, 1);
                    276: }
                    277: 
                    278: /*
                    279:  * Called only in a system call
                    280:  */
                    281: int
                    282: okaddr(ulong addr, ulong len, int write)
                    283: {
                    284:        Segment *s;
                    285: 
                    286:        if((long)len >= 0) {
                    287:                for(;;) {
                    288:                        s = seg(u->p, addr, 0);
                    289:                        if(s == 0 || (write && (s->type&SG_RONLY)))
                    290:                                break;
                    291: 
                    292:                        if(addr+len > s->top) {
                    293:                                len -= s->top - addr;
                    294:                                addr = s->top;
                    295:                                continue;
                    296:                        }
                    297:                        return 1;
                    298:                }
                    299:        }
                    300:        pprint("suicide: invalid address 0x%lux in sys call pc=0x%lux\n", addr, userpc());
                    301:        return 0;
                    302: }
                    303:   
                    304: void
                    305: validaddr(ulong addr, ulong len, int write)
                    306: {
                    307:        if(!okaddr(addr, len, write))
                    308:                pexit("Suicide", 0);
                    309: }
                    310:   
                    311: /*
                    312:  * &s[0] is known to be a valid address.
                    313:  */
                    314: void*
                    315: vmemchr(void *s, int c, int n)
                    316: {
                    317:        int m;
                    318:        char *t;
                    319:        ulong a;
                    320: 
                    321:        a = (ulong)s;
                    322:        m = BY2PG - (a & (BY2PG-1));
                    323:        if(m < n){
                    324:                t = vmemchr(s, c, m);
                    325:                if(t)
                    326:                        return t;
                    327:                if(!(a & KZERO))
                    328:                        validaddr(a+m, 1, 0);
                    329:                return vmemchr((void*)(a+m), c, n-m);
                    330:        }
                    331:        /*
                    332:         * All in one page
                    333:         */
                    334:        return memchr(s, c, n);
                    335: }
                    336: 
                    337: Segment*
                    338: seg(Proc *p, ulong addr, int dolock)
                    339: {
                    340:        Segment **s, **et, *n;
                    341: 
                    342:        et = &p->seg[NSEG];
                    343:        for(s = p->seg; s < et; s++)
                    344:                if(n = *s){
                    345:                        if(addr >= n->base && addr < n->top) {
                    346:                                if(dolock == 0)
                    347:                                        return n;
                    348:        
                    349:                                qlock(&n->lk);
                    350:                                if(addr >= n->base && addr < n->top)
                    351:                                        return n;
                    352:                                qunlock(&n->lk);
                    353:                        }
                    354:                }
                    355: 
                    356:        return 0;
                    357: }

unix.superglobalmegacorp.com

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