| plan 9 kernel history: overview | file list | diff list |
1991/01151/ss/mmu.c (diff list | history)
| 1990/1223/sys/src/9/ss/mmu.c:3,102 – 1990/1226/sys/src/9/ss/mmu.c:3,230 (short | long) | ||
| 1990/1223 | #include "mem.h" #include "dat.h" #include "fns.h" | |
| 1990/1226 | #include "io.h" | |
| 1990/1223 | struct { Lock; int init; | |
| 1990/1226 | int lowpmeg; | |
| 1990/1223 | KMap *free; | |
| 1990/1226 | KMap arena[(IOEND-IOSEGM)/BY2PG]; | |
| 1990/1223 | }kmapalloc; /* | |
| 1990/1226 | * On SPARC, tlbpid i == context i-1 so that 0 means unallocated */ int newpid(Proc*); void purgepid(int); /* | |
| 1990/1223 | * Called splhi, not in Running state */ void mapstack(Proc *p) { | |
| 1990/1226 | short tp; ulong tlbphys; | |
| 1990/1223 | ||
| 1990/1226 | tp = p->pidonmach[m->machno]; if(tp == 0){ tp = newpid(p); p->pidonmach[m->machno] = tp; } | |
| 1990/1223 | if(p->upage->va != (USERADDR|(p->pid&0xFFFF))) panic("mapstack %d 0x%lux 0x%lux", p->pid, p->upage->pa, p->upage->va); | |
| 1990/1226 | /* don't set m->pidhere[*tp] because we're only writing U entry */ tlbphys = PPN(p->upage->pa)|PTEVALID|PTEWRITE|PTEKERNEL|PTEMAINMEM; putcontext(tp-1); putpmeg(USERADDR, tlbphys); | |
| 1990/1223 | u = (User*)USERADDR; | |
| 1990/1226 | } | |
| 1990/1223 | ||
| 1990/1226 | /* * Process must be non-interruptible */ int newpid(Proc *p) { int i, j; Proc *sp; i = m->lastpid+1; if(i >= NCONTEXT+1) i = 1; sp = m->pidproc[i]; if(sp){ sp->pidonmach[m->machno] = 0; purgepid(i); } m->pidproc[i] = p; m->lastpid = i; print("new context %d\n", i); | |
| 1990/1223 | /* | |
| 1990/1226 | * kludge: each context is allowed 2 pmegs, one for text and one for stack | |
| 1990/1223 | */ | |
| 1990/1226 | putsegm(UZERO, kmapalloc.lowpmeg+(2*i)); putsegm(TSTKTOP-BY2SEGM, kmapalloc.lowpmeg+(2*i)+1); for(j=0; j<PG2SEGM; j++){ putpmeg(UZERO+j*BY2PG, INVALIDPTE); putpmeg((TSTKTOP-BY2SEGM)+j*BY2PG, INVALIDPTE); } return i; } | |
| 1990/1223 |
| |
| 1990/1226 | void purgepid(int pid) { int i, rpid; | |
| 1990/1223 |
| |
| 1990/1226 | if(m->pidhere[pid] == 0) return; print("purge pid %d\n", pid); memset(m->pidhere, 0, sizeof m->pidhere); putcontext(pid-1); /* * Clear context from cache */ for(i=0; i<0x1000; i++) putwE((i<<4), 0); print("purge done\n"); | |
| 1990/1223 | } | |
| 1990/1226 | ||
| 1990/1223 | void | |
| 1990/1226 | mmuinit(void) | |
| 1990/1223 | { | |
| 1990/1226 | ulong l, i, j, c, pte; /* * First map lots of memory as kernel addressable in all contexts */ i = 0; /* used */ for(c=0; c<NCONTEXT; c++) for(i=0; i<conf.maxialloc/BY2SEGM; i++) putcxsegm(c, KZERO+i*BY2SEGM, i); kmapalloc.lowpmeg = i; /* * Make sure cache is turned on for kernel */ pte = PTEVALID|PTEWRITE|PTEKERNEL|PTEMAINMEM; for(i=0; i<conf.maxialloc/BY2PG; i++) putpmeg(KZERO+i*BY2PG, pte+i); /* * Create invalid pmeg; use highest segment */ putsegm(INVALIDSEGM, INVALIDPMEG); for(i=0; i<PG2SEGM; i++) putpmeg(INVALIDSEGM+i*BY2PG, INVALIDPTE); for(c=0; c<NCONTEXT; c++){ putcontext(c); putsegm(INVALIDSEGM, INVALIDPMEG); /* * Invalidate user addresses */ /* for(l=UZERO; l<KZERO; l+=BY2SEGM) putsegm(l, INVALIDPMEG); */ putsegm(0x0000, INVALIDPMEG); /* * One segment for screen */ putsegm(SCREENSEGM, SCREENPMEG); if(c == 0){ pte = PTEVALID|PTEWRITE|PTEKERNEL|PTENOCACHE| PTEIO|((DISPLAYRAM>>PGSHIFT)&0xFFFF); for(i=0; i<PG2SEGM; i++) putpmeg(SCREENSEGM+i*BY2PG, pte+i); } /* * First page of IO space includes ROM; be careful */ putsegm(IOSEGM0, IOPMEG0); /* IOSEGM == ROMSEGM */ if(c == 0){ pte = PTEVALID|PTEKERNEL|PTENOCACHE| PTEIO|((EPROM>>PGSHIFT)&0xFFFF); for(i=0; i<PG2ROM; i++) putpmeg(IOSEGM0+i*BY2PG, pte+i); for(; i<PG2SEGM; i++) putpmeg(IOSEGM0+i*BY2PG, INVALIDPTE); } /* * Remaining segments for IO and kmap */ for(j=1; j<NIOSEGM; j++){ putsegm(IOSEGM0+j*BY2SEGM, IOPMEG0+j); if(c == 0) for(i=0; i<PG2SEGM; i++) putpmeg(IOSEGM0+j*BY2SEGM+i*BY2PG, INVALIDPTE); } } putcontext(0); | |
| 1990/1223 | } | |
| 1990/1226 | ||
| 1990/1223 | void putmmu(ulong tlbvirt, ulong tlbphys) { | |
| 1990/1226 | short tp; Proc *p; | |
| 1990/1223 |
| |
| 1990/1226 | splhi(); p = u->p; /* if(p->state != Running) panic("putmmu state %lux %lux %s\n", u, p, statename[p->state]); */ p->state = MMUing; tp = p->pidonmach[m->machno]; if(tp == 0){ tp = newpid(p); p->pidonmach[m->machno] = tp; | |
| 1990/1223 | } | |
| 1990/1226 | /* * kludge part 2: make sure we've got a valid segment */ if(tlbvirt>=TSTKTOP || (UZERO+BY2SEGM<=tlbvirt && tlbvirt<(TSTKTOP-BY2SEGM))) panic("putmmu %lux", tlbvirt); putpmeg(tlbvirt, tlbphys); m->pidhere[tp] = 1; p->state = Running; spllo(); | |
| 1990/1223 | } void flushmmu(void) { | |
| 1990/1226 | splhi(); /* easiest is to forget what pid we had.... */ memset(u->p->pidonmach, 0, sizeof u->p->pidonmach); /* ....then get a new one by trying to map our stack */ mapstack(u->p); spllo(); | |
| 1990/1223 | } void | |
| 1990/1226 | cacheinit(void) | |
| 1990/1223 | { | |
| 1990/1226 | int i; /* * Initialize cache by clearing the valid bit * (along with the others) in all cache entries */ for(i=0; i<0x1000; i++) putw2(CACHETAGS+(i<<4), 0); /* * Turn cache on */ putb2(ENAB, getb2(ENAB)|ENABCACHE); /**/ | |
| 1990/1223 | } void | |
| 1990/1223/sys/src/9/ss/mmu.c:103,130 – 1990/1226/sys/src/9/ss/mmu.c:231,249 | ||
| 1990/1223 | kmapinit(void) { KMap *k; | |
| 1990/1226 | int i; | |
| 1990/1223 |
| |
| 1990/1226 | print("low pmeg %d\n", kmapalloc.lowpmeg); | |
| 1990/1223 | kmapalloc.free = 0; | |
| 1990/1226 | k = kmapalloc.arena; for(i=0; i<(IOEND-IOSEGM)/BY2PG; i++,k++){ k->va = IOSEGM+i*BY2PG; | |
| 1990/1223 | kunmap(k); } } KMap* | |
| 1990/1226 | kmap1(Page *pg, ulong flag) | |
| 1990/1223 | { KMap *k; | |
| 1990/1223/sys/src/9/ss/mmu.c:137,154 – 1990/1226/sys/src/9/ss/mmu.c:256,287 | ||
| 1990/1223 | kmapalloc.free = k->next; unlock(&kmapalloc); k->pa = pg->pa; | |
| 1990/1226 | /* * Cache is virtual and a pain to deal with. * Must avoid having the same entry in the cache twice, so * must use NOCACHE or else extreme cleverness elsewhere. */ putpmeg(k->va, PPN(k->pa)|PTEVALID|PTEKERNEL|PTEWRITE|PTENOCACHE|flag); | |
| 1990/1223 | return k; } | |
| 1990/1226 | KMap* kmap(Page *pg) { return kmap1(pg, PTEMAINMEM); } | |
| 1990/1223 | void kunmap(KMap *k) { | |
| 1990/1226 | ulong pte; int i; | |
| 1990/1223 | k->pa = 0; lock(&kmapalloc); k->next = kmapalloc.free; kmapalloc.free = k; | |
| 1990/1226 | putpmeg(k->va, INVALIDPTE); | |
| 1990/1223 | unlock(&kmapalloc); } | |
| 1990/1223/sys/src/9/ss/mmu.c:155,159 – 1990/1226/sys/src/9/ss/mmu.c:288,292 | ||
| 1990/1223 | void invalidateu(void) { | |
| 1990/1226 | putpmeg(USERADDR, INVALIDPTE); | |
| 1990/1223 | } | |
| 1990/1226/sys/src/9/ss/mmu.c:40,45 – 1990/1227/sys/src/9/ss/mmu.c:40,50 (short | long) | ||
| 1990/1226 | /* don't set m->pidhere[*tp] because we're only writing U entry */ tlbphys = PPN(p->upage->pa)|PTEVALID|PTEWRITE|PTEKERNEL|PTEMAINMEM; putcontext(tp-1); | |
| 1990/1227 | /* * putw4(USERADDR, tlbphys) might be good enough but * there is that fuss in pexit/pwait() copying between * u areas and that might surprise any cache entries */ | |
| 1990/1226 | putpmeg(USERADDR, tlbphys); | |
| 1990/1223 | u = (User*)USERADDR; | |
| 1990/1226 | } | |
| 1990/1226/sys/src/9/ss/mmu.c:64,69 – 1990/1227/sys/src/9/ss/mmu.c:69,75 | ||
| 1990/1226 | m->pidproc[i] = p; m->lastpid = i; print("new context %d\n", i); | |
| 1990/1227 | putcontext(i-1); | |
| 1990/1223 | /* | |
| 1990/1226 | * kludge: each context is allowed 2 pmegs, one for text and one for stack | |
| 1990/1223 | */ | |
| 1990/1226/sys/src/9/ss/mmu.c:128,138 – 1990/1227/sys/src/9/ss/mmu.c:134,143 | ||
| 1990/1226 | /* * Invalidate user addresses */ | |
| 1990/1227 | for(l=UZERO; l<(KZERO&VAMASK); l+=BY2SEGM) | |
| 1990/1226 | putsegm(l, INVALIDPMEG); | |
| 1990/1227 | ||
| 1990/1226 | /* * One segment for screen */ | |
| 1990/1226/sys/src/9/ss/mmu.c:168,176 – 1990/1227/sys/src/9/ss/mmu.c:173,178 | ||
| 1990/1226 | putcontext(0); | |
| 1990/1223 | } | |
| 1990/1226 | ||
| 1990/1223 | void putmmu(ulong tlbvirt, ulong tlbphys) { | |
| 1990/1226/sys/src/9/ss/mmu.c:200,205 – 1990/1227/sys/src/9/ss/mmu.c:202,222 | ||
| 1990/1223 | } void | |
| 1990/1227 | putpmeg(ulong virt, ulong phys) { int i; virt &= VAMASK; virt &= ~(BY2PG-1); /* * Flush old entries from cache */ for(i=0; i<0x100; i++) putwD(virt+(i<<4), 0); putw4(virt, phys); } void | |
| 1990/1223 | flushmmu(void) { | |
| 1990/1226 | splhi(); | |
| 1990/1226/sys/src/9/ss/mmu.c:233,239 – 1990/1227/sys/src/9/ss/mmu.c:250,255 | ||
| 1990/1223 | KMap *k; | |
| 1990/1226 | int i; | |
| 1990/1223 | ||
| 1990/1226 |
| |
| 1990/1223 | kmapalloc.free = 0; | |
| 1990/1226 | k = kmapalloc.arena; for(i=0; i<(IOEND-IOSEGM)/BY2PG; i++,k++){ | |
| 1990/1226/sys/src/9/ss/mmu.c:243,249 – 1990/1227/sys/src/9/ss/mmu.c:259,265 | ||
| 1990/1223 | } KMap* | |
| 1990/1226 |
| |
| 1990/1227 | kmappa(ulong pa, ulong flag) | |
| 1990/1223 | { KMap *k; | |
| 1990/1226/sys/src/9/ss/mmu.c:255,267 – 1990/1227/sys/src/9/ss/mmu.c:271,283 | ||
| 1990/1223 | } kmapalloc.free = k->next; unlock(&kmapalloc); | |
| 1990/1227 | k->pa = pa; | |
| 1990/1226 | /* * Cache is virtual and a pain to deal with. * Must avoid having the same entry in the cache twice, so * must use NOCACHE or else extreme cleverness elsewhere. */ | |
| 1990/1227 | putpmeg(k->va, PPN(pa)|PTEVALID|PTEKERNEL|PTEWRITE|PTENOCACHE|flag); | |
| 1990/1223 | return k; } | |
| 1990/1226/sys/src/9/ss/mmu.c:268,274 – 1990/1227/sys/src/9/ss/mmu.c:284,290 | ||
| 1990/1226 | KMap* kmap(Page *pg) { | |
| 1990/1227 | return kmappa(pg->pa, PTEMAINMEM); | |
| 1990/1226 | } | |
| 1990/1223 | void | |
| 1990/1227/sys/src/9/ss/mmu.c:68,74 – 1990/1231/sys/src/9/ss/mmu.c:68,73 (short | long) | ||
| 1990/1226 | } m->pidproc[i] = p; m->lastpid = i; | |
| 1990/1227 | putcontext(i-1); | |
| 1990/1223 | /* | |
| 1990/1226 | * kludge: each context is allowed 2 pmegs, one for text and one for stack | |
| 1990/1227/sys/src/9/ss/mmu.c:83,88 – 1990/1231/sys/src/9/ss/mmu.c:82,94 | ||
| 1990/1226 | } | |
| 1990/1223 | ||
| 1990/1226 | void | |
| 1990/1231 | putcontext(int c) { m->pidhere[c] = 1; putcxreg(c); } void | |
| 1990/1226 | purgepid(int pid) { int i, rpid; | |
| 1990/1227/sys/src/9/ss/mmu.c:181,190 – 1990/1231/sys/src/9/ss/mmu.c:187,192 | ||
| 1990/1223 | ||
| 1990/1226 | splhi(); p = u->p; | |
| 1990/1227/sys/src/9/ss/mmu.c:196,203 – 1990/1231/sys/src/9/ss/mmu.c:198,203 | ||
| 1990/1226 | if(tlbvirt>=TSTKTOP || (UZERO+BY2SEGM<=tlbvirt && tlbvirt<(TSTKTOP-BY2SEGM))) panic("putmmu %lux", tlbvirt); putpmeg(tlbvirt, tlbphys); | |
| 1990/1223 | } | |
| 1990/1227/sys/src/9/ss/mmu.c:205,210 – 1990/1231/sys/src/9/ss/mmu.c:205,211 | ||
| 1990/1227 | putpmeg(ulong virt, ulong phys) { int i; | |
| 1990/1231 | int tp; | |
| 1990/1227 | virt &= VAMASK; virt &= ~(BY2PG-1); | |
| 1990/1227/sys/src/9/ss/mmu.c:213,218 – 1990/1231/sys/src/9/ss/mmu.c:214,221 | ||
| 1990/1227 | */ for(i=0; i<0x100; i++) putwD(virt+(i<<4), 0); | |
| 1990/1231 | if(u && u->p) m->pidhere[u->p->pidonmach[m->machno]] = 1; /* UGH! */ | |
| 1990/1227 | putw4(virt, phys); } | |
| 1990/1231/sys/src/9/ss/mmu.c:175,180 – 1991/0108/sys/src/9/ss/mmu.c:175,184 (short | long) | ||
| 1990/1226 | for(i=0; i<PG2SEGM; i++) putpmeg(IOSEGM0+j*BY2SEGM+i*BY2PG, INVALIDPTE); } | |
| 1991/0108 | /* * Lance */ putsegm(LANCESEGM, LANCEPMEG); | |
| 1990/1226 | } putcontext(0); | |
| 1990/1223 | } | |
| 1991/0108/sys/src/9/ss/mmu.c:55,61 – 1991/0109/sys/src/9/ss/mmu.c:55,61 (short | long) | ||
| 1990/1226 | int newpid(Proc *p) { | |
| 1991/0109 | int i, j, k; | |
| 1990/1226 | Proc *sp; i = m->lastpid+1; | |
| 1991/0108/sys/src/9/ss/mmu.c:69,81 – 1991/0109/sys/src/9/ss/mmu.c:69,84 | ||
| 1990/1226 | m->pidproc[i] = p; m->lastpid = i; | |
| 1990/1227 | putcontext(i-1); | |
| 1991/0109 | /* print("new pid %d\n", i); /**/ | |
| 1990/1223 | /* | |
| 1990/1226 |
| |
| 1991/0109 | * kludge: each context is allowed 5 pmegs, four for text & data and one for stack | |
| 1990/1223 | */ | |
| 1990/1226 |
| |
| 1991/0109 | for(j=0; j<4; j++) putsegm(UZERO, kmapalloc.lowpmeg+(2*i)+j); putsegm(TSTKTOP-BY2SEGM, kmapalloc.lowpmeg+(2*i)+4); | |
| 1990/1226 | for(j=0; j<PG2SEGM; j++){ | |
| 1991/0109 | for(k=0; k<4; k++) putpmeg(UZERO+k*BY2SEGM+j*BY2PG, INVALIDPTE); | |
| 1990/1226 | putpmeg((TSTKTOP-BY2SEGM)+j*BY2PG, INVALIDPTE); } return i; | |
| 1991/0108/sys/src/9/ss/mmu.c:95,101 – 1991/0109/sys/src/9/ss/mmu.c:98,104 | ||
| 1990/1223 | ||
| 1990/1226 | if(m->pidhere[pid] == 0) return; | |
| 1991/0109 | /* print("purge pid %d\n", pid);/**/ | |
| 1990/1226 | memset(m->pidhere, 0, sizeof m->pidhere); putcontext(pid-1); /* | |
| 1991/0108/sys/src/9/ss/mmu.c:103,109 – 1991/0109/sys/src/9/ss/mmu.c:106,112 | ||
| 1990/1226 | */ for(i=0; i<0x1000; i++) putwE((i<<4), 0); | |
| 1991/0109 | /* print("purge done\n");/**/ | |
| 1990/1223 | } | |
| 1990/1226 | ||
| 1991/0108/sys/src/9/ss/mmu.c:199,205 – 1991/0109/sys/src/9/ss/mmu.c:202,208 | ||
| 1990/1226 | /* * kludge part 2: make sure we've got a valid segment */ | |
| 1991/0109 | if(tlbvirt>=TSTKTOP || (UZERO+4*BY2SEGM<=tlbvirt && tlbvirt<(TSTKTOP-BY2SEGM))) | |
| 1990/1226 | panic("putmmu %lux", tlbvirt); putpmeg(tlbvirt, tlbphys); spllo(); | |
| 1991/0109/sys/src/9/ss/mmu.c:14,19 – 1991/0110/sys/src/9/ss/mmu.c:14,21 (short | long) | ||
| 1990/1226 | KMap arena[(IOEND-IOSEGM)/BY2PG]; | |
| 1990/1223 | }kmapalloc; | |
| 1991/0110 | #define NKLUDGE 8 | |
| 1990/1223 | /* | |
| 1990/1226 | * On SPARC, tlbpid i == context i-1 so that 0 means unallocated */ | |
| 1991/0109/sys/src/9/ss/mmu.c:20,25 – 1991/0110/sys/src/9/ss/mmu.c:22,28 | ||
| 1990/1226 | int newpid(Proc*); void purgepid(int); | |
| 1991/0110 | int pidtime[NTLBPID]; /* should be per m */ | |
| 1990/1226 | /* | |
| 1990/1223 | * Called splhi, not in Running state | |
| 1991/0109/sys/src/9/ss/mmu.c:36,49 – 1991/0110/sys/src/9/ss/mmu.c:39,50 | ||
| 1990/1226 | p->pidonmach[m->machno] = tp; } | |
| 1990/1223 | if(p->upage->va != (USERADDR|(p->pid&0xFFFF))) | |
| 1990/1226 |
| |
| 1991/0110 | panic("mapstack %s %d %lux 0x%lux 0x%lux", p->text, p->pid, p->upage, p->upage->pa, p->upage->va); | |
| 1990/1226 | tlbphys = PPN(p->upage->pa)|PTEVALID|PTEWRITE|PTEKERNEL|PTEMAINMEM; putcontext(tp-1); | |
| 1990/1227 | /* | |
| 1991/0110 | * shouldn't need putpmeg because nothing has been mapped at * USERADDR in this context except this page. however, it crashes. | |
| 1990/1227 | */ | |
| 1990/1226 | putpmeg(USERADDR, tlbphys); | |
| 1990/1223 | u = (User*)USERADDR; | |
| 1991/0109/sys/src/9/ss/mmu.c:56,83 – 1991/0110/sys/src/9/ss/mmu.c:57,90 | ||
| 1990/1226 | newpid(Proc *p) { | |
| 1991/0109 | int i, j, k; | |
| 1991/0110 | ulong t; | |
| 1990/1226 | Proc *sp; | |
| 1991/0110 | t = ~0; i = 1+((m->ticks)&(NCONTEXT-1)); /* random guess */ for(j=1; j<NTLBPID; j++) if(pidtime[j] < t){ i = j; t = pidtime[j]; } | |
| 1990/1226 | sp = m->pidproc[i]; if(sp){ sp->pidonmach[m->machno] = 0; purgepid(i); } | |
| 1991/0110 | pidtime[i] = m->ticks; | |
| 1990/1226 | m->pidproc[i] = p; m->lastpid = i; | |
| 1990/1227 | putcontext(i-1); | |
| 1991/0109 |
| |
| 1990/1223 | /* | |
| 1991/0109 |
| |
| 1991/0110 | * kludge: each context is allowed NKLUDGE pmegs, NKLUDGE-1 for text & data and 1 for stack | |
| 1990/1223 | */ | |
| 1991/0109 |
| |
| 1991/0110 | for(j=0; j<NKLUDGE-1; j++) putsegm(UZERO+j*BY2SEGM, kmapalloc.lowpmeg+(NKLUDGE*(i-1))+j); putsegm(TSTKTOP-BY2SEGM, kmapalloc.lowpmeg+(NKLUDGE*(i-1))+(NKLUDGE-1)); | |
| 1990/1226 | for(j=0; j<PG2SEGM; j++){ | |
| 1991/0109 |
| |
| 1991/0110 | for(k=0; k<NKLUDGE-1; k++) | |
| 1991/0109 | putpmeg(UZERO+k*BY2SEGM+j*BY2PG, INVALIDPTE); | |
| 1990/1226 | putpmeg((TSTKTOP-BY2SEGM)+j*BY2PG, INVALIDPTE); } | |
| 1991/0109/sys/src/9/ss/mmu.c:87,112 – 1991/0110/sys/src/9/ss/mmu.c:94,123 | ||
| 1990/1226 | void | |
| 1990/1231 | putcontext(int c) { | |
| 1991/0110 | m->pidhere[c+1] = 1; | |
| 1990/1231 | putcxreg(c); } void | |
| 1990/1226 |
| |
| 1991/0110 | flushcontext(void) | |
| 1990/1226 | { | |
| 1991/0110 | int i; | |
| 1990/1223 | ||
| 1991/0110 | /* * Clear context from cache */ for(i=0; i<0x1000; i+=16) putwE16((i<<4), 0); } void purgepid(int pid) { | |
| 1990/1226 | if(m->pidhere[pid] == 0) return; | |
| 1991/0109 |
| |
| 1990/1226 | memset(m->pidhere, 0, sizeof m->pidhere); putcontext(pid-1); | |
| 1991/0109 |
| |
| 1991/0110 | flushcontext(); | |
| 1990/1223 | } | |
| 1990/1226 | ||
| 1991/0109/sys/src/9/ss/mmu.c:129,135 – 1991/0110/sys/src/9/ss/mmu.c:140,145 | ||
| 1990/1226 | pte = PTEVALID|PTEWRITE|PTEKERNEL|PTEMAINMEM; for(i=0; i<conf.maxialloc/BY2PG; i++) putpmeg(KZERO+i*BY2PG, pte+i); | |
| 1991/0109/sys/src/9/ss/mmu.c:178,187 – 1991/0110/sys/src/9/ss/mmu.c:188,193 | ||
| 1990/1226 | for(i=0; i<PG2SEGM; i++) putpmeg(IOSEGM0+j*BY2SEGM+i*BY2PG, INVALIDPTE); } | |
| 1991/0108 |
| |
| 1990/1226 | } putcontext(0); | |
| 1990/1223 | } | |
| 1991/0109/sys/src/9/ss/mmu.c:202,209 – 1991/0110/sys/src/9/ss/mmu.c:208,217 | ||
| 1990/1226 | /* * kludge part 2: make sure we've got a valid segment */ | |
| 1991/0109 |
| |
| 1990/1226 |
| |
| 1991/0110 | if(tlbvirt>=TSTKTOP || (UZERO+(NKLUDGE-1)*BY2SEGM<=tlbvirt && tlbvirt<(TSTKTOP-BY2SEGM))){ pprint("putmmu %lux", tlbvirt); pexit("Suicide", 0); } | |
| 1990/1226 | putpmeg(tlbvirt, tlbphys); spllo(); | |
| 1990/1223 | } | |
| 1991/0109/sys/src/9/ss/mmu.c:219,226 – 1991/0110/sys/src/9/ss/mmu.c:227,234 | ||
| 1990/1227 | /* * Flush old entries from cache */ | |
| 1991/0110 | for(i=0; i<0x100; i+=16) putwD16(virt+(i<<4), 0); | |
| 1990/1231 | if(u && u->p) m->pidhere[u->p->pidonmach[m->machno]] = 1; /* UGH! */ | |
| 1990/1227 | putw4(virt, phys); | |
| 1991/0109/sys/src/9/ss/mmu.c:229,235 – 1991/0110/sys/src/9/ss/mmu.c:237,249 | ||
| 1990/1227 | void | |
| 1990/1223 | flushmmu(void) { | |
| 1991/0110 | int tp; | |
| 1990/1226 | splhi(); | |
| 1991/0110 | flushcontext(); tp = u->p->pidonmach[m->machno]; if(tp) pidtime[tp] = 0; | |
| 1990/1226 | /* easiest is to forget what pid we had.... */ memset(u->p->pidonmach, 0, sizeof u->p->pidonmach); /* ....then get a new one by trying to map our stack */ | |
| 1991/0109/sys/src/9/ss/mmu.c:240,253 – 1991/0110/sys/src/9/ss/mmu.c:254,272 | ||
| 1990/1223 | void | |
| 1990/1226 | cacheinit(void) | |
| 1990/1223 | { | |
| 1990/1226 |
| |
| 1991/0110 | int c, i; | |
| 1990/1226 | /* * Initialize cache by clearing the valid bit * (along with the others) in all cache entries */ | |
| 1991/0110 | for(c=0; c<NCONTEXT; c++){ /* necessary? */ putcontext(c); for(i=0; i<0x1000; i++) putw2(CACHETAGS+(i<<4), 0); } putcontext(0); | |
| 1990/1226 | /* * Turn cache on */ | |
| 1991/0109/sys/src/9/ss/mmu.c:260,265 – 1991/0110/sys/src/9/ss/mmu.c:279,285 | ||
| 1990/1223 | KMap *k; | |
| 1990/1226 | int i; | |
| 1990/1223 | ||
| 1991/0110 | print("low pmeg %d high pmeg %d\n", kmapalloc.lowpmeg, TOPPMEG); | |
| 1990/1223 | kmapalloc.free = 0; | |
| 1990/1226 | k = kmapalloc.arena; for(i=0; i<(IOEND-IOSEGM)/BY2PG; i++,k++){ | |
| 1991/0109/sys/src/9/ss/mmu.c:272,277 – 1991/0110/sys/src/9/ss/mmu.c:292,298 | ||
| 1990/1227 | kmappa(ulong pa, ulong flag) | |
| 1990/1223 | { KMap *k; | |
| 1991/0110 | ulong s; | |
| 1990/1223 | lock(&kmapalloc); k = kmapalloc.free; | |
| 1991/0109/sys/src/9/ss/mmu.c:287,293 – 1991/0110/sys/src/9/ss/mmu.c:308,336 | ||
| 1990/1226 | * Must avoid having the same entry in the cache twice, so * must use NOCACHE or else extreme cleverness elsewhere. */ | |
| 1991/0110 | s = splhi(); #ifdef stupid { int i, c, d; c = u->p->pidonmach[m->machno]; /* * Flush old entries from cache */ for(d=0; d<NCONTEXT; d++){ putcontext(d); for(i=0; i<0x100; i+=16) putwD16(k->va+(i<<4), 0); } putcontext(c-1); if(u && u->p) m->pidhere[c] = 1; /* UGH! */ putw4(k->va, PPN(pa)|PTEVALID|PTEKERNEL|PTEWRITE|PTENOCACHE|flag); } #else | |
| 1990/1227 | putpmeg(k->va, PPN(pa)|PTEVALID|PTEKERNEL|PTEWRITE|PTENOCACHE|flag); | |
| 1991/0110 | #endif splx(s); | |
| 1990/1223 | return k; } | |
| 1991/0110/sys/src/9/ss/mmu.c:14,20 – 1991/0111/sys/src/9/ss/mmu.c:14,20 (short | long) | ||
| 1990/1226 | KMap arena[(IOEND-IOSEGM)/BY2PG]; | |
| 1990/1223 | }kmapalloc; | |
| 1991/0110 |
| |
| 1991/0111 | #define NKLUDGE 12 | |
| 1991/0110 | ||
| 1990/1223 | /* | |
| 1990/1226 | * On SPARC, tlbpid i == context i-1 so that 0 means unallocated | |
| 1991/0110/sys/src/9/ss/mmu.c:77,82 – 1991/0111/sys/src/9/ss/mmu.c:77,83 | ||
| 1990/1226 | m->pidproc[i] = p; m->lastpid = i; | |
| 1990/1227 | putcontext(i-1); | |
| 1991/0111 | ||
| 1990/1223 | /* | |
| 1991/0110 | * kludge: each context is allowed NKLUDGE pmegs, NKLUDGE-1 for text & data and 1 for stack | |
| 1990/1223 | */ | |
| 1991/0110/sys/src/9/ss/mmu.c:153,163 – 1991/0111/sys/src/9/ss/mmu.c:154,171 | ||
| 1990/1226 | /* * Invalidate user addresses */ | |
| 1990/1227 |
| |
| 1990/1226 | putsegm(l, INVALIDPMEG); | |
| 1990/1227 | ||
| 1991/0111 | #ifdef doesntwork | |
| 1990/1226 | /* | |
| 1991/0111 | * Invalidate high kernel addresses */ for(l=conf.maxialloc; l<IOSEGM0; l+=BY2SEGM) putsegm(l, INVALIDPMEG); #endif /* | |
| 1990/1226 | * One segment for screen */ putsegm(SCREENSEGM, SCREENPMEG); | |
| 1991/0110/sys/src/9/ss/mmu.c:210,216 – 1991/0111/sys/src/9/ss/mmu.c:218,224 | ||
| 1990/1226 | */ | |
| 1991/0110 | if(tlbvirt>=TSTKTOP || (UZERO+(NKLUDGE-1)*BY2SEGM<=tlbvirt && tlbvirt<(TSTKTOP-BY2SEGM))){ pprint("putmmu %lux", tlbvirt); | |
| 1991/0111 | pexit("Suicide", 1); | |
| 1991/0110 | } | |
| 1990/1226 | putpmeg(tlbvirt, tlbphys); spllo(); | |
| 1991/0110/sys/src/9/ss/mmu.c:309,335 – 1991/0111/sys/src/9/ss/mmu.c:317,323 | ||
| 1990/1226 | * must use NOCACHE or else extreme cleverness elsewhere. */ | |
| 1991/0110 | s = splhi(); | |
| 1990/1227 | putpmeg(k->va, PPN(pa)|PTEVALID|PTEKERNEL|PTEWRITE|PTENOCACHE|flag); | |
| 1991/0110 |
| |
| 1990/1223 | return k; } | |
| 1991/0111/sys/src/9/ss/mmu.c:79,95 – 1991/0112/sys/src/9/ss/mmu.c:79,96 (short | long) | ||
| 1990/1227 | putcontext(i-1); | |
| 1991/0111 | ||
| 1990/1223 | /* | |
| 1991/0110 |
| |
| 1991/0112 | * kludge: each context is allowed NKLUDGE pmegs. * NKLUDGE-1 for text & data and 1 for stack. * initialize by giving just a stack segment. | |
| 1990/1223 | */ | |
| 1991/0112 | i--; /* now i==context */ p->nmmuseg = 0; | |
| 1991/0110 | for(j=0; j<NKLUDGE-1; j++) | |
| 1990/1226 |
| |
| 1991/0110 |
| |
| 1991/0109 |
| |
| 1991/0112 | putsegm(UZERO+j*BY2SEGM, INVALIDPMEG); putsegm(TSTKTOP-BY2SEGM, kmapalloc.lowpmeg+NKLUDGE*i+(NKLUDGE-1)); for(j=0; j<PG2SEGM; j++) | |
| 1990/1226 | putpmeg((TSTKTOP-BY2SEGM)+j*BY2PG, INVALIDPTE); | |
| 1991/0112 | return i+1; | |
| 1990/1226 | } | |
| 1990/1223 | ||
| 1990/1226 | void | |
| 1991/0111/sys/src/9/ss/mmu.c:205,210 – 1991/0112/sys/src/9/ss/mmu.c:206,213 | ||
| 1990/1223 | { | |
| 1990/1226 | short tp; Proc *p; | |
| 1991/0112 | ulong seg, l; int j, k; | |
| 1990/1223 | ||
| 1990/1226 | splhi(); p = u->p; | |
| 1991/0111/sys/src/9/ss/mmu.c:216,225 – 1991/0112/sys/src/9/ss/mmu.c:219,248 | ||
| 1990/1226 | /* * kludge part 2: make sure we've got a valid segment */ | |
| 1991/0110 |
| |
| 1991/0112 | if(TSTKTOP-BY2SEGM<=tlbvirt && tlbvirt<TSTKTOP) /* stack; easy */ goto put; /* UZERO is known to be zero here */ if(tlbvirt < UZERO+p->nmmuseg*BY2SEGM) /* in range; easy */ goto put; seg = tlbvirt/BY2SEGM; if(seg >= (UZERO/BY2SEGM)+(NKLUDGE-1)){ pprint("putmmu %lux\n", tlbvirt); print("putmmu %lux %d %s\n", tlbvirt, seg, p->text); | |
| 1991/0111 | pexit("Suicide", 1); | |
| 1991/0110 | } | |
| 1991/0112 | /* * Prepare mmu up to this address */ tp--; /* now tp==context */ tp = tp*NKLUDGE; l = UZERO+p->nmmuseg*BY2SEGM; for(j=p->nmmuseg; j<=seg; j++){ putsegm(l, kmapalloc.lowpmeg+tp+j); for(k=0; k<PG2SEGM; k++,l+=BY2PG) putpmeg(l, INVALIDPTE); } p->nmmuseg = seg+1; put: | |
| 1990/1226 | putpmeg(tlbvirt, tlbphys); spllo(); | |
| 1990/1223 | } | |
| 1991/0112/sys/src/9/ss/mmu.c:69,82 – 1991/0115/sys/src/9/ss/mmu.c:69,80 (short | long) | ||
| 1991/0110 | } | |
| 1990/1226 | sp = m->pidproc[i]; | |
| 1991/0115 | if(sp) | |
| 1990/1226 | sp->pidonmach[m->machno] = 0; | |
| 1991/0115 | purgepid(i); /* also does putcontext */ | |
| 1991/0110 | pidtime[i] = m->ticks; | |
| 1990/1226 | m->pidproc[i] = p; m->lastpid = i; | |
| 1990/1227 |
| |
| 1991/0111 | ||
| 1990/1223 | /* | |
| 1991/0112 | * kludge: each context is allowed NKLUDGE pmegs. | |
| 1991/0112/sys/src/9/ss/mmu.c:96,102 – 1991/0115/sys/src/9/ss/mmu.c:94,99 | ||
| 1990/1226 | void | |
| 1990/1231 | putcontext(int c) { | |
| 1991/0110 |
| |
| 1990/1231 | putcxreg(c); } | |
| 1991/0112/sys/src/9/ss/mmu.c:115,123 – 1991/0115/sys/src/9/ss/mmu.c:112,117 | ||
| 1991/0110 | void purgepid(int pid) { | |
| 1990/1226 |
| |
| 1991/0110 | flushcontext(); | |
| 1990/1223 | } | |
| 1991/0112/sys/src/9/ss/mmu.c:233,240 – 1991/0115/sys/src/9/ss/mmu.c:227,233 | ||
| 1991/0112 | /* * Prepare mmu up to this address */ | |
| 1991/0115 | tp = (tp-1)*NKLUDGE; /* now tp==base of pmeg area for this proc */ | |
| 1991/0112 | l = UZERO+p->nmmuseg*BY2SEGM; for(j=p->nmmuseg; j<=seg; j++){ putsegm(l, kmapalloc.lowpmeg+tp+j); | |
| 1991/0112/sys/src/9/ss/mmu.c:260,267 – 1991/0115/sys/src/9/ss/mmu.c:253,258 | ||
| 1990/1227 | */ | |
| 1991/0110 | for(i=0; i<0x100; i+=16) putwD16(virt+(i<<4), 0); | |
| 1990/1231 |
| |
| 1990/1227 | putw4(virt, phys); } | |
| 1991/0115/sys/src/9/ss/mmu.c:152,165 – 1991/01151/sys/src/9/ss/mmu.c:152,157 (short | long) | ||
| 1990/1227 | for(l=UZERO; l<(KZERO&VAMASK); l+=BY2SEGM) | |
| 1990/1226 | putsegm(l, INVALIDPMEG); | |
| 1990/1227 | ||
| 1991/0111 |
| |
| 1990/1226 |
| |
| 1991/0111 |
| |
| 1990/1226 | * One segment for screen */ | |
| 1991/01151/sys/src/9/ss/mmu.c:50,55 – 1991/0507/sys/src/9/ss/mmu.c:50,61 (short | long) | ||
| 1990/1223 | u = (User*)USERADDR; | |
| 1990/1226 | } | |
| 1990/1223 | ||
| 1991/0507 | void mmurelease(Proc *p) { memset(p->pidonmach, 0, sizeof p->pidonmach); } | |
| 1990/1226 | /* * Process must be non-interruptible */ | |
| 1991/0507/sys/src/9/ss/mmu.c:22,27 – 1991/0706/sys/src/9/ss/mmu.c:22,29 (short | long) | ||
| 1990/1226 | int newpid(Proc*); void purgepid(int); | |
| 1991/0706 | void flushcontext(void); | |
| 1991/0110 | int pidtime[NTLBPID]; /* should be per m */ | |
| 1990/1226 | /* | |
| 1991/0507/sys/src/9/ss/mmu.c:33,38 – 1991/0706/sys/src/9/ss/mmu.c:35,50 | ||
| 1990/1226 | short tp; ulong tlbphys; | |
| 1990/1223 | ||
| 1991/0706 | if(p->newtlb) { flushcontext(); tp = u->p->pidonmach[m->machno]; if(tp) pidtime[tp] = 0; /* easiest is to forget what pid we had.... */ memset(u->p->pidonmach, 0, sizeof u->p->pidonmach); p->newtlb = 0; } | |
| 1990/1226 | tp = p->pidonmach[m->machno]; if(tp == 0){ tp = newpid(p); | |
| 1991/0507/sys/src/9/ss/mmu.c:194,200 – 1991/0706/sys/src/9/ss/mmu.c:206,212 | ||
| 1990/1223 | } void | |
| 1991/0706 | putmmu(ulong tlbvirt, ulong tlbphys, Page *pg) | |
| 1990/1223 | { | |
| 1990/1226 | short tp; Proc *p; | |
| 1991/0706/sys/src/9/ss/mmu.c:50,56 – 1991/0928/sys/src/9/ss/mmu.c:50,56 (short | long) | ||
| 1990/1226 | tp = newpid(p); p->pidonmach[m->machno] = tp; } | |
| 1990/1223 |
| |
| 1991/0928 | if(p->upage->va != (USERADDR|(p->pid&0xFFFF)) && p->pid != 0) | |
| 1991/0110 | panic("mapstack %s %d %lux 0x%lux 0x%lux", p->text, p->pid, p->upage, p->upage->pa, p->upage->va); | |
| 1990/1226 | tlbphys = PPN(p->upage->pa)|PTEVALID|PTEWRITE|PTEKERNEL|PTEMAINMEM; putcontext(tp-1); | |
| 1991/0928/sys/src/9/ss/mmu.c:23,28 – 1991/1007/sys/src/9/ss/mmu.c:23,29 (short | long) | ||
| 1990/1226 | int newpid(Proc*); void purgepid(int); | |
| 1991/0706 | void flushcontext(void); | |
| 1991/1007 | void putpmegnf(ulong, ulong); | |
| 1991/0706 | ||
| 1991/0110 | int pidtime[NTLBPID]; /* should be per m */ | |
| 1990/1226 | ||
| 1991/0928/sys/src/9/ss/mmu.c:36,47 – 1991/1007/sys/src/9/ss/mmu.c:37,43 | ||
| 1990/1226 | ulong tlbphys; | |
| 1990/1223 | ||
| 1991/0706 | if(p->newtlb) { | |
| 1991/1007 | mmurelease(p); | |
| 1991/0706 | p->newtlb = 0; } | |
| 1991/0928/sys/src/9/ss/mmu.c:55,64 – 1991/1007/sys/src/9/ss/mmu.c:51,60 | ||
| 1990/1226 | tlbphys = PPN(p->upage->pa)|PTEVALID|PTEWRITE|PTEKERNEL|PTEMAINMEM; putcontext(tp-1); | |
| 1990/1227 | /* | |
| 1991/0110 |
| |
| 1991/1007 | * Don't need to flush cache because no other page has been * mapped at USERADDR in this context; can call putpmegnf. | |
| 1990/1227 | */ | |
| 1990/1226 |
| |
| 1991/1007 | putpmegnf(USERADDR, tlbphys); | |
| 1990/1223 | u = (User*)USERADDR; | |
| 1990/1226 | } | |
| 1990/1223 | ||
| 1991/0928/sys/src/9/ss/mmu.c:65,70 – 1991/1007/sys/src/9/ss/mmu.c:61,72 | ||
| 1991/0507 | void mmurelease(Proc *p) { | |
| 1991/1007 | int tp; tp = p->pidonmach[m->machno]; if(tp) pidtime[tp] = 0; /* easiest is to forget what pid we had.... */ | |
| 1991/0507 | memset(p->pidonmach, 0, sizeof p->pidonmach); } | |
| 1991/0928/sys/src/9/ss/mmu.c:80,86 – 1991/1007/sys/src/9/ss/mmu.c:82,88 | ||
| 1990/1226 | ||
| 1991/0110 | t = ~0; i = 1+((m->ticks)&(NCONTEXT-1)); /* random guess */ | |
| 1991/1007 | for(j=1; t && j<NTLBPID; j++) | |
| 1991/0110 | if(pidtime[j] < t){ i = j; t = pidtime[j]; | |
| 1991/0928/sys/src/9/ss/mmu.c:105,111 – 1991/1007/sys/src/9/ss/mmu.c:107,113 | ||
| 1991/0112 | putsegm(UZERO+j*BY2SEGM, INVALIDPMEG); putsegm(TSTKTOP-BY2SEGM, kmapalloc.lowpmeg+NKLUDGE*i+(NKLUDGE-1)); for(j=0; j<PG2SEGM; j++) | |
| 1990/1226 |
| |
| 1991/1007 | putpmegnf((TSTKTOP-BY2SEGM)+j*BY2PG, INVALIDPTE); | |
| 1991/0112 | return i+1; | |
| 1990/1226 | } | |
| 1990/1223 | ||
| 1991/0928/sys/src/9/ss/mmu.c:242,248 – 1991/1007/sys/src/9/ss/mmu.c:244,250 | ||
| 1991/0112 | for(j=p->nmmuseg; j<=seg; j++){ putsegm(l, kmapalloc.lowpmeg+tp+j); for(k=0; k<PG2SEGM; k++,l+=BY2PG) | |
| 1991/1007 | putpmegnf(l, INVALIDPTE); | |
| 1991/0112 | } p->nmmuseg = seg+1; put: | |
| 1991/0928/sys/src/9/ss/mmu.c:267,284 – 1991/1007/sys/src/9/ss/mmu.c:269,290 | ||
| 1990/1227 | } void | |
| 1991/1007 | putpmegnf(ulong virt, ulong phys) /* no need to flush */ { virt &= VAMASK; virt &= ~(BY2PG-1); putw4(virt, phys); } int nflushmmu; void | |
| 1990/1223 | flushmmu(void) { | |
| 1991/0110 | int tp; | |
| 1991/1007 | nflushmmu++; | |
| 1990/1226 | splhi(); | |
| 1991/0110 |
| |
| 1990/1226 |
| |
| 1991/1007 | u->p->newtlb = 1; | |
| 1990/1226 | mapstack(u->p); spllo(); | |
| 1990/1223 | } | |
| 1991/1007/sys/src/9/ss/mmu.c:341,360 – 1992/0101/sys/src/9/ss/mmu.c:341,369 (short | long) | ||
| 1990/1223 | kmapalloc.free = k->next; unlock(&kmapalloc); | |
| 1990/1227 | k->pa = pa; | |
| 1992/0101 | s = splhi(); putpmeg(k->va, PPN(pa)|PTEVALID|PTEKERNEL|PTEWRITE|flag); splx(s); return k; } KMap* kmap(Page *pg) { | |
| 1990/1226 | /* * Cache is virtual and a pain to deal with. * Must avoid having the same entry in the cache twice, so * must use NOCACHE or else extreme cleverness elsewhere. */ | |
| 1991/0110 |
| |
| 1990/1227 |
| |
| 1991/0110 |
| |
| 1990/1223 |
| |
| 1992/0101 | return kmappa(pg->pa, PTEMAINMEM|PTENOCACHE); | |
| 1990/1223 | } | |
| 1990/1226 | KMap* | |
| 1992/0101 | kmapperm(Page *pg) | |
| 1990/1226 | { | |
| 1992/0101 | /* * Here we know it's a permanent entry and can be cached. */ | |
| 1990/1227 | return kmappa(pg->pa, PTEMAINMEM); | |
| 1990/1226 | } | |
| 1992/0101/sys/src/9/ss/mmu.c:1,5 – 1992/0321/sys/src/9/ss/mmu.c:1,5 (short | long) | ||
| 1990/1223 | #include "u.h" | |
| 1992/0321 | #include "../port/lib.h" | |
| 1990/1223 | #include "mem.h" #include "dat.h" #include "fns.h" | |
| 1992/0321/sys/src/9/ss/mmu.c:136,160 – 1992/0619/sys/src/9/ss/mmu.c:136,166 (short | long) | ||
| 1991/0110 | flushcontext(); | |
| 1990/1223 | } | |
| 1990/1226 | ||
| 1990/1223 | void | |
| 1990/1226 | mmuinit(void) | |
| 1990/1223 | { | |
| 1990/1226 |
| |
| 1992/0619 | ulong ktop, l, i, j, c, pte; | |
| 1990/1226 | /* | |
| 1992/0619 | * TEMP: just map the first 4M of bank 0 for the kernel - philw */ ktop = 4*1024*1024; /* | |
| 1990/1226 | * First map lots of memory as kernel addressable in all contexts */ i = 0; /* used */ for(c=0; c<NCONTEXT; c++) | |
| 1992/0619 | for(i=0; i < ktop/BY2SEGM; i++) | |
| 1990/1226 | putcxsegm(c, KZERO+i*BY2SEGM, i); | |
| 1992/0619 | ||
| 1990/1226 | kmapalloc.lowpmeg = i; | |
| 1992/0619 | ||
| 1990/1226 | /* * Make sure cache is turned on for kernel */ pte = PTEVALID|PTEWRITE|PTEKERNEL|PTEMAINMEM; | |
| 1992/0619 | ktop /= BY2PG; for(i=0; i < ktop; i++) | |
| 1990/1226 | putpmeg(KZERO+i*BY2PG, pte+i); /* | |
| 1992/0321/sys/src/9/ss/mmu.c:163,168 – 1992/0619/sys/src/9/ss/mmu.c:169,175 | ||
| 1990/1226 | putsegm(INVALIDSEGM, INVALIDPMEG); for(i=0; i<PG2SEGM; i++) putpmeg(INVALIDSEGM+i*BY2PG, INVALIDPTE); | |
| 1992/0619 | ||
| 1990/1226 | for(c=0; c<NCONTEXT; c++){ putcontext(c); putsegm(INVALIDSEGM, INVALIDPMEG); | |
| 1992/0321/sys/src/9/ss/mmu.c:317,323 – 1992/0619/sys/src/9/ss/mmu.c:324,331 | ||
| 1990/1223 | KMap *k; | |
| 1990/1226 | int i; | |
| 1990/1223 | ||
| 1991/0110 |
| |
| 1992/0619 | print("low pmeg %d high pmeg %d\n", kmapalloc.lowpmeg, TOPPMEG); | |
| 1990/1223 | kmapalloc.free = 0; | |
| 1990/1226 | k = kmapalloc.arena; for(i=0; i<(IOEND-IOSEGM)/BY2PG; i++,k++){ | |
| 1992/0619/sys/src/9/ss/mmu.c:76,82 – 1992/0711/sys/src/9/ss/mmu.c:76,82 (short | long) | ||
| 1990/1226 | int newpid(Proc *p) { | |
| 1991/0109 |
| |
| 1992/0711 | int i, j; | |
| 1991/0110 | ulong t; | |
| 1990/1226 | Proc *sp; | |
| 1992/0619/sys/src/9/ss/mmu.c:222,227 – 1992/0711/sys/src/9/ss/mmu.c:222,228 | ||
| 1991/0112 | ulong seg, l; int j, k; | |
| 1990/1223 | ||
| 1992/0711 | USED(pg); | |
| 1990/1226 | splhi(); p = u->p; tp = p->pidonmach[m->machno]; | |
| 1992/0619/sys/src/9/ss/mmu.c:263,269 – 1992/0711/sys/src/9/ss/mmu.c:264,269 | ||
| 1990/1227 | putpmeg(ulong virt, ulong phys) { int i; | |
| 1990/1231 |
| |
| 1990/1227 | virt &= VAMASK; virt &= ~(BY2PG-1); | |
| 1992/0619/sys/src/9/ss/mmu.c:287,294 – 1992/0711/sys/src/9/ss/mmu.c:287,292 | ||
| 1991/1007 | void | |
| 1990/1223 | flushmmu(void) { | |
| 1991/0110 |
| |
| 1991/1007 | nflushmmu++; | |
| 1990/1226 | splhi(); | |
| 1991/1007 | u->p->newtlb = 1; | |
| 1992/0619/sys/src/9/ss/mmu.c:378,386 – 1992/0711/sys/src/9/ss/mmu.c:376,381 | ||
| 1990/1223 | void kunmap(KMap *k) { | |
| 1990/1226 |
| |
| 1990/1223 | k->pa = 0; lock(&kmapalloc); k->next = kmapalloc.free; | |
| 1992/0711/sys/src/9/ss/mmu.c:142,150 – 1992/0722/sys/src/9/ss/mmu.c:142,150 (short | long) | ||
| 1992/0619 | ulong ktop, l, i, j, c, pte; | |
| 1990/1226 | /* | |
| 1992/0619 |
| |
| 1992/0722 | * TEMP: just map the first 8M of bank 0 for the kernel - philw | |
| 1992/0619 | */ | |
| 1992/0722 | ktop = 8*1024*1024; | |
| 1992/0619 | /* | |
| 1990/1226 | * First map lots of memory as kernel addressable in all contexts */ | |
| 1992/0711/sys/src/9/ss/mmu.c:270,277 – 1992/0722/sys/src/9/ss/mmu.c:270,277 | ||
| 1990/1227 | /* * Flush old entries from cache */ | |
| 1991/0110 |
| |
| 1992/0722 | for(i=0; i<VACSIZE; i+=16*VACLINESZ) putwD16(virt+i, 0); | |
| 1990/1227 | putw4(virt, phys); } | |
| 1992/0722/sys/src/9/ss/mmu.c:125,132 – 1992/0724/sys/src/9/ss/mmu.c:125,132 (short | long) | ||
| 1991/0110 | /* * Clear context from cache */ | |
| 1992/0724 | for(i=0; i<VACSIZE; i+=16*VACLINESZ) putwE16(i, 0); | |
| 1991/0110 | } void | |
| 1992/0722/sys/src/9/ss/mmu.c:142,150 – 1992/0724/sys/src/9/ss/mmu.c:142,150 | ||
| 1992/0619 | ulong ktop, l, i, j, c, pte; | |
| 1990/1226 | /* | |
| 1992/0722 |
| |
| 1992/0724 | * TEMP: just map the first 4M of bank 0 for the kernel - philw | |
| 1992/0619 | */ | |
| 1992/0722 |
| |
| 1992/0724 | ktop = 4*1024*1024; | |
| 1992/0619 | /* | |
| 1990/1226 | * First map lots of memory as kernel addressable in all contexts */ | |
| 1992/0722/sys/src/9/ss/mmu.c:270,276 – 1992/0724/sys/src/9/ss/mmu.c:270,276 | ||
| 1990/1227 | /* * Flush old entries from cache */ | |
| 1992/0722 |
| |
| 1992/0724 | for(i=0; i<BY2PG; i+=16*VACLINESZ) | |
| 1992/0722 | putwD16(virt+i, 0); | |
| 1990/1227 | putw4(virt, phys); } | |
| 1992/0722/sys/src/9/ss/mmu.c:305,312 – 1992/0724/sys/src/9/ss/mmu.c:305,312 | ||
| 1990/1226 | */ | |
| 1991/0110 | for(c=0; c<NCONTEXT; c++){ /* necessary? */ putcontext(c); | |
| 1992/0724 | for(i=0; i<VACSIZE; i+=VACLINESZ) putw2(CACHETAGS+i, 0); | |
| 1991/0110 | } putcontext(0); | |
| 1992/0724/sys/src/9/ss/mmu.c:5,20 – 1992/0806/sys/src/9/ss/mmu.c:5,33 (short | long) | ||
| 1990/1223 | #include "fns.h" | |
| 1990/1226 | #include "io.h" | |
| 1990/1223 | ||
| 1992/0806 | void compile(void); #define NCODE 1024 static ulong code[NCODE]; static ulong *codep = code; void (*putcontext)(ulong); void (*putenab)(ulong); ulong (*getenab)(void); void (*putpmegspace)(ulong, ulong); void (*putsysspace)(ulong, ulong); ulong (*getsysspace)(ulong); ulong (*flushcx)(ulong); ulong (*flushpg)(ulong); | |
| 1990/1223 | struct { Lock; | |
| 1990/1226 | int lowpmeg; | |
| 1990/1223 | KMap *free; | |
| 1990/1226 | KMap arena[(IOEND-IOSEGM)/BY2PG]; | |
| 1990/1223 | }kmapalloc; | |
| 1991/0111 |
| |
| 1992/0806 | #define NKLUDGE 11 /* <= ((TOPPMEG-kmap.lowpmeg)/NCONTEXT) */ | |
| 1991/0110 | ||
| 1990/1223 | /* | |
| 1990/1226 | * On SPARC, tlbpid i == context i-1 so that 0 means unallocated | |
| 1992/0724/sys/src/9/ss/mmu.c:112,132 – 1992/0806/sys/src/9/ss/mmu.c:125,138 | ||
| 1990/1226 | } | |
| 1990/1223 | ||
| 1990/1226 | void | |
| 1990/1231 |
| |
| 1991/0110 | flushcontext(void) | |
| 1990/1226 | { | |
| 1991/0110 |
| |
| 1992/0806 | ulong a; | |
| 1990/1223 | ||
| 1991/0110 |
| |
| 1992/0724 |
| |
| 1992/0806 | a = 0; do a = flushcx(a); while(a < VACSIZE); | |
| 1991/0110 | } void | |
| 1992/0724/sys/src/9/ss/mmu.c:141,150 – 1992/0806/sys/src/9/ss/mmu.c:147,157 | ||
| 1990/1223 | { | |
| 1992/0619 | ulong ktop, l, i, j, c, pte; | |
| 1990/1226 | ||
| 1992/0806 | compile(); | |
| 1990/1226 | /* | |
| 1992/0724 |
| |
| 1992/0806 | * xinit sets conf.npage0 to maximum kernel address | |
| 1992/0619 | */ | |
| 1992/0724 |
| |
| 1992/0806 | ktop = PADDR(conf.npage0); | |
| 1992/0619 | /* | |
| 1990/1226 | * First map lots of memory as kernel addressable in all contexts */ | |
| 1992/0724/sys/src/9/ss/mmu.c:263,278 – 1992/0806/sys/src/9/ss/mmu.c:270,295 | ||
| 1990/1223 | void | |
| 1990/1227 | putpmeg(ulong virt, ulong phys) { | |
| 1992/0806 | ulong a, evirt; | |
| 1990/1227 | virt &= VAMASK; virt &= ~(BY2PG-1); | |
| 1992/0806 | #ifdef asdf if(conf.ss2) putw6(virt, 0); else for(i=0; i<BY2PG; i+=16*VACLINESZ) putwD16(virt+i, 0); #endif | |
| 1990/1227 | /* * Flush old entries from cache */ | |
| 1992/0724 |
| |
| 1992/0722 |
| |
| 1990/1227 |
| |
| 1992/0806 | a = virt; evirt = virt+BY2PG; do a = flushpg(a); while(a < evirt); putpmegspace(virt, phys); | |
| 1990/1227 | } void | |
| 1992/0724/sys/src/9/ss/mmu.c:280,293 – 1992/0806/sys/src/9/ss/mmu.c:297,308 | ||
| 1991/1007 | { virt &= VAMASK; virt &= ~(BY2PG-1); | |
| 1992/0806 | putpmegspace(virt, phys); | |
| 1991/1007 | } | |
| 1990/1223 | flushmmu(void) { | |
| 1991/1007 |
| |
| 1990/1226 | splhi(); | |
| 1991/1007 | u->p->newtlb = 1; | |
| 1990/1226 | mapstack(u->p); | |
| 1992/0724/sys/src/9/ss/mmu.c:297,319 – 1992/0806/sys/src/9/ss/mmu.c:312,331 | ||
| 1990/1223 | void | |
| 1990/1226 | cacheinit(void) | |
| 1990/1223 | { | |
| 1991/0110 |
| |
| 1992/0806 | int i; | |
| 1990/1226 | ||
| 1992/0806 | putcontext(0); | |
| 1990/1226 | /* * Initialize cache by clearing the valid bit * (along with the others) in all cache entries */ | |
| 1991/0110 |
| |
| 1992/0724 |
| |
| 1991/0110 |
| |
| 1992/0806 | for(i=0; i<VACSIZE; i+=VACLINESZ) putsysspace(CACHETAGS+i, 0); | |
| 1991/0110 | ||
| 1990/1226 | /* * Turn cache on */ | |
| 1992/0806 | putenab(getenab()|ENABCACHE); /**/ | |
| 1990/1223 | } void | |
| 1992/0724/sys/src/9/ss/mmu.c:322,329 – 1992/0806/sys/src/9/ss/mmu.c:334,339 | ||
| 1990/1223 | KMap *k; | |
| 1990/1226 | int i; | |
| 1990/1223 | ||
| 1992/0619 |
| |
| 1990/1223 | kmapalloc.free = 0; | |
| 1990/1226 | k = kmapalloc.arena; for(i=0; i<(IOEND-IOSEGM)/BY2PG; i++,k++){ | |
| 1992/0724/sys/src/9/ss/mmu.c:388,391 – 1992/0806/sys/src/9/ss/mmu.c:398,558 | ||
| 1990/1223 | invalidateu(void) { | |
| 1990/1226 | putpmeg(USERADDR, INVALIDPTE); | |
| 1992/0806 | } /* * Compile MMU code for this machine, since the MMU can only * be addressed from parameterless machine instructions. * What's wrong with MMUs you can talk to from C? */ /* op3 */ #define LD 0 #define ADD 0 #define OR 2 #define LDA 16 #define LDUBA 17 #define STA 20 #define STBA 21 #define JMPL 56 /* op2 */ #define SETHI 4 void *compileconst(int, ulong, int); /* value to/from constant address */ void *compileldaddr(int, int); /* value from parameter address */ void *compilestaddr(int, int); /* value to parameter address */ void *compile16(ulong, int); /* 16 stores of zero */ void *compile1(ulong, int); /* 1 stores of zero */ #define ret() {*codep++ = (2<<30)|(0<<25)|(JMPL<<19)|(15<<14)|(1<<13)|8;} #define nop() {*codep++ = (0<<30)|(0<<25)|(SETHI<<22)|(0>>10);} void compile(void) { putcontext = compileconst(STBA, CONTEXT, 2); getenab = compileconst(LDUBA, ENAB, 2); putenab = compileconst(STBA, ENAB, 2); putpmegspace = compilestaddr(STA, 4); putsysspace = compilestaddr(STA, 2); getsysspace = compileldaddr(LDA, 2); if(conf.ss2){ flushpg = compile1(BY2PG, 6); flushcx = compile16(VACLINESZ, 7); }else{ flushpg = compile16(VACLINESZ, 0xD); flushcx = compile16(VACLINESZ, 0xE); } } void parameter(int param, int reg) { param += 1; /* 0th parameter is 1st word on stack */ param *= 4; /* LD #param(R1), Rreg */ *codep++ = (3<<30)|(reg<<25)|(LD<<19)|(1<<14)|(1<<13)|param; } void constant(ulong c, int reg) { *codep++ = (0<<30)|(reg<<25)|(SETHI<<22)|(c>>10); if(c & 0x3FF) *codep++ = (2<<30)|(reg<<25)|(OR<<19)|(reg<<14)|(1<<13)|(c&0x3FF); } /* * void f(int c) { *(word*,asi)addr = c } for stores * ulong f(void) { return *(word*,asi)addr } for loads */ void* compileconst(int op3, ulong addr, int asi) { void *a; a = codep; constant(addr, 8); /* MOVW $CONSTANT, R8 */ ret(); /* JMPL 8(R15), R0 */ /* in delay slot st or ld R7, (R8+R0, asi) */ *codep++ = (3<<30)|(7<<25)|(op3<<19)|(8<<14)|(asi<<5); return a; } /* * ulong f(ulong addr) { return *(word*,asi)addr } */ void* compileldaddr(int op3, int asi) { void *a; a = codep; ret(); /* JMPL 8(R15), R0 */ /* in delay slot ld (R7+R0, asi), R7 */ *codep++ = (3<<30)|(7<<25)|(op3<<19)|(7<<14)|(asi<<5); return a; } /* * void f(ulong addr, int c) { *(word*,asi)addr = c } */ void* compilestaddr(int op3, int asi) { void *a; a = codep; parameter(1, 8); /* MOVW (4*1)(FP), R8 */ ret(); /* JMPL 8(R15), R0 */ /* in delay slot st R8, (R7+R0, asi) */ *codep++ = (3<<30)|(8<<25)|(op3<<19)|(7<<14)|(asi<<5); return a; } /* * ulong f(ulong addr) { *addr=0; addr+=offset; return addr} * offset can be anything */ void* compile1(ulong offset, int asi) { void *a; a = codep; /* ST R0, (R7+R0, asi) */ *codep++ = (3<<30)|(0<<25)|(STA<<19)|(7<<14)|(asi<<5); if(offset < (1<<12)){ ret(); /* JMPL 8(R15), R0 */ /* in delay slot ADD $offset, R7 */ *codep++ = (2<<30)|(7<<25)|(ADD<<19)|(7<<14)|(1<<13)|offset; }else{ constant(offset, 8); ret(); /* JMPL 8(R15), R0 */ /* in delay slot ADD R8, R7 */ *codep++ = (2<<30)|(7<<25)|(ADD<<19)|(7<<14)|(0<<13)|8; } return a; } /* * ulong f(ulong addr) { for(i=0;i<16;i++) {*addr=0; addr+=offset}; return addr} * offset must be less than 1<<12 */ void* compile16(ulong offset, int asi) { void *a; int i; a = codep; for(i=0; i<16; i++){ /* ST R0, (R7+R0, asi) */ *codep++ = (3<<30)|(0<<25)|(STA<<19)|(7<<14)|(asi<<5); /* ADD $offset, R7 */ *codep++ = (2<<30)|(7<<25)|(ADD<<19)|(7<<14)|(1<<13)|offset; } ret(); /* JMPL 8(R15), R0 */ nop(); return a; | |
| 1990/1223 | } | |
| 1992/0806/sys/src/9/ss/mmu.c:89,101 – 1992/0807/sys/src/9/ss/mmu.c:89,103 (short | long) | ||
|
Created.
rsc Fri Mar 4 12:44:25 2005 | ||
| 1990/1226 | int newpid(Proc *p) { | |
| 1992/0711 |
| |
| 1992/0807 | int i, j, nc; | |
| 1991/0110 | ulong t; | |
| 1990/1226 | Proc *sp; | |
| 1991/0110 | t = ~0; | |
| 1991/1007 |
| |
| 1992/0807 | nc = conf.ncontext; i = 1+((m->ticks)&(nc-1)); /* random guess */ nc++; for(j=1; t && j<nc; j++) | |
| 1991/0110 | if(pidtime[j] < t){ i = j; t = pidtime[j]; | |
| 1992/0806/sys/src/9/ss/mmu.c:132,138 – 1992/0807/sys/src/9/ss/mmu.c:134,140 | ||
| 1992/0806 | a = 0; do a = flushcx(a); | |
| 1992/0807 | while(a < conf.vacsize); | |
| 1991/0110 | } void | |
| 1992/0806/sys/src/9/ss/mmu.c:156,162 – 1992/0807/sys/src/9/ss/mmu.c:158,164 | ||
| 1990/1226 | * First map lots of memory as kernel addressable in all contexts */ i = 0; /* used */ | |
| 1992/0807 | for(c=0; c<conf.ncontext; c++) | |
| 1992/0619 | for(i=0; i < ktop/BY2SEGM; i++) | |
| 1990/1226 | putcxsegm(c, KZERO+i*BY2SEGM, i); | |
| 1992/0619 | ||
| 1992/0806/sys/src/9/ss/mmu.c:177,183 – 1992/0807/sys/src/9/ss/mmu.c:179,185 | ||
| 1990/1226 | for(i=0; i<PG2SEGM; i++) putpmeg(INVALIDSEGM+i*BY2PG, INVALIDPTE); | |
| 1992/0619 | ||
| 1990/1226 |
| |
| 1992/0807 | for(c=0; c<conf.ncontext; c++){ | |
| 1990/1226 | putcontext(c); putsegm(INVALIDSEGM, INVALIDPMEG); /* | |
| 1992/0806/sys/src/9/ss/mmu.c:274,286 – 1992/0807/sys/src/9/ss/mmu.c:276,281 | ||
| 1990/1227 | virt &= VAMASK; virt &= ~(BY2PG-1); | |
| 1992/0806 |
| |
| 1990/1227 | /* * Flush old entries from cache */ | |
| 1992/0806/sys/src/9/ss/mmu.c:319,325 – 1992/0807/sys/src/9/ss/mmu.c:314,320 | ||
| 1990/1226 | * Initialize cache by clearing the valid bit * (along with the others) in all cache entries */ | |
| 1992/0806 |
| |
| 1992/0807 | for(i=0; i<conf.vacsize; i+=conf.vaclinesize) | |
| 1992/0806 | putsysspace(CACHETAGS+i, 0); | |
| 1991/0110 | ||
| 1990/1226 | /* | |
| 1992/0806/sys/src/9/ss/mmu.c:438,447 – 1992/0807/sys/src/9/ss/mmu.c:433,442 | ||
| 1992/0806 | getsysspace = compileldaddr(LDA, 2); if(conf.ss2){ flushpg = compile1(BY2PG, 6); | |
| 1992/0807 | flushcx = compile16(conf.vaclinesize, 7); | |
| 1992/0806 | }else{ | |
| 1992/0807 | flushpg = compile16(conf.vaclinesize, 0xD); flushcx = compile16(conf.vaclinesize, 0xE); | |
| 1992/0806 | } } | |
| 1992/0807/sys/src/9/ss/mmu.c:24,33 – 1992/0812/sys/src/9/ss/mmu.c:24,33 (short | long) | ||
| 1990/1223 | Lock; | |
| 1990/1226 | int lowpmeg; | |
| 1990/1223 | KMap *free; | |
| 1990/1226 |
| |
| 1992/0812 | KMap arena[(IOEND-IOSEGM0)/BY2PG]; | |
| 1990/1223 | }kmapalloc; | |
| 1992/0806 |
| |
| 1992/0812 | int NKLUDGE; | |
| 1991/0110 | ||
| 1990/1223 | /* | |
| 1990/1226 | * On SPARC, tlbpid i == context i-1 so that 0 means unallocated | |
| 1992/0807/sys/src/9/ss/mmu.c:163,168 – 1992/0812/sys/src/9/ss/mmu.c:163,170 | ||
| 1990/1226 | putcxsegm(c, KZERO+i*BY2SEGM, i); | |
| 1992/0619 | ||
| 1990/1226 | kmapalloc.lowpmeg = i; | |
| 1992/0812 | if(PADDR(ktop) & (BY2SEGM-1)) kmapalloc.lowpmeg++; | |
| 1992/0619 | ||
| 1990/1226 | /* * Make sure cache is turned on for kernel | |
| 1992/0807/sys/src/9/ss/mmu.c:189,208 – 1992/0812/sys/src/9/ss/mmu.c:191,200 | ||
| 1990/1226 | putsegm(l, INVALIDPMEG); | |
| 1990/1227 | ||
| 1991/0111 | /* | |
| 1990/1226 |
| |
| 1992/0812 | * Map ROM | |
| 1990/1226 | */ | |
| 1992/0812 | putsegm(ROMSEGM, ROMPMEG); | |
| 1990/1226 | if(c == 0){ | |
| 1992/0807/sys/src/9/ss/mmu.c:211,219 – 1992/0812/sys/src/9/ss/mmu.c:203,211 | ||
| 1990/1226 | putpmeg(IOSEGM0+i*BY2PG, INVALIDPTE); } /* | |
| 1992/0812 | * Segments for IO and kmap | |
| 1990/1226 | */ | |
| 1992/0812 | for(j=0; j<NIOSEGM; j++){ | |
| 1990/1226 | putsegm(IOSEGM0+j*BY2SEGM, IOPMEG0+j); if(c == 0) for(i=0; i<PG2SEGM; i++) | |
| 1992/0807/sys/src/9/ss/mmu.c:221,226 – 1992/0812/sys/src/9/ss/mmu.c:213,220 | ||
| 1990/1226 | } } putcontext(0); | |
| 1992/0812 | NKLUDGE = ((TOPPMEG-kmapalloc.lowpmeg)/conf.ncontext); if(NKLUDGE>11)NKLUDGE=11; | |
| 1990/1223 | } void | |
| 1992/0807/sys/src/9/ss/mmu.c:331,338 – 1992/0812/sys/src/9/ss/mmu.c:325,332 | ||
| 1990/1223 | kmapalloc.free = 0; | |
| 1990/1226 | k = kmapalloc.arena; | |
| 1992/0812 | for(i=0; i<(IOEND-IOSEGM0)/BY2PG; i++,k++){ k->va = IOSEGM0+i*BY2PG; | |
| 1990/1223 | kunmap(k); } } | |
| 1992/0807/sys/src/9/ss/mmu.c:356,361 – 1992/0812/sys/src/9/ss/mmu.c:350,376 | ||
| 1992/0101 | putpmeg(k->va, PPN(pa)|PTEVALID|PTEKERNEL|PTEWRITE|flag); splx(s); return k; | |
| 1992/0812 | } ulong kmapregion(ulong pa, ulong n, ulong flag) { KMap *k; ulong va; int i, j; /* * kmap's are initially in reverse order so rearrange them. */ i = (n+(BY2PG-1))/BY2PG; va = 0; for(j=i-1; j>=0; j--){ k = kmappa(pa+j*BY2PG, flag); if(va && va != k->va+BY2PG) systemreset(); va = k->va; } return va; | |
| 1992/0101 | } KMap* | |
| 1992/0812/sys/src/9/ss/mmu.c:163,169 – 1992/0813/sys/src/9/ss/mmu.c:163,169 (short | long) | ||
| 1990/1226 | putcxsegm(c, KZERO+i*BY2SEGM, i); | |
| 1992/0619 | ||
| 1990/1226 | kmapalloc.lowpmeg = i; | |
| 1992/0812 |
| |
| 1992/0813 | if(ktop & (BY2SEGM-1)) | |
| 1992/0812 | kmapalloc.lowpmeg++; | |
| 1992/0619 | ||
| 1990/1226 | /* | |
| 1992/0812/sys/src/9/ss/mmu.c:196,206 – 1992/0813/sys/src/9/ss/mmu.c:196,206 | ||
| 1992/0812 | putsegm(ROMSEGM, ROMPMEG); | |
| 1990/1226 | if(c == 0){ pte = PTEVALID|PTEKERNEL|PTENOCACHE| | |
| 1992/0813 | PTEIO|PPN(EPROM); | |
| 1990/1226 | for(i=0; i<PG2ROM; i++) | |
| 1992/0813 | putpmeg(ROMSEGM+i*BY2PG, pte+i); | |
| 1990/1226 | for(; i<PG2SEGM; i++) | |
| 1992/0813 | putpmeg(ROMSEGM+i*BY2PG, INVALIDPTE); | |
| 1990/1226 | } /* | |
| 1992/0812 | * Segments for IO and kmap | |
| 1992/0812/sys/src/9/ss/mmu.c:214,220 – 1992/0813/sys/src/9/ss/mmu.c:214,219 | ||
| 1990/1226 | } putcontext(0); | |
| 1992/0812 | NKLUDGE = ((TOPPMEG-kmapalloc.lowpmeg)/conf.ncontext); | |
| 1990/1223 | } void | |
| 1992/0813/sys/src/9/ss/mmu.c:1,331 – 1992/0911/sys/src/9/ss/mmu.c:1,569 (short | long) | ||
| 1990/1223 |
| |
| 1992/0321 |
| |
| 1990/1223 |
| |
| 1990/1226 |
| |
| 1992/0911 | #include "u.h" #include "../port/lib.h" #include "mem.h" #include "dat.h" #include "fns.h" #include "io.h" | |
| 1990/1223 | ||
| 1992/0806 |
| |
| 1992/0911 | #define SERIALPORT 0xF0000000 /* MMU bypass */ | |
| 1992/0806 |
| |
| 1992/0911 | static int rawputc(int c) { if(c == '\n') rawputc('\r'); while((getsysspaceb(SERIALPORT+4) & (1<<2)) == 0) delay(10); putsysspaceb(SERIALPORT+6, c); if(c == '\n') delay(20); return c; } | |
| 1992/0806 | ||
| 1990/1223 |
| |
| 1992/0911 | void rawputs(char *s) | |
| 1990/1223 | { | |
| 1990/1226 |
| |
| 1990/1223 |
| |
| 1992/0812 |
| |
| 1990/1223 |
| |
| 1992/0911 | while(*s) rawputc(*s++); } | |
| 1990/1223 | ||
| 1992/0812 |
| |
| 1992/0911 | void rawprint(char *fmt, ...) { char buf[PRINTSIZE]; | |
| 1991/0110 | ||
| 1992/0911 | doprint(buf, buf+sizeof(buf), fmt, (&fmt+1)); rawputs(buf); } static void rawpanic(char *fmt, ...) { char buf[PRINTSIZE]; int s; s = splhi(); doprint(buf, buf+sizeof(buf), fmt, (&fmt+1)); rawputs("rawpanic: "); rawputs(buf); systemreset(); splx(s); } | |
| 1990/1223 | /* | |
| 1990/1226 |
| |
| 1992/0911 | * WARNING: Even though all MMU data is in the mach structure or * pointed to by it, this code will not work on a multi-processor * without modification. | |
| 1990/1226 | */ | |
| 1992/0911 | /* * doubly linked list for LRU algorithm */ struct List { List *prev; /* less recently used */ List *next; /* more recently used */ }; | |
| 1990/1226 |
| |
| 1991/0706 |
| |
| 1991/1007 |
| |
| 1992/0911 | /* * a Sparc context description */ struct Ctx { List; /* MUST BE FIRST IN STRUCTURE!! */ | |
| 1991/0706 | ||
| 1991/0110 |
| |
| 1992/0911 | Proc *proc; /* process that owns this context */ Pmeg *pmeg; /* list of pmeg's used by this context */ ushort index; /* which context this is */ }; | |
| 1990/1226 | /* | |
| 1990/1223 |
| |
| 1992/0911 | * a Sparc PMEG description | |
| 1990/1223 | */ | |
| 1992/0911 | struct Pmeg | |
| 1990/1223 | { | |
| 1990/1226 |
| |
| 1992/0911 | List; /* MUST BE FIRST IN STRUCTURE!! */ | |
| 1990/1223 | ||
| 1991/0706 |
| |
| 1991/1007 |
| |
| 1991/0706 |
| |
| 1992/0911 | ulong lo; /* low water mark of used entries */ ulong hi; /* high water mark of used entries */ ushort index; /* which Pmeg this is */ ulong virt; /* virtual address this Pmeg represents */ Ctx *ctx; /* context Pmeg belongs to */ Pmeg *cnext; /* next pmeg used in same context */ }; #define HOWMANY(x, y) (((x)+((y)-1))/(y)) #define ROUNDUP(x, y) (HOWMANY((x), (y))*(y)) static Pmeg* allocpmeg(ulong); static void freepmeg(Pmeg*, int); static Ctx* allocctx(Proc*); static void freectx(Ctx*, int); static void putpme(ulong, ulong, int); static void mklast(List**, List*); static void mkfirst(List**, List*); static void remove(List**, List*); static void add(List**, List*); static void flushpage(ulong); static void putctx(Ctx*); /* * move to end of use list */ static void mklast(List **list, List *entry) { List *first; first = *list; if(entry == first){ *list = first->next; return; | |
| 1991/0706 | } | |
| 1990/1226 |
| |
| 1992/0911 | /* remove from list */ entry->prev->next = entry->next; entry->next->prev = entry->prev; /* chain back in */ entry->prev = first->prev; entry->next = first; first->prev->next = entry; first->prev = entry; } /* * move to front of use list */ static void mkfirst(List **list, List *entry) { List *first; first = *list; if(entry == first) return; /* already at front */ /* unchain */ entry->prev->next = entry->next; entry->next->prev = entry->prev; /* chain back in */ entry->prev = first->prev; entry->next = first; first->prev->next = entry; first->prev = entry; *list = entry; } /* * remove from list */ static void remove(List **list, List *entry) { if(*list == entry) *list = entry->next; entry->prev->next = entry->next; entry->next->prev = entry->prev; } /* * add to list */ static void add(List **list, List *entry) { List *first; first = *list; if(first == 0){ entry->prev = entry; entry->next = entry; } else { entry->prev = first->prev; entry->next = first; first->prev->next = entry; first->prev = entry; | |
| 1990/1226 | } | |
| 1991/0928 |
| |
| 1991/0110 |
| |
| 1990/1226 |
| |
| 1990/1227 |
| |
| 1991/1007 |
| |
| 1990/1227 |
| |
| 1991/1007 |
| |
| 1990/1223 |
| |
| 1992/0911 | *list = entry; | |
| 1990/1226 | } | |
| 1990/1223 | ||
| 1991/0507 |
| |
| 1992/0911 | /* * add a pmeg to the current context for the given address */ static Pmeg* allocpmeg(ulong virt) | |
| 1991/0507 | { | |
| 1991/1007 |
| |
| 1992/0911 | Pmeg *p; Ctx *c; | |
| 1991/1007 |
| |
| 1991/0507 |
| |
| 1992/0911 | virt = virt & ~(BY2SEGM-1); for(;;){ p = (Pmeg*)m->plist; c = p->ctx; if(c == 0) break; m->needpmeg = 1; sched(); splhi(); } /* add to current context */ p->ctx = m->cctx; p->cnext = m->cctx->pmeg; m->cctx->pmeg = p; p->virt = virt; p->lo = virt; p->hi = virt; putsegspace(p->virt, p->index); mklast(&m->plist, p); return p; | |
| 1991/0507 | } | |
| 1992/0911 | static void freepmeg(Pmeg *p, int flush) { ulong x; /* invalidate any used PTE's, flush cache */ for(x = p->lo; x <= p->hi; x += BY2PG) putpme(x, INVALIDPTE, flush); /* invalidate segment pointer */ putsegspace(p->virt, INVALIDPMEG); p->hi = 0; p->lo = 0; p->cnext = 0; p->ctx = 0; p->virt = 0; } | |
| 1990/1226 | /* | |
| 1992/0911 | * get a context for a process. | |
| 1990/1226 | */ | |
| 1992/0911 | static Ctx* allocctx(Proc *proc) | |
| 1990/1226 | { | |
| 1992/0807 |
| |
| 1991/0110 |
| |
| 1990/1226 |
| |
| 1992/0911 | Ctx *c; | |
| 1990/1226 | ||
| 1991/0110 |
| |
| 1992/0807 |
| |
| 1991/0110 |
| |
| 1990/1226 |
| |
| 1991/0115 |
| |
| 1990/1226 |
| |
| 1991/0115 |
| |
| 1991/0110 |
| |
| 1990/1226 |
| |
| 1992/0911 | c = (Ctx*)m->clist; putctx(c); if(c->proc) freectx(c, 1); c->proc = proc; c->proc->ctxonmach[m->machno] = c; mklast(&m->clist, c); return c; } | |
| 1991/0111 | ||
| 1990/1223 |
| |
| 1991/0112 |
| |
| 1990/1223 |
| |
| 1991/0112 |
| |
| 1991/0110 |
| |
| 1991/0112 |
| |
| 1991/1007 |
| |
| 1991/0112 |
| |
| 1992/0911 | static void freectx(Ctx *c, int flush) { Pmeg *p; putctx(c); /* give back mappings */ while(p = c->pmeg){ c->pmeg = p->cnext; freepmeg(p, flush); mkfirst(&m->plist, p); } /* flush u-> */ flushpage(USERADDR); /* detach from process */ c->proc->ctxonmach[m->machno] = 0; c->proc = 0; | |
| 1990/1226 | } | |
| 1990/1223 | ||
| 1990/1226 |
| |
| 1991/0110 |
| |
| 1992/0911 | static void putctx(Ctx *c) | |
| 1990/1226 | { | |
| 1992/0806 |
| |
| 1992/0911 | putcontext(c->index); m->cctx = c; } | |
| 1990/1223 | ||
| 1992/0806 |
| |
| 1992/0911 | static void flushpage(ulong virt) { ulong a, evirt; a = virt; evirt = virt+BY2PG; | |
| 1992/0806 | do | |
| 1992/0807 |
| |
| 1992/0911 | a = flushpg(a); while(a < evirt); | |
| 1991/0110 | } | |
| 1992/0911 | /* * stuff an entry into a pmeg */ static void putpme(ulong virt, ulong phys, int flush) { virt = virt & ~(BY2PG-1); if(flush) flushpage(virt); putpmegspace(virt, phys); } /* * put a mapping into current context */ | |
| 1991/0110 | void | |
| 1992/0911 | putmmu(ulong virt, ulong phys, Page *pg) | |
| 1991/0110 | { | |
| 1990/1226 |
| |
| 1991/0110 |
| |
| 1992/0911 | ulong x, v; Pmeg *p; int s; USED(pg); s = splhi(); v = virt & ~(BY2SEGM-1); x = getsegspace(v); if(x == INVALIDPMEG) p = allocpmeg(v); else p = &m->pmeg[x - m->pfirst]; if(virt < p->lo) p->lo = virt; if(virt > p->hi) p->hi = virt; putpme(virt, phys, 1); splx(s); | |
| 1990/1223 | } | |
| 1992/0911 | /* * Initialize cache by clearing the valid bit * (along with the others) in all cache entries */ | |
| 1990/1223 | void | |
| 1992/0911 | cacheinit(void) { int i; for(i=0; i<conf.vacsize; i+=conf.vaclinesize) putsysspace(CACHETAGS+i, 0); /* * Turn cache on */ putenab(getenab()&~ENABCACHE); } /* * set up initial mappings and a the LRU lists for contexts and pmegs */ void | |
| 1990/1226 | mmuinit(void) | |
| 1990/1223 | { | |
| 1992/0619 |
| |
| 1992/0911 | int c, i, j; ulong va, ktop, pme; int fp; /* first free pmeg */ Pmeg *p; Ctx *ctx; | |
| 1990/1226 | ||
| 1992/0911 | conf.ncontext = 1; /**/ | |
| 1992/0806 | compile(); | |
| 1992/0911 | ||
| 1990/1226 | /* | |
| 1992/0806 |
| |
| 1992/0911 | * First map kernel text, data, bss, and xalloc regions. * xinit sets conf.npage0 to end of these. | |
| 1992/0619 | */ | |
| 1992/0806 |
| |
| 1992/0911 | ktop = PGROUND(conf.npage0); i = 0; for(c = 0; c < conf.ncontext; c++){ i = 0; for(va = KZERO; va < ktop; va += BY2SEGM) putcxsegm(c, va, i++); } fp = i; | |
| 1992/0619 | /* | |
| 1990/1226 |
| |
| 1992/0911 | * Make sure cache is turned on for kernel | |
| 1990/1226 | */ | |
| 1992/0807 |
| |
| 1992/0619 |
| |
| 1990/1226 |
| |
| 1992/0911 | pme = PTEVALID|PTEWRITE|PTEKERNEL|PTEMAINMEM; i = 0; for(va = KZERO; va < ktop; va += BY2PG, i++) putpme(va, pme+i, 1); | |
| 1992/0619 | ||
| 1990/1226 |
| |
| 1992/0813 |
| |
| 1992/0812 |
| |
| 1992/0619 | ||
| 1990/1226 | /* | |
| 1992/0911 | * invalidate rest of kernel's PMEG | |
| 1990/1226 | */ | |
| 1992/0619 |
| |
| 1990/1226 |
| |
| 1992/0911 | va = ROUNDUP(ktop, BY2SEGM); for(; ktop < va; ktop += BY2PG) putpme(ktop, INVALIDPTE, 1); | |
| 1990/1226 | /* | |
| 1992/0911 | * allocate pmegs for kmap'ing | |
| 1990/1226 | */ | |
| 1992/0619 | ||
| 1992/0807 |
| |
| 1992/0911 | for(c = 0; c < conf.ncontext; c++){ | |
| 1990/1226 | putcontext(c); | |
| 1990/1227 |
| |
| 1990/1226 |
| |
| 1990/1227 | ||
| 1991/0111 |
| |
| 1992/0812 |
| |
| 1990/1226 |
| |
| 1992/0812 |
| |
| 1990/1226 |
| |
| 1992/0813 |
| |
| 1990/1226 |
| |
| 1992/0813 |
| |
| 1990/1226 |
| |
| 1992/0813 |
| |
| 1990/1226 |
| |
| 1992/0812 |
| |
| 1990/1226 |
| |
| 1992/0812 |
| |
| 1990/1226 |
| |
| 1992/0911 | i = fp; for(va = IOSEGM; va < IOSEGM+IOSEGSIZE; va += BY2SEGM) putsegspace(va, i++); | |
| 1990/1226 | } | |
| 1992/0812 |
| |
| 1990/1223 |
| |
| 1992/0911 | fp = i; | |
| 1990/1223 |
| |
| 1991/0706 |
| |
| 1990/1223 |
| |
| 1990/1226 |
| |
| 1991/0112 |
| |
| 1990/1223 | ||
| 1992/0711 |
| |
| 1990/1226 |
| |
| 1992/0911 | /* * Invalidate all entries in all other pmegs */ for(j = fp; j < conf.npmeg; j++){ putsegspace(INVALIDSEGM, j); for(va = INVALIDSEGM; va < INVALIDSEGM+BY2SEGM; va += BY2PG) putpme(va, INVALIDPTE, 1); | |
| 1990/1223 | } | |
| 1992/0911 | ||
| 1990/1226 | /* | |
| 1992/0911 | * invalidate everything outside the kernel in every context | |
| 1990/1226 | */ | |
| 1991/0112 |
| |
| 1991/0111 |
| |
| 1992/0911 | for(c = 0; c < conf.ncontext; c++){ putcontext(c); for(va = UZERO; va < (KZERO & VAMASK); va += BY2SEGM) putsegspace(va, INVALIDPMEG); for(va = ktop; va < IOSEGM; va += BY2SEGM) putsegspace(va, INVALIDPMEG); | |
| 1991/0110 | } | |
| 1992/0911 | ||
| 1991/0112 | /* | |
| 1992/0911 | * allocate MMU management data for this CPU | |
| 1991/0112 | */ | |
| 1991/0115 |
| |
| 1991/0112 |
| |
| 1991/1007 |
| |
| 1992/0911 | m->pmeg = p = xalloc((INVALIDPMEG - fp) * sizeof(Pmeg)); m->pfirst = fp; for(; fp < INVALIDPMEG; fp++, p++){ p->index = fp; add(&m->plist, p); | |
| 1991/0112 | } | |
| 1990/1226 |
| |
| 1992/0911 | m->cctx = ctx = xalloc(conf.ncontext * sizeof(Ctx)); for(i = 0; i < conf.ncontext; i++, ctx++){ ctx->index = i; add(&m->clist, ctx); } putctx(m->cctx); | |
| 1990/1223 | } | |
| 1992/0911 | /* * give up our mmu context */ | |
| 1990/1223 | void | |
| 1990/1227 |
| |
| 1992/0911 | mmurelease(Proc *p) | |
| 1990/1227 | { | |
| 1992/0806 |
| |
| 1992/0911 | Ctx *c; | |
| 1990/1227 |
| |
| 1992/0806 |
| |
| 1992/0911 | c = p->ctxonmach[m->machno]; if(c == 0) return; freectx(c, 1); mkfirst(&m->clist, c); | |
| 1990/1227 | } | |
| 1992/0911 | /* * set up context for a process */ | |
| 1990/1227 | void | |
| 1991/1007 |
| |
| 1992/0911 | mapstack(Proc *p) | |
| 1991/1007 | { | |
| 1992/0806 |
| |
| 1992/0911 | Ctx *c; ulong tlbphys; Pmeg *pm, *f, **l; if(p->upage->va != (USERADDR|(p->pid&0xFFFF)) && p->pid != 0) panic("mapstack %s %d %lux 0x%lux 0x%lux", p->text, p->pid, p->upage, p->upage->pa, p->upage->va); /* free a pmeg if a process needs one */ if(m->needpmeg){ pm = (Pmeg*)m->plist; if(c = pm->ctx){ /* remove from context list */ l = &c->pmeg; for(f = *l; f; f = f->cnext){ if(f == pm){ *l = f->cnext; break; } l = &f->cnext; } /* flush cache & remove mappings */ putctx(c); freepmeg(pm, 1); } m->needpmeg = 0; } /* give up our context if it is unclean */ if(p->newtlb){ c = p->ctxonmach[m->machno]; if(c) freectx(c, 1); p->newtlb = 0; } /* set to this proc's context */ c = p->ctxonmach[m->machno]; if(c == 0) allocctx(p); else putctx(c); /* make sure there's a mapping for u-> */ tlbphys = PPN(p->upage->pa)|PTEVALID|PTEWRITE|PTEKERNEL|PTEMAINMEM; putpmegspace(USERADDR, tlbphys); u = (User*)USERADDR; | |
| 1991/1007 | } void | |
| 1990/1223 | flushmmu(void) { | |
| 1992/0911 | Ctx *c; Pmeg *p; | |
| 1990/1226 | splhi(); | |
| 1991/1007 |
| |
| 1990/1226 |
| |
| 1992/0911 | c = u->p->ctxonmach[m->machno]; if(c == 0) panic("flushmmu"); while(p = c->pmeg){ c->pmeg = p->cnext; freepmeg(p, 1); mkfirst(&m->plist, p); } | |
| 1990/1226 | spllo(); | |
| 1990/1223 | } void | |
| 1990/1226 |
| |
| 1992/0911 | invalidateu(void) | |
| 1990/1223 | { | |
| 1992/0806 |
| |
| 1990/1226 | ||
| 1992/0806 |
| |
| 1990/1226 |
| |
| 1992/0807 |
| |
| 1992/0806 |
| |
| 1991/0110 | ||
| 1990/1226 |
| |
| 1992/0806 |
| |
| 1992/0911 | putpme(USERADDR, INVALIDPTE, 1); | |
| 1990/1223 | } | |
| 1992/0911 | struct { Lock; KMap *free; KMap arena[IOSEGSIZE/BY2PG]; }kmapalloc; | |
| 1990/1223 | void kmapinit(void) { KMap *k; | |
| 1990/1226 |
| |
| 1992/0911 | ulong va; | |
| 1990/1223 | kmapalloc.free = 0; | |
| 1990/1226 | k = kmapalloc.arena; | |
| 1992/0812 |
| |
| 1992/0911 | for(va = IOSEGM; va < IOSEGM + IOSEGSIZE; va += BY2PG, k++){ k->va = va; | |
| 1990/1223 | kunmap(k); } } | |
| 1992/0813/sys/src/9/ss/mmu.c:346,356 – 1992/0911/sys/src/9/ss/mmu.c:584,606 | ||
| 1990/1223 | unlock(&kmapalloc); | |
| 1990/1227 | k->pa = pa; | |
| 1992/0101 | s = splhi(); | |
| 1992/0911 | putpme(k->va, PPN(pa)|PTEVALID|PTEKERNEL|PTEWRITE|flag, 1); | |
| 1992/0101 | splx(s); return k; | |
| 1992/0812 | } | |
| 1992/0911 | void kunmap(KMap *k) { k->pa = 0; lock(&kmapalloc); k->next = kmapalloc.free; kmapalloc.free = k; putpme(k->va, INVALIDPTE, 1); unlock(&kmapalloc); } | |
| 1992/0812 | ulong kmapregion(ulong pa, ulong n, ulong flag) { | |
| 1992/0813/sys/src/9/ss/mmu.c:383,567 – 1992/0911/sys/src/9/ss/mmu.c:633,635 | ||
| 1992/0101 | return kmappa(pg->pa, PTEMAINMEM|PTENOCACHE); | |
| 1990/1223 | } | |
| 1990/1226 |
| |
| 1992/0101 |
| |
| 1990/1226 |
| |
| 1992/0101 |
| |
| 1990/1227 |
| |
| 1990/1226 |
| |
| 1990/1223 |
| |
| 1990/1226 |
| |
| 1990/1223 |
| |
| 1990/1226 |
| |
| 1992/0806 |
| |
| 1992/0807 |
| |
| 1992/0806 |
| |
| 1992/0807 |
| |
| 1992/0806 |
| |
| 1990/1223 |
| |
| Too many diffs (26 > 25). Stopping. | ||