19ef1f84bSDavid du Colombier #include "u.h"
29ef1f84bSDavid du Colombier #include "../port/lib.h"
39ef1f84bSDavid du Colombier #include "mem.h"
49ef1f84bSDavid du Colombier #include "dat.h"
59ef1f84bSDavid du Colombier #include "fns.h"
69ef1f84bSDavid du Colombier #include "../port/error.h"
79ef1f84bSDavid du Colombier
89ef1f84bSDavid du Colombier Segment* (*_globalsegattach)(Proc*, char*);
99ef1f84bSDavid du Colombier
109ef1f84bSDavid du Colombier static Lock physseglock;
119ef1f84bSDavid du Colombier
129ef1f84bSDavid du Colombier int
addphysseg(Physseg * new)139ef1f84bSDavid du Colombier addphysseg(Physseg* new)
149ef1f84bSDavid du Colombier {
159ef1f84bSDavid du Colombier Physseg *ps;
169ef1f84bSDavid du Colombier
179ef1f84bSDavid du Colombier /*
189ef1f84bSDavid du Colombier * Check not already entered and there is room
199ef1f84bSDavid du Colombier * for a new entry and the terminating null entry.
209ef1f84bSDavid du Colombier */
219ef1f84bSDavid du Colombier lock(&physseglock);
229ef1f84bSDavid du Colombier for(ps = physseg; ps->name; ps++){
239ef1f84bSDavid du Colombier if(strcmp(ps->name, new->name) == 0){
249ef1f84bSDavid du Colombier unlock(&physseglock);
259ef1f84bSDavid du Colombier return -1;
269ef1f84bSDavid du Colombier }
279ef1f84bSDavid du Colombier }
289ef1f84bSDavid du Colombier if(ps-physseg >= nphysseg-2){
299ef1f84bSDavid du Colombier unlock(&physseglock);
309ef1f84bSDavid du Colombier return -1;
319ef1f84bSDavid du Colombier }
329ef1f84bSDavid du Colombier
339ef1f84bSDavid du Colombier *ps = *new;
349ef1f84bSDavid du Colombier unlock(&physseglock);
359ef1f84bSDavid du Colombier
369ef1f84bSDavid du Colombier return 0;
379ef1f84bSDavid du Colombier }
389ef1f84bSDavid du Colombier
399ef1f84bSDavid du Colombier int
isphysseg(char * name)409ef1f84bSDavid du Colombier isphysseg(char *name)
419ef1f84bSDavid du Colombier {
429ef1f84bSDavid du Colombier int rv;
439ef1f84bSDavid du Colombier Physseg *ps;
449ef1f84bSDavid du Colombier
459ef1f84bSDavid du Colombier lock(&physseglock);
469ef1f84bSDavid du Colombier rv = 0;
479ef1f84bSDavid du Colombier for(ps = physseg; ps->name; ps++){
489ef1f84bSDavid du Colombier if(strcmp(ps->name, name) == 0){
499ef1f84bSDavid du Colombier rv = 1;
509ef1f84bSDavid du Colombier break;
519ef1f84bSDavid du Colombier }
529ef1f84bSDavid du Colombier }
539ef1f84bSDavid du Colombier unlock(&physseglock);
549ef1f84bSDavid du Colombier return rv;
559ef1f84bSDavid du Colombier }
569ef1f84bSDavid du Colombier
579ef1f84bSDavid du Colombier /* Needs to be non-static for BGP support */
589ef1f84bSDavid du Colombier uintptr
ibrk(uintptr addr,int seg)599ef1f84bSDavid du Colombier ibrk(uintptr addr, int seg)
609ef1f84bSDavid du Colombier {
619ef1f84bSDavid du Colombier Segment *s, *ns;
629ef1f84bSDavid du Colombier uintptr newtop, pgsize;
639ef1f84bSDavid du Colombier usize newsize;
649ef1f84bSDavid du Colombier int i, mapsize;
659ef1f84bSDavid du Colombier Pte **map;
669ef1f84bSDavid du Colombier
679ef1f84bSDavid du Colombier s = up->seg[seg];
684498a243SDavid du Colombier if(s == nil)
699ef1f84bSDavid du Colombier error(Ebadarg);
709ef1f84bSDavid du Colombier
719ef1f84bSDavid du Colombier if(addr == 0)
729ef1f84bSDavid du Colombier return s->top;
739ef1f84bSDavid du Colombier
749ef1f84bSDavid du Colombier qlock(&s->lk);
7535a7d776SDavid du Colombier if(waserror()){
7635a7d776SDavid du Colombier qunlock(&s->lk);
7735a7d776SDavid du Colombier nexterror();
7835a7d776SDavid du Colombier }
799ef1f84bSDavid du Colombier
809ef1f84bSDavid du Colombier /* We may start with the bss overlapping the data */
819ef1f84bSDavid du Colombier if(addr < s->base) {
824498a243SDavid du Colombier if(seg != BSEG || up->seg[DSEG] == nil || addr < up->seg[DSEG]->base)
839ef1f84bSDavid du Colombier error(Enovmem);
849ef1f84bSDavid du Colombier addr = s->base;
859ef1f84bSDavid du Colombier }
869ef1f84bSDavid du Colombier
8757fe3081SDavid du Colombier pgsize = segpgsize(s);
889ef1f84bSDavid du Colombier newtop = ROUNDUP(addr, pgsize);
899ef1f84bSDavid du Colombier newsize = (newtop-s->base)/pgsize;
909ef1f84bSDavid du Colombier if(newtop < s->top) {
919ef1f84bSDavid du Colombier /*
929ef1f84bSDavid du Colombier * do not shrink a segment shared with other procs, as the
939ef1f84bSDavid du Colombier * to-be-freed address space may have been passed to the kernel
949ef1f84bSDavid du Colombier * already by another proc and is past the validaddr stage.
959ef1f84bSDavid du Colombier */
9635a7d776SDavid du Colombier if(s->ref > 1)
979ef1f84bSDavid du Colombier error(Einuse);
989ef1f84bSDavid du Colombier mfreeseg(s, newtop, s->top);
999ef1f84bSDavid du Colombier s->top = newtop;
10035a7d776SDavid du Colombier poperror();
1019ef1f84bSDavid du Colombier s->size = newsize;
1029ef1f84bSDavid du Colombier qunlock(&s->lk);
1039ef1f84bSDavid du Colombier mmuflush();
1049ef1f84bSDavid du Colombier return newtop;
1059ef1f84bSDavid du Colombier }
1069ef1f84bSDavid du Colombier
1079ef1f84bSDavid du Colombier for(i = 0; i < NSEG; i++) {
1089ef1f84bSDavid du Colombier ns = up->seg[i];
1094498a243SDavid du Colombier if(ns == nil || ns == s)
1109ef1f84bSDavid du Colombier continue;
1111105a4a2SDavid du Colombier if(newtop > ns->base && s->base < ns->top)
1129ef1f84bSDavid du Colombier error(Esoverlap);
1139ef1f84bSDavid du Colombier }
1149ef1f84bSDavid du Colombier
1159ef1f84bSDavid du Colombier mapsize = HOWMANY(newsize, PTEPERTAB);
11635a7d776SDavid du Colombier if(mapsize > SEGMAPSIZE)
1179ef1f84bSDavid du Colombier error(Enovmem);
1189ef1f84bSDavid du Colombier if(mapsize > s->mapsize){
1199ef1f84bSDavid du Colombier map = smalloc(mapsize*sizeof(Pte*));
1209ef1f84bSDavid du Colombier memmove(map, s->map, s->mapsize*sizeof(Pte*));
1219ef1f84bSDavid du Colombier if(s->map != s->ssegmap)
1229ef1f84bSDavid du Colombier free(s->map);
1239ef1f84bSDavid du Colombier s->map = map;
1249ef1f84bSDavid du Colombier s->mapsize = mapsize;
1259ef1f84bSDavid du Colombier }
1269ef1f84bSDavid du Colombier
1279ef1f84bSDavid du Colombier s->top = newtop;
1289ef1f84bSDavid du Colombier s->size = newsize;
12935a7d776SDavid du Colombier
13035a7d776SDavid du Colombier poperror();
1319ef1f84bSDavid du Colombier qunlock(&s->lk);
1329ef1f84bSDavid du Colombier
1339ef1f84bSDavid du Colombier return newtop;
1349ef1f84bSDavid du Colombier }
1359ef1f84bSDavid du Colombier
1369ef1f84bSDavid du Colombier void
syssegbrk(Ar0 * ar0,va_list list)1379ef1f84bSDavid du Colombier syssegbrk(Ar0* ar0, va_list list)
1389ef1f84bSDavid du Colombier {
1399ef1f84bSDavid du Colombier int i;
1409ef1f84bSDavid du Colombier uintptr addr;
1419ef1f84bSDavid du Colombier Segment *s;
1429ef1f84bSDavid du Colombier
1439ef1f84bSDavid du Colombier /*
1449ef1f84bSDavid du Colombier * int segbrk(void*, void*);
1459ef1f84bSDavid du Colombier * should be
1469ef1f84bSDavid du Colombier * void* segbrk(void* saddr, void* addr);
1479ef1f84bSDavid du Colombier */
1489ef1f84bSDavid du Colombier addr = PTR2UINT(va_arg(list, void*));
1499ef1f84bSDavid du Colombier for(i = 0; i < NSEG; i++) {
1509ef1f84bSDavid du Colombier s = up->seg[i];
1519ef1f84bSDavid du Colombier if(s == nil || addr < s->base || addr >= s->top)
1529ef1f84bSDavid du Colombier continue;
1539ef1f84bSDavid du Colombier switch(s->type&SG_TYPE) {
1549ef1f84bSDavid du Colombier case SG_TEXT:
1559ef1f84bSDavid du Colombier case SG_DATA:
1569ef1f84bSDavid du Colombier case SG_STACK:
1579ef1f84bSDavid du Colombier error(Ebadarg);
1589ef1f84bSDavid du Colombier default:
1599ef1f84bSDavid du Colombier addr = PTR2UINT(va_arg(list, void*));
1609ef1f84bSDavid du Colombier ar0->v = UINT2PTR(ibrk(addr, i));
1619ef1f84bSDavid du Colombier return;
1629ef1f84bSDavid du Colombier }
1639ef1f84bSDavid du Colombier }
1649ef1f84bSDavid du Colombier error(Ebadarg);
1659ef1f84bSDavid du Colombier }
1669ef1f84bSDavid du Colombier
1679ef1f84bSDavid du Colombier void
sysbrk_(Ar0 * ar0,va_list list)1689ef1f84bSDavid du Colombier sysbrk_(Ar0* ar0, va_list list)
1699ef1f84bSDavid du Colombier {
1709ef1f84bSDavid du Colombier uintptr addr;
1719ef1f84bSDavid du Colombier
1729ef1f84bSDavid du Colombier /*
1739ef1f84bSDavid du Colombier * int brk(void*);
1749ef1f84bSDavid du Colombier *
1759ef1f84bSDavid du Colombier * Deprecated; should be for backwards compatibility only.
1769ef1f84bSDavid du Colombier */
1779ef1f84bSDavid du Colombier addr = PTR2UINT(va_arg(list, void*));
1789ef1f84bSDavid du Colombier
1799ef1f84bSDavid du Colombier ibrk(addr, BSEG);
1809ef1f84bSDavid du Colombier
1819ef1f84bSDavid du Colombier ar0->i = 0;
1829ef1f84bSDavid du Colombier }
1839ef1f84bSDavid du Colombier
1849ef1f84bSDavid du Colombier static uintptr
segattach(Proc * p,int attr,char * name,uintptr va,usize len)1859ef1f84bSDavid du Colombier segattach(Proc* p, int attr, char* name, uintptr va, usize len)
1869ef1f84bSDavid du Colombier {
1879ef1f84bSDavid du Colombier int sno;
1889ef1f84bSDavid du Colombier Segment *s, *os;
1899ef1f84bSDavid du Colombier Physseg *ps;
190c4f97bc1SDavid du Colombier uintptr pgsize;
1919ef1f84bSDavid du Colombier
1929ef1f84bSDavid du Colombier /* BUG: Only ok for now */
193fe56f827SDavid du Colombier if((va != 0 && va < UTZERO) || iskaddr(va))
1949ef1f84bSDavid du Colombier error("virtual address in kernel");
1959ef1f84bSDavid du Colombier
1969ef1f84bSDavid du Colombier vmemchr(name, 0, ~0);
1979ef1f84bSDavid du Colombier
1989ef1f84bSDavid du Colombier for(sno = 0; sno < NSEG; sno++)
1999ef1f84bSDavid du Colombier if(p->seg[sno] == nil && sno != ESEG)
2009ef1f84bSDavid du Colombier break;
2019ef1f84bSDavid du Colombier
2029ef1f84bSDavid du Colombier if(sno == NSEG)
2039ef1f84bSDavid du Colombier error("too many segments in process");
2049ef1f84bSDavid du Colombier
2059ef1f84bSDavid du Colombier /*
2069ef1f84bSDavid du Colombier * first look for a global segment with the
2079ef1f84bSDavid du Colombier * same name
2089ef1f84bSDavid du Colombier */
2099ef1f84bSDavid du Colombier if(_globalsegattach != nil){
2109ef1f84bSDavid du Colombier s = (*_globalsegattach)(p, name);
2119ef1f84bSDavid du Colombier if(s != nil){
2129ef1f84bSDavid du Colombier p->seg[sno] = s;
2139ef1f84bSDavid du Colombier return s->base;
2149ef1f84bSDavid du Colombier }
2159ef1f84bSDavid du Colombier }
2169ef1f84bSDavid du Colombier
217c4f97bc1SDavid du Colombier for(ps = physseg; ps->name; ps++)
218c4f97bc1SDavid du Colombier if(strcmp(name, ps->name) == 0)
219c4f97bc1SDavid du Colombier goto found;
220c4f97bc1SDavid du Colombier
221c4f97bc1SDavid du Colombier error("segment not found");
222c4f97bc1SDavid du Colombier found:
223c4f97bc1SDavid du Colombier pgsize = physsegpgsize(ps);
224c4f97bc1SDavid du Colombier len = ROUNDUP(len, pgsize);
2259ef1f84bSDavid du Colombier if(len == 0)
2269ef1f84bSDavid du Colombier error("length overflow");
2279ef1f84bSDavid du Colombier
2289ef1f84bSDavid du Colombier /*
2299ef1f84bSDavid du Colombier * Find a hole in the address space.
2309ef1f84bSDavid du Colombier * Starting at the lowest possible stack address - len,
2319ef1f84bSDavid du Colombier * check for an overlapping segment, and repeat at the
2329ef1f84bSDavid du Colombier * base of that segment - len until either a hole is found
2339ef1f84bSDavid du Colombier * or the address space is exhausted.
2349ef1f84bSDavid du Colombier */
2359ef1f84bSDavid du Colombier //need check here to prevent mapping page 0?
2369ef1f84bSDavid du Colombier if(va == 0) {
2379ef1f84bSDavid du Colombier va = p->seg[SSEG]->base - len;
2389ef1f84bSDavid du Colombier for(;;) {
2399ef1f84bSDavid du Colombier os = isoverlap(p, va, len);
2409ef1f84bSDavid du Colombier if(os == nil)
2419ef1f84bSDavid du Colombier break;
2429ef1f84bSDavid du Colombier va = os->base;
2439ef1f84bSDavid du Colombier if(len > va)
2449ef1f84bSDavid du Colombier error("cannot fit segment at virtual address");
2459ef1f84bSDavid du Colombier va -= len;
2469ef1f84bSDavid du Colombier }
2479ef1f84bSDavid du Colombier }
2489ef1f84bSDavid du Colombier
249c4f97bc1SDavid du Colombier va = va&~(pgsize-1);
2509ef1f84bSDavid du Colombier if(isoverlap(p, va, len) != nil)
2519ef1f84bSDavid du Colombier error(Esoverlap);
2529ef1f84bSDavid du Colombier
253c4f97bc1SDavid du Colombier if((len/pgsize) > ps->size)
2549ef1f84bSDavid du Colombier error("len > segment size");
2559ef1f84bSDavid du Colombier
2569ef1f84bSDavid du Colombier attr &= ~SG_TYPE; /* Turn off what is not allowed */
2579ef1f84bSDavid du Colombier attr |= ps->attr; /* Copy in defaults */
2589ef1f84bSDavid du Colombier
2599ef1f84bSDavid du Colombier s = newseg(attr, va, va+len);
2609ef1f84bSDavid du Colombier s->pseg = ps;
2619ef1f84bSDavid du Colombier p->seg[sno] = s;
2629ef1f84bSDavid du Colombier
2639ef1f84bSDavid du Colombier return va;
2649ef1f84bSDavid du Colombier }
2659ef1f84bSDavid du Colombier
2669ef1f84bSDavid du Colombier void
syssegattach(Ar0 * ar0,va_list list)2679ef1f84bSDavid du Colombier syssegattach(Ar0* ar0, va_list list)
2689ef1f84bSDavid du Colombier {
2699ef1f84bSDavid du Colombier int attr;
2709ef1f84bSDavid du Colombier char *name;
2719ef1f84bSDavid du Colombier uintptr va;
2729ef1f84bSDavid du Colombier usize len;
2739ef1f84bSDavid du Colombier
2749ef1f84bSDavid du Colombier /*
2759ef1f84bSDavid du Colombier * long segattach(int, char*, void*, ulong);
2769ef1f84bSDavid du Colombier * should be
2779ef1f84bSDavid du Colombier * void* segattach(int, char*, void*, usize);
2789ef1f84bSDavid du Colombier */
2799ef1f84bSDavid du Colombier attr = va_arg(list, int);
2809ef1f84bSDavid du Colombier name = va_arg(list, char*);
2819ef1f84bSDavid du Colombier va = PTR2UINT(va_arg(list, void*));
2829ef1f84bSDavid du Colombier len = va_arg(list, usize);
2839ef1f84bSDavid du Colombier
2849ef1f84bSDavid du Colombier ar0->v = UINT2PTR(segattach(up, attr, validaddr(name, 1, 0), va, len));
2859ef1f84bSDavid du Colombier }
2869ef1f84bSDavid du Colombier
2879ef1f84bSDavid du Colombier void
syssegdetach(Ar0 * ar0,va_list list)2889ef1f84bSDavid du Colombier syssegdetach(Ar0* ar0, va_list list)
2899ef1f84bSDavid du Colombier {
2909ef1f84bSDavid du Colombier int i;
2919ef1f84bSDavid du Colombier uintptr addr;
2929ef1f84bSDavid du Colombier Segment *s;
2939ef1f84bSDavid du Colombier
2949ef1f84bSDavid du Colombier /*
2959ef1f84bSDavid du Colombier * int segdetach(void*);
2969ef1f84bSDavid du Colombier */
2979ef1f84bSDavid du Colombier addr = PTR2UINT(va_arg(list, void*));
2989ef1f84bSDavid du Colombier
2999ef1f84bSDavid du Colombier qlock(&up->seglock);
3009ef1f84bSDavid du Colombier if(waserror()){
3019ef1f84bSDavid du Colombier qunlock(&up->seglock);
3029ef1f84bSDavid du Colombier nexterror();
3039ef1f84bSDavid du Colombier }
3049ef1f84bSDavid du Colombier
3059ef1f84bSDavid du Colombier s = 0;
3069ef1f84bSDavid du Colombier for(i = 0; i < NSEG; i++)
3079ef1f84bSDavid du Colombier if(s = up->seg[i]) {
3089ef1f84bSDavid du Colombier qlock(&s->lk);
3099ef1f84bSDavid du Colombier if((addr >= s->base && addr < s->top) ||
3109ef1f84bSDavid du Colombier (s->top == s->base && addr == s->base))
3119ef1f84bSDavid du Colombier goto found;
3129ef1f84bSDavid du Colombier qunlock(&s->lk);
3139ef1f84bSDavid du Colombier }
3149ef1f84bSDavid du Colombier
3159ef1f84bSDavid du Colombier error(Ebadarg);
3169ef1f84bSDavid du Colombier
3179ef1f84bSDavid du Colombier found:
3189ef1f84bSDavid du Colombier /*
3199ef1f84bSDavid du Colombier * Can't detach the initial stack segment
3209ef1f84bSDavid du Colombier * because the clock writes profiling info
3219ef1f84bSDavid du Colombier * there.
3229ef1f84bSDavid du Colombier */
3239ef1f84bSDavid du Colombier if(s == up->seg[SSEG]){
3249ef1f84bSDavid du Colombier qunlock(&s->lk);
3259ef1f84bSDavid du Colombier error(Ebadarg);
3269ef1f84bSDavid du Colombier }
3279ef1f84bSDavid du Colombier up->seg[i] = 0;
3289ef1f84bSDavid du Colombier qunlock(&s->lk);
3299ef1f84bSDavid du Colombier putseg(s);
3309ef1f84bSDavid du Colombier qunlock(&up->seglock);
3319ef1f84bSDavid du Colombier poperror();
3329ef1f84bSDavid du Colombier
3339ef1f84bSDavid du Colombier /* Ensure we flush any entries from the lost segment */
3349ef1f84bSDavid du Colombier mmuflush();
3359ef1f84bSDavid du Colombier
3369ef1f84bSDavid du Colombier ar0->i = 0;
3379ef1f84bSDavid du Colombier }
3389ef1f84bSDavid du Colombier
3399ef1f84bSDavid du Colombier void
syssegfree(Ar0 * ar0,va_list list)3409ef1f84bSDavid du Colombier syssegfree(Ar0* ar0, va_list list)
3419ef1f84bSDavid du Colombier {
3429ef1f84bSDavid du Colombier Segment *s;
343c4f97bc1SDavid du Colombier uintptr from, to, pgsize;
3449ef1f84bSDavid du Colombier usize len;
3459ef1f84bSDavid du Colombier
3469ef1f84bSDavid du Colombier /*
3479ef1f84bSDavid du Colombier * int segfree(void*, ulong);
3489ef1f84bSDavid du Colombier * should be
3499ef1f84bSDavid du Colombier * int segfree(void*, usize);
3509ef1f84bSDavid du Colombier */
3519ef1f84bSDavid du Colombier from = PTR2UINT(va_arg(list, void*));
3529ef1f84bSDavid du Colombier s = seg(up, from, 1);
3539ef1f84bSDavid du Colombier if(s == nil)
3549ef1f84bSDavid du Colombier error(Ebadarg);
3559ef1f84bSDavid du Colombier len = va_arg(list, usize);
356c4f97bc1SDavid du Colombier pgsize = segpgsize(s);
357c4f97bc1SDavid du Colombier to = (from + len) & ~(pgsize-1);
3589ef1f84bSDavid du Colombier if(to < from || to > s->top){
3599ef1f84bSDavid du Colombier qunlock(&s->lk);
3609ef1f84bSDavid du Colombier error(Ebadarg);
3619ef1f84bSDavid du Colombier }
362c4f97bc1SDavid du Colombier from = ROUNDUP(from, pgsize);
3639ef1f84bSDavid du Colombier
3649ef1f84bSDavid du Colombier mfreeseg(s, from, to);
3659ef1f84bSDavid du Colombier qunlock(&s->lk);
3669ef1f84bSDavid du Colombier mmuflush();
3679ef1f84bSDavid du Colombier
3689ef1f84bSDavid du Colombier ar0->i = 0;
3699ef1f84bSDavid du Colombier }
3709ef1f84bSDavid du Colombier
3719ef1f84bSDavid du Colombier static void
pteflush(Pte * pte,int s,int e)3729ef1f84bSDavid du Colombier pteflush(Pte *pte, int s, int e)
3739ef1f84bSDavid du Colombier {
3749ef1f84bSDavid du Colombier int i;
3759ef1f84bSDavid du Colombier
376*0d74731bSDavid du Colombier for(i = s; i < e; i++)
377*0d74731bSDavid du Colombier mmucachectl(pte->pages[i], PG_TXTFLUSH);
3789ef1f84bSDavid du Colombier }
3799ef1f84bSDavid du Colombier
3809ef1f84bSDavid du Colombier void
syssegflush(Ar0 * ar0,va_list list)3819ef1f84bSDavid du Colombier syssegflush(Ar0* ar0, va_list list)
3829ef1f84bSDavid du Colombier {
3839ef1f84bSDavid du Colombier Segment *s;
3849ef1f84bSDavid du Colombier uintptr addr, pgsize;
3859ef1f84bSDavid du Colombier Pte *pte;
3869ef1f84bSDavid du Colombier usize chunk, l, len, pe, ps;
3879ef1f84bSDavid du Colombier
3889ef1f84bSDavid du Colombier /*
3899ef1f84bSDavid du Colombier * int segflush(void*, ulong);
3909ef1f84bSDavid du Colombier * should be
3919ef1f84bSDavid du Colombier * int segflush(void*, usize);
3929ef1f84bSDavid du Colombier */
3939ef1f84bSDavid du Colombier addr = PTR2UINT(va_arg(list, void*));
3949ef1f84bSDavid du Colombier len = va_arg(list, usize);
3959ef1f84bSDavid du Colombier
3969ef1f84bSDavid du Colombier while(len > 0) {
3979ef1f84bSDavid du Colombier s = seg(up, addr, 1);
3989ef1f84bSDavid du Colombier if(s == nil)
3999ef1f84bSDavid du Colombier error(Ebadarg);
4009ef1f84bSDavid du Colombier
4019ef1f84bSDavid du Colombier s->flushme = 1;
40257fe3081SDavid du Colombier pgsize = segpgsize(s);
4039ef1f84bSDavid du Colombier more:
4049ef1f84bSDavid du Colombier l = len;
4059ef1f84bSDavid du Colombier if(addr+l > s->top)
4069ef1f84bSDavid du Colombier l = s->top - addr;
4079ef1f84bSDavid du Colombier
4089ef1f84bSDavid du Colombier ps = addr-s->base;
4099ef1f84bSDavid du Colombier pte = s->map[ps/s->ptemapmem];
4109ef1f84bSDavid du Colombier ps &= s->ptemapmem-1;
4119ef1f84bSDavid du Colombier pe = s->ptemapmem;
4129ef1f84bSDavid du Colombier if(pe-ps > l){
4139ef1f84bSDavid du Colombier pe = ps + l;
4149ef1f84bSDavid du Colombier pe = (pe+pgsize-1)&~(pgsize-1);
4159ef1f84bSDavid du Colombier }
4169ef1f84bSDavid du Colombier if(pe == ps) {
4179ef1f84bSDavid du Colombier qunlock(&s->lk);
4189ef1f84bSDavid du Colombier error(Ebadarg);
4199ef1f84bSDavid du Colombier }
4209ef1f84bSDavid du Colombier
4219ef1f84bSDavid du Colombier if(pte)
4229ef1f84bSDavid du Colombier pteflush(pte, ps/pgsize, pe/pgsize);
4239ef1f84bSDavid du Colombier
4249ef1f84bSDavid du Colombier chunk = pe-ps;
4259ef1f84bSDavid du Colombier len -= chunk;
4269ef1f84bSDavid du Colombier addr += chunk;
4279ef1f84bSDavid du Colombier
4289ef1f84bSDavid du Colombier if(len > 0 && addr < s->top)
4299ef1f84bSDavid du Colombier goto more;
4309ef1f84bSDavid du Colombier
4319ef1f84bSDavid du Colombier qunlock(&s->lk);
4329ef1f84bSDavid du Colombier }
4339ef1f84bSDavid du Colombier mmuflush();
4349ef1f84bSDavid du Colombier
4359ef1f84bSDavid du Colombier ar0->i = 0;
4369ef1f84bSDavid du Colombier }
437