shithub: riscv

Download patch

ref: 6b22a732e80cfbb28db8d707d5938141abf63a79
parent: 52698c726c4838a7e2eb9477d53c68b12206b926
parent: 8f9642a5148f44771dd7c9e029885bb9cf45a303
author: cinap_lenrek <cinap_lenrek@felloff.net>
date: Sun May 27 19:05:00 EDT 2018

merge

--- a/sys/man/8/plan9.ini
+++ b/sys/man/8/plan9.ini
@@ -500,6 +500,15 @@
 and
 .I slot
 to use as a root device for bootstrapping.
+.SS \fLramdisk\fIX\fL=\fIsize\fP
+.SS \fLramdisk\fIX\fL=\fIsize sectorsize\fP
+.SS \fLramdisk\fIX\fL=\fIaddress size sectorsize\fP
+This reserves physical memory as a ramdisk that will appear as an
+.IR sd(3)
+device. When the
+.I address
+argument is omited or zero, then the ramdisk will be allocated
+from the top of physical memory.
 .SS AUDIO
 .SS \fLaudio\fIX\fL=\fIvalue\fP
 This defines a sound interface. PCI based audio devices such as
--- a/sys/src/9/pc/dat.h
+++ b/sys/src/9/pc/dat.h
@@ -126,8 +126,6 @@
 	ulong	nimage;		/* number of page cache image headers */
 	ulong	nswap;		/* number of swap pages */
 	int	nswppo;		/* max # of pageouts per segment pass */
-	ulong	base0;		/* base of bank 0 */
-	ulong	base1;		/* base of bank 1 */
 	ulong	copymode;	/* 0 is copy on write, 1 is copy on reference */
 	ulong	ialloc;		/* max interrupt time allocation in bytes */
 	ulong	pipeqsize;	/* size in bytes of pipe queues */
--- a/sys/src/9/pc/main.c
+++ b/sys/src/9/pc/main.c
@@ -36,6 +36,7 @@
 	i8253init();
 	cpuidentify();
 	meminit();
+	ramdiskinit();
 	confinit();
 	xinit();
 	archinit();
--- a/sys/src/9/pc/pc
+++ b/sys/src/9/pc/pc
@@ -106,6 +106,7 @@
 	sdmmc		pci pmmc
 	sdnvme		pci
 	sdloop
+	sdram
 
 	uarti8250
 	uartisa
--- a/sys/src/9/pc64/main.c
+++ b/sys/src/9/pc64/main.c
@@ -305,6 +305,7 @@
 	i8253init();
 	cpuidentify();
 	meminit();
+	ramdiskinit();
 	confinit();
 	xinit();
 	archinit();
--- a/sys/src/9/pc64/pc64
+++ b/sys/src/9/pc64/pc64
@@ -104,6 +104,7 @@
 	sdmmc		pci pmmc
 	sdnvme		pci
 	sdloop
+	sdram
 
 	uarti8250
 	uartisa
--- a/sys/src/9/port/fault.c
+++ b/sys/src/9/port/fault.c
@@ -5,63 +5,6 @@
 #include	"fns.h"
 #include	"../port/error.h"
 
-int
-fault(uintptr addr, int read)
-{
-	Segment *s;
-	char *sps;
-	int pnd, attr;
-
-	if(up == nil)
-		panic("fault: nil up");
-	if(up->nlocks){
-		Lock *l = up->lastlock;
-		print("fault: nlocks %d, proc %lud %s, addr %#p, lock %#p, lpc %#p\n", 
-			up->nlocks, up->pid, up->text, addr, l, l ? l->pc : 0);
-	}
-
-	pnd = up->notepending;
-	sps = up->psstate;
-	up->psstate = "Fault";
-
-	m->pfault++;
-	for(;;) {
-		spllo();
-
-		s = seg(up, addr, 1);		/* leaves s locked if seg != nil */
-		if(s == nil) {
-			up->psstate = sps;
-			return -1;
-		}
-
-		attr = s->type;
-		if((attr & SG_TYPE) == SG_PHYSICAL)
-			attr |= s->pseg->attr;
-		if((attr & SG_FAULT) != 0 || !read && (attr & SG_RONLY) != 0) {
-			qunlock(s);
-			up->psstate = sps;
-			if(up->kp && up->nerrlab)	/* for segio */
-				error(Eio);
-			return -1;
-		}
-
-		if(fixfault(s, addr, read) == 0)
-			break;
-
-		splhi();
-		switch(up->procctl){
-		case Proc_exitme:
-		case Proc_exitbig:
-			procctl();
-		}
-	}
-
-	up->psstate = sps;
-	up->notepending |= pnd;
-
-	return 0;
-}
-
 static void
 faulterror(char *s, Chan *c)
 {
@@ -196,10 +139,7 @@
 		(*p)->txtflush = ~0;
 }
 
-void	(*checkaddr)(uintptr, Segment *, Page *);
-uintptr	addr2check;
-
-int
+static int
 fixfault(Segment *s, uintptr addr, int read)
 {
 	int type;
@@ -276,19 +216,8 @@
 		(*pg)->modref = PG_MOD|PG_REF;
 		break;
 
-	case SG_PHYSICAL:
-		if(*pg == nil){
-			new = smalloc(sizeof(Page));
-			new->va = addr;
-			new->pa = s->pseg->pa+(addr-s->base);
-			new->ref = 1;
-			*pg = new;
-		}
-		/* wet floor */
 	case SG_FIXED:			/* Never paged out */
-		if (checkaddr && addr == addr2check)
-			(*checkaddr)(addr, s, *pg);
-		mmuphys = PPN((*pg)->pa) |PTEWRITE|PTEUNCACHED|PTEVALID;
+		mmuphys = PPN((*pg)->pa) | PTEWRITE | PTEUNCACHED | PTEVALID;
 		(*pg)->modref = PG_MOD|PG_REF;
 		break;
 	}
@@ -295,6 +224,90 @@
 	qunlock(s);
 
 	putmmu(addr, mmuphys, *pg);
+
+	return 0;
+}
+
+static void
+mapphys(Segment *s, uintptr addr, int attr)
+{
+	uintptr mmuphys;
+	Page pg = {0};
+
+	addr &= ~(BY2PG-1);
+	pg.ref = 1;
+	pg.va = addr;
+	pg.pa = s->pseg->pa+(addr-s->base);
+
+	mmuphys = PPN(pg.pa) | PTEVALID;
+	if((attr & SG_RONLY) == 0)
+		mmuphys |= PTEWRITE;
+	if((attr & SG_CACHED) == 0)
+		mmuphys |= PTEUNCACHED;
+	qunlock(s);
+
+	putmmu(addr, mmuphys, &pg);
+}
+
+int
+fault(uintptr addr, int read)
+{
+	Segment *s;
+	char *sps;
+	int pnd, attr;
+
+	if(up == nil)
+		panic("fault: nil up");
+	if(up->nlocks){
+		Lock *l = up->lastlock;
+		print("fault: nlocks %d, proc %lud %s, addr %#p, lock %#p, lpc %#p\n", 
+			up->nlocks, up->pid, up->text, addr, l, l ? l->pc : 0);
+	}
+
+	pnd = up->notepending;
+	sps = up->psstate;
+	up->psstate = "Fault";
+
+	m->pfault++;
+	for(;;) {
+		spllo();
+
+		s = seg(up, addr, 1);		/* leaves s locked if seg != nil */
+		if(s == nil) {
+			up->psstate = sps;
+			return -1;
+		}
+
+		attr = s->type;
+		if((attr & SG_TYPE) == SG_PHYSICAL)
+			attr |= s->pseg->attr;
+
+		if((attr & SG_FAULT) != 0 || !read && (attr & SG_RONLY) != 0) {
+			qunlock(s);
+			up->psstate = sps;
+			if(up->kp && up->nerrlab)	/* for segio */
+				error(Eio);
+			return -1;
+		}
+
+		if((attr & SG_TYPE) == SG_PHYSICAL){
+			mapphys(s, addr, attr);
+			break;
+		}
+
+		if(fixfault(s, addr, read) == 0)
+			break;
+
+		splhi();
+		switch(up->procctl){
+		case Proc_exitme:
+		case Proc_exitbig:
+			procctl();
+		}
+	}
+
+	up->psstate = sps;
+	up->notepending |= pnd;
 
 	return 0;
 }
--- a/sys/src/9/port/mkdevc
+++ b/sys/src/9/port/mkdevc
@@ -43,9 +43,11 @@
 		arch[narch++] = $1;
 	else if($1 ~ "^ad.*")
 		adifc[nadifc++] = $1;
-	else if($1 ~ "^sd.*")
+	else if($1 ~ "^sd.*"){
 		sdifc[nsdifc++] = $1;
-	else if($1 ~ "^uart.*")
+		if($1 == "sdram")
+			ramdisk = 1;
+	}else if($1 ~ "^uart.*")
 		physuart[nphysuart++] = substr($1, 5, length($1)-4) "physuart";
 	else if($1 ~ "^vga.*"){
 		if(NF == 1)
@@ -136,6 +138,8 @@
 			printf "\t&%sifc,\n", sdifc[i];
 	  	printf "\tnil,\n};\n\n";
 	}
+	if(!ramdisk)
+		printf "void ramdiskinit(void)\n{\n}\n\n";
 
 	if(devuart){
 		for(i = 0; i < nphysuart; i++)
--- a/sys/src/9/port/portdat.h
+++ b/sys/src/9/port/portdat.h
@@ -373,6 +373,7 @@
 	SG_RONLY	= 0040,		/* Segment is read only */
 	SG_CEXEC	= 0100,		/* Detach at exec */
 	SG_FAULT	= 0200,		/* Fault on access */
+	SG_CACHED	= 0400,
 };
 
 #define PG_ONSWAP	1
--- a/sys/src/9/port/portfns.h
+++ b/sys/src/9/port/portfns.h
@@ -109,7 +109,6 @@
 void		fdclose(int, int);
 Chan*		fdtochan(int, int, int, int);
 int		findmount(Chan**, Mhead**, int, int, Qid);
-int		fixfault(Segment*, uintptr, int);
 void		flushmmu(void);
 void		forceclosefgrp(void);
 void		forkchild(Proc*, Ureg*);
@@ -284,6 +283,7 @@
 void		qnoblock(Queue*, int);
 void		randominit(void);
 ulong		randomread(void*, ulong);
+void		ramdiskinit(void);
 void		rdb(void);
 long		readblist(Block*, uchar*, long, ulong);
 int		readnum(ulong, char*, ulong, ulong, int);
--- /dev/null
+++ b/sys/src/9/port/sdram.c
@@ -1,0 +1,256 @@
+/*
+ *  ramdisk driver
+ */
+
+#include "u.h"
+#include "../port/lib.h"
+#include "../port/error.h"
+#include "mem.h"
+#include "dat.h"
+#include "fns.h"
+#include "io.h"
+
+#include "../port/sd.h"
+
+typedef struct Ctlr Ctlr;
+struct Ctlr {
+	SDev	*dev;
+	Segment	*seg;
+	Segio	sio;
+
+	ulong	nb;
+	ulong	ss;
+	ulong	off;
+
+	char	buf[16];
+
+	Physseg;
+};
+
+static Ctlr ctlrs[4];
+
+extern SDifc sdramifc;
+
+static uvlong
+ramdiskalloc(uvlong base, ulong pages)
+{
+	uvlong limit, mbase, mlimit;
+	int i, j;
+
+	if(pages == 0)
+		return 0;
+
+	if(base == 0){
+		/* allocate pages from the end of memoy banks */
+		for(i=nelem(conf.mem)-1; i>=0; i--)
+			if(conf.mem[i].npage >= pages){
+				conf.mem[i].npage -= pages;
+				return (uvlong)conf.mem[i].base + (uvlong)conf.mem[i].npage*BY2PG;
+			}
+		return 0;
+	}
+
+	/* exclude pages from memory banks */
+	limit = base + (uvlong)pages*BY2PG;
+	for(i=0; i<nelem(conf.mem); i++){
+		mbase = conf.mem[i].base;
+		mlimit = mbase + (uvlong)conf.mem[i].npage*BY2PG;
+		if(base >= mlimit || limit <= mbase)
+			continue;
+		if(base >= mbase)
+			conf.mem[i].npage = (base - mbase) / BY2PG;
+		if(limit < mlimit){
+			for(j=0; j<nelem(conf.mem); j++){
+				if(conf.mem[j].npage == 0){
+					conf.mem[j].base = limit;
+					conf.mem[j].npage = (mlimit - limit) / BY2PG;
+					break;
+				}
+			}
+		}
+	}
+
+	return base;
+}
+
+static void
+ramdiskinit0(Ctlr *ctlr, uvlong base, uvlong size, ulong ss)
+{
+	ulong nb, off;
+
+	if(ss == 0)
+		ss = 512;
+
+	nb = size / ss;
+	off = base & (BY2PG-1);
+	size = (uvlong)nb*ss;
+	size += off;
+	size += BY2PG-1;
+	size &= ~(BY2PG-1);
+	base &= ~(BY2PG-1);
+
+	if(size == 0 || size != (uintptr)size){
+		print("%s: invalid parameters\n", ctlr->name);
+		return;
+	}
+
+	base = ramdiskalloc(base, size/BY2PG);
+	if(base == 0){
+		print("%s: allocation failed\n", ctlr->name);
+		return;
+	}
+	ctlr->nb = nb;
+	ctlr->ss = ss;
+	ctlr->off = off;
+	ctlr->pa = base;
+	ctlr->size = size;
+	print("%s: %llux+%lud %llud %lud (%lud sectors)\n",
+		ctlr->name, (uvlong)ctlr->pa, ctlr->off, (uvlong)ctlr->size, ctlr->ss, ctlr->nb);
+}
+
+static vlong
+getsizenum(char **p)
+{
+	vlong v = strtoll(*p, p, 0);
+	switch(**p){
+	case 'T': case 't': v <<= 10;
+	case 'G': case 'g': v <<= 10;
+	case 'M': case 'm': v <<= 10;
+	case 'K': case 'k': v <<= 10;
+		(*p)++;
+	}
+	return v;
+}
+
+void
+ramdiskinit(void)
+{
+	Ctlr *ctlr;
+	uvlong a[3];
+	char *p;
+	int ctlrno, n;
+
+	for(ctlrno=0; ctlrno<nelem(ctlrs); ctlrno++){
+		ctlr = &ctlrs[ctlrno];
+		if(ctlr->nb != 0)
+			continue;
+
+		snprint(ctlr->name = ctlr->buf, sizeof(ctlr->buf), "ramdisk%d", ctlrno);
+		if((p = getconf(ctlr->name)) == nil)
+			continue;
+
+		for(n = 0; n < nelem(a); n++){
+			while(*p == ' ' || *p == '\t')
+				p++;
+			if(*p == 0)
+				break;
+			a[n] = getsizenum(&p);
+			switch(*p){
+			case '-': case '+':
+				a[n] += getsizenum(&p);
+				break;
+			}
+		}
+		switch(n){
+		case 1:	/* ramdiskX=size */
+			ramdiskinit0(ctlr, 0, a[0], 0);
+			break;
+		case 2:	/* ramdiskX=size ss */
+			ramdiskinit0(ctlr, 0, a[0], (ulong)a[1]);
+			break;
+		case 3:	/* ramdiskX=base size ss */
+			ramdiskinit0(ctlr, a[0], a[1], (ulong)a[2]);
+			break;
+		}
+	}
+}
+
+static SDev*
+rampnp(void)
+{
+	SDev *sdev;
+	Ctlr *ctlr;
+
+	for(ctlr = ctlrs; ctlr < &ctlrs[nelem(ctlrs)]; ctlr++){
+		if(ctlr->nb == 0 || ctlr->dev != nil)
+			continue;
+		sdev = malloc(sizeof(SDev));
+		if(sdev == nil)
+			break;
+		sdev->idno = 'Z';
+		sdev->ifc = &sdramifc;
+		sdev->nunit = 1;
+		sdev->ctlr = ctlr;
+		ctlr->dev = sdev;
+		return sdev;
+	}
+	return nil;
+}
+
+static int
+ramenable(SDev* dev)
+{
+	Ctlr *ctlr = dev->ctlr;
+
+	ctlr->attr = SG_CACHED;
+	ctlr->seg = newseg(SG_PHYSICAL, UTZERO, ctlr->size/BY2PG);
+	if(ctlr->seg == nil)
+		return 0;
+	ctlr->seg->pseg = ctlr;
+	return 1;
+}
+
+static int
+ramverify(SDunit*)
+{
+	return 1;
+}
+
+static int
+ramonline(SDunit *unit)
+{
+	Ctlr *ctlr = unit->dev->ctlr;
+	unit->sectors = ctlr->nb;
+	unit->secsize = ctlr->ss;
+	return 1;
+}
+
+static int
+ramrctl(SDunit *unit, char *p, int l)
+{
+	return snprint(p, l, "geometry %llud %ld\n",
+		unit->sectors, unit->secsize);
+}
+
+static long
+rambio(SDunit *unit, int, int write, void *data, long nb, uvlong bno)
+{
+	Ctlr *ctlr = unit->dev->ctlr;
+	long secsize = unit->secsize;
+	return segio(&ctlr->sio, ctlr->seg, data, nb*secsize, bno*secsize + ctlr->off, !write);
+}
+
+static int
+ramrio(SDreq *r)
+{
+	int i, rw, count;
+	uvlong lba;
+
+	if((i = sdfakescsi(r)) != SDnostatus)
+		return r->status = i;
+	if((i = sdfakescsirw(r, &lba, &count, &rw)) != SDnostatus)
+		return i;
+	r->rlen = rambio(r->unit, r->lun, rw == SDwrite, r->data, count, lba);
+	return r->status = SDok;
+}
+
+SDifc sdramifc = {
+	.name	= "ram",
+	.pnp	= rampnp,
+	.enable	= ramenable,
+	.verify	= ramverify,
+	.online	= ramonline,
+	.rctl	= ramrctl,
+	.bio	= rambio,
+	.rio	= ramrio,
+};
--- a/sys/src/9/port/segment.c
+++ b/sys/src/9/port/segment.c
@@ -64,6 +64,9 @@
 	s->sema.prev = &s->sema;
 	s->sema.next = &s->sema;
 
+	if((type & SG_TYPE) == SG_PHYSICAL)
+		return s;
+
 	mapsize = ROUND(size, PTEPERTAB)/PTEPERTAB;
 	if(mapsize > nelem(s->ssegmap)){
 		s->map = malloc(mapsize*sizeof(Pte*));
@@ -104,13 +107,16 @@
 	} else if(decref(s) != 0)
 		return;
 
-	emap = &s->map[s->mapsize];
-	for(pte = s->map; pte < emap; pte++)
-		if(*pte != nil)
-			freepte(s, *pte);
+	if(s->mapsize > 0){
+		emap = &s->map[s->mapsize];
+		for(pte = s->map; pte < emap; pte++)
+			if(*pte != nil)
+				freepte(s, *pte);
 
-	if(s->map != s->ssegmap)
-		free(s->map);
+		if(s->map != s->ssegmap)
+			free(s->map);
+	}
+
 	if(s->profile != nil)
 		free(s->profile);
 
@@ -212,7 +218,7 @@
 	uintptr soff;
 	Page **pg;
 
-	if(p->va < s->base || p->va >= s->top)
+	if(p->va < s->base || p->va >= s->top || s->mapsize == 0)
 		panic("segpage");
 
 	soff = p->va - s->base;
--- a/sys/src/boot/pc/sub.c
+++ b/sys/src/boot/pc/sub.c
@@ -187,6 +187,7 @@
 
 static void apmconf(int);
 static void e820conf(void);
+static void ramdiskconf(int);
 static void uartconf(char*);
 
 static char*
@@ -249,6 +250,7 @@
 		memset(confend, 0, BOOTARGSLEN);
 
 		e820conf();
+		ramdiskconf(0);
 	}
 	nowait = 1;
 	inblock = 0;
@@ -411,6 +413,78 @@
 
 	if(confend == s)
 		return;
+
+	*confend++ = '\n';
+	*confend = 0;
+
+	print(s);
+}
+
+static int
+checksum(void *v, int n)
+{
+	uchar *p, s;
+
+	s = 0;
+	p = v;
+	while(n-- > 0)
+		s += *p++;
+	return s;
+}
+
+static void
+ramdiskconf(int id)
+{
+	struct {
+		/* ACPI header */
+		char	sig[4];
+		u32int	len;
+		uchar	revision;
+		uchar	csum;
+		char	oem_id[6];
+		char	oem_table_id[8];
+		u32int	oem_revision;
+		char	asl_compiler_id[4];
+		u32int	asl_compiler_revision;
+
+		u32int	safe_hook;
+
+		/* MDI structure */
+		u16int	bytes;
+		uchar	version_minor;
+		uchar	version_major;
+		u32int	diskbuf;
+		u32int	disksize;
+		u32int	cmdline;
+		u32int	oldint13;
+		u32int	oldint15;
+		u16int	olddosmem;
+		uchar	bootloaderid;
+		uchar	sector_shift;
+		u16int	dpt_ptr;
+	} *mbft;
+	int shift;
+	char *s;
+
+#define BDA	((uchar*)0x400)
+	mbft = (void*)((((BDA[0x14]<<8) | BDA[0x13])<<10) - 1024);
+	for(; (ulong)&mbft->sector_shift < 0xA0000; mbft = (void*)((ulong)mbft + 16)){
+		if(memcmp("mBFT", mbft, 4) == 0
+		&& mbft->len < 1024 && (uchar*)mbft + mbft->len > &mbft->sector_shift
+		&& checksum(mbft, mbft->len) == 0)
+			goto Found;
+	}
+	return;
+Found:
+	shift = mbft->sector_shift;
+	if(shift == 0)
+		shift = 9;
+
+	s = confend;
+	addconfx("ramdisk", 1, id);
+	addconfx("=0x", 8, mbft->diskbuf);
+	addconfx(" 0x", 8, mbft->disksize<<shift);
+	addconfx(" 0x", 8, 1UL<<shift);
 
 	*confend++ = '\n';
 	*confend = 0;