This commit is contained in:
cinap_lenrek 2015-04-12 22:31:34 +02:00
commit 81e6b7e9c9
6 changed files with 94 additions and 10 deletions

View file

@ -134,7 +134,7 @@ Cmdtab proccmd[] = {
};
/* Segment type from portdat.h */
static char *sname[]={ "Text", "Data", "Bss", "Stack", "Shared", "Phys", };
static char *sname[]={ "Text", "Data", "Bss", "Stack", "Shared", "Phys", "Fixed", };
/*
* Qids are, in path:

View file

@ -56,6 +56,7 @@ static Segment* globalsegattach(Proc *p, char *name);
static int cmddone(void*);
static void segmentkproc(void*);
static void docmd(Globalseg *g, int cmd);
static Segment* fixedseg(uintptr va, ulong len);
/*
* returns with globalseg incref'd
@ -98,7 +99,7 @@ segmentgen(Chan *c, char*, Dirtab*, int, int s, Dir *dp)
{
Qid q;
Globalseg *g;
ulong size;
uintptr size;
switch(TYPE(c)) {
case Qtopdir:
@ -328,7 +329,11 @@ segmentread(Chan *c, void *a, long n, vlong voff)
g = c->aux;
if(g->s == nil)
error("segment not yet allocated");
sprint(buf, "va %#lux %#lux\n", g->s->base, g->s->top-g->s->base);
if(g->s->type&SG_TYPE == SG_FIXED)
sprint(buf, "va %#p %#p fixed %#p\n", g->s->base, g->s->top-g->s->base,
g->s->map[0]->pages[0]->pa);
else
sprint(buf, "va %#p %#p\n", g->s->base, g->s->top-g->s->base);
return readstr(voff, a, n, buf);
case Qdata:
g = c->aux;
@ -362,7 +367,7 @@ segmentwrite(Chan *c, void *a, long n, vlong voff)
{
Cmdbuf *cb;
Globalseg *g;
ulong va, len, top;
uintptr va, top, len;
if(c->qid.type == QTDIR)
error(Eperm);
@ -376,14 +381,19 @@ segmentwrite(Chan *c, void *a, long n, vlong voff)
error("already has a virtual address");
if(cb->nf < 3)
error(Ebadarg);
va = strtoul(cb->f[1], 0, 0);
len = strtoul(cb->f[2], 0, 0);
va = strtoull(cb->f[1], 0, 0);
len = strtoull(cb->f[2], 0, 0);
top = PGROUND(va + len);
va = va&~(BY2PG-1);
len = (top - va) / BY2PG;
if(len == 0)
if(va == 0 || top > USTKTOP || top <= va)
error(Ebadarg);
g->s = newseg(SG_SHARED, va, len);
len = (top - va) / BY2PG;
if(cb->nf >= 4 && strcmp(cb->f[3], "fixed") == 0){
if(!iseve())
error(Eperm);
g->s = fixedseg(va, len);
} else
g->s = newseg(SG_SHARED, va, len);
} else
error(Ebadctl);
break;
@ -561,6 +571,73 @@ segmentkproc(void *arg)
pexit("done", 1);
}
/*
* allocate a fixed segment with sequential run of of adjacent
* user memory pages.
*/
static Segment*
fixedseg(uintptr va, ulong len)
{
KMap *k;
Segment *s;
Page **f, *p;
ulong n, i, j;
int color;
s = newseg(SG_FIXED, va, len);
if(waserror()){
putseg(s);
nexterror();
}
lock(&palloc);
i = 0;
p = palloc.pages;
color = getpgcolor(va);
for(n = palloc.user; n >= len; n--, p++){
if(p->ref != 0 || i != 0 && (p[-1].pa+BY2PG) != p->pa || i == 0 && p->color != color){
Retry:
i = 0;
continue;
}
if(++i < len)
continue;
for(j = 0; j < i; j++, p--){
for(f = &palloc.head; *f != nil; f = &((*f)->next)){
if(*f == p){
*f = p->next;
goto Freed;
}
}
while(j-- > 0)
pagechainhead(++p);
goto Retry;
Freed:
palloc.freecount--;
}
unlock(&palloc);
while(i-- > 0){
p++;
p->ref = 1;
p->va = va;
p->modref = 0;
p->txtflush = ~0;
k = kmap(p);
memset((void*)VA(k), 0, BY2PG);
kunmap(k);
segpage(s, p);
va += BY2PG;
}
poperror();
return s;
}
unlock(&palloc);
error(Enomem);
return nil;
}
Dev segmentdevtab = {
'g',
"segment",

View file

@ -267,6 +267,7 @@ fixfault(Segment *s, uintptr addr, int read, int doputmmu)
copypage(old, *pg);
putpage(old);
}
case SG_FIXED: /* Never paged out */
mmuphys = PPN((*pg)->pa) | PTEWRITE | PTEVALID;
(*pg)->modref = PG_MOD|PG_REF;
break;

View file

@ -341,6 +341,7 @@ enum
SG_STACK = 03,
SG_SHARED = 04,
SG_PHYSICAL = 05,
SG_FIXED = 06,
SG_RONLY = 0040, /* Segment is read only */
SG_CEXEC = 0100, /* Detach at exec */

View file

@ -156,6 +156,7 @@ dupseg(Segment **seg, int segno, int share)
case SG_TEXT: /* New segment shares pte set */
case SG_SHARED:
case SG_PHYSICAL:
case SG_FIXED:
goto sameseg;
case SG_STACK:
@ -489,8 +490,11 @@ mfreeseg(Segment *s, uintptr start, ulong pages)
if(pages == 0)
return;
if((s->type&SG_TYPE) == SG_PHYSICAL)
switch(s->type&SG_TYPE){
case SG_PHYSICAL:
case SG_FIXED:
return;
}
/*
* we have to make sure other processors flush the

View file

@ -751,6 +751,7 @@ syssegbrk(va_list list)
case SG_DATA:
case SG_STACK:
case SG_PHYSICAL:
case SG_FIXED:
error(Ebadarg);
default:
return (uintptr)ibrk(va_arg(list, uintptr), i);