## diffname carrera/mmu.c 1993/0903 ## diff -e /dev/null /n/fornaxdump/1993/0903/sys/src/brazil/carrera/mmu.c 0a #include "u.h" #include "../port/lib.h" #include "mem.h" #include "dat.h" #include "fns.h" /* * tlb entry 0 is used only by mmuswitch() to set the current tlb pid. */ /* * Kmap entries start at tlb index 1 and work their way up until * kmapinval() removes them. They then restart at 1. As long as there * are few kmap entries they will not pass TLBROFF (the WIRED tlb entry * limit) and interfere with user tlb entries. */ /* * All invalidations of the tlb are via indexed entries. The virtual * address used is always 'KZERO | (x<<(PGSHIFT+1) | currentpid' where * 'x' is the index into the tlb. This ensures that the current pid doesn't * change and that no two invalidated entries have matching virtual * addresses just in case SGI/MIPS ever makes a chip that cares (as * they keep threatening). These entries should never be used in * lookups since accesses to KZERO addresses don't go through the tlb. */ #define TLBINVAL(x, pid) puttlbx(x, KZERO|((x)<<(PGSHIFT+1))|(pid), 0, 0, PGSZ4K) void tlbinit(void) { int i; for(i=0; inext = k+1; k->next = 0; unlock(&kmaplock); } /* * Arrange that the KMap'd virtual address will hit the same * primary cache line as pg->va by making bits 14...12 of the * tag the same as virtual address. These bits are the index * into the primary cache and are checked whenever accessing * the secondary cache through the primary. Violation causes * a VCE trap. */ KMap * kmap(Page *pg) { int s; KMap *k; ulong pte; ulong x, virt; s = splhi(); lock(&kmaplock); if(kmapfree == 0) panic("out of kmap"); k = kmapfree; kmapfree = k->next; k->pg = pg; /* One for the allocation, * One for kactive */ k->ref = 2; k->konmach[m->machno] = m->kactive; m->kactive = k; virt = pg->va; /* bits 14..12 form the secondary-cache virtual index */ virt &= PIDX; virt |= KMAPADDR | ((k-kpte)<virt = virt; pte = PPN(pg->pa)|PTECOHERXCLW|PTEGLOBL|PTEWRITE|PTEVALID; if(virt & BY2PG) { k->phys0 = PTEGLOBL; k->phys1 = pte; } else { k->phys0 = pte; k->phys1 = PTEGLOBL; } x = m->ktlbnext; puttlbx(x, (virt & ~BY2PG)|TLBPID(tlbvirt()), k->phys0, k->phys1, PGSZ4K); m->ktlbx[x] = 1; if(++x >= NTLB) m->ktlbnext = 1; else m->ktlbnext = x; unlock(&kmaplock); splx(s); return k; } void kunmap(KMap *k) { int s; s = splhi(); if(decref(k) == 0) { k->virt = 0; k->phys0 = 0; k->phys1 = 0; k->pg = 0; lock(&kmaplock); k->next = kmapfree; kmapfree = k; unlock(&kmaplock); } splx(s); } void kfault(ulong addr) { KMap *k, *f; ulong x, index; index = (addr & ~KSEGM) >> KMAPSHIFT; if(index >= KPTESIZE) panic("kmapfault: %lux", addr); k = &kpte[index]; if(k->virt == 0) panic("kmapfault: unmapped %lux", addr); for(f = m->kactive; f; f = f->konmach[m->machno]) if(f == k) break; if(f == 0) { incref(k); k->konmach[m->machno] = m->kactive; m->kactive = k; } x = m->ktlbnext; puttlbx(x, (k->virt & ~BY2PG)|TLBPID(tlbvirt()), k->phys0, k->phys1, PGSZ4K); m->ktlbx[x] = 1; if(++x >= NTLB) m->ktlbnext = 1; else m->ktlbnext = x; } void kmapinval() { int mno, i; KMap *k, *next; int curpid; uchar *ktlbx; if(m->kactive == 0) return; curpid = PTEPID(TLBPID(tlbvirt())); ktlbx = m->ktlbx; for(i = 0; i < NTLB; i++, ktlbx++){ if(*ktlbx == 0) continue; TLBINVAL(i, curpid); *ktlbx = 0; } mno = m->machno; for(k = m->kactive; k; k = next) { next = k->konmach[mno]; kunmap(k); } m->kactive = 0; m->ktlbnext = 1; } void mmuswitch(Proc *p) { int tp; if(p->newtlb) { memset(p->pidonmach, 0, sizeof p->pidonmach); p->newtlb = 0; } tp = p->pidonmach[m->machno]; if(tp == 0) tp = newtlbpid(p); puttlbx(0, KZERO|PTEPID(tp), 0, 0, PGSZ4K); } void mmurelease(Proc *p) { memset(p->pidonmach, 0, sizeof p->pidonmach); } /* * Process must be splhi */ int newtlbpid(Proc *p) { int i, s; Proc **h; i = m->lastpid; h = m->pidproc; for(s = 0; s < NTLBPID; s++) { i++; if(i >= NTLBPID) i = 1; if(h[i] == 0) break; } if(h[i]) purgetlb(i); if(h[i] != 0) panic("newtlb"); m->pidproc[i] = p; p->pidonmach[m->machno] = i; m->lastpid = i; return i; } void putmmu(ulong tlbvirt, ulong tlbphys, Page *pg) { short tp; char *ctl; Softtlb *entry; int s; s = splhi(); tp = up->pidonmach[m->machno]; if(tp == 0) tp = newtlbpid(up); tlbvirt |= PTEPID(tp); if((tlbphys & PTEALGMASK) != PTEUNCACHED) { tlbphys &= ~PTEALGMASK; tlbphys |= PTECOHERXCLW; } entry = putstlb(tlbvirt, tlbphys); puttlb(entry->virt, entry->phys0, entry->phys1); ctl = &pg->cachectl[m->machno]; if(*ctl == PG_TXTFLUSH) { icflush((void*)pg->va, BY2PG); *ctl = PG_NOFLUSH; } splx(s); } void purgetlb(int pid) { int i, mno; Proc *sp, **pidproc; Softtlb *entry, *etab; m->tlbpurge++; /* * find all pid entries that are no longer used by processes */ mno = m->machno; pidproc = m->pidproc; for(i=1; ipidonmach[mno] != i) pidproc[i] = 0; } /* * shoot down the one we want */ sp = pidproc[pid]; if(sp != 0) sp->pidonmach[mno] = 0; pidproc[pid] = 0; /* * clean out all dead pids from the stlb; */ entry = m->stb; for(etab = &entry[STLBSIZE]; entry < etab; entry++) if(pidproc[TLBPID(entry->virt)] == 0) entry->virt = 0; /* * clean up the hardware */ for(i=TLBROFF; inewtlb = 1; mmuswitch(up); splx(s); } void clearmmucache(void) { } Softtlb* putstlb(ulong tlbvirt, ulong tlbphys) { int k; Softtlb *entry; k = tlbvirt & BY2PG; tlbvirt &= ~BY2PG; entry = &m->stb[(tlbvirt ^ (tlbvirt>>13)) & (STLBSIZE-1)]; if(entry->virt != tlbvirt) { entry->virt = tlbvirt; entry->phys0 = 0; entry->phys1 = 0; } if(k) entry->phys1 = tlbphys; else entry->phys0 = tlbphys; if(entry->phys0 == 0 && entry->phys1 == 0) entry->virt = 0; return entry; } . ## diffname carrera/mmu.c 1993/0904 ## diff -e /n/fornaxdump/1993/0903/sys/src/brazil/carrera/mmu.c /n/fornaxdump/1993/0904/sys/src/brazil/carrera/mmu.c 199c m->ktlbnext = TLBROFF; . 167c m->ktlbnext = TLBROFF; . 110c m->ktlbnext = TLBROFF; . 54a m->ktlbnext = TLBROFF; . ## diffname carrera/mmu.c 1993/0905 ## diff -e /n/fornaxdump/1993/0904/sys/src/brazil/carrera/mmu.c /n/fornaxdump/1993/0905/sys/src/brazil/carrera/mmu.c 188c for(i = TLBROFF; i < NTLB; i++, ktlbx++){ . 105c k->phys1 = PTEGLOBL|PTECOHERXCLW; . 100c k->phys0 = PTEGLOBL|PTECOHERXCLW; . ## diffname carrera/mmu.c 1993/0906 ## diff -e /n/fornaxdump/1993/0905/sys/src/brazil/carrera/mmu.c /n/fornaxdump/1993/0906/sys/src/brazil/carrera/mmu.c 166c virt = (k->virt&~BY2PG)|TLBPID(tlbvirt()); puttlbx(x, virt, k->phys0, k->phys1, PGSZ4K); . 148c index = (addr & ~KMAPADDR) >> KMAPSHIFT; . 146c ulong x, index, virt; . ## diffname carrera/mmu.c 1993/0915 ## diff -e /n/fornaxdump/1993/0906/sys/src/brazil/carrera/mmu.c /n/fornaxdump/1993/0915/sys/src/brazil/carrera/mmu.c 270a /* * Fix up EISA memory address which are greater * than 32 bits physical: 0x100000000 */ if((tlbphys&0xffff0000) == PPN(Eisamphys)) { tlbphys &= ~PPN(Eisamphys); tlbphys |= 0x04000000; } . 264d 260a int s; . 5a #include "io.h" . ## diffname carrera/mmu.c 1993/1013 ## diff -e /n/fornaxdump/1993/0915/sys/src/brazil/carrera/mmu.c /n/fornaxdump/1993/1013/sys/src/brazil/carrera/mmu.c 148a addr = ur->badvaddr; . 147a ulong addr; . 144c kfault(Ureg *ur) . 6a #include "ureg.h" . ## diffname carrera/mmu.c 1993/1208 ## diff -e /n/fornaxdump/1993/1013/sys/src/brazil/carrera/mmu.c /n/fornaxdump/1993/1208/sys/src/brazil/carrera/mmu.c 130a puttlb((k->virt & ~BY2PG) | TLBPID(tlbvirt()), k->phys0 & ~PTEVALID, k->phys1 & ~PTEVALID); . ## diffname carrera/mmu.c 1993/1209 ## diff -e /n/fornaxdump/1993/1208/sys/src/brazil/carrera/mmu.c /n/fornaxdump/1993/1209/sys/src/brazil/carrera/mmu.c 298a ((ulong*)0xA0090000)[8] = 0x6000; . 297a ((ulong*)0xA0090000)[8] = 0x5000; . 296a ((ulong*)0xA0090000)[8] = 0x4000; . 295a ((ulong*)0xA0090000)[8] = 0x3000; . 294a ulong tlb[4]; extern int gettlbp(ulong, ulong*); extern ulong tlbvirt(void); ((ulong*)0xA0090000)[6] = tlbphys; ((ulong*)0xA0090000)[7] = pg->va; ((ulong*)0xA0090000)[8] = 0x2000; if(gettlbp((pg->va & ~BY2PG)|TLBPID(tlbvirt()), tlb) < 0){ print("entry->virt %lux pg->va %lux\n", entry->virt, pg->va); panic("icflush not in TLB"); } if(pg->va == 0x19000) { print("xx>> virt %lux phys0 %lux phys1 %lux\n", tlb[0],tlb[1],tlb[2]); } . 293a ((ulong*)0xA0090000)[8] = 0x1000; ((ulong*)0xA0090000)[5] = tlbvirt; . 8a Mach machstruct[100]; . ## diffname carrera/mmu.c 1993/1210 ## diff -e /n/fornaxdump/1993/1209/sys/src/brazil/carrera/mmu.c /n/fornaxdump/1993/1210/sys/src/brazil/carrera/mmu.c 309c if(0 && pg->va == 0x19000) { . 133d ## diffname carrera/mmu.c 1993/1211 ## diff -e /n/fornaxdump/1993/1210/sys/src/brazil/carrera/mmu.c /n/fornaxdump/1993/1211/sys/src/brazil/carrera/mmu.c 318d 316d 314d 312d 298,310d 295,296c if(*ctl == PG_DATFLUSH) { dcflush((void*)pg->va, BY2PG); *ctl = PG_NOFLUSH; }else . 209d 195,196c ktlbx = m->ktlbx+TLBROFF; for(i = TLBROFF; i < NTLB; i++, ktlbx++) { . 190d 187d 185c int mno, i, curpid; . 9,10d ## diffname carrera/mmu.c 1993/1212 ## diff -e /n/fornaxdump/1993/1211/sys/src/brazil/carrera/mmu.c /n/fornaxdump/1993/1212/sys/src/brazil/carrera/mmu.c 296a break; . 293,295c break; case PG_NEWCOL: cleancache(); /* Too expensive */ . 290c switch(*ctl) { case PG_TXTFLUSH: icflush((void*)pg->va, BY2PG); *ctl = PG_NOFLUSH; break; case PG_DATFLUSH: . ## diffname carrera/mmu.c 1993/1213 ## diff -e /n/fornaxdump/1993/1212/sys/src/brazil/carrera/mmu.c /n/fornaxdump/1993/1213/sys/src/brazil/carrera/mmu.c 148,149c ulong x, index, virt, addr; . ## diffname carrera/mmu.c 1993/1218 ## diff -e /n/fornaxdump/1993/1213/sys/src/brazil/carrera/mmu.c /n/fornaxdump/1993/1218/sys/src/brazil/carrera/mmu.c 200a TLBINVAL(k->tlbi[mno], curpid); . 190,197d 184d 182c int mno, curpid; . 172d 170a k->tlbi[mno] = x; . 164c k->konmach[mno] = m->kactive; . 161a . 159c for(f = m->kactive; f; f = f->konmach[mno]) . 151a . 149a mno = m->machno; . 146a int mno; . 111,112c k->tlbi[m->machno] = x; puttlbx(x, (virt&~BY2PG)|TLBPID(tlbvirt()), k->phys0, k->phys1, PGSZ4K); . ## diffname carrera/mmu.c 1993/1219 ## diff -e /n/fornaxdump/1993/1218/sys/src/brazil/carrera/mmu.c /n/fornaxdump/1993/1219/sys/src/brazil/carrera/mmu.c 213a . 159c if(k->virt == 0 || k->ref < 1) . ## diffname carrera/mmu.c 1993/1221 ## diff -e /n/fornaxdump/1993/1219/sys/src/brazil/carrera/mmu.c /n/fornaxdump/1993/1221/sys/src/brazil/carrera/mmu.c 288c cleancache(); /* Too expensive */ /* icflush((void*)pg->va, BY2PG);*/ . ## diffname carrera/mmu.c 1993/1228 ## diff -e /n/fornaxdump/1993/1221/sys/src/brazil/carrera/mmu.c /n/fornaxdump/1993/1228/sys/src/brazil/carrera/mmu.c 288,289c icflush((void*)pg->va, BY2PG); . ## diffname carrera/mmu.c 1994/0728 ## diff -e /n/fornaxdump/1993/1228/sys/src/brazil/carrera/mmu.c /n/fornaxdump/1994/0728/sys/src/brazil/carrera/mmu.c 80,81c if(kmapfree == 0) { unlock(&kmaplock); kmapinval(); /* try and free some */ lock(&kmaplock); if(kmapfree == 0) panic("out of kmap"); } . ## diffname carrera/mmu.c 1994/0808 ## diff -e /n/fornaxdump/1994/0728/sys/src/brazil/carrera/mmu.c /n/fornaxdump/1994/0808/sys/src/brazil/carrera/mmu.c 56d 50d ## diffname carrera/mmu.c 2001/0527 # deleted ## diff -e /n/fornaxdump/1994/0808/sys/src/brazil/carrera/mmu.c /n/emeliedump/2001/0527/sys/src/9/carrera/mmu.c 1,391d