diff options
author | cinap_lenrek <cinap_lenrek@felloff.net> | 2018-05-27 22:59:19 +0200 |
---|---|---|
committer | cinap_lenrek <cinap_lenrek@felloff.net> | 2018-05-27 22:59:19 +0200 |
commit | 5da4f0fc0f55b43815adbdbc8f2e0e26eaac84e6 (patch) | |
tree | 1381230c9dc8060f167b2988a55052c598fdd7f5 /sys/src/9/port/fault.c | |
parent | ad7390dda820db424821b19c572a44b4cc0838e8 (diff) |
sdram: experimental ramdisk driver
this driver makes regions of physical memory accessible as a disk.
to use it, ramdiskinit() has to be called before confinit(), so
that conf.mem[] banks can be reserved. currently, only pc and pc64
kernel use it, but otherwise the implementation is portable.
ramdisks are not zeroed when allocated, so that the contents are
preserved across warm reboots.
to not waste memory, physical segments do not allocate Page structures
or populate the segment pte's anymore. theres also a new SG_CHACHED
attribute.
Diffstat (limited to 'sys/src/9/port/fault.c')
-rw-r--r-- | sys/src/9/port/fault.c | 159 |
1 files changed, 86 insertions, 73 deletions
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 */ |