ref: 81e6b7e9c958bd5da3c93e204fff59e6868bd0fc
parent: 2a1d36928154c3b295510664191d3e47403f73b9
parent: 461c2b68a16ab3314202ec7796fe7eb8a7731f2d
author: cinap_lenrek <[email protected]>
date: Sun Apr 12 18:31:34 EDT 2015
merge
--- a/sys/src/9/port/devproc.c
+++ b/sys/src/9/port/devproc.c
@@ -134,7 +134,7 @@
};
/* 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:
--- a/sys/src/9/port/devsegment.c
+++ b/sys/src/9/port/devsegment.c
@@ -56,6 +56,7 @@
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 @@
{
Qid q;
Globalseg *g;
- ulong size;
+ uintptr size;
switch(TYPE(c)) {
case Qtopdir:
@@ -328,7 +329,11 @@
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 @@
{
Cmdbuf *cb;
Globalseg *g;
- ulong va, len, top;
+ uintptr va, top, len;
if(c->qid.type == QTDIR)
error(Eperm);
@@ -376,14 +381,19 @@
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;
@@ -559,6 +569,73 @@
}
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 = {
--- a/sys/src/9/port/fault.c
+++ b/sys/src/9/port/fault.c
@@ -267,6 +267,7 @@
copypage(old, *pg);
putpage(old);
}
+ case SG_FIXED: /* Never paged out */
mmuphys = PPN((*pg)->pa) | PTEWRITE | PTEVALID;
(*pg)->modref = PG_MOD|PG_REF;
break;
--- a/sys/src/9/port/portdat.h
+++ b/sys/src/9/port/portdat.h
@@ -341,6 +341,7 @@
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 */
--- a/sys/src/9/port/segment.c
+++ b/sys/src/9/port/segment.c
@@ -156,6 +156,7 @@
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 @@
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
--- a/sys/src/9/port/sysproc.c
+++ b/sys/src/9/port/sysproc.c
@@ -751,6 +751,7 @@
case SG_DATA:
case SG_STACK:
case SG_PHYSICAL:
+ case SG_FIXED:
error(Ebadarg);
default:
return (uintptr)ibrk(va_arg(list, uintptr), i);