|
|
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: }
This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.