## diffname bitsy/mmu.c 2000/0902 ## diff -e /dev/null /n/emeliedump/2000/0902/sys/src/9/bitsy/mmu.c 0a #include "u.h" #include "../port/lib.h" #include "mem.h" #include "dat.h" #include "fns.h" #include "io.h" #include "ureg.h" #include "../port/error.h" void putmmu(ulong va, ulong pa, Page*) { USED(va, pa); } void mmurelease(Proc* proc) { USED(proc); } void mmuswitch(Proc* proc) { USED(proc); } . ## diffname bitsy/mmu.c 2000/0905 ## diff -e /n/emeliedump/2000/0902/sys/src/9/bitsy/mmu.c /n/emeliedump/2000/0905/sys/src/9/bitsy/mmu.c 10a mmuinit(void) { } void . ## diffname bitsy/mmu.c 2000/0906 ## diff -e /n/emeliedump/2000/0905/sys/src/9/bitsy/mmu.c /n/emeliedump/2000/0906/sys/src/9/bitsy/mmu.c 12a ulong a, e; /* set up the domain register to cause all domains to obey pte access bits */ putdac(0x55555555); /* get a prototype level 1 page */ l1page = xspanalloc(BY2PG, 16*1024, 0); memset(l1page, 0, BY2PG); /* map DRAM */ e = PHYSDRAM0 + BY2PG*con for( /* map zeros */ /* map flash */ . 9a /* real protection bits */ enum { Small_Page= (2<<0), Large_Page= (1<<0), Cached= (1<<3), Buffered= (1<<2), UserRO= (0xAA<<4), UserRW= (0xFF<<4), KernelRW= (0x55<<4), }; /* * table to map fault.c bits to physical bits */ static ulong phystrans[8] = { [PTEVALID] Small_Page|Cached|Buffered|UserRO, [PTEVALID|PTEWRITE] Small_Page|Cached|Buffered|UserRW, [PTEVALID|UNCACHED] Small_Page|UserRO, [PTEVALID|UNCACHED|PTEWRITE] Small_Page|UserRW, }; ulong *l1page; /* * We map all of memory, flash, and the zeros area with sections. * Special use space is mapped on the fly with regmap. */ . ## diffname bitsy/mmu.c 2000/0907 ## diff -e /n/emeliedump/2000/0906/sys/src/9/bitsy/mmu.c /n/emeliedump/2000/0907/sys/src/9/bitsy/mmu.c 52,56c /* direct map DRAM */ e = conf.base1 + BY2PG*conf.npage2; for(a = PHYSDRAM0; a < e; a += OneMeg) l1table[a>>20] = L1Section | L1KernelRW | L1Cached | L1Buffered | (a&L1SectBaseMask); /* direct map zeros area */ for(a = PHYSNULL0; a < PHYSNULL0 + 128 * OneMeg; a += OneMeg) l1table[a>>20] = L1Section | L1KernelRW | L1Cached | L1Buffered | (a&L1SectBaseMask); /* direct map flash */ for(a = PHYFLASH0; a < PHYFLASH0 + 128 * OneMeg; a += OneMeg) l1table[a>>20] = L1Section | L1KernelRW | L1Cached | L1Buffered | (a&L1SectBaseMask); /* map the uart so that we can continue using iprint */ uart3regs = mapspecial(UART3REGS, 64); } /* * map special use space */ ulong* mapspecial(ulong addr, int len) { ulong *t; ulong a, i; /* first see if we've mapped it somewhere, the first hole means we're done */ for(a = REGZERO; a < REGTOP; a += OneMeg){ if((l1table[a>>20] & L1TypeMask) != L1PageTable){ /* create a page table and break */ t = xspanalloc(BY2PG, 1024, 0); memzero(t, BY2PG, 0); l1table[a>>20] = L1PageTable | L1Domain0 | (((ulong)t) & L1PTBaseMask); break; } t = (ulong*)(l1table[a>>20] & L1PTBaseMask); for(i = 0; i < OneMeg; i += BY2PG){ if((t[a>>20] & L2TypeMask) != L2SmallPage) break; } if(i < OneMeg){ a += i; break; } } . 49,50c l1table = xspanalloc(BY2PG, 16*1024, 0); memset(l1table, 0, BY2PG); . 34c ulong *l1table; . 28,31c [PTEVALID] L2SmallPage|L2Cached|L2Buffered|L2UserRO, [PTEVALID|PTEWRITE] L2SmallPage|L2Cached|L2Buffered|L2UserRW, [PTEVALID|PTEUNCACHED] L2SmallPage|L2UserRO, [PTEVALID|PTEUNCACHED|PTEWRITE] L2SmallPage|L2UserRW, [PTEKERNEL|PTEVALID] L2SmallPage|L2Cached|L2Buffered|L2KernelRW, [PTEKERNEL|PTEVALID|PTEWRITE] L2SmallPage|L2Cached|L2Buffered|L2KernelRW, [PTEKERNEL|PTEVALID|PTEUNCACHED] L2SmallPage|L2KernelRW, [PTEKERNEL|PTEVALID|PTEUNCACHED|PTEWRITE] L2SmallPage|L2KernelRW, . 26c static ulong phystrans[16] = . 22d 13,19c /* level 1 descriptor bits */ L1TypeMask= (3<<0), L1Invalid= (0<<0), L1PageTable= (1<<0), L1Section= (2<<0), L1Cached= (1<<3), L1Buffered= (1<<2), L1Domain0= (0<<5), L1KernelRW= (0x1<<10), L1UserRO= (0x2<<10), L1UserRW= (0x3<<10), L1SectBaseMask= (0xFFF<<20), L1PTBaseMask= (0x3FFFFF<<10), /* level 2 descriptor bits */ L2TypeMask= (3<<0), L2SmallPage= (2<<0), L2LargePage= (1<<0), L2Cached= (1<<3), L2Buffered= (1<<2), L2KernelRW= (0x55<<4), L2UserRO= (0xAA<<4), L2UserRW= (0xFF<<4), L2PageBaseMask= (0xFFFFF<<12), . ## diffname bitsy/mmu.c 2000/0909 ## diff -e /n/emeliedump/2000/0907/sys/src/9/bitsy/mmu.c /n/emeliedump/2000/0909/sys/src/9/bitsy/mmu.c 120a /* we get here if no entry was found mapping this physical address */ . 117c virtaddr += i; . 113c if((t[virtaddr>>20] & L2TypeMask) != L2SmallPage) . 111c t = (ulong*)(l1table[virtaddr>>20] & L1PTBaseMask); . 108c l1table[virtaddr>>20] = L1PageTable | L1Domain0 | (((ulong)t) & L1PTBaseMask); . 103,104c for(virtaddr = REGZERO; virtaddr < REGTOP; virtaddr += OneMeg){ if((l1table[virtaddr>>20] & L1TypeMask) != L1PageTable){ . 100c ulong virtaddr, i; . 97c mapspecial(ulong physaddr, int len) . ## diffname bitsy/mmu.c 2000/0920 ## diff -e /n/emeliedump/2000/0909/sys/src/9/bitsy/mmu.c /n/emeliedump/2000/0920/sys/src/9/bitsy/mmu.c 122,123c /* we get here if no entry was found mapping this physical range */ . 114a . 113c if((t[(virtaddr+i)>>20] & L2TypeMask) != L2SmallPage) . 94c * map special use space . ## diffname bitsy/mmu.c 2000/0921 ## diff -e /n/emeliedump/2000/0920/sys/src/9/bitsy/mmu.c /n/emeliedump/2000/0921/sys/src/9/bitsy/mmu.c 115c if(candidate == 0){ /* look for start of range */ if((entry & L2PageBaseMask) != base) continue; candidate = virtaddr+i; } else { /* look for contiunued range */ if((entry & L2PageBaseMask) != base + off) candidate = 0; continue; } } /* if we're at the end of the range, area is already mapped */ if((entry & L2PageBaseMask) == end) return candidate + (physaddr-base); . 113c entry = t[(virtaddr+i)>>20]; /* first hole means nothing left, add map */ if((entry & L2TypeMask) != L2SmallPage) . 108c l1table[virtaddr>>20] = L1PageTable | L1Domain0 | (((ulong)t) & L1PTBaseMask); . 101a base = physaddr & ~(BY2PG-1); end = (physaddr+len-1) & ~(BY2PG-1); if(len > 128*1024) usemeg = 1; off = 0; candidate = 0; . 100c ulong virtaddr, i, base, end, off, entry, candidate; . 94c * map special space, assume that the space isn't already mapped . ## diffname bitsy/mmu.c 2000/0923 ## diff -e /n/emeliedump/2000/0921/sys/src/9/bitsy/mmu.c /n/emeliedump/2000/0923/sys/src/9/bitsy/mmu.c 134c if((entry & L2PageBaseMask) != base + off){ . 96a mapspecmeg(ulong physaddr, int len) ulong* . 94c * map special space uncached, assume that the space isn't already mapped . ## diffname bitsy/mmu.c 2000/0924 ## diff -e /n/emeliedump/2000/0923/sys/src/9/bitsy/mmu.c /n/emeliedump/2000/0924/sys/src/9/bitsy/mmu.c 152c /* didn't fit */ if(base <= end) return nil; return rv; . 146,149d 141,144d 125,139c /* found unused entry on level 2 table */ if((entry & L2TypeMask) != L2SmallPage){ if(rv == nil) rv = (ulong*)(va+i*BY2PG+off); t[i>>PGSHIFT] = L2SmallPage | L2KernelRW | (base & L2PageBaseMask); base += BY2PG; continue; . 123c entry = t[i>>PGSHIFT]; . 121c t = (ulong*)(l1table[va>>20] & L1PTBaseMask); . 119d 117c l1table[va>>20] = L1PageTable | L1Domain0 | . 111,114c for(va = REGZERO; va < REGTOP && base >= end; va += OneMeg){ if((l1table[va>>20] & L1TypeMask) != L1PageTable){ /* found unused entry on level 1 table */ if(livelarge){ if(rv == nil) rv = (ulong*)(va+i*BY2PG+off); l1table[va>>20] = L1Section | L1KernelRW | (base&L1SectBaseMask); base += OneMeg; continue; } /* create a page table and keep going */ . 104,109c rv = nil; livelarge = len >= 128*1024; if(livelarge){ base = pa & ~(OneMeg-1); end = (pa+len-1) & ~(OneMeg-1); } else { base = pa & ~(BY2PG-1); end = (pa+len-1) & ~(BY2PG-1); } off = pa - base; . 102c ulong va, i, base, end, off; int livelarge; ulong* rv; . 97,99c mapspecial(ulong pa, int len) . ## diffname bitsy/mmu.c 2000/0928 ## diff -e /n/emeliedump/2000/0924/sys/src/9/bitsy/mmu.c /n/emeliedump/2000/0928/sys/src/9/bitsy/mmu.c 130c memset(t, 0, BY2PG); . 100c ulong va, i, base, end, off, entry; . 90c // uart3regs = mapspecial(UART3REGS, 64); /* set up the domain register to cause all domains to obey pte access bits */ iprint("setting up domain access\n"); putdac(0x55555555); /* point to map */ iprint("setting tlb map %lux\n", (ulong)l1table); putttb((ulong)l1table); . 85c for(a = PHYSFLASH0; a < PHYSFLASH0 + 128 * OneMeg; a += OneMeg) . 78a /* direct map devs */ for(a = REGZERO; a < REGTOP; a += OneMeg) l1table[a>>20] = L1Section | L1KernelRW | (a&L1SectBaseMask); . 74c e = conf.base1 + BY2PG*conf.npage1; . 66,68d ## diffname bitsy/mmu.c 2000/0929 ## diff -e /n/emeliedump/2000/0928/sys/src/9/bitsy/mmu.c /n/emeliedump/2000/0929/sys/src/9/bitsy/mmu.c 151c rv = (ulong*)(va+i+off); . 143a /* here if we're using page maps instead of sections */ . 137,141c /* create an L2 page table and keep going */ t = xspanalloc(BY2PG, 1024, 0); memset(t, 0, BY2PG); l1table[va>>20] = L1PageTable | L1Domain0 | (((ulong)t) & L1PTBaseMask); } break; case L1Section: continue; case L1PageTable: if(livelarge) continue; break; . 135c } else { . 132c (base & L1SectBaseMask); . 130c rv = (ulong*)(va+off); . 124,126c for(va = REGZERO; va < REGTOP && base <= end; va += OneMeg){ switch(l1table[va>>20] & L1TypeMask){ default: . 99a /* map the uart so that we can continue using iprint */ uart3regs = (Uartregs*)mapspecial(UART3REGS, 64); /* enable mmu, and make 0xFFFF0000 the virtual address of the exception vecs */ mmuenable(); iprint("uart3regs now at %lux\n", uart3regs); . 95c putdac(0xFFFFFFFF); . 90,91c /* map first page of DRAM also into 0xFFFF0000 for the interrupt vectors */ t = xspanalloc(BY2PG, 16*1024, 0); memset(t, 0, BY2PG); l1table[0xFFFF0000>>20] = L1PageTable | L1Domain0 | (((ulong)t) & L1PTBaseMask); t[0xF0000>>PGSHIFT] = L2SmallPage | L2KernelRW | PHYSDRAM0; . 87,88c l1table[a>>20] = L1Section | L1KernelRW | (a&L1SectBaseMask) | L1Cached | L1Buffered; . 82,83c l1table[a>>20] = L1Section | L1KernelRW | (a&L1SectBaseMask); . 76,79d 73,74c l1table[a>>20] = L1Section | L1KernelRW | (a&L1SectBaseMask) | L1Cached | L1Buffered; . 64a ulong *t; . ## diffname bitsy/mmu.c 2000/1002 ## diff -e /n/emeliedump/2000/0929/sys/src/9/bitsy/mmu.c /n/emeliedump/2000/1002/sys/src/9/bitsy/mmu.c 112c void* . 101c uart3regs = mapspecial(UART3REGS, 64); . ## diffname bitsy/mmu.c 2000/1006 ## diff -e /n/emeliedump/2000/1002/sys/src/9/bitsy/mmu.c /n/emeliedump/2000/1006/sys/src/9/bitsy/mmu.c 105,106d 100,102d ## diffname bitsy/mmu.c 2000/1007 ## diff -e /n/emeliedump/2000/1006/sys/src/9/bitsy/mmu.c /n/emeliedump/2000/1007/sys/src/9/bitsy/mmu.c 100c /* enable mmu */ wbflush(); flushcache(); flushmmu(); . 89,90c l1table[a>>20] = L1PageTable | L1Domain0 | (((ulong)t) & L1PTBaseMask); t[(a&0xfffff)>>PGSHIFT] = L2SmallPage | L2KernelRW | (PHYSDRAM0 & L2PageBaseMask); . 86,87c /* * double map start of ram to exception vectors */ a = EVECTORS; t = xspanalloc(BY2PG, 1024, 0); . 68,69c l1table = xspanalloc(16*1024, 16*1024, 0); memset(l1table, 0, 16*1024); . 56a . ## diffname bitsy/mmu.c 2000/1011 ## diff -e /n/emeliedump/2000/1007/sys/src/9/bitsy/mmu.c /n/emeliedump/2000/1011/sys/src/9/bitsy/mmu.c 200c /* set pid */ if(p->pid <= 0) p->pid = newtlbpid(p); putpid(p->pid<<25); /* set domain register to this + the kernel's domains */ putdac((Dclient<<(2*p->pid)) | Dclient); . 198c mmuswitch(Proc* p) . 194c Page *pg; int i; for(i = 0; i < nelem(p->l1); i++){ pg = p->l1[i]; if(pg == nil) continue; if(--pg->ref) panic("mmurelease: pg->ref %d\n", pg->ref); pagechainhead(pg); p->l1[i] = nil; } . 192c mmurelease(Proc* p) . 190a /* * this is called with palloc locked so the pagechainhead is kosher */ . 188c ulong pva; Page *p; ulong *t; /* if user memory, offset by pid value */ if((va & 0xfe000000) == 0) pva = va | (up->pid << 25); else pva = va; /* always point L1 entry to L2 page, can't hurt */ p = up->l1[va>>20]; if(p == nil){ p = auxpage(); if(p == nil) pexit("out of memory", 1); p->va = VA(kmap(p)); up->l1[va>>20] = p; } l1table[pva>>20] = L1PageTable | L1Domain0 | (p->pa & L1PTBaseMask); t = (ulong*)p->va; /* set L2 entry */ t[(pva & (OneMeg-1))>>PGSHIFT] = mmubits[pa & (PTEKERNEL|PTEVALID|PTEUNCACHED|PTEWRITE)] | (pa & ~(PTEKERNEL|PTEVALID|PTEUNCACHED|PTEWRITE)); wbflush(); . 184a /* * find a new pid. If none exist, flush all pids, mmu, and caches. */ static Lock pidlock; int newtlbpid(Proc *p) { return p->pid; } /* * table to map fault.c bits to physical bits */ static ulong mmubits[16] = { [PTEVALID] L2SmallPage|L2Cached|L2Buffered|L2UserRO, [PTEVALID|PTEWRITE] L2SmallPage|L2Cached|L2Buffered|L2UserRW, [PTEVALID|PTEUNCACHED] L2SmallPage|L2UserRO, [PTEVALID|PTEUNCACHED|PTEWRITE] L2SmallPage|L2UserRW, [PTEKERNEL|PTEVALID] L2SmallPage|L2Cached|L2Buffered|L2KernelRW, [PTEKERNEL|PTEVALID|PTEWRITE] L2SmallPage|L2Cached|L2Buffered|L2KernelRW, [PTEKERNEL|PTEVALID|PTEUNCACHED] L2SmallPage|L2KernelRW, [PTEKERNEL|PTEVALID|PTEUNCACHED|PTEWRITE] L2SmallPage|L2KernelRW, }; /* * add an entry to the current map */ . 153a /* if it's already mapped in a one meg area, don't remap */ entry = l1table[va>>20]; i = entry & L1SectBaseMask; if(pa >= i && (pa+len) <= i + OneMeg) if((entry & ~L1SectBaseMask) == (L1Section | L1KernelRW | L1Domain0)) return (void*)(va + (pa & (OneMeg-1))); . 140c l1table[va>>20] = L1Section | L1KernelRW | L1Domain0 | . 98c putdac(Dclient); . 86a /* map peripheral control module regs */ mapspecial(0x80000000, OneMeg); /* map system control module regs */ mapspecial(0x90000000, OneMeg); . 82,85c /* map flash */ for(o = 0; o < 128 * OneMeg; o += OneMeg) l1table[(FLASHZERO+o)>>20] = L1Section | L1KernelRW | L1Domain0 | L1Cached | L1Buffered | ((PHYSFLASH0+o)&L1SectBaseMask); . 78,80c /* map zeros area */ for(o = 0; o < 128 * OneMeg; o += OneMeg) l1table[(NULLZERO+o)>>20] = L1Section | L1KernelRW | L1Domain0 | ((PHYSNULL0+o)&L1SectBaseMask); . 72,76c /* map DRAM */ for(o = 0; o < DRAMTOP; o += OneMeg) l1table[(DRAMZERO+o)>>20] = L1Section | L1KernelRW| L1Domain0 | L1Cached | L1Buffered | ((PHYSDRAM0+o)&L1SectBaseMask); . 65c ulong a, o; . 39,52c /* domain values */ Dnoaccess= 0, Dclient= 1, Dmanager= 3, . 37d 20c L1DomShift= 5, L1Domain0= (0<tlbpid)) | Dclient); . 284,286c if(p->tlbpid <= 0) p->tlbpid = newtlbpid(p); iprint("using tlbpid %d\n", p->tlbpid); putpid(p->tlbpid<<25); . 237c pva = va | (up->tlbpid << 25); . 235c iprint("putmmu(0x%.8lux, 0x%.8lux)\n", va, pa); /* if user memory, add pid value */ . 206c int i; ilock(&pidlock); i = ++(m->lastpid); if(i >= nelem(m->pid2proc)){ flushpids(); i = m->lastpid = 0; } m->pid2proc[i] = p; p->tlbpid = i+1; iunlock(&pidlock); return p->tlbpid; . 202a void flushpids(void) { memset(l1table, 0, BY2WD*nelem(m->pid2proc)*32); memset(m->pid2proc, 0, sizeof(m->pid2proc)); flushcache(); flushmmu(); } . 199c * maintain pids . 107d 103d ## diffname bitsy/mmu.c 2000/1013 ## diff -e /n/emeliedump/2000/1012/sys/src/9/bitsy/mmu.c /n/emeliedump/2000/1013/sys/src/9/bitsy/mmu.c 302,309c // flushcache(); /* drain and flush the cache */ // flushmmu(); // memmove(l1table, p->l1table, sizeof(p->l1table)); . 295c p->l1page[i] = nil; . 288,289c for(i = 0; i < nelem(p->l1page); i++){ pg = p->l1page[i]; . 276c flushmmu(); . 274a iprint("%lux[%lux] = %lux\n", (ulong)t, (va & (OneMeg-1))>>PGSHIFT, t[(va & (OneMeg-1))>>PGSHIFT]); . 273c t[(va & (OneMeg-1))>>PGSHIFT] = mmubits[pa & (PTEKERNEL|PTEVALID|PTEUNCACHED|PTEWRITE)] . 269c l1table[va>>20] = L1PageTable | L1Domain0 | (p->pa & L1PTBaseMask); iprint("%lux[%lux] = %lux\n", l1table, va>>20, l1table[va>>20]); up->l1table[va>>20] = l1table[va>>20]; . 267c up->l1page[va>>20] = p; . 261c p = up->l1page[va>>20]; . 254,259d 249d 197,227d 71c for(o = 0; o < 128*OneMeg; o += OneMeg) . 69a /* map low mem */ for(o = 0; o < 1*OneMeg; o += OneMeg) l1table[(0+o)>>20] = L1Section | L1KernelRW| L1Domain0 | L1Cached | L1Buffered | ((0+o)&L1SectBaseMask); . ## diffname bitsy/mmu.c 2000/1014 ## diff -e /n/emeliedump/2000/1013/sys/src/9/bitsy/mmu.c /n/emeliedump/2000/1014/sys/src/9/bitsy/mmu.c 273,275c iprint("switching to proc %d\n", p->pid); memmove(l1table, p->l1table, sizeof(p->l1table)); cleanaddr((ulong)l1table); wbflush(); } void peekmmu(ulong va) { ulong e; e = l1table[va>>20]; switch(e & L1TypeMask){ default: iprint("l1: %lux invalid\n", e); break; case L1PageTable: iprint("l1: %lux pt\n", e); va &= OneMeg-1; va >>= PGSHIFT; e &= L1PTBaseMask; e = ((ulong*)e)[va]; iprint("l2: %lux\n", e); break; case L1Section: iprint("l1: %lux section\n", e); break; } . 247c wbflush(); . 245a cleanaddr((ulong)&t[(va & (OneMeg-1))>>PGSHIFT]); . 237a cleanaddr((ulong)&l1table[va>>20]); . 235a memset((uchar*)(p->va), 0, BY2PG); . ## diffname bitsy/mmu.c 2000/1015 ## diff -e /n/emeliedump/2000/1014/sys/src/9/bitsy/mmu.c /n/emeliedump/2000/1015/sys/src/9/bitsy/mmu.c 279a /* lose any possible stale tlb entries */ mmuinvalidate(); } void flushmmu(void) { int s; s = splhi(); up->newtlb = 1; mmuswitch(up); splx(s); . 278c /* make sure map is in memory and drain write buffer */ cacheflushaddr((ulong)l1table); . 276c if(p->newtlb){ mmuptefree(p); p->newtlb = 0; } /* write back dirty cache entries before changing map */ cacheflush(); /* move in new map */ . 270a if(p->mmufree && palloc.r.p) wakeup(&palloc.r); p->mmufree = nil; memset(l1table, 0, sizeof(p->l1table)); . 269d 265a p->l1page[i] = nil; pg->next = p->mmufree; p->mmufree = pg; } memset(p->l1table, 0, sizeof(p->l1table)); } /* * this is called with palloc locked so the pagechainhead is kosher */ void mmurelease(Proc* p) { Page *pg, *next; /* write back dirty cache entries before changing map */ cacheflush(); mmuptefree(p); for(pg = p->mmufree; pg; pg = next){ next = pg->next; . 262c for(i = 0; i < Nmeg; i++){ . 257c mmuptefree(Proc *p) . 254c * free up all page tables for this proc . 247,248c //iprint("%lux[%lux] = %lux\n", (ulong)t, (va & (OneMeg-1))>>PGSHIFT, t[(va & (OneMeg-1))>>PGSHIFT]); cacheflushaddr((ulong)&t[(va & (OneMeg-1))>>PGSHIFT]); . 239,240c cacheflushaddr((ulong)&l1table[va>>20]); //iprint("%lux[%lux] = %lux\n", l1table, va>>20, l1table[va>>20]); . 227c //iprint("putmmu(0x%.8lux, 0x%.8lux)\n", va, pa); . 118a cacheflush(); . 116,117c mmuinvalidate(); . 84a | L1Cached | L1Buffered . ## diffname bitsy/mmu.c 2000/1016 ## diff -e /n/emeliedump/2000/1015/sys/src/9/bitsy/mmu.c /n/emeliedump/2000/1016/sys/src/9/bitsy/mmu.c 302a if(m->mmupid == p->pid && p->newtlb == 0) return; m->mmupid = p->pid; . 301c mmuswitch(Proc *p) . 248c print("%lux[%lux] = %lux\n", (ulong)t, (va & (OneMeg-1))>>PGSHIFT, t[(va & (OneMeg-1))>>PGSHIFT]); . 243c t = (ulong*)pg->va; . 241c print("%lux[%lux] = %lux\n", l1table, va>>20, l1table[va>>20]); . 239c l1table[va>>20] = L1PageTable | L1Domain0 | (pg->pa & L1PTBaseMask); . 230,237c pg = up->l1page[va>>20]; if(pg == nil){ pg = up->mmufree; if(pg != nil){ up->mmufree = pg->next; } else { pg = auxpage(); if(pg == nil) pexit("out of memory", 1); } pg->va = VA(kmap(pg)); up->l1page[va>>20] = pg; memset((uchar*)(pg->va), 0, BY2PG); . 228c print("putmmu(0x%.8lux, 0x%.8lux)\n", va, pa); . 225c Page *pg; . ## diffname bitsy/mmu.c 2000/1018 ## diff -e /n/emeliedump/2000/1016/sys/src/9/bitsy/mmu.c /n/emeliedump/2000/1018/sys/src/9/bitsy/mmu.c 323,325c /* make sure map is in memory */ cachewbregion(l1table, sizeof(p->l1table)); . 317,319d 311a /* write back dirty cache entries and invalidate all cache entries */ cacheflush(); . 302a cachewbregion(l1table, sizeof(p->l1table)); . 256c /* write back dirty entries - we need this because the pio() in * fault.c is writing via a different virt addr and won't clean * its changes out of the dcache. Page coloring doesn't work * on this mmu because the virtual cache is set associative * rather than direct mapped. */ cachewb(); if(pg->cachectl[0] == PG_TXTFLUSH){ /* pio() sets PG_TXTFLUSH whenever a text page has been written */ icacheinvalidate(); pg->cachectl[0] = PG_NOFLUSH; } splx(s); . 253,254d 251c l2p = &t[(va & (OneMeg-1))>>PGSHIFT]; *l2p = mmubits[pa & (PTEKERNEL|PTEVALID|PTEUNCACHED|PTEWRITE)] . 249a /* always point L1 entry to L2 page, can't hurt */ l1p = &l1table[va>>20]; *l1p = L1PageTable | L1Domain0 | (l2pg->pa & L1PTBaseMask); up->l1table[va>>20] = *l1p; t = (ulong*)l2pg->va; . 244,248d 240,242c l2pg->va = VA(kmap(l2pg)); up->l1page[va>>20] = l2pg; memset((uchar*)(l2pg->va), 0, BY2PG); . 236,237c l2pg = auxpage(); if(l2pg == nil) . 228,234c s = splhi(); /* clear out the current entry */ mmuinvalidateaddr(va); l2pg = up->l1page[va>>20]; if(l2pg == nil){ l2pg = up->mmufree; if(l2pg != nil){ up->mmufree = l2pg->next; . 225,226c Page *l2pg; ulong *t, *l1p, *l2p; int s; . 223c putmmu(ulong va, ulong pa, Page *pg) . ## diffname bitsy/mmu.c 2000/1019 ## diff -e /n/emeliedump/2000/1018/sys/src/9/bitsy/mmu.c /n/emeliedump/2000/1019/sys/src/9/bitsy/mmu.c 378c iprint("l1: %lux[%lux] = %lux section\n", l1table, va>>20, e); . 374,375c d = ((ulong*)e)[va]; iprint("l2: %lux[%lux] = %lux\n", e, va, d); . 370c iprint("l1: %lux[%lux] = %lux pt\n", l1table, va>>20, e); . 367c iprint("l1: %lux[%lux] = %lux invalid\n", l1table, va>>20, e); . 362c ulong e, d; . 198a cacheflush(); . 181c for(i = 0; i < OneMeg && base <= end; i += BY2PG){ . 174c if(large) . 148c if(large){ . 134,135c large = len >= 128*1024; if(large){ . 130c int large; . ## diffname bitsy/mmu.c 2000/1106 ## diff -e /n/emeliedump/2000/1019/sys/src/9/bitsy/mmu.c /n/emeliedump/2000/1106/sys/src/9/bitsy/mmu.c 343c cachewbregion((ulong)l1table, sizeof(p->l1table)); . 321c cachewbregion((ulong)l1table, sizeof(p->l1table)); . ## diffname bitsy/mmu.c 2000/1118 ## diff -e /n/emeliedump/2000/1106/sys/src/9/bitsy/mmu.c /n/emeliedump/2000/1118/sys/src/9/bitsy/mmu.c 201a } /* map in i/o registers */ void* mapspecial(ulong pa, int len) { return _map(pa, len, REGZERO, REGTOP, L1KernelRW, L2KernelRW); } /* map add on memory */ void* mapmem(ulong pa, int len) { return _map(pa, len, EMEMZERO, EMEMTOP, L1KernelRW|L1Cached|L1Buffered, L2KernelRW|L2Cached|L2Buffered); } /* map a virtual address to a physical one */ ulong mmu_paddr(ulong va) { ulong entry; ulong *t; entry = l1table[va>>20]; switch(entry & L1TypeMask){ case L1Section: return (entry & L1SectBaseMask) | (va & (OneMeg-1)); case L1PageTable: t = (ulong*)(entry & L1PTBaseMask); va &= OneMeg-1; entry = t[va>>PGSHIFT]; switch(entry & L1TypeMask){ case L2SmallPage: return (entry & L2PageBaseMask) | (va & (BY2PG-1)); } } return 0; } /* map a physical address to a virtual one */ static ulong findva(ulong pa, ulong zero, ulong top) { int i; ulong entry, va; ulong start, end; ulong *t; for(va = zero; va < top; va += OneMeg){ /* search the L1 entry */ entry = l1table[va>>20]; switch(entry & L1TypeMask){ default: return 0; /* no holes */ case L1Section: start = entry & L1SectBaseMask; end = start + OneMeg; if(pa >= start && pa < end) return va | (pa & (OneMeg-1)); continue; case L1PageTable: break; } /* search the L2 entry */ t = (ulong*)(l1table[va>>20] & L1PTBaseMask); for(i = 0; i < OneMeg; i += BY2PG){ entry = t[i>>PGSHIFT]; /* found unused entry on level 2 table */ if((entry & L2TypeMask) != L2SmallPage) break; start = entry & L2PageBaseMask; end = start + BY2PG; if(pa >= start && pa < end) return va | (BY2PG*i) | (pa & (BY2PG-1)); } } return 0; } ulong mmu_kaddr(ulong pa) { ulong va; /* try the easy stuff first (the first case is true most of the time) */ if(pa >= PHYSDRAM0 && pa <= PHYSDRAM0+(DRAMTOP-DRAMZERO)) return DRAMZERO+(pa-PHYSDRAM0); if(pa >= PHYSFLASH0 && pa <= PHYSFLASH0+(FLASHTOP-FLASHZERO)) return FLASHZERO+(pa-PHYSFLASH0); if(pa >= PHYSNULL0 && pa <= PHYSNULL0+(NULLTOP-NULLZERO)) return NULLZERO+(pa-PHYSNULL0); if(!mmuinited) return 0; /* this shouldn't happen */ /* walk the map for the special regs and extended memory */ va = findva(pa, EMEMZERO, EMEMTOP); if(va != 0) return va; return findva(pa, REGZERO, REGTOP); . 188c t[i>>PGSHIFT] = L2SmallPage | l2prop | . 169c if((entry & ~L1SectBaseMask) == (L1Section | l1prop | L1Domain0)) . 151c l1table[va>>20] = L1Section | l1prop | L1Domain0 | . 144c for(va = zero; va < top && base <= end; va += OneMeg){ . 125,126c static void* _map(ulong pa, int len, ulong zero, ulong top, ulong l1prop, ulong l2prop) . 123c * map on request . 119a mmuinited = 1; . 91d 89c for(o = 0; o < FLASHTOP-FLASHZERO; o += OneMeg) . 83c for(o = 0; o < NULLTOP-NULLZERO; o += OneMeg) . 77c for(o = 0; o < DRAMTOP-DRAMZERO; o += OneMeg) . 70c /* map low mem (I really don't know why I have to do this -- presotto) */ . 55d 53a static int mmuinited; . ## diffname bitsy/mmu.c 2000/1121 ## diff -e /n/emeliedump/2000/1118/sys/src/9/bitsy/mmu.c /n/emeliedump/2000/1121/sys/src/9/bitsy/mmu.c 216,217c ulong l1, l2; if(cached){ l1 = L1KernelRW|L1Cached|L1Buffered; l2 = L2KernelRW|L2Cached|L2Buffered; } else { l1 = L1KernelRW; l2 = L2KernelRW; } return _map(pa, len, EMEMZERO, EMEMTOP, l1, l2); . 214c mapmem(ulong pa, int len, int cached) . ## diffname bitsy/mmu.c 2000/1130 ## diff -e /n/emeliedump/2000/1121/sys/src/9/bitsy/mmu.c /n/emeliedump/2000/1130/sys/src/9/bitsy/mmu.c 81a /* uncached DRAM */ for(o = 0; o < UCDRAMTOP-UCDRAMZERO; o += OneMeg) l1table[(UCDRAMZERO+o)>>20] = L1Section | L1KernelRW| L1Domain0 | ((PHYSDRAM0+o)&L1SectBaseMask); . ## diffname bitsy/mmu.c 2001/0810 ## diff -e /n/emeliedump/2000/1130/sys/src/9/bitsy/mmu.c /n/emeliedump/2001/0810/sys/src/9/bitsy/mmu.c 124,125d 112a mmurestart(); mmuinited = 1; } void mmurestart(void) { . ## diffname bitsy/mmu.c 2001/0813 ## diff -e /n/emeliedump/2001/0810/sys/src/9/bitsy/mmu.c /n/emeliedump/2001/0813/sys/src/9/bitsy/mmu.c 127a icacheinvalidate(); /* you never know ... (sape) */ . ## diffname bitsy/mmu.c 2001/0814 ## diff -e /n/emeliedump/2001/0813/sys/src/9/bitsy/mmu.c /n/emeliedump/2001/0814/sys/src/9/bitsy/mmu.c 128d 120a . ## diffname bitsy/mmu.c 2001/0815 ## diff -e /n/emeliedump/2001/0814/sys/src/9/bitsy/mmu.c /n/emeliedump/2001/0815/sys/src/9/bitsy/mmu.c 263c ulong .