diff --git a/sys/man/8/plan9.ini b/sys/man/8/plan9.ini index 981e43fc5..29bdb7acf 100644 --- a/sys/man/8/plan9.ini +++ b/sys/man/8/plan9.ini @@ -500,6 +500,15 @@ on AoE 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 diff --git a/sys/src/9/pc/dat.h b/sys/src/9/pc/dat.h index 34a1841bc..7bb2e8c6f 100644 --- a/sys/src/9/pc/dat.h +++ b/sys/src/9/pc/dat.h @@ -126,8 +126,6 @@ struct Conf 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 */ diff --git a/sys/src/9/pc/main.c b/sys/src/9/pc/main.c index 3ef3d773e..e47abdc3a 100644 --- a/sys/src/9/pc/main.c +++ b/sys/src/9/pc/main.c @@ -36,6 +36,7 @@ main(void) i8253init(); cpuidentify(); meminit(); + ramdiskinit(); confinit(); xinit(); archinit(); diff --git a/sys/src/9/pc/pc b/sys/src/9/pc/pc index 923621f91..ffdb41a4a 100644 --- a/sys/src/9/pc/pc +++ b/sys/src/9/pc/pc @@ -106,6 +106,7 @@ misc sdmmc pci pmmc sdnvme pci sdloop + sdram uarti8250 uartisa diff --git a/sys/src/9/pc64/main.c b/sys/src/9/pc64/main.c index 7e1b8449a..997322e43 100644 --- a/sys/src/9/pc64/main.c +++ b/sys/src/9/pc64/main.c @@ -305,6 +305,7 @@ main() i8253init(); cpuidentify(); meminit(); + ramdiskinit(); confinit(); xinit(); archinit(); diff --git a/sys/src/9/pc64/pc64 b/sys/src/9/pc64/pc64 index a9a672225..ca464f96b 100644 --- a/sys/src/9/pc64/pc64 +++ b/sys/src/9/pc64/pc64 @@ -104,6 +104,7 @@ misc sdmmc pci pmmc sdnvme pci sdloop + sdram uarti8250 uartisa diff --git a/sys/src/9/port/fault.c b/sys/src/9/port/fault.c index 8180747e4..eaa1d5bd1 100644 --- 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 @@ done: (*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 @@ fixfault(Segment *s, uintptr addr, int read) (*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; } @@ -299,6 +228,90 @@ fixfault(Segment *s, uintptr addr, int read) 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; +} + /* * Called only in a system call */ diff --git a/sys/src/9/port/mkdevc b/sys/src/9/port/mkdevc index 004bc4f41..283c69a27 100755 --- a/sys/src/9/port/mkdevc +++ b/sys/src/9/port/mkdevc @@ -43,9 +43,11 @@ collect && section == "misc"{ 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 @@ END{ 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++) diff --git a/sys/src/9/port/portdat.h b/sys/src/9/port/portdat.h index 059af4e60..3f4ec4e75 100644 --- a/sys/src/9/port/portdat.h +++ b/sys/src/9/port/portdat.h @@ -373,6 +373,7 @@ enum 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 diff --git a/sys/src/9/port/portfns.h b/sys/src/9/port/portfns.h index 5f60c1b9e..004017145 100644 --- a/sys/src/9/port/portfns.h +++ b/sys/src/9/port/portfns.h @@ -109,7 +109,6 @@ int fault(uintptr, int); 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 @@ int qwrite(Queue*, void*, int); 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); diff --git a/sys/src/9/port/sdram.c b/sys/src/9/port/sdram.c new file mode 100644 index 000000000..2853c1afd --- /dev/null +++ b/sys/src/9/port/sdram.c @@ -0,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= mlimit || limit <= mbase) + continue; + if(base >= mbase) + conf.mem[i].npage = (base - mbase) / BY2PG; + if(limit < mlimit){ + for(j=0; jname); + 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; ctlrnonb != 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, +}; diff --git a/sys/src/9/port/segment.c b/sys/src/9/port/segment.c index ca67c4b56..eedbb7b14 100644 --- a/sys/src/9/port/segment.c +++ b/sys/src/9/port/segment.c @@ -64,6 +64,9 @@ newseg(int type, uintptr base, ulong size) 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 @@ putseg(Segment *s) } 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 @@ segpage(Segment *s, Page *p) 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;