shithub: riscv

Download patch

ref: 81e6b7e9c958bd5da3c93e204fff59e6868bd0fc
parent: 2a1d36928154c3b295510664191d3e47403f73b9
parent: 461c2b68a16ab3314202ec7796fe7eb8a7731f2d
author: cinap_lenrek <cinap_lenrek@felloff.net>
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);