diff options
author | cinap_lenrek <cinap_lenrek@felloff.net> | 2023-10-29 17:43:24 +0000 |
---|---|---|
committer | cinap_lenrek <cinap_lenrek@felloff.net> | 2023-10-29 17:43:24 +0000 |
commit | 1fd5f5205dd80e00b9a069567e46dd3a261ecd24 (patch) | |
tree | b43a3b0d53aafd24aabed17dcddf18103ee9da3e | |
parent | 015180f99be4553dc4851f63edff04d0fc16a66a (diff) |
bcm64: use generic 9/arm64/mmu.c
-rw-r--r-- | sys/src/9/bcm64/fns.h | 8 | ||||
-rw-r--r-- | sys/src/9/bcm64/mem.c | 146 | ||||
-rw-r--r-- | sys/src/9/bcm64/mem.h | 1 | ||||
-rw-r--r-- | sys/src/9/bcm64/mkfile | 7 | ||||
-rw-r--r-- | sys/src/9/bcm64/mmu.c | 516 |
5 files changed, 156 insertions, 522 deletions
diff --git a/sys/src/9/bcm64/fns.h b/sys/src/9/bcm64/fns.h index 6249bf77c..327152cce 100644 --- a/sys/src/9/bcm64/fns.h +++ b/sys/src/9/bcm64/fns.h @@ -68,16 +68,18 @@ extern void kmapinval(void); #define VA(k) ((uintptr)(k)) extern KMap *kmap(Page*); extern void kunmap(KMap*); +extern void kmapram(uintptr, uintptr); extern uintptr mmukmap(uintptr, uintptr, usize); extern void* vmap(uvlong, vlong); extern void vunmap(void*, vlong); +extern void mmu1init(void); +extern void putasid(Proc*); +/* mem */ +extern void mmuidmap(uintptr*); extern void mmu0init(uintptr*); -extern void mmu1init(void); extern void meminit(void); -extern void putasid(Proc*); - /* clock */ extern void clockinit(void); extern void synccycles(void); diff --git a/sys/src/9/bcm64/mem.c b/sys/src/9/bcm64/mem.c new file mode 100644 index 000000000..53df006ba --- /dev/null +++ b/sys/src/9/bcm64/mem.c @@ -0,0 +1,146 @@ +#include "u.h" +#include "../port/lib.h" +#include "mem.h" +#include "dat.h" +#include "fns.h" +#include "../arm64/sysreg.h" + +#define INITMAP (ROUND((uintptr)end + BY2PG, PGLSZ(1))-KZERO) + +/* + * Create initial identity map in top-level page table + * (L1BOT) for TTBR0. This page table is only used until + * mmu1init() loads m->mmutop. + */ +void +mmuidmap(uintptr *l1bot) +{ + uintptr pa, pe, attr; + + attr = PTEWRITE | PTEAF | PTEKERNEL | PTEUXN | PTESH(SHARE_INNER); + pe = -KZERO; + for(pa = PHYSDRAM; pa < pe; pa += PGLSZ(PTLEVELS-1)) + l1bot[PTLX(pa, PTLEVELS-1)] = pa | PTEVALID | PTEBLOCK | attr; +} + +/* + * Create initial shared kernel page table (L1) for TTBR1. + * This page table coveres the KZERO and VIRTIO. + */ +void +mmu0init(uintptr *l1) +{ + uintptr va, pa, pe, attr; + + /* KZERO */ + attr = PTEWRITE | PTEAF | PTEKERNEL | PTEUXN | PTESH(SHARE_INNER); + pe = -KZERO; + for(pa = PHYSDRAM, va = KZERO; pa < pe; pa += PGLSZ(1), va += PGLSZ(1)) + l1[PTL1X(va, 1)] = pa | PTEVALID | PTEBLOCK | attr; + + /* VIRTIO */ + attr = PTEWRITE | PTEAF | PTEKERNEL | PTEUXN | PTEPXN | PTESH(SHARE_OUTER) | PTEDEVICE; + pe = soc.physio + soc.iosize; + for(pa = soc.physio, va = soc.virtio; pa < pe; pa += PGLSZ(1), va += PGLSZ(1)){ + if(((pa|va) & PGLSZ(1)-1) != 0){ + l1[PTL1X(va, 1)] = (uintptr)l1 | PTEVALID | PTETABLE; + for(; pa < pe && ((va|pa) & PGLSZ(1)-1) != 0; pa += PGLSZ(0), va += PGLSZ(0)){ + assert(l1[PTLX(va, 0)] == 0); + l1[PTLX(va, 0)] = pa | PTEVALID | PTEPAGE | attr; + } + break; + } + l1[PTL1X(va, 1)] = pa | PTEVALID | PTEBLOCK | attr; + } + + /* ARMLOCAL */ + attr = PTEWRITE | PTEAF | PTEKERNEL | PTEUXN | PTEPXN | PTESH(SHARE_OUTER) | PTEDEVICE; + pe = soc.armlocal + MB; + for(pa = soc.armlocal, va = ARMLOCAL; pa < pe; pa += PGLSZ(1), va += PGLSZ(1)){ + if(((pa|va) & PGLSZ(1)-1) != 0){ + l1[PTL1X(va, 1)] = (uintptr)l1 | PTEVALID | PTETABLE; + for(; pa < pe && ((va|pa) & PGLSZ(1)-1) != 0; pa += PGLSZ(0), va += PGLSZ(0)){ + assert(l1[PTLX(va, 0)] == 0); + l1[PTLX(va, 0)] = pa | PTEVALID | PTEPAGE | attr; + } + break; + } + l1[PTL1X(va, 1)] = pa | PTEVALID | PTEBLOCK | attr; + } + + if(PTLEVELS > 2) + for(va = KSEG0; va != 0; va += PGLSZ(2)) + l1[PTL1X(va, 2)] = (uintptr)&l1[L1TABLEX(va, 1)] | PTEVALID | PTETABLE; + if(PTLEVELS > 3) + for(va = KSEG0; va != 0; va += PGLSZ(3)) + l1[PTL1X(va, 3)] = (uintptr)&l1[L1TABLEX(va, 2)] | PTEVALID | PTETABLE; +} + +void +meminit(void) +{ + uvlong memsize = 0; + uintptr pa, va; + char *p, *e; + int i; + + if(p = getconf("*maxmem")){ + memsize = strtoull(p, &e, 0) - PHYSDRAM; + for(i = 1; i < nelem(conf.mem); i++){ + if(e <= p || *e != ' ') + break; + p = ++e; + conf.mem[i].base = strtoull(p, &e, 0); + if(e <= p || *e != ' ') + break; + p = ++e; + conf.mem[i].limit = strtoull(p, &e, 0); + } + } + + if (memsize < INITMAP) /* sanity */ + memsize = INITMAP; + + getramsize(&conf.mem[0]); + if(conf.mem[0].limit == 0){ + conf.mem[0].base = PHYSDRAM; + conf.mem[0].limit = PHYSDRAM + memsize; + }else if(p != nil) + conf.mem[0].limit = conf.mem[0].base + memsize; + + /* + * now we know the real memory regions, unmap + * everything above INITMAP and map again with + * the proper sizes. + */ + coherence(); + for(va = INITMAP+KZERO; va != 0; va += PGLSZ(1)) + ((uintptr*)L1)[PTL1X(va, 1)] = 0; + flushtlb(); + + pa = PGROUND((uintptr)end)-KZERO; + for(i=0; i<nelem(conf.mem); i++){ + if(conf.mem[i].limit >= KMAPEND-KMAP) + conf.mem[i].limit = KMAPEND-KMAP; + + if(conf.mem[i].limit <= conf.mem[i].base){ + conf.mem[i].limit = conf.mem[i].base = 0; + continue; + } + + if(conf.mem[i].base < PHYSDRAM + soc.dramsize + && conf.mem[i].limit > PHYSDRAM + soc.dramsize) + conf.mem[i].limit = PHYSDRAM + soc.dramsize; + + /* take kernel out of allocatable space */ + if(pa > conf.mem[i].base && pa < conf.mem[i].limit) + conf.mem[i].base = pa; + + kmapram(conf.mem[i].base, conf.mem[i].limit); + } + flushtlb(); + + /* rampage() is now done, count up the pages for each bank */ + for(i=0; i<nelem(conf.mem); i++) + conf.mem[i].npage = (conf.mem[i].limit - conf.mem[i].base)/BY2PG; +} diff --git a/sys/src/9/bcm64/mem.h b/sys/src/9/bcm64/mem.h index 5fb30e68e..1ed184d05 100644 --- a/sys/src/9/bcm64/mem.h +++ b/sys/src/9/bcm64/mem.h @@ -54,6 +54,7 @@ #define ARMLOCAL (0xFFFFFFFFBF800000ULL) /* - 0x40000000 0xFF800000 */ #define VGPIO (0xFFFFFFFFBFA00000ULL|PTEUNCACHED) /* virtual gpio for pi3 ACT LED */ +#define VDRAM KZERO #define KZERO (0xFFFFFFFFC0000000ULL) /* kernel address space */ diff --git a/sys/src/9/bcm64/mkfile b/sys/src/9/bcm64/mkfile index b489c9ce7..0476d825b 100644 --- a/sys/src/9/bcm64/mkfile +++ b/sys/src/9/bcm64/mkfile @@ -47,6 +47,7 @@ OBJ=\ fpu.$O\ main.$O\ mmu.$O\ + mem.$O\ sysreg.$O\ random.$O\ trap.$O\ @@ -97,7 +98,7 @@ cache.v8.$O: ../arm64/cache.v8.s init9.$O: ../arm64/init9.s $AS $AFLAGS -I. -. ../arm64/init9.s -REPCC=`{../port/mkfilelist ../bcm | sed 's/(fpu|trap)[|)]//g'} +REPCC=`{../port/mkfilelist ../bcm | sed 's/(mmu|fpu|trap)[|)]//g'} ^($REPCC)\.$O:R: '../bcm/\1.c' $CC $CFLAGS -I. -. ../bcm/$stem1.c @@ -108,8 +109,8 @@ REPCC=`{../port/mkfilelist ../bcm | sed 's/(fpu|trap)[|)]//g'} arch.$O clock.$O fpiarm.$O main.$O mmu.$O screen.$O syscall.$O trap.$O: \ /$objtype/include/ureg.h trap.$O main.$O: /sys/include/tos.h -l.$O cache.v8.$O mmu.$O rebootcode.$O: mem.h -l.$O cache.v8.$O archbcm3.$O clock.$O fpu.$O trap.$O mmu.$O rebootcode.$O: ../arm64/sysreg.h +l.$O cache.v8.$O mmu.$O mem.$O rebootcode.$O: mem.h +l.$O cache.v8.$O archbcm3.$O clock.$O fpu.$O trap.$O rebootcode.$O: ../arm64/sysreg.h main.$O: rebootcode.i pcibcm.$O: ../port/pci.h diff --git a/sys/src/9/bcm64/mmu.c b/sys/src/9/bcm64/mmu.c deleted file mode 100644 index 9a8a34fa2..000000000 --- a/sys/src/9/bcm64/mmu.c +++ /dev/null @@ -1,516 +0,0 @@ -#include "u.h" -#include "../port/lib.h" -#include "mem.h" -#include "dat.h" -#include "fns.h" -#include "../arm64/sysreg.h" - -#define INITMAP (ROUND((uintptr)end + BY2PG, PGLSZ(1))-KZERO) - -/* - * Create initial identity map in top-level page table - * (L1BOT) for TTBR0. This page table is only used until - * mmu1init() loads m->mmutop. - */ -void -mmuidmap(uintptr *l1bot) -{ - uintptr pa, pe, attr; - - attr = PTEWRITE | PTEAF | PTEKERNEL | PTEUXN | PTESH(SHARE_INNER); - pe = -KZERO; - for(pa = PHYSDRAM; pa < pe; pa += PGLSZ(PTLEVELS-1)) - l1bot[PTLX(pa, PTLEVELS-1)] = pa | PTEVALID | PTEBLOCK | attr; -} - -/* - * Create initial shared kernel page table (L1) for TTBR1. - * This page table coveres the KZERO and VIRTIO. - */ -void -mmu0init(uintptr *l1) -{ - uintptr va, pa, pe, attr; - - /* KZERO */ - attr = PTEWRITE | PTEAF | PTEKERNEL | PTEUXN | PTESH(SHARE_INNER); - pe = -KZERO; - for(pa = PHYSDRAM, va = KZERO; pa < pe; pa += PGLSZ(1), va += PGLSZ(1)) - l1[PTL1X(va, 1)] = pa | PTEVALID | PTEBLOCK | attr; - - /* VIRTIO */ - attr = PTEWRITE | PTEAF | PTEKERNEL | PTEUXN | PTEPXN | PTESH(SHARE_OUTER) | PTEDEVICE; - pe = soc.physio + soc.iosize; - for(pa = soc.physio, va = soc.virtio; pa < pe; pa += PGLSZ(1), va += PGLSZ(1)){ - if(((pa|va) & PGLSZ(1)-1) != 0){ - l1[PTL1X(va, 1)] = (uintptr)l1 | PTEVALID | PTETABLE; - for(; pa < pe && ((va|pa) & PGLSZ(1)-1) != 0; pa += PGLSZ(0), va += PGLSZ(0)){ - assert(l1[PTLX(va, 0)] == 0); - l1[PTLX(va, 0)] = pa | PTEVALID | PTEPAGE | attr; - } - break; - } - l1[PTL1X(va, 1)] = pa | PTEVALID | PTEBLOCK | attr; - } - - /* ARMLOCAL */ - attr = PTEWRITE | PTEAF | PTEKERNEL | PTEUXN | PTEPXN | PTESH(SHARE_OUTER) | PTEDEVICE; - pe = soc.armlocal + MB; - for(pa = soc.armlocal, va = ARMLOCAL; pa < pe; pa += PGLSZ(1), va += PGLSZ(1)){ - if(((pa|va) & PGLSZ(1)-1) != 0){ - l1[PTL1X(va, 1)] = (uintptr)l1 | PTEVALID | PTETABLE; - for(; pa < pe && ((va|pa) & PGLSZ(1)-1) != 0; pa += PGLSZ(0), va += PGLSZ(0)){ - assert(l1[PTLX(va, 0)] == 0); - l1[PTLX(va, 0)] = pa | PTEVALID | PTEPAGE | attr; - } - break; - } - l1[PTL1X(va, 1)] = pa | PTEVALID | PTEBLOCK | attr; - } - - if(PTLEVELS > 2) - for(va = KSEG0; va != 0; va += PGLSZ(2)) - l1[PTL1X(va, 2)] = (uintptr)&l1[L1TABLEX(va, 1)] | PTEVALID | PTETABLE; - if(PTLEVELS > 3) - for(va = KSEG0; va != 0; va += PGLSZ(3)) - l1[PTL1X(va, 3)] = (uintptr)&l1[L1TABLEX(va, 2)] | PTEVALID | PTETABLE; -} - -void -mmu1init(void) -{ - m->mmutop = mallocalign(L1TOPSIZE, BY2PG, 0, 0); - if(m->mmutop == nil) - panic("mmu1init: no memory for mmutop"); - memset(m->mmutop, 0, L1TOPSIZE); - mmuswitch(nil); -} - -/* KZERO maps the first 1GB of ram */ -uintptr -paddr(void *va) -{ - if((uintptr)va >= KZERO) - return (uintptr)va-KZERO; - panic("paddr: va=%#p pc=%#p", va, getcallerpc(&va)); - return 0; -} - -uintptr -cankaddr(uintptr pa) -{ - if(pa < (uintptr)-KZERO) - return -KZERO - pa; - return 0; -} - -void* -kaddr(uintptr pa) -{ - if(pa < (uintptr)-KZERO) - return (void*)(pa + KZERO); - panic("kaddr: pa=%#p pc=%#p", pa, getcallerpc(&pa)); - return nil; -} - -static void* -kmapaddr(uintptr pa) -{ - if(pa < (uintptr)-KZERO) - return (void*)(pa + KZERO); - if(pa >= KMAPEND-KMAP) - panic("kmapaddr: pa=%#p pc=%#p", pa, getcallerpc(&pa)); - return (void*)(pa + KMAP); -} - -KMap* -kmap(Page *p) -{ - return kmapaddr(p->pa); -} - -void -kunmap(KMap*) -{ -} - -void -kmapinval(void) -{ -} - -static void* -rampage(void) -{ - uintptr pa; - - if(conf.npage) - return mallocalign(BY2PG, BY2PG, 0, 0); - - pa = conf.mem[0].base; - assert((pa % BY2PG) == 0); - assert(pa < INITMAP); - conf.mem[0].base += BY2PG; - return KADDR(pa); -} - -static void -l1map(uintptr va, uintptr pa, uintptr pe, uintptr attr) -{ - uintptr *l1, *l0; - - assert(pa < pe); - - va &= -BY2PG; - pa &= -BY2PG; - pe = PGROUND(pe); - - attr |= PTEKERNEL | PTEAF; - - l1 = (uintptr*)L1; - - while(pa < pe){ - if(l1[PTL1X(va, 1)] == 0 && (pe-pa) >= PGLSZ(1) && ((va|pa) & PGLSZ(1)-1) == 0){ - l1[PTL1X(va, 1)] = PTEVALID | PTEBLOCK | pa | attr; - va += PGLSZ(1); - pa += PGLSZ(1); - continue; - } - if(l1[PTL1X(va, 1)] & PTEVALID) { - assert((l1[PTL1X(va, 1)] & PTETABLE) == PTETABLE); - l0 = KADDR(l1[PTL1X(va, 1)] & -PGLSZ(0)); - } else { - l0 = rampage(); - memset(l0, 0, BY2PG); - l1[PTL1X(va, 1)] = PTEVALID | PTETABLE | PADDR(l0); - } - assert(l0[PTLX(va, 0)] == 0); - l0[PTLX(va, 0)] = PTEVALID | PTEPAGE | pa | attr; - va += BY2PG; - pa += BY2PG; - } -} - -static void -kmapram(uintptr base, uintptr limit) -{ - if(base < (uintptr)-KZERO && limit > (uintptr)-KZERO){ - kmapram(base, (uintptr)-KZERO); - kmapram((uintptr)-KZERO, limit); - return; - } - if(base < INITMAP) - base = INITMAP; - if(base >= limit || limit <= INITMAP) - return; - - l1map((uintptr)kmapaddr(base), base, limit, - PTEWRITE | PTEPXN | PTEUXN | PTESH(SHARE_INNER)); -} - -void -meminit(void) -{ - uvlong memsize = 0; - uintptr pa, va; - char *p, *e; - int i; - - if(p = getconf("*maxmem")){ - memsize = strtoull(p, &e, 0) - PHYSDRAM; - for(i = 1; i < nelem(conf.mem); i++){ - if(e <= p || *e != ' ') - break; - p = ++e; - conf.mem[i].base = strtoull(p, &e, 0); - if(e <= p || *e != ' ') - break; - p = ++e; - conf.mem[i].limit = strtoull(p, &e, 0); - } - } - - if (memsize < INITMAP) /* sanity */ - memsize = INITMAP; - - getramsize(&conf.mem[0]); - if(conf.mem[0].limit == 0){ - conf.mem[0].base = PHYSDRAM; - conf.mem[0].limit = PHYSDRAM + memsize; - }else if(p != nil) - conf.mem[0].limit = conf.mem[0].base + memsize; - - /* - * now we know the real memory regions, unmap - * everything above INITMAP and map again with - * the proper sizes. - */ - coherence(); - for(va = INITMAP+KZERO; va != 0; va += PGLSZ(1)) - ((uintptr*)L1)[PTL1X(va, 1)] = 0; - flushtlb(); - - pa = PGROUND((uintptr)end)-KZERO; - for(i=0; i<nelem(conf.mem); i++){ - if(conf.mem[i].limit >= KMAPEND-KMAP) - conf.mem[i].limit = KMAPEND-KMAP; - - if(conf.mem[i].limit <= conf.mem[i].base){ - conf.mem[i].limit = conf.mem[i].base = 0; - continue; - } - - if(conf.mem[i].base < PHYSDRAM + soc.dramsize - && conf.mem[i].limit > PHYSDRAM + soc.dramsize) - conf.mem[i].limit = PHYSDRAM + soc.dramsize; - - /* take kernel out of allocatable space */ - if(pa > conf.mem[i].base && pa < conf.mem[i].limit) - conf.mem[i].base = pa; - - kmapram(conf.mem[i].base, conf.mem[i].limit); - } - flushtlb(); - - /* rampage() is now done, count up the pages for each bank */ - for(i=0; i<nelem(conf.mem); i++) - conf.mem[i].npage = (conf.mem[i].limit - conf.mem[i].base)/BY2PG; -} - -uintptr -mmukmap(uintptr va, uintptr pa, usize size) -{ - uintptr attr, off; - - if(va == 0) - return 0; - - off = pa & BY2PG-1; - - attr = va & PTEMA(7); - attr |= PTEWRITE | PTEUXN | PTEPXN | PTESH(SHARE_OUTER); - - va &= -BY2PG; - pa &= -BY2PG; - - l1map(va, pa, pa + off + size, attr); - flushtlb(); - - return va + off; -} - -void* -vmap(uvlong pa, vlong size) -{ - static uintptr base = VMAP; - uvlong pe = pa + size; - uintptr va; - - va = base; - base += PGROUND(pe) - (pa & -BY2PG); - - return (void*)mmukmap(va | PTEDEVICE, pa, size); -} - -void -vunmap(void *, vlong) -{ -} - -static uintptr* -mmuwalk(uintptr va, int level) -{ - uintptr *table, pte; - Page *pg; - int i, x; - - x = PTLX(va, PTLEVELS-1); - table = m->mmutop; - for(i = PTLEVELS-2; i >= level; i--){ - pte = table[x]; - if(pte & PTEVALID) { - if(pte & (0xFFFFULL<<48)) - iprint("strange pte %#p va %#p\n", pte, va); - pte &= ~(0xFFFFULL<<48 | BY2PG-1); - } else { - pg = up->mmufree; - if(pg == nil) - return nil; - up->mmufree = pg->next; - pg->va = va & -PGLSZ(i+1); - if((pg->next = up->mmuhead[i+1]) == nil) - up->mmutail[i+1] = pg; - up->mmuhead[i+1] = pg; - pte = pg->pa; - memset(kmapaddr(pte), 0, BY2PG); - coherence(); - table[x] = pte | PTEVALID | PTETABLE; - } - table = kmapaddr(pte); - x = PTLX(va, (uintptr)i); - } - return &table[x]; -} - -static Proc *asidlist[256]; - -static int -allocasid(Proc *p) -{ - static Lock lk; - Proc *x; - int a; - - lock(&lk); - a = p->asid; - if(a < 0) - a = -a; - if(a == 0) - a = p->pid; - for(;; a++){ - a %= nelem(asidlist); - if(a == 0) - continue; // reserved - x = asidlist[a]; - if(x == p || x == nil || (x->asid < 0 && x->mach == nil)) - break; - } - p->asid = a; - asidlist[a] = p; - unlock(&lk); - - return x != p; -} - -static void -freeasid(Proc *p) -{ - int a; - - a = p->asid; - if(a < 0) - a = -a; - if(a > 0 && asidlist[a] == p) - asidlist[a] = nil; - p->asid = 0; -} - -void -putasid(Proc *p) -{ - /* - * Prevent the following scenario: - * pX sleeps on cpuA, leaving its page tables in mmutop - * pX wakes up on cpuB, and exits, freeing its page tables - * pY on cpuB allocates a freed page table page and overwrites with data - * cpuA takes an interrupt, and is now running with bad page tables - * In theory this shouldn't hurt because only user address space tables - * are affected, and mmuswitch will clear mmutop before a user process is - * dispatched. But empirically it correlates with weird problems, eg - * resetting of the core clock at 0x4000001C which confuses local timers. - */ - if(conf.nmach > 1) - mmuswitch(nil); - - if(p->asid > 0) - p->asid = -p->asid; -} - -void -putmmu(uintptr va, uintptr pa, Page *pg) -{ - uintptr *pte, old; - int s; - - s = splhi(); - while((pte = mmuwalk(va, 0)) == nil){ - spllo(); - up->mmufree = newpage(0, nil, 0); - splhi(); - } - old = *pte; - *pte = 0; - if((old & PTEVALID) != 0) - flushasidvall((uvlong)up->asid<<48 | va>>12); - else - flushasidva((uvlong)up->asid<<48 | va>>12); - *pte = pa | PTEPAGE | PTEUSER | PTEPXN | PTENG | PTEAF | - (((pa & PTEMA(7)) == PTECACHED)? PTESH(SHARE_INNER): PTESH(SHARE_OUTER)); - if(needtxtflush(pg)){ - cachedwbinvse(kmap(pg), BY2PG); - cacheiinvse((void*)va, BY2PG); - donetxtflush(pg); - } - splx(s); -} - -static void -mmufree(Proc *p) -{ - int i; - - freeasid(p); - - for(i=1; i<PTLEVELS; i++){ - if(p->mmuhead[i] == nil) - break; - p->mmutail[i]->next = p->mmufree; - p->mmufree = p->mmuhead[i]; - p->mmuhead[i] = p->mmutail[i] = nil; - } -} - -void -mmuswitch(Proc *p) -{ - uintptr va; - Page *t; - - for(va = UZERO; va < USTKTOP; va += PGLSZ(PTLEVELS-1)) - m->mmutop[PTLX(va, PTLEVELS-1)] = 0; - - if(p == nil){ - setttbr(PADDR(m->mmutop)); - return; - } - - if(p->newtlb){ - mmufree(p); - p->newtlb = 0; - } - - if(allocasid(p)) - flushasid((uvlong)p->asid<<48); - - setttbr((uvlong)p->asid<<48 | PADDR(m->mmutop)); - - for(t = p->mmuhead[PTLEVELS-1]; t != nil; t = t->next){ - va = t->va; - m->mmutop[PTLX(va, PTLEVELS-1)] = t->pa | PTEVALID | PTETABLE; - } -} - -void -mmurelease(Proc *p) -{ - mmuswitch(nil); - mmufree(p); - freepages(p->mmufree, nil, 0); - p->mmufree = nil; -} - -void -flushmmu(void) -{ - int x; - - x = splhi(); - up->newtlb = 1; - mmuswitch(up); - splx(x); -} - -void -checkmmu(uintptr, uintptr) -{ -} |