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;