M gnot/dat.h => gnot/dat.h +3 -1
@@ 153,6 153,7 @@ struct Conf
int nservice; /* number of services */
int nfsyschan; /* number of filsys open channels */
ulong maxialloc; /* maximum bytes used by ialloc */
+ int copymode; /* 0 is copy on write, 1 is copy on reference */
};
struct Dev
@@ 448,7 449,8 @@ struct Queue {
Queue *next; /* next queue in the stream */
void (*put)(Queue*, Block*);
QLock rlock; /* mutex for processes sleeping at r */
- Rendez r;
+ Rendez r; /* standard place to wait for flow control */
+ Rendez *rp; /* where flow control wakeups go to */
void *ptr; /* private info for the queue */
};
#define QHUNGUP 0x1 /* flag bit meaning the stream has been hung up */
M gnot/devcons.c => gnot/devcons.c +3 -0
@@ 311,6 311,9 @@ echo(int c)
case 'm':
mntdump();
return;
+ case 'i':
+ incontoggle();
+ return;
}
}else if(c == 0x14){
ctrlt++;
M gnot/devincon.c => gnot/devincon.c +11 -0
@@ 600,9 600,20 @@ inconoput(Queue *q, Block *bp)
if(size >= 16){
dev->cdata = 0;
MICROSECOND;
+ for(end = NOW+1000; dev->status & TX_FULL;){
+ nop(); /* make sure we don't optimize too much */
+ if(NOW > end){
+ print("incon output stuck\n");
+ freemsg(q, bp);
+ qunlock(&ip->xmit);
+ return;
+ }
+ }
dev->cdata = chan;
MICROSECOND;
}
+ if(dev->status & TX_FULL)
+ print("inconfull\n");
dev->cdata = ctl;
}
MICROSECOND;
D gnot/fault.c => gnot/fault.c +0 -347
@@ 1,347 0,0 @@
-#include "u.h"
-#include "lib.h"
-#include "mem.h"
-#include "dat.h"
-#include "fns.h"
-#include "ureg.h"
-#include "errno.h"
-
-#define FORMAT(ur) ((((ur)->vo)>>12)&0xF)
-#define OFFSET(ur) (((ur)->vo)&0xFFF)
-
-
-struct FFrame
-{
- ushort ireg0; /* internal register */
- ushort ssw; /* special status word */
- ushort ipsc; /* instr. pipe stage c */
- ushort ipsb; /* instr. pipe stage b */
- ulong addr; /* data cycle fault address */
- ushort ireg1; /* internal register */
- ushort ireg2; /* internal register */
- ulong dob; /* data output buffer */
- ushort ireg3[4]; /* more stuff */
- ulong baddr; /* stage b address */
- ushort ireg4[26]; /* more more stuff */
-};
-
-/*
- * SSW bits
- */
-#define RW 0x0040 /* read/write for data cycle */
-#define FC 0x8000 /* fault on stage C of instruction pipe */
-#define FB 0x4000 /* fault on stage B of instruction pipe */
-#define RC 0x2000 /* rerun flag for stage C of instruction pipe */
-#define RB 0x1000 /* rerun flag for stage B of instruction pipe */
-#define DF 0x0100 /* fault/rerun flag for data cycle */
-#define RM 0x0080 /* read-modify-write on data cycle */
-#define READ 0x0040
-#define WRITE 0x0000
-#define SIZ 0x0030 /* size code for data cycle */
-#define FC2 0x0004 /* address space for data cycle */
-#define FC1 0x0002
-#define FC0 0x0001
-
-void
-fault(Ureg *ur, FFrame *f)
-{
- ulong addr, mmuvirt, mmuphys, n, badvaddr;
- Seg *s;
- PTE *opte, *pte, *npte;
- Orig *o;
- char *l;
- Page *pg;
- KMap *k, *k1;
- int zeroed = 0, head = 1;
- int i, user, read, insyscall;
-
- if(u == 0){
- dumpregs(ur);
- panic("fault u==0 pc=%lux", ur->pc);
- }
- insyscall = u->p->insyscall;
- u->p->insyscall = 1;
- addr = 0; /* set */
- if(f->ssw & DF)
- addr = f->addr;
- else if(FORMAT(ur) == 0xA){
- if(f->ssw & FC)
- addr = ur->pc+2;
- else if(f->ssw & FB)
- addr = ur->pc+4;
- else
- panic("prefetch pagefault");
- }else if(FORMAT(ur) == 0xB){
- if(f->ssw & FC)
- addr = f->baddr-2;
- else if(f->ssw & FB)
- addr = f->baddr;
- else
- panic("prefetch pagefault");
- }else
- panic("prefetch format");
- addr &= VAMASK;
- badvaddr = addr;
- addr &= ~(BY2PG-1);
- user = !(ur->sr&SUPER);
- if(f->ssw & DF)
- read = (f->ssw&READ) && !(f->ssw&RM);
- else
- read = f->ssw&(FB|FC);
-/* print("fault pc=%lux addr=%lux read %d\n", ur->pc, badvaddr, read); /**/
-
- s = seg(u->p, addr);
- if(s == 0){
- if(addr>USTKTOP){
- cant:
- if(user){
- pprint("user %s error addr=0x%lux\n", read? "read" : "write", badvaddr);
- pprint("status=0x%lux pc=0x%lux sp=0x%lux\n", ur->sr, ur->pc, ur->sp);
- pexit("Suicide", 0);
- }
- u->p->state = MMUing;
- dumpregs(ur);
- panic("fault: 0x%lux", badvaddr);
- exit();
- }
- s = &u->p->seg[SSEG];
- if(s->o==0 || addr<s->maxva-USTACKSIZE || addr>=s->maxva)
- goto cant;
- /* grow stack */
- o = s->o;
- n = o->npte;
- if(waserror()){
- pprint("can't allocate stack page\n");
- goto cant;
- }
- growpte(o, (s->maxva-addr)>>PGSHIFT);
- poperror();
- /* stacks grown down, sigh */
- lock(o);
- memcpy(o->pte+(o->npte-n), o->pte, n*sizeof(PTE));
- memset(o->pte, 0, (o->npte-n)*sizeof(PTE));
- unlock(o);
- s->minva = addr;
- o->va = addr;
- }else
- o = s->o;
- if(!read && (o->flag&OWRPERM)==0)
- goto cant;
- lock(o);
- opte = &o->pte[(addr-o->va)>>PGSHIFT];
- pte = opte;
- if(s->mod){
- while(pte = pte->nextmod) /* assign = */
- if(pte->proc == u->p){
- if(pte->page==0 || pte->page->va!=addr)
- panic("bad page %lux", pte->page);
- head = 0;
- break;
- }
- if(pte == 0)
- pte = opte;
- }
- if(pte->page == 0){
- if(o->chan==0 || addr>(o->va+(o->maxca-o->minca))){
- /*
- * Zero fill page. If we are really doing a copy-on-write
- * (e.g. into shared bss) we'll move the page later.
- */
- pte->page = newpage(0, o, addr);
- o->npage++;
- zeroed = 1;
- }else{
- /*
- * Demand load. Release o because it could take a while.
- */
- unlock(o);
- n = (o->va+(o->maxca-o->minca)) - addr;
- if(n > BY2PG)
- n = BY2PG;
- pg = newpage(1, o, addr);
- k = kmap(pg);
- qlock(o->chan);
- if(waserror()){
- kunmap(k);
- qunlock(o->chan);
- pg->o = 0;
- pg->ref--;
- pexit("load i/o error", 0);
- }
- o->chan->offset = (addr-o->va) + o->minca;
- l = (char*)VA(k);
- if((*devtab[o->chan->type].read)(o->chan, l, n) != n)
- error(Eioload);
- qunlock(o->chan);
- if(n<BY2PG)
- memset(l+n, 0, BY2PG-n);
- lock(o);
- kunmap(k);
- poperror();
- opte = &o->pte[(addr-s->minva)>>PGSHIFT]; /* could move */
- pte = opte;
- if(pte->page == 0){
- pte->page = pg;
- o->npage++;
- }else{ /* someone beat us to it */
- pg->o = 0;
- pg->ref--;
- }
- }
- }
- /*
- * Copy on write
- */
- if((o->flag & OWRPERM) && !read
- && ((head && ((o->flag&OPURE) || o->nproc>1))
- || (!head && pte->page->ref>1))){
-
- /*
- * Look for the easy way out: are we the last non-modified?
- */
- if(head && !(o->flag&OPURE)){
- npte = opte;
- for(i=0; npte; i++)
- npte = npte->nextmod;
- if(i == o->nproc)
- goto easy;
- }
- if(head){
- /*
- * Add to mod list
- */
- pte = newmod();
- pte->proc = u->p;
- pte->page = opte->page;
- pte->page->ref++;
- o->npage++;
- /*
- * Link into opte mod list (same va)
- */
- pte->nextmod = opte->nextmod;
- opte->nextmod = pte;
- /*
- * Link into proc mod list (increasing va)
- */
- npte = s->mod;
- if(npte == 0){
- s->mod = pte;
- pte->nextva = 0;
- }else{
- while(npte->nextva && npte->nextva->page->va<addr)
- npte = npte->nextva;
- pte->nextva = npte->nextva;
- npte->nextva = pte;
- }
- head = 0;
- }
- pg = pte->page;
- if(zeroed){ /* move page */
- pg->ref--;
- o->npage--;
- opte->page = 0;
- }else{ /* copy page */
- pte->page = newpage(1, o, addr);
- k = kmap(pte->page);
- k1 = kmap(pg);
- memcpy((void*)VA(k), (void*)VA(k1), BY2PG);
- kunmap(k);
- kunmap(k1);
- if(pg->ref <= 1)
- panic("pg->ref <= 1");
- pg->ref--;
- }
- easy:
- mmuphys = 0;
- }else{
- mmuphys = PTERONLY;
- if(o->flag & OWRPERM)
- if(o->flag & OPURE){
- if(!head && pte->page->ref==1)
- mmuphys = 0;
- }else
- if((head && o->nproc==1)
- || (!head && pte->page->ref==1))
- mmuphys = 0;
- }
- mmuvirt = addr;
- mmuphys |= PPN(pte->page->pa) | PTEVALID;
- usepage(pte->page, 1);
- if(pte->page->va != addr)
- panic("wrong addr in tail %lux %lux", pte->page->va, addr);
- if(pte->proc && pte->proc != u->p){
- print("wrong proc in tail %d %s\n", head, u->p->text);
- print("u->p %lux pte->proc %lux\n", u->p, pte->proc);
- panic("addr %lux seg %d wrong proc in tail", addr, s-u->p->seg);
- }
- unlock(o);
- putmmu(mmuvirt, mmuphys);
- u->p->insyscall = insyscall;
-}
-
-/*
- * Called only in a system call
- */
-void
-validaddr(ulong addr, ulong len, int write)
-{
- Seg *s, *ns;
-
- if((long)len < 0){
- Err:
- pprint("invalid address in sys call pc %lux sp %lux\n", ((Ureg*)UREGADDR)->pc, ((Ureg*)UREGADDR)->sp);
- postnote(u->p, 1, "sys: bad address", NDebug);
- error(Ebadarg);
- }
- Again:
- s = seg(u->p, addr);
- if(s==0){
- s = &u->p->seg[SSEG];
- if(s->o==0 || addr<s->maxva-USTACKSIZE || addr>=s->maxva)
- goto Err;
- }
- if(write && (s->o->flag&OWRPERM)==0)
- goto Err;
- if(addr+len > s->maxva){
- len -= s->maxva - addr;
- addr = s->maxva;
- goto Again;
- }
-}
-/*
- * &s[0] is known to be a valid address.
- */
-void*
-vmemchr(void *s, int c, int n)
-{
- int m;
- char *t;
- ulong a;
-
- a = (ulong)s;
- m = BY2PG - (a & (BY2PG-1));
- if(m < n){
- t = vmemchr(s, c, m);
- if(t)
- return t;
- if(!(a & KZERO))
- validaddr(a+m, 1, 0);
- return vmemchr((void*)(a+m), c, n-m);
- }
- /*
- * All in one page
- */
- return memchr(s, c, n);
-}
-
-Seg*
-seg(Proc *p, ulong addr)
-{
- int i;
- Seg *s;
-
- for(i=0,s=p->seg; i<NSEG; i++,s++)
- if(s->o && s->minva<=addr && addr<s->maxva)
- return s;
- return 0;
-}
A gnot/fault68020.c => gnot/fault68020.c +105 -0
@@ 0,0 1,105 @@
+#include "u.h"
+#include "lib.h"
+#include "mem.h"
+#include "dat.h"
+#include "fns.h"
+#include "ureg.h"
+#include "errno.h"
+
+#define FORMAT(ur) ((((ur)->vo)>>12)&0xF)
+#define OFFSET(ur) (((ur)->vo)&0xFFF)
+
+
+struct FFrame
+{
+ ushort ireg0; /* internal register */
+ ushort ssw; /* special status word */
+ ushort ipsc; /* instr. pipe stage c */
+ ushort ipsb; /* instr. pipe stage b */
+ ulong addr; /* data cycle fault address */
+ ushort ireg1; /* internal register */
+ ushort ireg2; /* internal register */
+ ulong dob; /* data output buffer */
+ ushort ireg3[4]; /* more stuff */
+ ulong baddr; /* stage b address */
+ ushort ireg4[26]; /* more more stuff */
+};
+
+/*
+ * SSW bits
+ */
+#define RW 0x0040 /* read/write for data cycle */
+#define FC 0x8000 /* fault on stage C of instruction pipe */
+#define FB 0x4000 /* fault on stage B of instruction pipe */
+#define RC 0x2000 /* rerun flag for stage C of instruction pipe */
+#define RB 0x1000 /* rerun flag for stage B of instruction pipe */
+#define DF 0x0100 /* fault/rerun flag for data cycle */
+#define RM 0x0080 /* read-modify-write on data cycle */
+#define READ 0x0040
+#define WRITE 0x0000
+#define SIZ 0x0030 /* size code for data cycle */
+#define FC2 0x0004 /* address space for data cycle */
+#define FC1 0x0002
+#define FC0 0x0001
+
+void
+fault68020(Ureg *ur, FFrame *f)
+{
+ ulong addr, mmuvirt, mmuphys, n, badvaddr;
+ Seg *s;
+ PTE *opte, *pte, *npte;
+ Orig *o;
+ char *l;
+ Page *pg;
+ KMap *k, *k1;
+ int zeroed = 0, head = 1;
+ int i, user, read, insyscall;
+
+ if(u == 0){
+ dumpregs(ur);
+ panic("fault u==0 pc=%lux", ur->pc);
+ }
+ insyscall = u->p->insyscall;
+ u->p->insyscall = 1;
+ addr = 0; /* set */
+ if(f->ssw & DF)
+ addr = f->addr;
+ else if(FORMAT(ur) == 0xA){
+ if(f->ssw & FC)
+ addr = ur->pc+2;
+ else if(f->ssw & FB)
+ addr = ur->pc+4;
+ else
+ panic("prefetch pagefault");
+ }else if(FORMAT(ur) == 0xB){
+ if(f->ssw & FC)
+ addr = f->baddr-2;
+ else if(f->ssw & FB)
+ addr = f->baddr;
+ else
+ panic("prefetch pagefault");
+ }else
+ panic("prefetch format");
+ addr &= VAMASK;
+ badvaddr = addr;
+ addr &= ~(BY2PG-1);
+ user = !(ur->sr&SUPER);
+ if(f->ssw & DF)
+ read = (f->ssw&READ) && !(f->ssw&RM);
+ else
+ read = f->ssw&(FB|FC);
+/* print("fault pc=%lux addr=%lux read %d\n", ur->pc, badvaddr, read); /**/
+
+ if(fault(addr, read) < 0){
+ if(user){
+ pprint("user %s error addr=0x%lux\n", read? "read" : "write", badvaddr);
+ pprint("status=0x%lux pc=0x%lux sp=0x%lux\n", ur->sr, ur->pc, ur->sp);
+ pexit("Suicide", 0);
+ }
+ u->p->state = MMUing;
+ dumpregs(ur);
+ panic("fault: 0x%lux", badvaddr);
+ exit();
+ }
+ u->p->insyscall = insyscall;
+}
M gnot/fns.h => gnot/fns.h +8 -6
@@ 49,7 49,8 @@ void envpgclose(Env *);
void error(int);
void errors(char*);
void exit(void);
-void fault(Ureg*, FFrame*);
+int fault(ulong, int);
+void fault68020(Ureg*, FFrame*);
void fdclose(int);
Chan *fdtochan(int, int);
void filsys(Chan*, char*, long);
@@ 65,8 66,9 @@ void fpregsave(char*);
void fprestore(FPsave*);
void fpregrestore(char*);
void freeb(Block*);
+int freebroken(void);
void freenextmod(PTE*);
-void freepage(Orig*);
+void freepage(Orig*, int);
void freepte(Orig*);
void freesegs(int);
void freealarm(Alarm*);
@@ 102,7 104,7 @@ Chan *namec(char*, int, int, ulong);
void nexterror(void);
Alarm *newalarm(void);
Chan *newchan(void);
-PTE *newmod(void);
+PTE *newmod(Orig *o);
Mount *newmount(void);
Orig *neworig(ulong, ulong, int, Chan*);
Page *newpage(int, Orig*, ulong);
@@ 126,6 128,9 @@ int pprint(char*, ...);
void printinit(void);
void printslave(void);
void procinit0(void);
+void procrestore(Proc*, uchar*);
+void procsave(uchar*, int);
+void procsetup(Proc*);
Proc *proctab(int);
Queue *pushq(Stream*, Qinfo*);
void putbq(Blist*, Block*);
@@ 144,8 149,6 @@ void qlock(QLock*);
void qunlock(QLock*);
void restartprint(Alarm*);
void restfpregs(FPsave*);
-void restore(Proc*, uchar*);
-void save(uchar*, int);
void savefpregs(FPsave*);
void sched(void);
void schedinit(void);
@@ 157,7 160,6 @@ int segaddr(Seg*, ulong, ulong);
void serviceinit(void);
void service(char*, Chan*, Chan*, void (*)(Chan*, char*, long));
int setlabel(Label*);
-void setup(Proc*);
char *skipslash(char*);
void sleep(Rendez*, int(*)(void*), void*);
int splhi(void);
M gnot/l.s => gnot/l.s +1 -1
@@ 200,7 200,7 @@ TEXT buserror(SB), $0
MOVL A0, ((8+8)*BY2WD)(A7)
PEA ((8+8+1+2)*BY2WD)(A7)
PEA 4(A7)
- BSR fault(SB)
+ BSR fault68020(SB)
ADDL $8, A7
MOVL ((8+8)*BY2WD)(A7), A0
MOVL A0, USP
M gnot/main.c => gnot/main.c +6 -5
@@ 339,13 339,14 @@ confinit(void)
conf.npipe = conf.nstream/2;
conf.nservice = 3*mul; /* was conf.nproc/5 */
conf.nfsyschan = 31 + conf.nchan/20;
+ conf.copymode = 0; /* copy on write */
}
/*
* set up floating point for a new process
*/
void
-setup(Proc *p)
+procsetup(Proc *p)
{
long fpnull;
@@ 361,7 362,7 @@ setup(Proc *p)
* Save the part of the process state.
*/
void
-save(uchar *state, int len)
+procsave(uchar *state, int len)
{
Balu *balu;
@@ 385,12 386,12 @@ save(uchar *state, int len)
}
/*
- * Restore what save() saves
+ * Restore what procsave() saves
*
- * Save() makes sure that what state points to is long enough
+ * Procsave() makes sure that what state points to is long enough
*/
void
-restore(Proc *p, uchar *state)
+procrestore(Proc *p, uchar *state)
{
Balu *balu;
M gnot/mem.h => gnot/mem.h +1 -0
@@ 68,6 68,7 @@
* MMU entries
*/
#define PTEVALID (1<<13)
+#define PTEWRITE 0
#define PTERONLY (1<<14)
#define PTEKERNEL (1<<15)
#define INVALIDPTE 0
D gnot/page.c => gnot/page.c +0 -674
@@ 1,674 0,0 @@
-#include "u.h"
-#include "lib.h"
-#include "mem.h"
-#include "dat.h"
-#include "fns.h"
-#include "ureg.h"
-#include "errno.h"
-
-struct
-{
- Lock;
- ulong addr;
- int active;
- Page *page; /* base of Page structures, indexed by phys page number */
- ulong minppn; /* index of first usable page */
- Page *head; /* most recently used */
- Page *tail; /* least recently used */
-}palloc;
-
-struct
-{
- Lock;
- Orig *arena;
- Orig *free;
-}origalloc;
-
-typedef union PTEA PTEA;
-union PTEA{
- PTE;
- struct{
- ulong n; /* for growpte */
- Orig *o; /* for growpte */
- PTEA *next; /* for newmod */
- };
-};
-
-struct
-{
- Lock;
- PTEA *arena;
- PTEA *free;
- PTEA *end;
-}ptealloc;
-
-struct{
- Lock;
- PTEA *free;
-}modalloc;
-
-/*
- * Called to allocate permanent data structures, before calling pageinit().
- */
-void*
-ialloc(ulong n, int align)
-{
- ulong p;
-
- if(palloc.addr == 0)
- palloc.addr = ((ulong)&end)&~KZERO;
- if(n == 0) /* done by kmapinit */
- return (void*)(palloc.addr|KZERO);
- if(palloc.active)
- print("ialloc bad\n");
- if(align){
- palloc.addr += BY2PG-1;
- palloc.addr &= ~(BY2PG-1);
- }
- memset((void*)(palloc.addr|KZERO), 0, n);
- p = palloc.addr;
- palloc.addr += n;
- if(align){
- palloc.addr += BY2PG-1;
- palloc.addr &= ~(BY2PG-1);
- }
- if(palloc.addr >= (4*1024*1024-256*1024-BY2PG))
- panic("keep bill joy away");
- return (void*)(p|KZERO);
-}
-
-void
-audit(char *s)
-{
- int nf, nb;
- Page *p;
- static int here;
-
- do;while(here);
- here=1;
- p = palloc.head;
- nf=nb=0;
- while(p){
- print("%lux %lux %d\n", p->pa, p->va, p->ref);
- if(p->o){
- print("\t%d %lux %c\n", p->o->nproc, p->o->qid, devchar[p->o->type]);
- delay(100); /* let it drain; there's a lot here */
- }
- nf++;
- p = p->next;
- }
- p = palloc.tail;
- while(p){
- nb++;
- p = p->prev;
- }
- print("%s: nf: %d nb: %d\n", s, nf, nb);
- delay(1000);
- here=0;
-}
-
-void
-pageinit(void)
-{
- ulong pa, nb, ppn;
- ulong i;
- Page *p;
- PTEA *pte;
- Orig *o;
-
- ptealloc.arena = ialloc(conf.npte*sizeof(PTEA), 0);
- ptealloc.free = ptealloc.arena;
- ptealloc.end = ptealloc.arena+conf.npte;
-
- modalloc.free = ialloc(conf.nmod*sizeof(PTEA), 0);
-
- pte = modalloc.free;
- for(i=0; i<conf.nmod-1; i++,pte++)
- pte->next = pte+1;
- pte->next = 0;
-
- origalloc.free = ialloc(conf.norig*sizeof(Orig), 0);
- origalloc.arena = origalloc.free;
-
- o = origalloc.free;
- for(i=0; i<conf.norig-1; i++,o++)
- o->next = o+1;
- o->next = 0;
- palloc.active = 1;
-
- nb = (conf.npage<<PGSHIFT) - palloc.addr;
- nb -= ((nb+(BY2PG-1))>>PGSHIFT)*sizeof(Page); /* safe overestimate */
- nb &= ~(BY2PG-1);
- pa = (conf.npage<<PGSHIFT) - nb; /* physical addr of first free page */
- ppn = pa >> PGSHIFT; /* physical page number of first free page */
- palloc.page = (Page *)((palloc.addr - ppn*sizeof(Page))|KZERO);
- /*
- * Now palloc.page[ppn] describes first free page
- */
- palloc.minppn = ppn;
- palloc.addr = ppn<<PGSHIFT;
-
- palloc.head = &palloc.page[ppn];
- palloc.tail = &palloc.page[conf.npage-1];
- memset(palloc.head, 0, (conf.npage-ppn)*sizeof(Page));
- print("%lud free pages\n", conf.npage-ppn);
- for(p=palloc.head; p<=palloc.tail; p++,ppn++){
- p->next = p+1;
- p->prev = p-1;
- if(ppn < conf.npage0)
- p->pa = conf.base0+(ppn<<PGSHIFT);
- else
- p->pa = conf.base1+((ppn-conf.npage0)<<PGSHIFT);
- }
- palloc.head->prev = 0;
- palloc.tail->next = 0;
-}
-
-Page*
-newpage(int noclear, Orig *o, ulong va)
-{
- Page *p;
- Orig *o1;
- KMap *k;
-
- if(palloc.active == 0)
- print("newpage inactive\n");
-loop:
- lock(&palloc);
- for(p=palloc.tail; p; p=p->prev){
- if(p->ref == 0)
- goto out;
-#ifdef asdf
- if(p->ref == 1){ /* a pageout daemon should do this */
- o1 = p->o;
- if(o1 && o1->nproc==0 && canlock(o1)){
- if(o1->nproc){
- unlock(o1);
- continue;
- }
- print("free %d pages va %lux %lux %c\n", o1->npage, o->va, o1->qid, devchar[o1->type]);
- freepage(o1);
- /* neworig will free the orig and pte's later */
- unlock(o1);
- if(p->ref == 0)
- goto out;
- print("newpage ref != 0");
- }
- }
-#endif
- }
- print("no physical memory\n");
- unlock(&palloc);
- if(u == 0)
- panic("newpage");
- u->p->state = Wakeme;
- alarm(1000, wakeme, u->p);
- sched();
- goto loop;
- out:
- if(p->o){
- print("page in use %lux %lux %lux\n", p->va, p->o, origalloc.arena);
- print("%c %lux %lux, %d %d %d\n", devchar[p->o->type], p->o->va, p->o->qid, p->o->flag, p->o->nproc, p->o->npte);
- panic("shit");
- }
- p->ref = 1;
- usepage(p, 0);
- unlock(&palloc);
- if(!noclear){
- k = kmap(p);
- memset((void*)VA(k), 0, BY2PG);
- kunmap(k);
- }
- p->o = o;
- p->va = va;
-
- return p;
-}
-
-/*
- * Move page to head of list
- */
-void
-usepage(Page *p, int dolock)
-{
- if(dolock)
- lock(&palloc);
- /*
- * Unlink
- */
- if(p->prev)
- p->prev->next = p->next;
- else
- palloc.head = p->next;
- if(p->next)
- p->next->prev = p->prev;
- else
- palloc.tail = p->prev;
- /*
- * Link
- */
- p->next = palloc.head;
- p->prev = 0;
- if(p->next)
- p->next->prev = p;
- else
- palloc.tail = p;
- palloc.head = p;
- if(dolock)
- unlock(&palloc);
-}
-
-/*
- * Move page to tail of list
- */
-void
-unusepage(Page *p, int dolock)
-{
-}
-
-Orig*
-lookorig(ulong va, ulong npte, int flag, Chan *c)
-{
- Orig *o;
- ulong i;
-
- for(o=origalloc.arena,i=0; i<conf.norig; i++,o++)
- if(o->npage && eqqid(o->qid, c->qid) && o->va==va){
- lock(o);
- if(o->npage && eqqid(o->qid, c->qid))
- if(o->va==va && o->npte==npte && o->flag==flag)
- if(o->mchan==c->mchan && eqqid(o->mqid, c->mqid) && o->type==c->type){
- if(o->chan == 0){
- o->chan = c;
- incref(c);
- }
- o->nproc++;
- unlock(o);
- return o;
- }
- unlock(o);
- }
- return 0;
-}
-
-Orig*
-neworig(ulong va, ulong npte, int flag, Chan *c)
-{
- Orig *o;
- int i, freed;
-
- lock(&origalloc);
-loop:
- if(o = origalloc.free){ /* assign = */
- origalloc.free = o->next;
- o->va = va;
- o->pte = 0;
- o->flag = flag;
- o->nproc = 1;
- o->npage = 0;
- o->chan = c;
- if(c){
- o->type = c->type;
- o->qid = c->qid;
- o->mchan = c->mchan;
- o->mqid = c->mqid;
- incref(c);
- }else{
- o->type = ~0;
- o->qid.path = -1;
- o->qid.vers = 0;
- o->mqid.path = -1;
- o->mqid.vers = 0;
- o->mchan = 0;
- }
- if(u && u->p && waserror()){
- unlock(&origalloc);
- nexterror();
- }
- growpte(o, npte);
- if(u && u->p)
- poperror();
- unlock(&origalloc);
- return o;
- }
- /*
- * This is feeble. Orig's should perhaps be held in
- * an LRU list. This algorithm is too aggressive.
- */
- freed = 0;
- for(o=origalloc.arena,i=0; i<conf.norig; i++,o++){
- if(o->nproc==0 && canlock(o)){
- if(o->nproc){
- unlock(o);
- continue;
- }
- freepage(o);
- freepte(o);
- unlock(o);
- o->next = origalloc.free;
- origalloc.free = o;
- freed++;
- }
- }
- if(freed)
- goto loop;
- print("no origs freed\n");
- unlock(&origalloc);
- if(u == 0)
- panic("neworig");
- u->p->state = Wakeme;
- alarm(1000, wakeme, u->p);
- sched();
- lock(&origalloc);
- goto loop;
-}
-
-PTE*
-newmod(void)
-{
- PTEA *pte;
-
-loop:
- lock(&modalloc);
- if(pte = modalloc.free){ /* assign = */
- modalloc.free = pte->next;
- unlock(&modalloc);
- memset(pte, 0, sizeof(PTE));
- return pte;
- }
- unlock(&modalloc);
- print("no mods\n");
- if(u == 0)
- panic("newmod");
- u->p->state = Wakeme;
- alarm(1000, wakeme, u->p);
- sched();
- goto loop;
-}
-
-/*
- * Duplicate mod structure for this segment (old) in new process p.
- * old->o must be locked.
- */
-void
-forkmod(Seg *old, Seg *new, Proc *p)
-{
- Orig *o;
- PTE *pte, *ppte, *opte, *npte;
- ulong va;
-
- o = old->o;
- ppte = 0;
- pte = old->mod;
- while(pte){
-if(pte->page==0) panic("forkmod zero page");
-if(pte->proc != u->p) panic("forkmod wrong page");
- npte = newmod();
- npte->proc = p;
- npte->page = pte->page;
- pte->page->ref++;
- o->npage++;
- /*
- * Link into mod list for this va
- */
- npte->nextmod = pte->nextmod;
- pte->nextmod = npte;
- /*
- * Link into mod list for new segment
- */
- if(ppte == 0)
- new->mod = npte;
- else
- ppte->nextva = npte;
- npte->nextva = 0;
- ppte = npte;
- pte = pte->nextva;
- }
-}
-
-void
-freesegs(int save)
-{
- int i, j;
- Seg *s;
- Orig *o;
- PTE *pte, *opte;
- PTEA *old;
- Page *pg;
- Chan *c;
-
- s = u->p->seg;
- for(i=0; i<NSEG; i++,s++){
- if(i == save)
- continue;
- o = s->o;
- if(o == 0)
- continue;
- lock(o);
- if(pte = s->mod){ /* assign = */
- while(pte){
- opte = &o->pte[(pte->page->va-o->va)>>PGSHIFT];
- while(opte->nextmod != pte){
- if(opte->page && opte->page->va != pte->page->va)
- panic("pte %lux %lux\n", opte->page->va, pte->page->va);
- opte = opte->nextmod;
- if(opte == 0)
- panic("freeseg opte==0");
- }
- opte->nextmod = pte->nextmod;
- pg = pte->page;
- if(pg->ref == 1){
- pte->page = 0;
- pg->o = 0;
- }
- pg->ref--;
- o->npage--;
- old = (PTEA*)pte;
- pte = pte->nextva;
- lock(&modalloc);
- old->next = modalloc.free;
- modalloc.free = old;
- unlock(&modalloc);
- }
- }
- o->nproc--;
- if(o->nproc == 0){
- if(c = o->chan){ /* assign = */
- o->chan = 0;
- close(c);
- }
- if(!(o->flag&OCACHED) || o->npage==0){
- freepage(o);
- freepte(o);
- unlock(o);
- lock(&origalloc);
- o->next = origalloc.free;
- origalloc.free = o;
- unlock(&origalloc);
- }else
- unlock(o);
- }else{
- /*
- * BUG: there is a leak here. if the origin pte is being used only
- * by the exiting process, the associated page will linger. the fix
- * is to remember either the length of the mod list at each va or
- * the number of processes sharing the origin pte, and to promote one
- * of the mods to the origin pte when no process is left using the
- * origin pte.
- */
- unlock(o);
- }
- }
-}
-
-/*
- * Adjust segment to desired size. This implementation is rudimentary.
- */
-int
-segaddr(Seg *s, ulong min, ulong max)
-{
- Orig *o;
-
- if(max < min)
- return 0;
- if(min != s->minva) /* can't grow down yet (stacks: fault.c) */
- return 0;
- max = (max+(BY2PG-1)) & ~(BY2PG-1);
- o = s->o;
- if(max == s->maxva)
- return 1;
- if(max > s->maxva){
- /*
- * Grow
- */
- /* BUG: check spill onto other segments */
- if(o->va+BY2PG*o->npte < max)
- growpte(o, (max-o->va)>>PGSHIFT);
- s->maxva = max;
- return 1;
- }
- /*
- * Shrink
- */
- print("segaddr shrink");
- for(;;);
-}
-
-/*
- * o is locked
- */
-void
-freepage(Orig *o)
-{
- PTE *pte;
- Page *pg;
- int i;
-
- pte = o->pte;
- for(i=0; i<o->npte; i++,pte++)
- if(pg = pte->page){ /* assign = */
- if(pg->ref == 1){
- pte->page = 0;
- pg->o = 0;
- }
- pg->ref--;
- }
- o->npage = 0;
-}
-
-/*
- * Compacting allocator
- */
-
-void
-freepte(Orig *o) /* o is locked */
-{
- PTEA *p;
- p = (PTEA*)(o->pte - 1);
- p->o = 0;
-}
-
-/*
- * o is locked. this will always do a grow; if n<=o->npte someone
- * else got here first and we can just return.
- */
-void
-growpte(Orig *o, ulong n)
-{
- PTEA *p;
- ulong nfree;
-
- lock(&ptealloc);
- lock(o);
- if(o->pte){
- if(o->npte >= n)
- goto Return;
- p = (PTEA*)(o->pte - 1);
- n++;
- if(p+p->n == ptealloc.free){
- if(!compactpte(o, n - p->n))
- goto Trouble;
- p = (PTEA*)(o->pte - 1);
- ptealloc.free += n - p->n;
- }else{
- if(!compactpte(o, n))
- goto Trouble;
- p = ptealloc.free;
- ptealloc.free += n;
- memcpy(p+1, o->pte, o->npte*sizeof(PTE));
- p->o = o;
- ((PTEA*)(o->pte-1))->o = 0;
- o->pte = p+1;
- }
- memset(p+1+o->npte, 0, (n-(1+o->npte))*sizeof(PTE));
- p->n = n;
- o->npte = n-1;
- goto Return;
- }
- n++;
- if(!compactpte(o, n))
- goto Trouble;
- p = ptealloc.free;
- ptealloc.free += n;
- memset(p, 0, n*sizeof(PTE));
- p->n = n;
- p->o = o;
- o->pte = p+1;
- o->npte = n-1;
- Return:
- unlock(&ptealloc);
- unlock(o);
- return;
-
- Trouble:
- unlock(&ptealloc);
- unlock(o);
- if(u && u->p)
- error(Enovmem);
- panic("growpte fails %d %lux %d\n", n, o->va, o->npte);
-}
-
-int
-compactpte(Orig *o, ulong n)
-{
- PTEA *p1, *p2;
- Orig *p2o;
-
- if(ptealloc.end-ptealloc.free >= n)
- return 1;
- p1 = ptealloc.arena; /* dest */
- p2 = ptealloc.arena; /* source */
- while(p2 < ptealloc.free){
- p2o = p2->o;
- if(p2o == 0){
- Free:
- p2 += p2->n;
- continue;
- }
- if(p1 != p2){
- if(p2o != o)
- lock(p2o);
- if(p2->o != p2o){ /* freepte()d very recently */
- if(p2->o)
- panic("compactpte p2->o %lux\n", p2->o);
- unlock(p2o);
- goto Free;
- }
- memcpy(p1, p2, p2->n*sizeof(PTE));
- p2o->pte = p1+1;
- if(p2o != o)
- unlock(p2o);
- }
- p2 += p1->n;
- p1 += p1->n;
- }
- ptealloc.free = p1;
- if(ptealloc.end-ptealloc.free >= n)
- return 1;
- unlock(o);
- unlock(&ptealloc);
- if(u && u->p)
- print("%s: %s: ", u->p->text, u->p->pgrp->user);
- print("compactpte fails addr %lux\n", o->va+n*BY2PG);
- return 0;
-}
M port/fault.c => port/fault.c +25 -41
@@ 6,11 6,10 @@
#include "ureg.h"
#include "errno.h"
-void
-fault(Ureg *ur, int user, int code)
+int
+fault(ulong addr, int read)
{
- ulong addr, mmuvirt, mmuphys, n;
- extern char *excname[];
+ ulong mmuvirt, mmuphys, n;
Seg *s;
PTE *opte, *pte, *npte;
Orig *o;
@@ 18,34 17,21 @@ fault(Ureg *ur, int user, int code)
Page *pg;
int zeroed = 0, head = 1;
int i;
-
- addr = ur->badvaddr;
- addr &= ~(BY2PG-1);
+ KMap *k, *k1;
s = seg(u->p, addr);
if(s == 0){
- if(addr>USTKTOP){
- cant:
- if(user){
- pprint("user %s badvaddr=0x%lux\n", excname[code], ur->badvaddr);
- pprint("status=0x%lux pc=0x%lux sp=0x%lux\n", ur->status, ur->pc, ur->sp);
- pexit("Suicide", 0);
- }
- print("kernel %s badvaddr=0x%lux\n", excname[code], ur->badvaddr);
- print("status=0x%lux pc=0x%lux sp=0x%lux\n", ur->status, ur->pc, ur->sp);
- u->p->state = MMUing;
- dumpregs(ur);
- panic("fault");
- }
+ if(addr>USTKTOP)
+ return -1;
s = &u->p->seg[SSEG];
if(s->o==0 || addr<s->maxva-USTACKSIZE || addr>=s->maxva)
- goto cant;
+ return -1;
/* grow stack */
o = s->o;
n = o->npte;
if(waserror()){
pprint("can't allocate stack page\n");
- goto cant;
+ return -1;
}
growpte(o, (s->maxva-addr)>>PGSHIFT);
poperror();
@@ 58,8 44,8 @@ fault(Ureg *ur, int user, int code)
o->va = addr;
}else
o = s->o;
- if((code==CTLBM || code==CTLBS) && (o->flag&OWRPERM)==0)
- goto cant;
+ if(!read && (o->flag&OWRPERM)==0)
+ return -1;
lock(o);
opte = &o->pte[(addr-o->va)>>PGSHIFT];
pte = opte;
@@ 92,23 78,25 @@ fault(Ureg *ur, int user, int code)
if(n > BY2PG)
n = BY2PG;
pg = newpage(1, o, addr);
+ k = kmap(pg);
qlock(o->chan);
if(waserror()){
+ kunmap(k);
qunlock(o->chan);
pg->o = 0;
pg->ref--;
pexit("load i/o error", 0);
}
o->chan->offset = (addr-o->va) + o->minca;
- l = (char*)(pg->pa|KZERO);
+ l = (char*)VA(k);
if((*devtab[o->chan->type].read)(o->chan, l, n) != n)
error(Eioload);
qunlock(o->chan);
- poperror();
- /* BUG: if was first page of bss, move to data */
if(n<BY2PG)
memset(l+n, 0, BY2PG-n);
lock(o);
+ kunmap(k);
+ poperror();
opte = &o->pte[(addr-s->minva)>>PGSHIFT]; /* could move */
pte = opte;
if(pte->page == 0){
@@ 121,9 109,9 @@ fault(Ureg *ur, int user, int code)
}
}
/*
- * Copy on reference
+ * Copy on reference (conf.copymode==1) or write (conf.copymode==0)
*/
- if((o->flag & OWRPERM)
+ if((o->flag & OWRPERM) && (conf.copymode || !read)
&& ((head && ((o->flag&OPURE) || o->nproc>1))
|| (!head && pte->page->ref>1))){
@@ 173,7 161,11 @@ fault(Ureg *ur, int user, int code)
opte->page = 0;
}else{ /* copy page */
pte->page = newpage(1, o, addr);
- memcpy((void*)(pte->page->pa|KZERO), (void*)(pg->pa|KZERO), BY2PG);
+ k = kmap(pte->page);
+ k1 = kmap(pg);
+ memcpy((void*)VA(k), (void*)VA(k1), BY2PG);
+ kunmap(k);
+ kunmap(k1);
if(pg->ref <= 1)
panic("pg->ref <= 1");
pg->ref--;
@@ 181,7 173,7 @@ fault(Ureg *ur, int user, int code)
easy:
mmuphys = PTEWRITE;
}else{
- mmuphys = 0;
+ mmuphys = PTERONLY;
if(o->flag & OWRPERM)
if(o->flag & OPURE){
if(!head && pte->page->ref==1)
@@ 192,7 184,7 @@ fault(Ureg *ur, int user, int code)
mmuphys = PTEWRITE;
}
mmuvirt = addr;
- mmuphys |= pte->page->pa | PTEVALID;
+ mmuphys |= PPN(pte->page->pa) | PTEVALID;
usepage(pte->page, 1);
if(pte->page->va != addr)
panic("wrong addr in tail %lux %lux", pte->page->va, addr);
@@ 203,6 195,7 @@ fault(Ureg *ur, int user, int code)
}
unlock(o);
putmmu(mmuvirt, mmuphys);
+ return 0;
}
/*
@@ 235,15 228,6 @@ validaddr(ulong addr, ulong len, int write)
}
}
-void
-evenaddr(ulong addr)
-{
- if(addr & 3){
- postnote(u->p, 1, "sys: odd address", NDebug);
- error(Ebadarg);
- }
-}
-
/*
* &s[0] is known to be a valid address.
*/
M port/page.c => port/page.c +6 -6
@@ 55,7 55,7 @@ ialloc(ulong n, int align)
{
ulong p;
- if(palloc.active)
+ if(palloc.active && n!=0)
print("ialloc bad\n");
if(palloc.addr == 0)
palloc.addr = ((ulong)&end)&~KZERO;
@@ 185,7 185,7 @@ loop:
continue;
}
print("free %d pages va %lux %lux %c\n", o1->npage, o->va, o1->qid, devchar[o1->type]);
- freepage(o1);
+ freepage(o1, 0);
/* neworig will free the orig and pte's later */
unlock(o1);
if(p->ref == 0)
@@ 367,7 367,7 @@ loop:
unlock(o);
continue;
}
- freepage(o);
+ freepage(o, 1);
freepte(o);
unlock(o);
o->next = origalloc.free;
@@ 506,7 506,7 @@ freesegs(int save)
close(c);
}
if(!(o->flag&OCACHED) || o->npage==0){
- freepage(o);
+ freepage(o, 1);
freepte(o);
unlock(o);
lock(&origalloc);
@@ 566,7 566,7 @@ segaddr(Seg *s, ulong min, ulong max)
* o is locked
*/
void
-freepage(Orig *o)
+freepage(Orig *o, int dolock)
{
PTE *pte;
Page *pg;
@@ 576,7 576,7 @@ freepage(Orig *o)
for(i=0; i<o->npte; i++,pte++)
if(pg = pte->page){ /* assign = */
if(pg->ref == 1){
- unusepage(pg, 1);
+ unusepage(pg, dolock);
pte->page = 0;
pg->o = 0;
}
M port/proc.c => port/proc.c +4 -3
@@ 59,7 59,6 @@ schedinit(void) /* never returns */
else if(p->state == Moribund){
p->pid = 0;
unlock(&p->debug);
- unusepage(p->upage, 1);
p->upage->ref--;
/* procalloc already locked */
p->qnext = procalloc.free;
@@ 83,13 82,13 @@ sched(void)
if(u){
splhi();
- save(procstate, sizeof(procstate));
+ procsave(procstate, sizeof(procstate));
if(setlabel(&u->p->sched)){ /* woke up */
p = u->p;
p->state = Running;
p->mach = m;
m->proc = p;
- restore(p, procstate);
+ procrestore(p, procstate);
spllo();
return;
}
@@ 481,6 480,7 @@ pexit(char *s, int freemem)
lock(&procalloc); /* sched() can't do this */
lock(&c->debug); /* sched() can't do this */
+ unusepage(c->upage, 1); /* sched() can't do this (it locks) */
c->state = Moribund;
sched(); /* never returns */
}
@@ 567,6 567,7 @@ kproc(char *name, void (*func)(void *), void *arg)
* Kernel stack
*/
p = newproc();
+ p->kp = 1;
p->upage = newpage(1, 0, USERADDR|(p->pid&0xFFFF));
k = kmap(p->upage);
upa = VA(k);
M port/stream.c => port/stream.c +9 -5
@@ 314,6 314,7 @@ allocq(Qinfo *qi)
q->put = qi->iput;
q->len = q->nb = 0;
q->ptr = 0;
+ q->rp = &q->r;
wq = q->other = q + 1;
wq->flag = QINUSE;
@@ 323,6 324,7 @@ allocq(Qinfo *qi)
wq->other = q;
wq->ptr = 0;
wq->len = wq->nb = 0;
+ wq->rp = &wq->r;
unlock(q);
@@ 495,7 497,7 @@ getq(Queue *q)
q->len -= BLEN(bp);
q->nb--;
if((q->flag&QHIWAT) && q->len<Streamhi/2 && q->nb<Streambhi/2){
- wakeup(&q->other->next->other->r);
+ wakeup(q->other->next->other->rp);
q->flag &= ~QHIWAT;
}
bp->next = 0;
@@ 928,7 930,7 @@ stputq(Queue *q, Block *bp)
freeb(bp);
q->flag |= QHUNGUP;
q->other->flag |= QHUNGUP;
- wakeup(&q->other->r);
+ wakeup(q->other->rp);
delim = 1;
} else {
delim = 0;
@@ 954,7 956,7 @@ stputq(Queue *q, Block *bp)
unlock(q);
}
if(delim)
- wakeup(&q->r);
+ wakeup(q->rp);
}
/*
@@ 1048,7 1050,8 @@ streamread(Chan *c, void *vbuf, long n)
else
error(Ehungup);
}
- sleep(&q->r, &isinput, (void *)q);
+ q->rp = &q->r;
+ sleep(q->rp, &isinput, (void *)q);
continue;
}
@@ 1167,7 1170,8 @@ flowctl(Queue *q)
qunlock(&q->rlock);
nexterror();
}
- sleep(&q->r, notfull, q->next);
+ q->rp = &q->r;
+ sleep(q->rp, notfull, q->next);
qunlock(&q->rlock);
poperror();
}
M port/sturp.c => port/sturp.c +1 -0
@@ 169,6 169,7 @@ urpopen(Queue *q, Stream *s)
}
q->ptr = q->other->ptr = up;
+ q->rp = &urpkr;
up->rq = q;
up->wq = q->other;
up->state = OPEN;
M port/sysproc.c => port/sysproc.c +8 -13
@@ 205,10 205,7 @@ sysexec(ulong *arg)
Binary:
t = (UTZERO+sizeof(Exec)+exec.text+(BY2PG-1)) & ~(BY2PG-1);
- /*
- * Last partial page of data goes into BSS.
- */
- d = (t + exec.data) & ~(BY2PG-1);
+ d = (t + exec.data + (BY2PG-1)) & ~(BY2PG-1);
bssend = t + exec.data + exec.bss;
b = (bssend + (BY2PG-1)) & ~(BY2PG-1);
if((t|d|b) & KZERO)
@@ 311,7 308,7 @@ sysexec(ulong *arg)
if(o == 0){
o = neworig(t, (d-t)>>PGSHIFT, OWRPERM|OPURE|OCACHED, tc);
o->minca = p->seg[TSEG].o->maxca;
- o->maxca = o->minca + (exec.data & ~(BY2PG-1));
+ o->maxca = o->minca + exec.data;
}
s->o = o;
s->minva = t;
@@ 319,15 316,13 @@ sysexec(ulong *arg)
s->mod = 0;
/*
- * BSS. Created afresh, starting with last page of data.
- * BUG: should pick up the last page of data, which should be cached in the
- * data segment.
+ * BSS. Created afresh.
*/
s = &p->seg[BSEG];
s->proc = p;
- o = neworig(d, (b-d)>>PGSHIFT, OWRPERM, tc);
- o->minca = p->seg[DSEG].o->maxca;
- o->maxca = o->minca + (exec.data & (BY2PG-1));
+ o = neworig(d, (b-d)>>PGSHIFT, OWRPERM, 0);
+ o->minca = 0;
+ o->maxca = 0;
s->o = o;
s->minva = d;
s->maxva = b;
@@ 353,7 348,7 @@ sysexec(ulong *arg)
unlock(o);
flushmmu();
- clearmmucache();
+ clearmmucache();
((Ureg*)UREGADDR)->pc = exec.entry + ENTRYOFFSET;
sp = (ulong*)(USTKTOP - ssize);
*--sp = nargs;
@@ 362,7 357,7 @@ sysexec(ulong *arg)
u->nnote = 0;
u->notify = 0;
u->notified = 0;
- setup(p);
+ procsetup(p);
unlock(&p->debug);
return 0;
}
M power/conf.h => power/conf.h +1 -0
@@ 29,6 29,7 @@ Conftab conftab[] = {
{"maxialloc", &conf.maxialloc },
{"base0", &conf.base0 },
{"base1", &conf.base1 },
+ {"copymode", &conf.copymode },
{ 0, 0 },
};
M power/dat.h => power/dat.h +5 -1
@@ 152,6 152,7 @@ struct Conf
ulong maxialloc; /* maximum bytes used by ialloc */
ulong base0; /* base of bank 0 */
ulong base1; /* base of bank 1 */
+ ulong copymode; /* 0 is copy on write, 1 is copy on reference */
};
struct Dev
@@ 336,6 337,7 @@ struct Proc
Rendez sleep; /* place for tsleep and syssleep */
int wokeup; /* whether sleep was interrupted */
ulong pc; /* DEBUG only */
+ int kp; /* true if kernel process */
};
@@ 378,6 380,7 @@ typedef void KMap;
#define VA(k) ((ulong)(k))
#define kmap(p) (KMap*)(p->pa|KZERO)
#define kunmap(k)
+#define PPN(x) x
/*
* operations available to a queue
@@ 438,7 441,8 @@ struct Queue {
Queue *next; /* next queue in the stream */
void (*put)(Queue*, Block*);
QLock rlock; /* mutex for r */
- Rendez r;
+ Rendez r; /* standard place to wait for flow control */
+ Rendez *rp; /* where flow control wakeups go to */
void *ptr; /* private info for the queue */
};
#define QHUNGUP 0x1 /* flag bit meaning the stream has been hung up */
M power/devrtc.c => power/devrtc.c +4 -1
@@ 27,7 27,7 @@ struct Rtc
QLock rtclock; /* mutex on clock operations */
static Dirtab rtcdir[]={
- "rtc", {1}, 0, 0600,
+ "rtc", {1, 0}, 0, 0600,
};
static uchar pattern[] =
@@ 145,6 145,9 @@ rtcread(Chan *c, void *buf, long n)
char atime[64];
Rtc rtc;
+ if(c->qid.path & CHDIR)
+ return devdirread(c, buf, n, rtcdir, 1, devgen);
+
nv = RTC;
/*
A power/faultmips.c => power/faultmips.c +47 -0
@@ 0,0 1,47 @@
+#include "u.h"
+#include "lib.h"
+#include "mem.h"
+#include "dat.h"
+#include "fns.h"
+#include "ureg.h"
+#include "errno.h"
+
+/*
+ * find out fault address and type of access.
+ * Call common fault handler.
+ */
+void
+faultmips(Ureg *ur, int user, int code)
+{
+ ulong addr;
+ extern char *excname[];
+ int read;
+
+ addr = ur->badvaddr;
+ addr &= ~(BY2PG-1);
+ read = !(code==CTLBM || code==CTLBS);
+ if(fault(addr, read) < 0){
+ if(user){
+ pprint("user %s badvaddr=0x%lux\n", excname[code], ur->badvaddr);
+ pprint("status=0x%lux pc=0x%lux sp=0x%lux\n", ur->status, ur->pc, ur->sp);
+ pexit("Suicide", 0);
+ }
+ print("kernel %s badvaddr=0x%lux\n", excname[code], ur->badvaddr);
+ print("status=0x%lux pc=0x%lux sp=0x%lux\n", ur->status, ur->pc, ur->sp);
+ u->p->state = MMUing;
+ dumpregs(ur);
+ panic("fault");
+ }
+}
+
+/*
+ * called in sysfile.c
+ */
+void
+evenaddr(ulong addr)
+{
+ if(addr & 3){
+ postnote(u->p, 1, "sys: odd address", NDebug);
+ error(Ebadarg);
+ }
+}
M power/fns.h => power/fns.h +10 -5
@@ 57,7 57,8 @@ void error(int);
void errors(char*);
void evenaddr(ulong);
void exit(void);
-void fault(Ureg*, int, int);
+int fault(ulong, int);
+void faultmips(Ureg*, int, int);
void fdclose(int);
Chan* fdtochan(int, int);
void firmware(void);
@@ 66,7 67,7 @@ void flushmmu(void);
void forkmod(Seg*, Seg*, Proc*);
void freeb(Block*);
int freebroken(void);
-void freepage(Orig*);
+void freepage(Orig*, int);
void freepte(Orig*);
void freesegs(int);
void freealarm(Alarm*);
@@ 155,11 156,9 @@ int readnum(ulong, char*, ulong, ulong, int);
void ready(Proc*);
void qlock(QLock*);
void qunlock(QLock*);
-void restore(Proc*, uchar*);
void restfpregs(FPsave*);
int return0(void*);
Proc *runproc(void);
-void save(uchar*, int);
void savefpregs(FPsave*);
void sched(void);
void schedinit(void);
@@ 167,7 166,6 @@ long seconds(void);
Seg *seg(Proc*, ulong);
int segaddr(Seg*, ulong, ulong);
int setlabel(Label*);
-void setup(Proc*);
void setvmevec(int, void (*)(int));
void sinit(void);
char* skipslash(char*);
@@ 212,3 210,10 @@ void wbflush(void);
#define waserror() setlabel(&u->errlab[u->nerrlab++])
#define poperror() u->nerrlab--
+
+/*
+ * no external state to save on the SGI
+ */
+#define procsetup(x)
+#define procsave(x,y)
+#define procrestore(x,y)
M power/main.c => power/main.c +1 -24
@@ 631,6 631,7 @@ confinit(void)
if(conf.nmach > MAXMACH)
panic("confinit");
+ conf.copymode = 1; /* copy on reference */
}
@@ 695,27 696,3 @@ arginit(void)
_argv = argv;
argsize = ssize;
}
-
-/*
- * set up machine dependent process state for a new process
- */
-void
-setup(Proc *p)
-{
-}
-
-/*
- * Save machine dependent process state
- */
-void
-save(uchar *state, int len)
-{
-}
-
-/*
- * Restore what save() saves
- */
-void
-restore(Proc *p, uchar *state)
-{
-}
M power/mem.h => power/mem.h +1 -0
@@ 94,6 94,7 @@
#define PTEGLOBL (1<<8)
#define PTEVALID (1<<9)
#define PTEWRITE (1<<10)
+#define PTERONLY 0
#define PTEPID(n) ((n)<<6)
#define NTLBPID 64 /* number of pids */
M power/trap.c => power/trap.c +1 -1
@@ 122,7 122,7 @@ trap(Ureg *ur)
spllo();
x = u->p->insyscall;
u->p->insyscall = 1;
- fault(ur, user, ecode);
+ faultmips(ur, user, ecode);
u->p->insyscall = x;
break;