13e12c5d1SDavid du Colombier #include "u.h" 23e12c5d1SDavid du Colombier #include "../port/lib.h" 33e12c5d1SDavid du Colombier #include "mem.h" 43e12c5d1SDavid du Colombier #include "dat.h" 53e12c5d1SDavid du Colombier #include "fns.h" 63e12c5d1SDavid du Colombier #include "../port/error.h" 73e12c5d1SDavid du Colombier 8*219b2ee8SDavid du Colombier Page *lkpage(Segment*, ulong); 93e12c5d1SDavid du Colombier void lkpgfree(Page*); 103e12c5d1SDavid du Colombier void imagereclaim(void); 113e12c5d1SDavid du Colombier 123e12c5d1SDavid du Colombier /* System specific segattach devices */ 13*219b2ee8SDavid du Colombier #include "io.h" 143e12c5d1SDavid du Colombier #include "segment.h" 153e12c5d1SDavid du Colombier 163e12c5d1SDavid du Colombier #define IHASHSIZE 64 173e12c5d1SDavid du Colombier #define ihash(s) imagealloc.hash[s%IHASHSIZE] 183e12c5d1SDavid du Colombier struct 193e12c5d1SDavid du Colombier { 203e12c5d1SDavid du Colombier Lock; 213e12c5d1SDavid du Colombier Image *free; 223e12c5d1SDavid du Colombier Image *hash[IHASHSIZE]; 233e12c5d1SDavid du Colombier QLock ireclaim; 243e12c5d1SDavid du Colombier }imagealloc; 253e12c5d1SDavid du Colombier 263e12c5d1SDavid du Colombier void 273e12c5d1SDavid du Colombier initseg(void) 283e12c5d1SDavid du Colombier { 293e12c5d1SDavid du Colombier Image *i, *ie; 303e12c5d1SDavid du Colombier 313e12c5d1SDavid du Colombier imagealloc.free = xalloc(conf.nimage*sizeof(Image)); 323e12c5d1SDavid du Colombier ie = &imagealloc.free[conf.nimage-1]; 333e12c5d1SDavid du Colombier for(i = imagealloc.free; i < ie; i++) 343e12c5d1SDavid du Colombier i->next = i+1; 353e12c5d1SDavid du Colombier i->next = 0; 363e12c5d1SDavid du Colombier } 373e12c5d1SDavid du Colombier 383e12c5d1SDavid du Colombier Segment * 393e12c5d1SDavid du Colombier newseg(int type, ulong base, ulong size) 403e12c5d1SDavid du Colombier { 413e12c5d1SDavid du Colombier Segment *s; 423e12c5d1SDavid du Colombier 433e12c5d1SDavid du Colombier if(size > (SEGMAPSIZE*PTEPERTAB)) 443e12c5d1SDavid du Colombier error(Enovmem); 453e12c5d1SDavid du Colombier 463e12c5d1SDavid du Colombier s = smalloc(sizeof(Segment)); 473e12c5d1SDavid du Colombier s->ref = 1; 483e12c5d1SDavid du Colombier s->type = type; 493e12c5d1SDavid du Colombier s->base = base; 503e12c5d1SDavid du Colombier s->top = base+(size*BY2PG); 513e12c5d1SDavid du Colombier s->size = size; 523e12c5d1SDavid du Colombier return s; 533e12c5d1SDavid du Colombier } 543e12c5d1SDavid du Colombier 553e12c5d1SDavid du Colombier void 563e12c5d1SDavid du Colombier putseg(Segment *s) 573e12c5d1SDavid du Colombier { 583e12c5d1SDavid du Colombier Pte **pp, **emap; 593e12c5d1SDavid du Colombier Image *i; 603e12c5d1SDavid du Colombier 613e12c5d1SDavid du Colombier if(s == 0) 623e12c5d1SDavid du Colombier return; 633e12c5d1SDavid du Colombier 643e12c5d1SDavid du Colombier i = s->image; 65*219b2ee8SDavid du Colombier if(i != 0) { 663e12c5d1SDavid du Colombier lock(i); 67*219b2ee8SDavid du Colombier lock(s); 68*219b2ee8SDavid du Colombier if(i->s == s && s->ref == 1) 693e12c5d1SDavid du Colombier i->s = 0; 703e12c5d1SDavid du Colombier unlock(i); 713e12c5d1SDavid du Colombier } 72*219b2ee8SDavid du Colombier else 73*219b2ee8SDavid du Colombier lock(s); 743e12c5d1SDavid du Colombier 75*219b2ee8SDavid du Colombier s->ref--; 76*219b2ee8SDavid du Colombier if(s->ref != 0) { 77*219b2ee8SDavid du Colombier unlock(s); 78*219b2ee8SDavid du Colombier return; 79*219b2ee8SDavid du Colombier } 80*219b2ee8SDavid du Colombier 813e12c5d1SDavid du Colombier qlock(&s->lk); 823e12c5d1SDavid du Colombier if(i) 833e12c5d1SDavid du Colombier putimage(i); 843e12c5d1SDavid du Colombier 853e12c5d1SDavid du Colombier emap = &s->map[SEGMAPSIZE]; 863e12c5d1SDavid du Colombier for(pp = s->map; pp < emap; pp++) 873e12c5d1SDavid du Colombier if(*pp) 883e12c5d1SDavid du Colombier freepte(s, *pp); 893e12c5d1SDavid du Colombier 903e12c5d1SDavid du Colombier qunlock(&s->lk); 913e12c5d1SDavid du Colombier free(s); 923e12c5d1SDavid du Colombier } 933e12c5d1SDavid du Colombier 943e12c5d1SDavid du Colombier void 953e12c5d1SDavid du Colombier relocateseg(Segment *s, ulong offset) 963e12c5d1SDavid du Colombier { 973e12c5d1SDavid du Colombier Pte **p, **endpte; 983e12c5d1SDavid du Colombier Page **pg, **endpages; 993e12c5d1SDavid du Colombier 1003e12c5d1SDavid du Colombier endpte = &s->map[SEGMAPSIZE]; 1013e12c5d1SDavid du Colombier for(p = s->map; p < endpte; p++) { 1023e12c5d1SDavid du Colombier if(*p) { 1033e12c5d1SDavid du Colombier endpages = &((*p)->pages[PTEPERTAB]); 1043e12c5d1SDavid du Colombier for(pg = (*p)->pages; pg < endpages; pg++) 1053e12c5d1SDavid du Colombier if(*pg) 1063e12c5d1SDavid du Colombier (*pg)->va += offset; 1073e12c5d1SDavid du Colombier } 1083e12c5d1SDavid du Colombier } 1093e12c5d1SDavid du Colombier } 1103e12c5d1SDavid du Colombier 1113e12c5d1SDavid du Colombier Segment* 112bd389b36SDavid du Colombier dupseg(Segment **seg, int segno, int share) 1133e12c5d1SDavid du Colombier { 1143e12c5d1SDavid du Colombier int i; 1153e12c5d1SDavid du Colombier Pte *pte; 116bd389b36SDavid du Colombier Segment *n, *s; 1173e12c5d1SDavid du Colombier 1183e12c5d1SDavid du Colombier SET(n); 119bd389b36SDavid du Colombier s = seg[segno]; 120bd389b36SDavid du Colombier 1213e12c5d1SDavid du Colombier switch(s->type&SG_TYPE) { 1223e12c5d1SDavid du Colombier case SG_TEXT: /* New segment shares pte set */ 1233e12c5d1SDavid du Colombier case SG_SHARED: 1243e12c5d1SDavid du Colombier case SG_PHYSICAL: 1253e12c5d1SDavid du Colombier case SG_SHDATA: 1263e12c5d1SDavid du Colombier incref(s); 1273e12c5d1SDavid du Colombier return s; 1283e12c5d1SDavid du Colombier 1293e12c5d1SDavid du Colombier case SG_STACK: 1303e12c5d1SDavid du Colombier qlock(&s->lk); 1313e12c5d1SDavid du Colombier n = newseg(s->type, s->base, s->size); 1323e12c5d1SDavid du Colombier break; 1333e12c5d1SDavid du Colombier 1343e12c5d1SDavid du Colombier case SG_BSS: /* Just copy on write */ 1353e12c5d1SDavid du Colombier qlock(&s->lk); 1363e12c5d1SDavid du Colombier if(share && s->ref == 1) { 1373e12c5d1SDavid du Colombier s->type = (s->type&~SG_TYPE)|SG_SHARED; 1383e12c5d1SDavid du Colombier incref(s); 1393e12c5d1SDavid du Colombier qunlock(&s->lk); 1403e12c5d1SDavid du Colombier return s; 1413e12c5d1SDavid du Colombier } 1423e12c5d1SDavid du Colombier n = newseg(s->type, s->base, s->size); 1433e12c5d1SDavid du Colombier break; 1443e12c5d1SDavid du Colombier 1453e12c5d1SDavid du Colombier case SG_DATA: /* Copy on write plus demand load info */ 146bd389b36SDavid du Colombier if(segno == TSEG) 147bd389b36SDavid du Colombier return data2txt(s); 148bd389b36SDavid du Colombier 1493e12c5d1SDavid du Colombier qlock(&s->lk); 1503e12c5d1SDavid du Colombier if(share && s->ref == 1) { 1513e12c5d1SDavid du Colombier s->type = (s->type&~SG_TYPE)|SG_SHDATA; 1523e12c5d1SDavid du Colombier incref(s); 1533e12c5d1SDavid du Colombier qunlock(&s->lk); 1543e12c5d1SDavid du Colombier return s; 1553e12c5d1SDavid du Colombier } 1563e12c5d1SDavid du Colombier n = newseg(s->type, s->base, s->size); 1573e12c5d1SDavid du Colombier 1583e12c5d1SDavid du Colombier incref(s->image); 1593e12c5d1SDavid du Colombier n->image = s->image; 1603e12c5d1SDavid du Colombier n->fstart = s->fstart; 1613e12c5d1SDavid du Colombier n->flen = s->flen; 1623e12c5d1SDavid du Colombier break; 1633e12c5d1SDavid du Colombier } 1643e12c5d1SDavid du Colombier for(i = 0; i < SEGMAPSIZE; i++) 1653e12c5d1SDavid du Colombier if(pte = s->map[i]) 1663e12c5d1SDavid du Colombier n->map[i] = ptecpy(pte); 1673e12c5d1SDavid du Colombier 1683e12c5d1SDavid du Colombier n->flushme = s->flushme; 1693e12c5d1SDavid du Colombier qunlock(&s->lk); 1703e12c5d1SDavid du Colombier return n; 1713e12c5d1SDavid du Colombier } 1723e12c5d1SDavid du Colombier 1733e12c5d1SDavid du Colombier void 1743e12c5d1SDavid du Colombier segpage(Segment *s, Page *p) 1753e12c5d1SDavid du Colombier { 1763e12c5d1SDavid du Colombier Pte **pte; 1773e12c5d1SDavid du Colombier ulong off; 1783e12c5d1SDavid du Colombier Page **pg; 1793e12c5d1SDavid du Colombier 1803e12c5d1SDavid du Colombier if(p->va < s->base || p->va >= s->top) 1813e12c5d1SDavid du Colombier panic("segpage"); 1823e12c5d1SDavid du Colombier 1833e12c5d1SDavid du Colombier off = p->va - s->base; 1843e12c5d1SDavid du Colombier pte = &s->map[off/PTEMAPMEM]; 1853e12c5d1SDavid du Colombier if(*pte == 0) 1863e12c5d1SDavid du Colombier *pte = ptealloc(); 1873e12c5d1SDavid du Colombier 1883e12c5d1SDavid du Colombier pg = &(*pte)->pages[(off&(PTEMAPMEM-1))/BY2PG]; 1893e12c5d1SDavid du Colombier *pg = p; 1903e12c5d1SDavid du Colombier if(pg < (*pte)->first) 1913e12c5d1SDavid du Colombier (*pte)->first = pg; 1923e12c5d1SDavid du Colombier if(pg > (*pte)->last) 1933e12c5d1SDavid du Colombier (*pte)->last = pg; 1943e12c5d1SDavid du Colombier } 1953e12c5d1SDavid du Colombier 1963e12c5d1SDavid du Colombier Image* 1973e12c5d1SDavid du Colombier attachimage(int type, Chan *c, ulong base, ulong len) 1983e12c5d1SDavid du Colombier { 1993e12c5d1SDavid du Colombier Image *i, **l; 2003e12c5d1SDavid du Colombier 2013e12c5d1SDavid du Colombier lock(&imagealloc); 2023e12c5d1SDavid du Colombier 2033e12c5d1SDavid du Colombier /* 2043e12c5d1SDavid du Colombier * Search the image cache for remains of the text from a previous 2053e12c5d1SDavid du Colombier * or currently running incarnation 2063e12c5d1SDavid du Colombier */ 2073e12c5d1SDavid du Colombier for(i = ihash(c->qid.path); i; i = i->hash) { 2083e12c5d1SDavid du Colombier if(c->qid.path == i->qid.path) { 2093e12c5d1SDavid du Colombier lock(i); 2103e12c5d1SDavid du Colombier if(eqqid(c->qid, i->qid) && 2113e12c5d1SDavid du Colombier eqqid(c->mqid, i->mqid) && 2123e12c5d1SDavid du Colombier c->mchan == i->mchan && 2133e12c5d1SDavid du Colombier c->type == i->type) { 2143e12c5d1SDavid du Colombier i->ref++; 2153e12c5d1SDavid du Colombier goto found; 2163e12c5d1SDavid du Colombier } 2173e12c5d1SDavid du Colombier unlock(i); 2183e12c5d1SDavid du Colombier } 2193e12c5d1SDavid du Colombier } 2203e12c5d1SDavid du Colombier 2213e12c5d1SDavid du Colombier /* 2223e12c5d1SDavid du Colombier * imagereclaim dumps pages from the free list which are cached by image 2233e12c5d1SDavid du Colombier * structures. This should free some image structures. 2243e12c5d1SDavid du Colombier */ 2253e12c5d1SDavid du Colombier while(!(i = imagealloc.free)) { 2263e12c5d1SDavid du Colombier unlock(&imagealloc); 2273e12c5d1SDavid du Colombier imagereclaim(); 2283e12c5d1SDavid du Colombier resrcwait(0); 2293e12c5d1SDavid du Colombier lock(&imagealloc); 2303e12c5d1SDavid du Colombier } 2313e12c5d1SDavid du Colombier 2323e12c5d1SDavid du Colombier imagealloc.free = i->next; 2333e12c5d1SDavid du Colombier 2343e12c5d1SDavid du Colombier lock(i); 2353e12c5d1SDavid du Colombier incref(c); 2363e12c5d1SDavid du Colombier i->c = c; 2373e12c5d1SDavid du Colombier i->type = c->type; 2383e12c5d1SDavid du Colombier i->qid = c->qid; 2393e12c5d1SDavid du Colombier i->mqid = c->mqid; 2403e12c5d1SDavid du Colombier i->mchan = c->mchan; 2413e12c5d1SDavid du Colombier i->ref = 1; 2423e12c5d1SDavid du Colombier l = &ihash(c->qid.path); 2433e12c5d1SDavid du Colombier i->hash = *l; 2443e12c5d1SDavid du Colombier *l = i; 2453e12c5d1SDavid du Colombier found: 2463e12c5d1SDavid du Colombier unlock(&imagealloc); 2473e12c5d1SDavid du Colombier 2483e12c5d1SDavid du Colombier if(i->s == 0) { 249*219b2ee8SDavid du Colombier /* Disaster after commit in exec */ 250*219b2ee8SDavid du Colombier if(waserror()) { 251*219b2ee8SDavid du Colombier unlock(i); 252*219b2ee8SDavid du Colombier pexit(Enovmem, 1); 253*219b2ee8SDavid du Colombier } 2543e12c5d1SDavid du Colombier i->s = newseg(type, base, len); 2553e12c5d1SDavid du Colombier i->s->image = i; 256*219b2ee8SDavid du Colombier poperror(); 2573e12c5d1SDavid du Colombier } 2583e12c5d1SDavid du Colombier else 2593e12c5d1SDavid du Colombier incref(i->s); 2603e12c5d1SDavid du Colombier 2613e12c5d1SDavid du Colombier return i; 2623e12c5d1SDavid du Colombier } 2633e12c5d1SDavid du Colombier 2643e12c5d1SDavid du Colombier void 2653e12c5d1SDavid du Colombier imagereclaim(void) 2663e12c5d1SDavid du Colombier { 2673e12c5d1SDavid du Colombier Page *p; 2683e12c5d1SDavid du Colombier 2693e12c5d1SDavid du Colombier /* Somebody is already cleaning the page cache */ 2703e12c5d1SDavid du Colombier if(!canqlock(&imagealloc.ireclaim)) 2713e12c5d1SDavid du Colombier return; 2723e12c5d1SDavid du Colombier 2733e12c5d1SDavid du Colombier lock(&palloc); 2743e12c5d1SDavid du Colombier for(p = palloc.head; p; p = p->next) { 2753e12c5d1SDavid du Colombier if(p->image && p->ref == 0 && p->image != &swapimage && canlock(p)) { 2763e12c5d1SDavid du Colombier if(p->ref == 0) 2773e12c5d1SDavid du Colombier uncachepage(p); 2783e12c5d1SDavid du Colombier unlock(p); 2793e12c5d1SDavid du Colombier } 2803e12c5d1SDavid du Colombier } 2813e12c5d1SDavid du Colombier unlock(&palloc); 2823e12c5d1SDavid du Colombier qunlock(&imagealloc.ireclaim); 2833e12c5d1SDavid du Colombier } 2843e12c5d1SDavid du Colombier 2853e12c5d1SDavid du Colombier void 2863e12c5d1SDavid du Colombier putimage(Image *i) 2873e12c5d1SDavid du Colombier { 2883e12c5d1SDavid du Colombier Chan *c; 2893e12c5d1SDavid du Colombier Image *f, **l; 2903e12c5d1SDavid du Colombier 2913e12c5d1SDavid du Colombier if(i == &swapimage) 2923e12c5d1SDavid du Colombier return; 2933e12c5d1SDavid du Colombier 2943e12c5d1SDavid du Colombier lock(i); 2953e12c5d1SDavid du Colombier if(--i->ref == 0) { 2963e12c5d1SDavid du Colombier l = &ihash(i->qid.path); 2973e12c5d1SDavid du Colombier i->qid = (Qid){~0, ~0}; 2983e12c5d1SDavid du Colombier unlock(i); 2993e12c5d1SDavid du Colombier c = i->c; 3003e12c5d1SDavid du Colombier 3013e12c5d1SDavid du Colombier lock(&imagealloc); 3023e12c5d1SDavid du Colombier for(f = *l; f; f = f->hash) { 3033e12c5d1SDavid du Colombier if(f == i) { 3043e12c5d1SDavid du Colombier *l = i->hash; 3053e12c5d1SDavid du Colombier break; 3063e12c5d1SDavid du Colombier } 3073e12c5d1SDavid du Colombier l = &f->hash; 3083e12c5d1SDavid du Colombier } 3093e12c5d1SDavid du Colombier 3103e12c5d1SDavid du Colombier i->next = imagealloc.free; 3113e12c5d1SDavid du Colombier imagealloc.free = i; 3123e12c5d1SDavid du Colombier unlock(&imagealloc); 3133e12c5d1SDavid du Colombier 3143e12c5d1SDavid du Colombier close(c); 3153e12c5d1SDavid du Colombier return; 3163e12c5d1SDavid du Colombier } 3173e12c5d1SDavid du Colombier unlock(i); 3183e12c5d1SDavid du Colombier } 3193e12c5d1SDavid du Colombier 3203e12c5d1SDavid du Colombier long 3213e12c5d1SDavid du Colombier ibrk(ulong addr, int seg) 3223e12c5d1SDavid du Colombier { 3233e12c5d1SDavid du Colombier Segment *s, *ns; 3243e12c5d1SDavid du Colombier ulong newtop, newsize; 3253e12c5d1SDavid du Colombier int i; 3263e12c5d1SDavid du Colombier 3273e12c5d1SDavid du Colombier s = u->p->seg[seg]; 3283e12c5d1SDavid du Colombier if(s == 0) 3293e12c5d1SDavid du Colombier error(Ebadarg); 3303e12c5d1SDavid du Colombier 3313e12c5d1SDavid du Colombier if(addr == 0) 3323e12c5d1SDavid du Colombier return s->base; 3333e12c5d1SDavid du Colombier 3343e12c5d1SDavid du Colombier qlock(&s->lk); 3353e12c5d1SDavid du Colombier 3363e12c5d1SDavid du Colombier /* We may start with the bss overlapping the data */ 3373e12c5d1SDavid du Colombier if(addr < s->base) { 3383e12c5d1SDavid du Colombier if(seg != BSEG || u->p->seg[DSEG] == 0 || addr < u->p->seg[DSEG]->base) { 3393e12c5d1SDavid du Colombier qunlock(&s->lk); 3403e12c5d1SDavid du Colombier error(Enovmem); 3413e12c5d1SDavid du Colombier } 3423e12c5d1SDavid du Colombier addr = s->base; 3433e12c5d1SDavid du Colombier } 3443e12c5d1SDavid du Colombier 3453e12c5d1SDavid du Colombier newtop = PGROUND(addr); 3463e12c5d1SDavid du Colombier newsize = (newtop-s->base)/BY2PG; 3473e12c5d1SDavid du Colombier if(newtop < s->top) { 3483e12c5d1SDavid du Colombier mfreeseg(s, newtop, (s->top-newtop)/BY2PG); 3493e12c5d1SDavid du Colombier qunlock(&s->lk); 350bd389b36SDavid du Colombier flushmmu(); 3513e12c5d1SDavid du Colombier return 0; 3523e12c5d1SDavid du Colombier } 3533e12c5d1SDavid du Colombier 3543e12c5d1SDavid du Colombier for(i = 0; i < NSEG; i++) { 3553e12c5d1SDavid du Colombier ns = u->p->seg[i]; 3563e12c5d1SDavid du Colombier if(ns == 0 || ns == s) 3573e12c5d1SDavid du Colombier continue; 3583e12c5d1SDavid du Colombier if(newtop >= ns->base && newtop < ns->top) { 3593e12c5d1SDavid du Colombier qunlock(&s->lk); 3603e12c5d1SDavid du Colombier error(Esoverlap); 3613e12c5d1SDavid du Colombier } 3623e12c5d1SDavid du Colombier } 3633e12c5d1SDavid du Colombier 3643e12c5d1SDavid du Colombier if(newsize > (PTEMAPMEM*SEGMAPSIZE)/BY2PG) { 3653e12c5d1SDavid du Colombier qunlock(&s->lk); 3663e12c5d1SDavid du Colombier error(Enovmem); 3673e12c5d1SDavid du Colombier } 3683e12c5d1SDavid du Colombier 3693e12c5d1SDavid du Colombier s->top = newtop; 3703e12c5d1SDavid du Colombier s->size = newsize; 3713e12c5d1SDavid du Colombier qunlock(&s->lk); 3723e12c5d1SDavid du Colombier return 0; 3733e12c5d1SDavid du Colombier } 3743e12c5d1SDavid du Colombier 3753e12c5d1SDavid du Colombier void 3763e12c5d1SDavid du Colombier mfreeseg(Segment *s, ulong start, int pages) 3773e12c5d1SDavid du Colombier { 3783e12c5d1SDavid du Colombier int i, j; 3793e12c5d1SDavid du Colombier ulong soff; 3803e12c5d1SDavid du Colombier Page *pg; 3813e12c5d1SDavid du Colombier 3823e12c5d1SDavid du Colombier soff = start-s->base; 3833e12c5d1SDavid du Colombier j = (soff&(PTEMAPMEM-1))/BY2PG; 3843e12c5d1SDavid du Colombier 3853e12c5d1SDavid du Colombier for(i = soff/PTEMAPMEM; i < SEGMAPSIZE; i++) { 3863e12c5d1SDavid du Colombier if(pages <= 0) 387bd389b36SDavid du Colombier break; 388bd389b36SDavid du Colombier if(s->map[i] == 0) { 389bd389b36SDavid du Colombier pages -= PTEPERTAB-j; 390bd389b36SDavid du Colombier j = 0; 391bd389b36SDavid du Colombier continue; 392bd389b36SDavid du Colombier } 3933e12c5d1SDavid du Colombier while(j < PTEPERTAB) { 394bd389b36SDavid du Colombier pg = s->map[i]->pages[j]; 395bd389b36SDavid du Colombier if(pg) { 3963e12c5d1SDavid du Colombier putpage(pg); 3973e12c5d1SDavid du Colombier s->map[i]->pages[j] = 0; 3983e12c5d1SDavid du Colombier } 3993e12c5d1SDavid du Colombier if(--pages == 0) 400bd389b36SDavid du Colombier return; 4013e12c5d1SDavid du Colombier j++; 4023e12c5d1SDavid du Colombier } 4033e12c5d1SDavid du Colombier j = 0; 4043e12c5d1SDavid du Colombier } 4053e12c5d1SDavid du Colombier } 4063e12c5d1SDavid du Colombier 407*219b2ee8SDavid du Colombier int 408*219b2ee8SDavid du Colombier isoverlap(ulong va, int len) 409*219b2ee8SDavid du Colombier { 410*219b2ee8SDavid du Colombier int i; 411*219b2ee8SDavid du Colombier Segment *ns; 412*219b2ee8SDavid du Colombier ulong newtop; 413*219b2ee8SDavid du Colombier 414*219b2ee8SDavid du Colombier newtop = va+len; 415*219b2ee8SDavid du Colombier for(i = 0; i < NSEG; i++) { 416*219b2ee8SDavid du Colombier ns = u->p->seg[i]; 417*219b2ee8SDavid du Colombier if(ns == 0) 418*219b2ee8SDavid du Colombier continue; 419*219b2ee8SDavid du Colombier if((newtop > ns->base && newtop <= ns->top) || 420*219b2ee8SDavid du Colombier (va >= ns->base && va < ns->top)) 421*219b2ee8SDavid du Colombier return 1; 422*219b2ee8SDavid du Colombier } 423*219b2ee8SDavid du Colombier return 0; 424*219b2ee8SDavid du Colombier } 425*219b2ee8SDavid du Colombier 4263e12c5d1SDavid du Colombier ulong 4273e12c5d1SDavid du Colombier segattach(Proc *p, ulong attr, char *name, ulong va, ulong len) 4283e12c5d1SDavid du Colombier { 4293e12c5d1SDavid du Colombier int i, sno; 430*219b2ee8SDavid du Colombier Segment *s; 431*219b2ee8SDavid du Colombier Physseg *ps; 4323e12c5d1SDavid du Colombier 4333e12c5d1SDavid du Colombier USED(p); 434*219b2ee8SDavid du Colombier if(va != 0 && (va&KZERO) == KZERO) /* BUG: Only ok for now */ 4353e12c5d1SDavid du Colombier error(Ebadarg); 4363e12c5d1SDavid du Colombier 4373e12c5d1SDavid du Colombier validaddr((ulong)name, 1, 0); 4383e12c5d1SDavid du Colombier vmemchr(name, 0, ~0); 4393e12c5d1SDavid du Colombier 4403e12c5d1SDavid du Colombier for(sno = 0; sno < NSEG; sno++) 441bd389b36SDavid du Colombier if(u->p->seg[sno] == 0 && sno != ESEG) 4423e12c5d1SDavid du Colombier break; 4433e12c5d1SDavid du Colombier 4443e12c5d1SDavid du Colombier if(sno == NSEG) 4453e12c5d1SDavid du Colombier error(Enovmem); 4463e12c5d1SDavid du Colombier 4473e12c5d1SDavid du Colombier len = PGROUND(len); 448*219b2ee8SDavid du Colombier 449*219b2ee8SDavid du Colombier /* Find a hole in the address space */ 450*219b2ee8SDavid du Colombier if(va == 0) { 451*219b2ee8SDavid du Colombier va = p->seg[SSEG]->base - len; 452*219b2ee8SDavid du Colombier for(i = 0; i < 20; i++) { 453*219b2ee8SDavid du Colombier if(isoverlap(va, len) == 0) 454*219b2ee8SDavid du Colombier break; 455*219b2ee8SDavid du Colombier va -= len; 4563e12c5d1SDavid du Colombier } 457*219b2ee8SDavid du Colombier } 458*219b2ee8SDavid du Colombier 459*219b2ee8SDavid du Colombier va = va&~(BY2PG-1); 460*219b2ee8SDavid du Colombier if(isoverlap(va, len)) 461*219b2ee8SDavid du Colombier error(Esoverlap); 4623e12c5d1SDavid du Colombier 4633e12c5d1SDavid du Colombier for(ps = physseg; ps->name; ps++) 4643e12c5d1SDavid du Colombier if(strcmp(name, ps->name) == 0) 4653e12c5d1SDavid du Colombier goto found; 4663e12c5d1SDavid du Colombier 4673e12c5d1SDavid du Colombier error(Ebadarg); 4683e12c5d1SDavid du Colombier found: 4693e12c5d1SDavid du Colombier if(len > ps->size) 4703e12c5d1SDavid du Colombier error(Enovmem); 4713e12c5d1SDavid du Colombier 4723e12c5d1SDavid du Colombier attr &= ~SG_TYPE; /* Turn off what we are not allowed */ 4733e12c5d1SDavid du Colombier attr |= ps->attr; /* Copy in defaults */ 4743e12c5d1SDavid du Colombier 4753e12c5d1SDavid du Colombier s = newseg(attr, va, len/BY2PG); 476*219b2ee8SDavid du Colombier s->pseg = ps; 4773e12c5d1SDavid du Colombier u->p->seg[sno] = s; 4783e12c5d1SDavid du Colombier 479*219b2ee8SDavid du Colombier return va; 4803e12c5d1SDavid du Colombier } 4813e12c5d1SDavid du Colombier 482*219b2ee8SDavid du Colombier void 483*219b2ee8SDavid du Colombier pteflush(Pte *pte, int s, int e) 484*219b2ee8SDavid du Colombier { 485*219b2ee8SDavid du Colombier int i; 486*219b2ee8SDavid du Colombier Page *p; 487*219b2ee8SDavid du Colombier 488*219b2ee8SDavid du Colombier for(i = s; i < e; i++) { 489*219b2ee8SDavid du Colombier p = pte->pages[i]; 490*219b2ee8SDavid du Colombier if(pagedout(p) == 0) 491*219b2ee8SDavid du Colombier memset(p->cachectl, PG_TXTFLUSH, sizeof(p->cachectl)); 492*219b2ee8SDavid du Colombier } 493*219b2ee8SDavid du Colombier } 494*219b2ee8SDavid du Colombier 495*219b2ee8SDavid du Colombier 4963e12c5d1SDavid du Colombier long 4973e12c5d1SDavid du Colombier syssegflush(ulong *arg) 498*219b2ee8SDavid du Colombier { Segment *s; 499*219b2ee8SDavid du Colombier ulong addr, l; 500*219b2ee8SDavid du Colombier Pte *pte; 501*219b2ee8SDavid du Colombier int chunk, ps, pe, len; 5023e12c5d1SDavid du Colombier 503*219b2ee8SDavid du Colombier addr = arg[0]; 504*219b2ee8SDavid du Colombier len = arg[1]; 505*219b2ee8SDavid du Colombier 506*219b2ee8SDavid du Colombier while(len > 0) { 507*219b2ee8SDavid du Colombier s = seg(u->p, addr, 1); 5083e12c5d1SDavid du Colombier if(s == 0) 5093e12c5d1SDavid du Colombier error(Ebadarg); 5103e12c5d1SDavid du Colombier 5113e12c5d1SDavid du Colombier s->flushme = 1; 512*219b2ee8SDavid du Colombier more: 513*219b2ee8SDavid du Colombier l = len; 514*219b2ee8SDavid du Colombier if(addr+l > s->top) 515*219b2ee8SDavid du Colombier l = s->top - addr; 5163e12c5d1SDavid du Colombier 517*219b2ee8SDavid du Colombier ps = addr-s->base; 518*219b2ee8SDavid du Colombier pte = s->map[ps/PTEMAPMEM]; 519*219b2ee8SDavid du Colombier ps &= PTEMAPMEM-1; 520*219b2ee8SDavid du Colombier pe = PTEMAPMEM; 521*219b2ee8SDavid du Colombier if(pe-ps > l){ 522*219b2ee8SDavid du Colombier pe = ps + l; 523*219b2ee8SDavid du Colombier pe = (pe+BY2PG-1)&~(BY2PG-1); 5243e12c5d1SDavid du Colombier } 525*219b2ee8SDavid du Colombier if(pe == ps) { 5263e12c5d1SDavid du Colombier qunlock(&s->lk); 527*219b2ee8SDavid du Colombier error(Ebadarg); 528*219b2ee8SDavid du Colombier } 529*219b2ee8SDavid du Colombier 530*219b2ee8SDavid du Colombier if(pte) 531*219b2ee8SDavid du Colombier pteflush(pte, ps/BY2PG, pe/BY2PG); 532*219b2ee8SDavid du Colombier 533*219b2ee8SDavid du Colombier chunk = pe-ps; 534*219b2ee8SDavid du Colombier len -= chunk; 535*219b2ee8SDavid du Colombier addr += chunk; 536*219b2ee8SDavid du Colombier 537*219b2ee8SDavid du Colombier if(len > 0 && addr < s->top) 538*219b2ee8SDavid du Colombier goto more; 539*219b2ee8SDavid du Colombier 540*219b2ee8SDavid du Colombier qunlock(&s->lk); 541*219b2ee8SDavid du Colombier } 5423e12c5d1SDavid du Colombier flushmmu(); 5433e12c5d1SDavid du Colombier return 0; 5443e12c5d1SDavid du Colombier } 545