summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorkib <kib@FreeBSD.org>2012-11-01 15:17:43 +0000
committerkib <kib@FreeBSD.org>2012-11-01 15:17:43 +0000
commit888a8bb7701dcdb784bfaeb4cf3753264a679a60 (patch)
tree69d3617b56dc064cee33fa82a5356bb843136422
parent872b317d89fc2a1a202495e2d8321c2c50b36f8c (diff)
downloadFreeBSD-src-888a8bb7701dcdb784bfaeb4cf3753264a679a60.zip
FreeBSD-src-888a8bb7701dcdb784bfaeb4cf3753264a679a60.tar.gz
Enable the new instructions for reading and writing bases for %fs,
%gs, when supported. Note that WRFSBASE and WRGSBASE are not very useful on FreeBSD right now, because a return from the kernel mode to userspace reloads the bases specified by the sysarch(2) syscall, most likely. Enable the Supervisor Mode Execution Prevention (SMEP) when supported. Since the loader(8) performs hand-off to the kernel with the page tables which contradict the SMEP, postpone enabling the SMEP on BSP until pmap switched for the proper kernel tables. Debugged with the help from: avg Tested by: avg, Michael Moll <kvedulv@kvedulv.de> MFC after: 1 month
-rw-r--r--sys/amd64/amd64/initcpu.c17
-rw-r--r--sys/amd64/amd64/pmap.c2
2 files changed, 18 insertions, 1 deletions
diff --git a/sys/amd64/amd64/initcpu.c b/sys/amd64/amd64/initcpu.c
index 148b1ec..4abed4c 100644
--- a/sys/amd64/amd64/initcpu.c
+++ b/sys/amd64/amd64/initcpu.c
@@ -34,6 +34,7 @@ __FBSDID("$FreeBSD$");
#include <sys/param.h>
#include <sys/kernel.h>
+#include <sys/pcpu.h>
#include <sys/systm.h>
#include <sys/sysctl.h>
@@ -153,11 +154,25 @@ void
initializecpu(void)
{
uint64_t msr;
+ uint32_t cr4;
+ cr4 = rcr4();
if ((cpu_feature & CPUID_XMM) && (cpu_feature & CPUID_FXSR)) {
- load_cr4(rcr4() | CR4_FXSR | CR4_XMM);
+ cr4 |= CR4_FXSR | CR4_XMM;
cpu_fxsr = hw_instruction_sse = 1;
}
+ if (cpu_stdext_feature & CPUID_STDEXT_FSGSBASE)
+ cr4 |= CR4_FSGSBASE;
+
+ /*
+ * Postpone enabling the SMEP on the boot CPU until the page
+ * tables are switched from the boot loader identity mapping
+ * to the kernel tables. The boot loader enables the U bit in
+ * its tables.
+ */
+ if (!IS_BSP() && (cpu_stdext_feature & CPUID_STDEXT_SMEP))
+ cr4 |= CR4_SMEP;
+ load_cr4(cr4);
if ((amd_feature & AMDID_NX) != 0) {
msr = rdmsr(MSR_EFER) | EFER_NXE;
wrmsr(MSR_EFER, msr);
diff --git a/sys/amd64/amd64/pmap.c b/sys/amd64/amd64/pmap.c
index 3098f2d..a80fc7b 100644
--- a/sys/amd64/amd64/pmap.c
+++ b/sys/amd64/amd64/pmap.c
@@ -622,6 +622,8 @@ pmap_bootstrap(vm_paddr_t *firstaddr)
/* XXX do %cr0 as well */
load_cr4(rcr4() | CR4_PGE | CR4_PSE);
load_cr3(KPML4phys);
+ if (cpu_stdext_feature & CPUID_STDEXT_SMEP)
+ load_cr4(rcr4() | CR4_SMEP);
/*
* Initialize the kernel pmap (which is statically allocated).
OpenPOWER on IntegriCloud