x86: use setters/getters for MSR_{FS,GS}_BASE
authorBarret Rhoden <brho@cs.berkeley.edu>
Mon, 29 Feb 2016 23:24:40 +0000 (18:24 -0500)
committerBarret Rhoden <brho@cs.berkeley.edu>
Mon, 29 Feb 2016 23:33:37 +0000 (18:33 -0500)
We need to be a little careful in the kernel with using these before cr4 is
set.  We'll eventually set cr4 to enable this usage in arch_pcpu_init.  For
the most part, any MSR accesses of this sort will happen after smp_boot,
which is fine.

Signed-off-by: Barret Rhoden <brho@cs.berkeley.edu>
kern/arch/x86/fsgsbase.h [new file with mode: 0644]
kern/arch/x86/process64.c
kern/arch/x86/smp_boot.c
kern/arch/x86/trap64.c
kern/arch/x86/trap64.h
kern/arch/x86/vmm/intel/vmx.c
kern/arch/x86/x86.h

diff --git a/kern/arch/x86/fsgsbase.h b/kern/arch/x86/fsgsbase.h
new file mode 100644 (file)
index 0000000..42fd433
--- /dev/null
@@ -0,0 +1,48 @@
+/* Copyright (c) 2016 Google Inc.
+ * Barret Rhoden <brho@cs.berkeley.edu>
+ * See LICENSE for details.
+ *
+ * Getters and setters for FS Base and GS base. */
+
+#pragma once
+
+#include <cpu_feat.h>
+#include <arch/x86.h>
+
+static inline uintptr_t read_fsbase(void)
+{
+       uintptr_t base;
+
+       if (!cpu_has_feat(CPU_FEAT_X86_FSGSBASE))
+               return read_msr(MSR_FS_BASE);
+       asm volatile ("rdfsbase %0" : "=r"(base));
+       return base;
+}
+
+static inline void write_fsbase(uintptr_t base)
+{
+       if (!cpu_has_feat(CPU_FEAT_X86_FSGSBASE)) {
+               write_msr(MSR_FS_BASE, base);
+               return;
+       }
+       asm volatile ("wrfsbase %0" : : "r"(base));
+}
+
+static inline uintptr_t read_gsbase(void)
+{
+       uintptr_t base;
+
+       if (!cpu_has_feat(CPU_FEAT_X86_FSGSBASE))
+               return read_msr(MSR_GS_BASE);
+       asm volatile ("rdgsbase %0" : "=r"(base));
+       return base;
+}
+
+static inline void write_gsbase(uintptr_t base)
+{
+       if (!cpu_has_feat(CPU_FEAT_X86_FSGSBASE)) {
+               write_msr(MSR_GS_BASE, base);
+               return;
+       }
+       asm volatile ("wrgsbase %0" : : "r"(base));
+}
index cddee5e..7de0db4 100644 (file)
@@ -3,6 +3,7 @@
 #include <process.h>
 #include <pmap.h>
 #include <smp.h>
+#include <arch/fsgsbase.h>
 
 #include <string.h>
 #include <assert.h>
@@ -15,8 +16,8 @@ static void __attribute__((noreturn)) proc_pop_hwtf(struct hw_trapframe *tf)
        if (x86_hwtf_is_partial(tf)) {
                swap_gs();
        } else {
-               write_msr(MSR_GS_BASE, (uint64_t)tf->tf_gsbase);
-               write_msr(MSR_FS_BASE, (uint64_t)tf->tf_fsbase);
+               write_gsbase(tf->tf_gsbase);
+               write_fsbase(tf->tf_fsbase);
        }
        asm volatile ("movq %0, %%rsp;          "
                      "popq %%rax;              "
@@ -45,8 +46,8 @@ static void __attribute__((noreturn)) proc_pop_swtf(struct sw_trapframe *tf)
        if (x86_swtf_is_partial(tf)) {
                swap_gs();
        } else {
-               write_msr(MSR_GS_BASE, (uint64_t)tf->tf_gsbase);
-               write_msr(MSR_FS_BASE, (uint64_t)tf->tf_fsbase);
+               write_gsbase(tf->tf_gsbase);
+               write_fsbase(tf->tf_fsbase);
        }
        /* We need to 0 out any registers that aren't part of the sw_tf and that we
         * won't use/clobber on the out-path.  While these aren't part of the sw_tf,
index 05df791..8dedc27 100644 (file)
@@ -22,6 +22,7 @@
 #include <env.h>
 #include <trap.h>
 #include <kmalloc.h>
+#include <arch/fsgsbase.h>
 
 #include "vmm/vmm.h"
 
@@ -81,7 +82,7 @@ void smp_final_core_init(void)
        int coreid = get_os_coreid(hw_core_id());
        struct per_cpu_info *pcpui = &per_cpu_info[coreid];
        pcpui->coreid = coreid;
-       write_msr(MSR_GS_BASE, (uint64_t)pcpui);
+       write_msr(MSR_GS_BASE, (uintptr_t)pcpui);       /* our cr4 isn't set yet */
        write_msr(MSR_KERN_GS_BASE, (uint64_t)pcpui);
        /* don't need this for the kernel anymore, but userspace can still use it */
        setup_rdtscp(coreid);
@@ -301,7 +302,7 @@ void __arch_pcpu_init(uint32_t coreid)
                pcpui->gdt = (segdesc_t*)(*my_stack_bot +
                                          sizeof(taskstate_t) + sizeof(pseudodesc_t));
        }
-       assert(read_msr(MSR_GS_BASE) == (uint64_t)pcpui);
+       assert(read_gsbase() == (uintptr_t)pcpui);
        assert(read_msr(MSR_KERN_GS_BASE) == (uint64_t)pcpui);
        /* Don't try setting up til after setting GS */
        x86_sysenter_init(x86_get_stacktop_tss(pcpui->tss));
index 0ed7528..2d7c14f 100644 (file)
@@ -55,7 +55,7 @@ void print_trapframe(struct hw_trapframe *hw_tf)
                                              x86_trapname(hw_tf->tf_trapno));
        /* FYI: these aren't physically adjacent to trap and err */
        if (hw_tf->tf_cs == GD_KT)
-               printk("  gsbs 0x%016lx\n",       read_msr(MSR_GS_BASE));
+               printk("  gsbs 0x%016lx\n",       read_gsbase());
        else
                printk("  gsbs 0x%016lx\n",       hw_tf->tf_gsbase);
        printk("  fsbs 0x%016lx\n",           hw_tf->tf_fsbase);
index db9c185..5c29a05 100644 (file)
@@ -13,6 +13,8 @@
 #error "Do not include arch/trap64.h directly."
 #endif
 
+#include <arch/fsgsbase.h>
+
 static inline bool in_kernel(struct hw_trapframe *hw_tf)
 {
        return (hw_tf->tf_cs & ~3) == GD_KT;
@@ -163,16 +165,16 @@ static inline bool arch_ctx_is_partial(struct user_context *ctx)
 static inline void x86_finalize_hwtf(struct hw_trapframe *tf)
 {
        tf->tf_gsbase = read_msr(MSR_KERNEL_GS_BASE);
-       write_msr(MSR_KERNEL_GS_BASE, read_msr(MSR_GS_BASE));
-       tf->tf_fsbase = read_msr(MSR_FS_BASE);
+       write_msr(MSR_KERNEL_GS_BASE, read_gsbase());
+       tf->tf_fsbase = read_fsbase();
        x86_hwtf_clear_partial(tf);
 }
 
 static inline void x86_finalize_swtf(struct sw_trapframe *tf)
 {
        tf->tf_gsbase = read_msr(MSR_KERNEL_GS_BASE);
-       write_msr(MSR_KERNEL_GS_BASE, read_msr(MSR_GS_BASE));
-       tf->tf_fsbase = read_msr(MSR_FS_BASE);
+       write_msr(MSR_KERNEL_GS_BASE, read_gsbase());
+       tf->tf_fsbase = read_fsbase();
        x86_swtf_clear_partial(tf);
 }
 
index 536190a..6f789ab 100644 (file)
@@ -877,7 +877,7 @@ static int vmx_setup_initial_guest_state(struct proc *p,
        vmcs_writel(GUEST_ES_BASE, 0);
        vmcs_writel(GUEST_GS_BASE, 0);
        vmcs_writel(GUEST_SS_BASE, 0);
-       rdmsrl(MSR_FS_BASE, tmpl);
+       tmpl = read_fsbase();
        vmcs_writel(GUEST_FS_BASE, tmpl);
 
        /* guest segment access rights */
index 993bd52..5a9364f 100644 (file)
 #define X86_CR8_TPR    0x0000000F /* task priority register */
 
 #ifndef __ASSEMBLER__
+
 static inline uint8_t inb(int port) __attribute__((always_inline));
 static inline void insb(int port, void *addr, int cnt)
               __attribute__((always_inline));