pc64: implement NX bit discovery, map kernel mappings no-execute

This commit is contained in:
cinap_lenrek 2019-08-27 03:55:12 +02:00
parent 49411b2ca1
commit 1e773c97e7
5 changed files with 35 additions and 21 deletions

View file

@ -244,6 +244,7 @@ struct Mach
int havetsc;
int havepge;
int havewatchpt8;
int havenx;
uvlong tscticks;
int pdballoc;
int pdbfree;

View file

@ -899,10 +899,26 @@ cpuidentify(void)
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))

View file

@ -222,6 +222,7 @@ struct Mach
int havetsc;
int havepge;
int havewatchpt8;
int havenx;
uvlong tscticks;
u64int dr7; /* shadow copy of dr7 */

View file

@ -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.

View file

@ -116,23 +116,18 @@ mmuinit(void)
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));
/* IA32_LSTAR */
wrmsr(0xc0000082, (uvlong)syscallentry);
/* SYSCALL flags mask */
wrmsr(0xc0000084, 0x200);
wrmsr(Star, ((uvlong)UE32SEL << 48) | ((uvlong)KESEL << 32));
wrmsr(Lstar, (uvlong)syscallentry);
wrmsr(Sfmask, 0x200);
/* IA32_PAT write combining */
if((MACHP(0)->cpuiddx & Pat) != 0
@ -443,7 +438,7 @@ putmmu(uintptr va, uintptr pa, Page *)
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 @@ kmap(Page *page)
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 @@ vmap(uintptr pa, int size)
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 @@ preallocpages(void)
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);