summaryrefslogtreecommitdiffstats
path: root/sys/amd64/include/cpufunc.h
diff options
context:
space:
mode:
authorpeter <peter@FreeBSD.org>2003-05-15 00:23:40 +0000
committerpeter <peter@FreeBSD.org>2003-05-15 00:23:40 +0000
commit12d7e4bee670b00c658676727ee630be6fbb7af1 (patch)
tree1cae0c59e2d1157890a9bc0eb09af3e021373ef6 /sys/amd64/include/cpufunc.h
parent7208ad8cbbe97024b739c1267077266cf9792ad3 (diff)
downloadFreeBSD-src-12d7e4bee670b00c658676727ee630be6fbb7af1.zip
FreeBSD-src-12d7e4bee670b00c658676727ee630be6fbb7af1.tar.gz
Collect the nastiness for preserving the kernel MSR_GSBASE around the
load_gs() calls into a single place that is less likely to go wrong. Eliminate the per-process context switching of MSR_GSBASE, because it should be constant for a single cpu. Instead, save/restore it during the loading of the new %gs selector for the new process. Approved by: re (amd64/* blanket)
Diffstat (limited to 'sys/amd64/include/cpufunc.h')
-rw-r--r--sys/amd64/include/cpufunc.h36
1 files changed, 36 insertions, 0 deletions
diff --git a/sys/amd64/include/cpufunc.h b/sys/amd64/include/cpufunc.h
index 21257dd..5d4c0dc 100644
--- a/sys/amd64/include/cpufunc.h
+++ b/sys/amd64/include/cpufunc.h
@@ -475,6 +475,41 @@ load_es(u_int sel)
__asm __volatile("movl %0,%%es" : : "rm" (sel));
}
+#ifdef _KERNEL
+/* This is defined in <machine/specialreg.h> but is too painful to get to */
+#ifndef MSR_FSBASE
+#define MSR_FSBASE 0xc0000100
+#endif
+static __inline void
+load_fs(u_int sel)
+{
+ register u_int32_t fsbase __asm("ecx");
+
+ /* Preserve the fsbase value across the selector load */
+ fsbase = MSR_FSBASE;
+ __asm __volatile("rdmsr; movl %0,%%fs; wrmsr"
+ : : "rm" (sel), "c" (fsbase) : "eax", "edx");
+}
+
+#ifndef MSR_GSBASE
+#define MSR_GSBASE 0xc0000101
+#endif
+static __inline void
+load_gs(u_int sel)
+{
+ register u_int32_t gsbase __asm("ecx");
+
+ /*
+ * Preserve the gsbase value across the selector load.
+ * Note that we have to disable interrupts because the gsbase
+ * being trashed happens to be the kernel gsbase at the time.
+ */
+ gsbase = MSR_GSBASE;
+ __asm __volatile("pushfq; cli; rdmsr; movl %0,%%gs; wrmsr; popfq"
+ : : "rm" (sel), "c" (gsbase) : "eax", "edx");
+}
+#else
+/* Usable by userland */
static __inline void
load_fs(u_int sel)
{
@@ -486,6 +521,7 @@ load_gs(u_int sel)
{
__asm __volatile("movl %0,%%gs" : : "rm" (sel));
}
+#endif
/* void lidt(struct region_descriptor *addr); */
static __inline void
OpenPOWER on IntegriCloud