code: plan9front

Download patch

ref: 1e773c97e79d74983edd9b46694956f76b0c7fd5
parent: 49411b2ca15b94b6631fd54d2576c5aeff63eb67
author: cinap_lenrek <cinap_lenrek@felloff.net>
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);