| plan 9 kernel history: overview | file list | diff list |
2000/1002/bitsy/mmu.c (diff list | history)
| 2000/1002/sys/src/9/bitsy/mmu.c:1,199 – 2000/1006/sys/src/9/bitsy/mmu.c:1,194 (short | long | prev | next) | ||
| 2000/0902 | #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" | |
| 2000/0906 | /* real protection bits */ enum { | |
| 2000/0907 | /* 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), | |
| 2000/0906 | }; /* * table to map fault.c bits to physical bits */ | |
| 2000/0907 | static ulong phystrans[16] = | |
| 2000/0906 | { | |
| 2000/0907 | [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, | |
| 2000/0906 | }; | |
| 2000/0907 | ulong *l1table; | |
| 2000/0906 | /* * We map all of memory, flash, and the zeros area with sections. * Special use space is mapped on the fly with regmap. */ | |
| 2000/0902 | void | |
| 2000/0905 | mmuinit(void) { | |
| 2000/0906 | ulong a, e; | |
| 2000/0929 | ulong *t; | |
| 2000/0906 | /* get a prototype level 1 page */ | |
| 2000/0907 | l1table = xspanalloc(BY2PG, 16*1024, 0); memset(l1table, 0, BY2PG); | |
| 2000/0906 | ||
| 2000/0907 | /* direct map DRAM */ | |
| 2000/0928 | e = conf.base1 + BY2PG*conf.npage1; | |
| 2000/0907 | for(a = PHYSDRAM0; a < e; a += OneMeg) | |
| 2000/0929 | l1table[a>>20] = L1Section | L1KernelRW | (a&L1SectBaseMask) | L1Cached | L1Buffered; | |
| 2000/0907 | /* direct map zeros area */ for(a = PHYSNULL0; a < PHYSNULL0 + 128 * OneMeg; a += OneMeg) | |
| 2000/0929 | l1table[a>>20] = L1Section | L1KernelRW | (a&L1SectBaseMask); | |
| 2000/0907 | /* direct map flash */ | |
| 2000/0928 | for(a = PHYSFLASH0; a < PHYSFLASH0 + 128 * OneMeg; a += OneMeg) | |
| 2000/0929 | l1table[a>>20] = L1Section | L1KernelRW | (a&L1SectBaseMask) | L1Cached | L1Buffered; | |
| 2000/0907 | ||
| 2000/0929 | /* 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; | |
| 2000/0928 | /* set up the domain register to cause all domains to obey pte access bits */ iprint("setting up domain access\n"); | |
| 2000/0929 | putdac(0xFFFFFFFF); | |
| 2000/0928 | /* point to map */ iprint("setting tlb map %lux\n", (ulong)l1table); putttb((ulong)l1table); | |
| 2000/0929 |
| |
| 2000/1002 |
| |
| 2000/0929 |
| |
| 2000/0907 | } /* | |
| 2000/0923 | * map special space uncached, assume that the space isn't already mapped | |
| 2000/0907 | */ | |
| 2000/1002 | void* | |
| 2000/0924 | mapspecial(ulong pa, int len) | |
| 2000/0907 | { ulong *t; | |
| 2000/0928 | ulong va, i, base, end, off, entry; | |
| 2000/0924 | int livelarge; ulong* rv; | |
| 2000/0907 | ||
| 2000/0924 | 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; | |
| 2000/0921 | ||
| 2000/0929 | for(va = REGZERO; va < REGTOP && base <= end; va += OneMeg){ switch(l1table[va>>20] & L1TypeMask){ default: | |
| 2000/0924 | /* found unused entry on level 1 table */ if(livelarge){ if(rv == nil) | |
| 2000/0929 | rv = (ulong*)(va+off); | |
| 2000/0924 | l1table[va>>20] = L1Section | L1KernelRW | | |
| 2000/0929 | (base & L1SectBaseMask); | |
| 2000/0924 | base += OneMeg; continue; | |
| 2000/0929 | } else { | |
| 2000/0924 | ||
| 2000/0929 | /* 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; | |
| 2000/0907 | } | |
| 2000/0924 | ||
| 2000/0929 | /* here if we're using page maps instead of sections */ | |
| 2000/0924 | t = (ulong*)(l1table[va>>20] & L1PTBaseMask); | |
| 2000/0907 | for(i = 0; i < OneMeg; i += BY2PG){ | |
| 2000/0924 | entry = t[i>>PGSHIFT]; | |
| 2000/0921 | ||
| 2000/0924 | /* found unused entry on level 2 table */ if((entry & L2TypeMask) != L2SmallPage){ if(rv == nil) | |
| 2000/0929 | rv = (ulong*)(va+i+off); | |
| 2000/0924 | t[i>>PGSHIFT] = L2SmallPage | L2KernelRW | (base & L2PageBaseMask); base += BY2PG; continue; | |
| 2000/0921 | } | |
| 2000/0907 | } } | |
| 2000/0909 | ||
| 2000/0924 | /* didn't fit */ if(base <= end) return nil; return rv; | |
| 2000/0905 | } void | |
| 2000/0902 | putmmu(ulong va, ulong pa, Page*) { USED(va, pa); } void mmurelease(Proc* proc) { USED(proc); } void mmuswitch(Proc* proc) { USED(proc); } | |