changelog shortlog tags branches files raw gz bz2 help

Mercurial > hg > plan9front / changeset: kernel: fixed segment support (for fpga experiments)

changeset 4420: 55c828851f06
parent 4418: cf348dd0fc31
child 4421: 86c3761d3518
author: cinap_lenrek@felloff.net
date: Sun, 12 Apr 2015 22:30:30 +0200
files: sys/src/9/port/devproc.c sys/src/9/port/devsegment.c sys/src/9/port/fault.c sys/src/9/port/portdat.h sys/src/9/port/segment.c sys/src/9/port/sysproc.c
description: kernel: fixed segment support (for fpga experiments)

fixed segments are continuous in physical memory but
allocated in user pages. unlike shared segments, they
are not allocated on demand but the pages are allocated
on creation time (devsegment). fixed segments are
never swapped out, segfreed or resized and can only be
destroyed as a whole.

the physical base address can be discovered by userspace
reading the ctl file in devsegment.
     1.1--- a/sys/src/9/port/devproc.c
     1.2+++ b/sys/src/9/port/devproc.c
     1.3@@ -134,7 +134,7 @@ Cmdtab proccmd[] = {
     1.4 };
     1.5 
     1.6 /* Segment type from portdat.h */
     1.7-static char *sname[]={ "Text", "Data", "Bss", "Stack", "Shared", "Phys", };
     1.8+static char *sname[]={ "Text", "Data", "Bss", "Stack", "Shared", "Phys", "Fixed", };
     1.9 
    1.10 /*
    1.11  * Qids are, in path:
     2.1--- a/sys/src/9/port/devsegment.c
     2.2+++ b/sys/src/9/port/devsegment.c
     2.3@@ -56,6 +56,7 @@ static	Segment* globalsegattach(Proc *p,
     2.4 static	int	cmddone(void*);
     2.5 static	void	segmentkproc(void*);
     2.6 static	void	docmd(Globalseg *g, int cmd);
     2.7+static	Segment* fixedseg(uintptr va, ulong len);
     2.8 
     2.9 /*
    2.10  *  returns with globalseg incref'd
    2.11@@ -98,7 +99,7 @@ segmentgen(Chan *c, char*, Dirtab*, int,
    2.12 {
    2.13 	Qid q;
    2.14 	Globalseg *g;
    2.15-	ulong size;
    2.16+	uintptr size;
    2.17 
    2.18 	switch(TYPE(c)) {
    2.19 	case Qtopdir:
    2.20@@ -328,7 +329,11 @@ segmentread(Chan *c, void *a, long n, vl
    2.21 		g = c->aux;
    2.22 		if(g->s == nil)
    2.23 			error("segment not yet allocated");
    2.24-		sprint(buf, "va %#lux %#lux\n", g->s->base, g->s->top-g->s->base);
    2.25+		if(g->s->type&SG_TYPE == SG_FIXED)
    2.26+			sprint(buf, "va %#p %#p fixed %#p\n", g->s->base, g->s->top-g->s->base,
    2.27+				g->s->map[0]->pages[0]->pa);
    2.28+		else
    2.29+			sprint(buf, "va %#p %#p\n", g->s->base, g->s->top-g->s->base);
    2.30 		return readstr(voff, a, n, buf);
    2.31 	case Qdata:
    2.32 		g = c->aux;
    2.33@@ -362,7 +367,7 @@ segmentwrite(Chan *c, void *a, long n, v
    2.34 {
    2.35 	Cmdbuf *cb;
    2.36 	Globalseg *g;
    2.37-	ulong va, len, top;
    2.38+	uintptr va, top, len;
    2.39 
    2.40 	if(c->qid.type == QTDIR)
    2.41 		error(Eperm);
    2.42@@ -376,14 +381,19 @@ segmentwrite(Chan *c, void *a, long n, v
    2.43 				error("already has a virtual address");
    2.44 			if(cb->nf < 3)
    2.45 				error(Ebadarg);
    2.46-			va = strtoul(cb->f[1], 0, 0);
    2.47-			len = strtoul(cb->f[2], 0, 0);
    2.48+			va = strtoull(cb->f[1], 0, 0);
    2.49+			len = strtoull(cb->f[2], 0, 0);
    2.50 			top = PGROUND(va + len);
    2.51 			va = va&~(BY2PG-1);
    2.52+			if(va == 0 || top > USTKTOP || top <= va)
    2.53+				error(Ebadarg);
    2.54 			len = (top - va) / BY2PG;
    2.55-			if(len == 0)
    2.56-				error(Ebadarg);
    2.57-			g->s = newseg(SG_SHARED, va, len);
    2.58+			if(cb->nf >= 4 && strcmp(cb->f[3], "fixed") == 0){
    2.59+				if(!iseve())
    2.60+					error(Eperm);
    2.61+				g->s = fixedseg(va, len);
    2.62+			} else
    2.63+				g->s = newseg(SG_SHARED, va, len);
    2.64 		} else
    2.65 			error(Ebadctl);
    2.66 		break;
    2.67@@ -561,6 +571,73 @@ segmentkproc(void *arg)
    2.68 	pexit("done", 1);
    2.69 }
    2.70 
    2.71+/*
    2.72+ * allocate a fixed segment with sequential run of of adjacent
    2.73+ * user memory pages.
    2.74+ */
    2.75+static Segment*
    2.76+fixedseg(uintptr va, ulong len)
    2.77+{
    2.78+	KMap *k;
    2.79+	Segment *s;
    2.80+	Page **f, *p;
    2.81+	ulong n, i, j;
    2.82+	int color;
    2.83+
    2.84+	s = newseg(SG_FIXED, va, len);
    2.85+	if(waserror()){
    2.86+		putseg(s);
    2.87+		nexterror();
    2.88+	}
    2.89+	lock(&palloc);
    2.90+	i = 0;
    2.91+	p = palloc.pages;
    2.92+	color = getpgcolor(va);
    2.93+	for(n = palloc.user; n >= len; n--, p++){
    2.94+		if(p->ref != 0 || i != 0 && (p[-1].pa+BY2PG) != p->pa || i == 0 && p->color != color){
    2.95+		Retry:
    2.96+			i = 0;
    2.97+			continue;
    2.98+		}
    2.99+		if(++i < len)
   2.100+			continue;
   2.101+		for(j = 0; j < i; j++, p--){
   2.102+			for(f = &palloc.head; *f != nil; f = &((*f)->next)){
   2.103+				if(*f == p){
   2.104+					*f = p->next;
   2.105+					goto Freed;
   2.106+				}
   2.107+			}
   2.108+			while(j-- > 0)
   2.109+				pagechainhead(++p);
   2.110+			goto Retry;
   2.111+		Freed:
   2.112+			palloc.freecount--;
   2.113+		}
   2.114+		unlock(&palloc);
   2.115+
   2.116+		while(i-- > 0){
   2.117+			p++;
   2.118+			p->ref = 1;
   2.119+			p->va = va;
   2.120+			p->modref = 0;
   2.121+			p->txtflush = ~0;
   2.122+			
   2.123+			k = kmap(p);
   2.124+			memset((void*)VA(k), 0, BY2PG);
   2.125+			kunmap(k);
   2.126+			
   2.127+			segpage(s, p);
   2.128+			va += BY2PG;
   2.129+		}
   2.130+		poperror();
   2.131+		return s;
   2.132+	}
   2.133+	unlock(&palloc);
   2.134+	error(Enomem);
   2.135+	return nil;
   2.136+}
   2.137+
   2.138 Dev segmentdevtab = {
   2.139 	'g',
   2.140 	"segment",
     3.1--- a/sys/src/9/port/fault.c
     3.2+++ b/sys/src/9/port/fault.c
     3.3@@ -267,6 +267,7 @@ fixfault(Segment *s, uintptr addr, int r
     3.4 			copypage(old, *pg);
     3.5 			putpage(old);
     3.6 		}
     3.7+	case SG_FIXED:			/* Never paged out */
     3.8 		mmuphys = PPN((*pg)->pa) | PTEWRITE | PTEVALID;
     3.9 		(*pg)->modref = PG_MOD|PG_REF;
    3.10 		break;
     4.1--- a/sys/src/9/port/portdat.h
     4.2+++ b/sys/src/9/port/portdat.h
     4.3@@ -341,6 +341,7 @@ enum
     4.4 	SG_STACK	= 03,
     4.5 	SG_SHARED	= 04,
     4.6 	SG_PHYSICAL	= 05,
     4.7+	SG_FIXED	= 06,
     4.8 
     4.9 	SG_RONLY	= 0040,		/* Segment is read only */
    4.10 	SG_CEXEC	= 0100,		/* Detach at exec */
     5.1--- a/sys/src/9/port/segment.c
     5.2+++ b/sys/src/9/port/segment.c
     5.3@@ -156,6 +156,7 @@ dupseg(Segment **seg, int segno, int sha
     5.4 	case SG_TEXT:		/* New segment shares pte set */
     5.5 	case SG_SHARED:
     5.6 	case SG_PHYSICAL:
     5.7+	case SG_FIXED:
     5.8 		goto sameseg;
     5.9 
    5.10 	case SG_STACK:
    5.11@@ -489,8 +490,11 @@ mfreeseg(Segment *s, uintptr start, ulon
    5.12 	if(pages == 0)
    5.13 		return;
    5.14 
    5.15-	if((s->type&SG_TYPE) == SG_PHYSICAL)
    5.16+	switch(s->type&SG_TYPE){
    5.17+	case SG_PHYSICAL:
    5.18+	case SG_FIXED:
    5.19 		return;
    5.20+	}
    5.21 
    5.22 	/*
    5.23 	 * we have to make sure other processors flush the
     6.1--- a/sys/src/9/port/sysproc.c
     6.2+++ b/sys/src/9/port/sysproc.c
     6.3@@ -751,6 +751,7 @@ syssegbrk(va_list list)
     6.4 		case SG_DATA:
     6.5 		case SG_STACK:
     6.6 		case SG_PHYSICAL:
     6.7+		case SG_FIXED:
     6.8 			error(Ebadarg);
     6.9 		default:
    6.10 			return (uintptr)ibrk(va_arg(list, uintptr), i);