diff options
Diffstat (limited to 'sys/src/9/pc64/mmu.c')
| -rw-r--r-- | sys/src/9/pc64/mmu.c | 60 |
1 files changed, 58 insertions, 2 deletions
diff --git a/sys/src/9/pc64/mmu.c b/sys/src/9/pc64/mmu.c index 6db61bf00..8560eb03c 100644 --- a/sys/src/9/pc64/mmu.c +++ b/sys/src/9/pc64/mmu.c @@ -73,6 +73,8 @@ taskswitch(uintptr stack) mmuflushtlb(); } +static void kernelro(void); + void mmuinit(void) { @@ -84,6 +86,9 @@ mmuinit(void) m->pml4[512] = 0; m->pml4[0] = 0; + if(m->machno == 0) + kernelro(); + m->tss = mallocz(sizeof(Tss), 1); if(m->tss == nil) panic("mmuinit: no memory for Tss"); @@ -244,8 +249,6 @@ mmucreate(uintptr *table, uintptr va, int level, int index) up->kmapcount++; } page = p->page; - } else if(conf.mem[0].npage != 0) { - page = mallocalign(PTSZ, BY2PG, 0, 0); } else { page = rampage(); } @@ -287,6 +290,59 @@ ptecount(uintptr va, int level) return (1<<PTSHIFT) - (va & PGLSZ(level+1)-1) / PGLSZ(level); } +static void +ptesplit(uintptr* table, uintptr va) +{ + uintptr *pte, pa, off; + + pte = mmuwalk(table, va, 1, 0); + if(pte == nil || (*pte & PTESIZE) == 0 || (va & PGLSZ(1)-1) == 0) + return; + table = rampage(); + if(table == nil) + panic("ptesplit: out of memory\n"); + va &= -PGLSZ(1); + pa = *pte & ~PTESIZE; + for(off = 0; off < PGLSZ(1); off += PGLSZ(0)) + table[PTLX(va + off, 0)] = pa + off; + *pte = PADDR(table) | PTEVALID|PTEWRITE; + invlpg(va); +} + +/* + * map kernel text segment readonly + * and everything else no-execute. + */ +static void +kernelro(void) +{ + uintptr *pte, psz, va; + + ptesplit(m->pml4, APBOOTSTRAP); + ptesplit(m->pml4, KTZERO); + ptesplit(m->pml4, (uintptr)etext-1); + + for(va = KZERO; va != 0; va += psz){ + psz = PGLSZ(0); + pte = mmuwalk(m->pml4, va, 0, 0); + if(pte == nil){ + if(va & PGLSZ(1)-1) + continue; + pte = mmuwalk(m->pml4, va, 1, 0); + if(pte == nil) + continue; + psz = PGLSZ(1); + } + if((*pte & PTEVALID) == 0) + continue; + if(va >= KTZERO && va < (uintptr)etext) + *pte &= ~PTEWRITE; + else if(va != (APBOOTSTRAP & -BY2PG)) + *pte |= PTENOEXEC; + invlpg(va); + } +} + void pmap(uintptr *pml4, uintptr pa, uintptr va, vlong size) { |
