summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--sys/src/9/pc64/apbootstrap.s5
-rw-r--r--sys/src/9/pc64/main.c7
-rw-r--r--sys/src/9/pc64/memory.c6
-rw-r--r--sys/src/9/pc64/mmu.c60
-rw-r--r--sys/src/9/pc64/squidboy.c1
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.