ref: 1e773c97e79d74983edd9b46694956f76b0c7fd5
parent: 49411b2ca15b94b6631fd54d2576c5aeff63eb67
author: cinap_lenrek <[email protected]>
date: Mon Aug 26 23:55:12 EDT 2019
pc64: implement NX bit discovery, map kernel mappings no-execute
--- a/sys/src/9/pc/dat.h
+++ b/sys/src/9/pc/dat.h
@@ -244,6 +244,7 @@
int havetsc;
int havepge;
int havewatchpt8;
+ int havenx;
uvlong tscticks;
int pdballoc;
int pdbfree;
--- a/sys/src/9/pc/devarch.c
+++ b/sys/src/9/pc/devarch.c
@@ -899,10 +899,26 @@
else
hwrandbuf = nil;
- /* 8-byte watchpoints are supported in Long Mode */
- if(sizeof(uintptr) == 8)
+ if(sizeof(uintptr) == 8) {
+ /* 8-byte watchpoints are supported in Long Mode */
m->havewatchpt8 = 1;
- else if(strcmp(m->cpuidid, "GenuineIntel") == 0){
+
+ /* check and enable NX bit */
+ cpuid(Highextfunc, regs);
+ if(regs[0] >= Procextfeat){
+ cpuid(Procextfeat, regs);
+ if((regs[3] & (1<<20)) != 0){
+ vlong efer;
+
+ /* enable no-execute feature */
+ if(rdmsr(Efer, &efer) != -1){
+ efer |= 1ull<<11;
+ if(wrmsr(Efer, efer) != -1)
+ m->havenx = 1;
+ }
+ }
+ }
+ } else if(strcmp(m->cpuidid, "GenuineIntel") == 0){
/* some random CPUs that support 8-byte watchpoints */
if(family == 15 && (model == 3 || model == 4 || model == 6)
|| family == 6 && (model == 15 || model == 23 || model == 28))
--- a/sys/src/9/pc64/dat.h
+++ b/sys/src/9/pc64/dat.h
@@ -222,6 +222,7 @@
int havetsc;
int havepge;
int havewatchpt8;
+ int havenx;
uvlong tscticks;
u64int dr7; /* shadow copy of dr7 */
--- a/sys/src/9/pc64/mem.h
+++ b/sys/src/9/pc64/mem.h
@@ -143,7 +143,7 @@
#define PTEPERTAB (PTEMAPMEM/BY2PG)
#define SEGMAPSIZE 65536
#define SSEGMAPSIZE 16
-#define PPN(x) ((x)&~(BY2PG-1))
+#define PPN(x) ((x)&~(1ull<<63 | BY2PG-1))
/*
* physical MMU
@@ -158,6 +158,7 @@
#define PTEUSER (1ull<<2)
#define PTESIZE (1ull<<7)
#define PTEGLOBAL (1ull<<8)
+#define PTENOEXEC ((uvlong)m->havenx<<63)
/*
* Hierarchical Page Tables.
--- a/sys/src/9/pc64/mmu.c
+++ b/sys/src/9/pc64/mmu.c
@@ -116,24 +116,19 @@
taskswitch((uintptr)m + MACHSIZE);
ltr(TSSSEL);
- wrmsr(0xc0000100, 0ull); /* 64 bit fsbase */
- wrmsr(0xc0000101, (uvlong)&machp[m->machno]); /* 64 bit gsbase */
- wrmsr(0xc0000102, 0ull); /* kernel gs base */
+ wrmsr(FSbase, 0ull);
+ wrmsr(GSbase, (uvlong)&machp[m->machno]);
+ wrmsr(KernelGSbase, 0ull);
/* enable syscall extension */
- rdmsr(0xc0000080, &v);
+ rdmsr(Efer, &v);
v |= 1ull;
- wrmsr(0xc0000080, v);
+ wrmsr(Efer, v);
- /* IA32_STAR */
- wrmsr(0xc0000081, ((uvlong)UE32SEL << 48) | ((uvlong)KESEL << 32));
+ wrmsr(Star, ((uvlong)UE32SEL << 48) | ((uvlong)KESEL << 32));
+ wrmsr(Lstar, (uvlong)syscallentry);
+ wrmsr(Sfmask, 0x200);
- /* IA32_LSTAR */
- wrmsr(0xc0000082, (uvlong)syscallentry);
-
- /* SYSCALL flags mask */
- wrmsr(0xc0000084, 0x200);
-
/* IA32_PAT write combining */
if((MACHP(0)->cpuiddx & Pat) != 0
&& rdmsr(0x277, &v) != -1){
@@ -443,7 +438,7 @@
if(pte == 0)
panic("putmmu: bug: va=%#p pa=%#p", va, pa);
old = *pte;
- *pte = pa | PTEVALID|PTEUSER;
+ *pte = pa | PTEUSER;
splx(x);
if(old & PTEVALID)
invlpg(va);
@@ -487,7 +482,7 @@
pte = mmuwalk(m->pml4, va, 0, 1);
if(pte == 0 || (*pte & PTEVALID) != 0)
panic("kmap: pa=%#p va=%#p", pa, va);
- *pte = pa | PTEWRITE|PTEVALID;
+ *pte = pa | PTEWRITE|PTENOEXEC|PTEVALID;
splx(x);
invlpg(va);
return (KMap*)va;
@@ -533,7 +528,7 @@
pa -= o;
va -= o;
size += o;
- pmap(m->pml4, pa | PTEUNCACHED|PTEWRITE|PTEVALID, va, size);
+ pmap(m->pml4, pa | PTEUNCACHED|PTEWRITE|PTENOEXEC|PTEVALID, va, size);
return (void*)(va+o);
}
@@ -616,7 +611,7 @@
pm->npage = (top - pm->base)/BY2PG;
va = base + VMAP;
- pmap(m->pml4, base | PTEGLOBAL|PTEWRITE|PTEVALID, va, psize);
+ pmap(m->pml4, base | PTEGLOBAL|PTEWRITE|PTENOEXEC|PTEVALID, va, psize);
palloc.pages = (void*)(va + tsize);