diff options
| -rw-r--r-- | sys/src/9/pc64/apbootstrap.s | 5 | ||||
| -rw-r--r-- | sys/src/9/pc64/main.c | 7 | ||||
| -rw-r--r-- | sys/src/9/pc64/memory.c | 6 | ||||
| -rw-r--r-- | sys/src/9/pc64/mmu.c | 60 | ||||
| -rw-r--r-- | sys/src/9/pc64/squidboy.c | 1 |
5 files changed, 74 insertions, 5 deletions
diff --git a/sys/src/9/pc64/apbootstrap.s b/sys/src/9/pc64/apbootstrap.s index 951abd5f3..c93d54f09 100644 --- a/sys/src/9/pc64/apbootstrap.s +++ b/sys/src/9/pc64/apbootstrap.s @@ -42,6 +42,9 @@ TEXT _apapic(SB), 1, $-4 /* address APBOOTSTRAP+0x18 */ QUAD $0 TEXT _apmach(SB), 1, $-4 /* address APBOOTSTRAP+0x20 */ QUAD $0 +TEXT _apefer(SB), 1, $-4 + QUAD $0x100 /* Long Mode Enable */ + TEXT _apbootstrap(SB), 1, $-4 MOVW CS, AX MOVW AX, DS /* initialise DS */ @@ -85,7 +88,7 @@ TEXT _ap32(SB), 1, $-4 MOVL $0xc0000080, CX /* Extended Feature Enable */ RDMSR - ORL $0x00000100, AX /* Long Mode Enable */ + ORL _apefer-KZERO(SB), AX WRMSR MOVL CR0, DX diff --git a/sys/src/9/pc64/main.c b/sys/src/9/pc64/main.c index c8e705f49..1abad73e4 100644 --- a/sys/src/9/pc64/main.c +++ b/sys/src/9/pc64/main.c @@ -301,6 +301,7 @@ static void rebootjump(uintptr entry, uintptr code, ulong size) { void (*f)(uintptr, uintptr, ulong); + uintptr *pte; splhi(); arch->introff(); @@ -310,6 +311,12 @@ rebootjump(uintptr entry, uintptr code, ulong size) */ *mmuwalk(m->pml4, 0, 3, 0) = *mmuwalk(m->pml4, KZERO, 3, 0); *mmuwalk(m->pml4, 0, 2, 0) = *mmuwalk(m->pml4, KZERO, 2, 0); + + if((pte = mmuwalk(m->pml4, REBOOTADDR, 1, 0)) != nil) + *pte &= ~PTENOEXEC; + if((pte = mmuwalk(m->pml4, REBOOTADDR, 0, 0)) != nil) + *pte &= ~PTENOEXEC; + mmuflushtlb(); /* setup reboot trampoline function */ diff --git a/sys/src/9/pc64/memory.c b/sys/src/9/pc64/memory.c index d737e6494..c2360abb3 100644 --- a/sys/src/9/pc64/memory.c +++ b/sys/src/9/pc64/memory.c @@ -221,6 +221,8 @@ rampage(void) { uintptr m; + if(conf.mem[0].npage != 0) + return xspanalloc(BY2PG, BY2PG, 0); m = mapalloc(&rmapram, 0, BY2PG, BY2PG); if(m == 0) return nil; @@ -543,11 +545,11 @@ map(uintptr base, uintptr len, int type) switch(type){ case MemRAM: mapfree(&rmapram, base, len); - flags = PTEWRITE|PTEVALID; + flags = PTEWRITE|PTENOEXEC|PTEVALID; break; case MemUMB: mapfree(&rmapumb, base, len); - flags = PTEWRITE|PTEUNCACHED|PTEVALID; + flags = PTEWRITE|PTEUNCACHED|PTENOEXEC|PTEVALID; break; case MemUPA: mapfree(&rmapupa, base, len); 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) { diff --git a/sys/src/9/pc64/squidboy.c b/sys/src/9/pc64/squidboy.c index e920c413b..dda4f257f 100644 --- a/sys/src/9/pc64/squidboy.c +++ b/sys/src/9/pc64/squidboy.c @@ -79,6 +79,7 @@ mpstartap(Apic* apic) apbootp[1] = (uintptr)PADDR(pml4); apbootp[2] = (uintptr)apic; apbootp[3] = (uintptr)mach; + apbootp[4] |= (uintptr)m->havenx<<11; /* EFER */ /* * Universal Startup Algorithm. |
