x86: fix EFER handling
PATCH 1/1 x86: fix EFER handling
Introduce a per-CPU shadow of what is currently in EFER, as context switch code must re-write this MSR so that all guests run with appropriate EFER.SCE and EFER.NX settings. Remove EFER from the set of MSRs that VMX deals with in a generic fashion.
Signed-off-by Jan Beulich <[email protected]>
xen/arch/x86/domain.c +8 -10
@@ -47,6 +47,7 @@#endif DEFINE_PER_CPU(struct vcpu *, curr_vcpu); +DEFINE_PER_CPU (__u64, efer);static void paravirt_ctxt_switch_from (struct vcpu *v);static void paravirt_ctxt_switch_to (struct vcpu *v);
@@ -1138,21 +1139,18 @@ void context_switch(struct vcpu *prev, s__context_switch ();#ifdef CONFIG_COMPAT -if (is_idle_vcpu (prev) || - (is_pv_32on64_domain (prev->domain) != -is_pv_32on64_domain (next->domain)) ) +if ( !is_hvm_vcpu (next) && + (is_idle_vcpu (prev) || +is_hvm_vcpu (prev) || +is_pv_32on64_vcpu (prev) !=is_pv_32on64_vcpu (next)) ) { -uint32_t efer_lo, efer_hi; +uint64_t efer =read_efer ();local_flush_tlb_one (GDT_VIRT_START (next) +FIRST_RESERVED_GDT_BYTE ); -rdmsr (MSR_EFER , efer_lo, efer_hi); -if ( !is_pv_32on64_domain (next->domain) == !(efer_lo &EFER_SCE ) ) - { - efer_lo ^=EFER_SCE ; -wrmsr (MSR_EFER , efer_lo, efer_hi); - } +if ( !is_pv_32on64_vcpu (next) == !(efer &EFER_SCE ) ) +write_efer (efer ^EFER_SCE ); }#endif
xen/arch/x86/hvm/svm/svm.c +14 -12
@@ -96,11 +96,8 @@ static inline void svm_inject_exception(static void stop_svm (void ) { -u32 eax, edx;/* We turn off the EFER_SVME bit. */ -rdmsr (MSR_EFER , eax, edx); - eax &= ~EFER_SVME ; -wrmsr (MSR_EFER , eax, edx); +write_efer (read_efer () & ~EFER_SVME ); } static void svm_store_cpu_guest_regs(
@@ -145,7 +142,13 @@ static inline int long_mode_do_msr_write {case MSR_EFER :/* Offending reserved bit will cause #GP. */ -if ( msr_content & ~(EFER_LME |EFER_LMA |EFER_NX |EFER_SCE ) ) +#ifdef __x86_64__ +if ( (msr_content & ~(EFER_LME |EFER_LMA |EFER_NX |EFER_SCE )) || +#else + if ( (msr_content & ~(EFER_NX | EFER_SCE)) || +#endif + (!cpu_has_nx && (msr_content & EFER_NX)) || + (!cpu_has_syscall && (msr_content & EFER_SCE)) ) {gdprintk (XENLOG_WARNING ,"Trying to set reserved bit in " "EFER: %"PRIx64"\n", msr_content);
@@ -502,7 +505,7 @@ int svm_vmcb_restore(struct vcpu *v, str } -void svm_save_cpu_state (struct vcpu *v,struct hvm_hw_cpu *data) +static void svm_save_cpu_state (struct vcpu *v,struct hvm_hw_cpu *data) {struct vmcb_struct *vmcb = v->arch.hvm_svm.vmcb;
@@ -518,7 +521,7 @@ void svm_save_cpu_state(struct vcpu *v, } -void svm_load_cpu_state (struct vcpu *v,struct hvm_hw_cpu *data) +static void svm_load_cpu_state (struct vcpu *v,struct hvm_hw_cpu *data) {struct vmcb_struct *vmcb = v->arch.hvm_svm.vmcb;
@@ -537,13 +540,13 @@ void svm_load_cpu_state(struct vcpu *v,hvm_set_guest_time (v, data->tsc); } -void svm_save_vmcb_ctxt (struct vcpu *v,struct hvm_hw_cpu *ctxt) +static void svm_save_vmcb_ctxt (struct vcpu *v,struct hvm_hw_cpu *ctxt) {svm_save_cpu_state (v, ctxt);svm_vmcb_save (v, ctxt); } -int svm_load_vmcb_ctxt (struct vcpu *v,struct hvm_hw_cpu *ctxt) +static int svm_load_vmcb_ctxt (struct vcpu *v,struct hvm_hw_cpu *ctxt) {svm_load_cpu_state (v, ctxt);if (svm_vmcb_restore (v, ctxt)) {
@@ -871,6 +874,7 @@ static struct hvm_function_table svm_fun .paging_enabled = svm_paging_enabled, .long_mode_enabled = svm_long_mode_enabled, .pae_enabled = svm_pae_enabled, + .nx_enabled = svm_nx_enabled, .interrupts_enabled = svm_interrupts_enabled, .guest_x86_mode = svm_guest_x86_mode, .get_guest_ctrl_reg = svm_get_ctrl_reg,
@@ -927,9 +931,7 @@ int start_svm(void) ((root_vmcb[cpu] = alloc_vmcb()) == NULL) )return 0 ; -rdmsr (MSR_EFER , eax, edx); - eax |=EFER_SVME ; -wrmsr (MSR_EFER , eax, edx); +write_efer (read_efer () |EFER_SVME );svm_npt_detect ();
xen/arch/x86/hvm/vmx/vmcs.c +0 -5
@@ -285,11 +285,6 @@ static void construct_vmcs(struct vcpu *vmx_vmcs_enter (v); - v->arch.hvm_vmx.cpu_cr2 =0 ; - v->arch.hvm_vmx.cpu_cr3 =0 ; -memset (&v->arch.hvm_vmx.msr_state,0 ,sizeof (v->arch.hvm_vmx.msr_state)); - v->arch.hvm_vmx.vmxassist_enabled =0 ; -/* VMCS controls. */ __vmwrite (PIN_BASED_VM_EXEC_CONTROL , vmx_pin_based_exec_control);__vmwrite (VM_EXIT_CONTROLS , vmx_vmexit_control);
xen/arch/x86/hvm/vmx/vmx.c +114 -34
314 lines not on this page · raw message
xen/arch/x86/mm/shadow/multi.c +4 -4
@@ -181,11 +181,11 @@ guest_supports_superpages(struct vcpu *vstatic inline int guest_supports_nx (struct vcpu *v) { +if (GUEST_PAGING_LEVELS ==2 || !cpu_has_nx ) +return 0 ;if ( !is_hvm_vcpu (v) ) -return cpu_has_nx; - -// XXX - fix this! -return 1 ; +return 1 ; +return hvm_nx_enabled (v); }
xen/include/asm-x86/cpufeature.h +2 -0
@@ -114,6 +114,7 @@#define cpu_has_xmm2 boot_cpu_has(X86_FEATURE_XMM2)#define cpu_has_xmm3 boot_cpu_has(X86_FEATURE_XMM3)#define cpu_has_ht boot_cpu_has(X86_FEATURE_HT) +#define cpu_has_syscall boot_cpu_has(X86_FEATURE_SYSCALL)#define cpu_has_mp boot_cpu_has(X86_FEATURE_MP)#define cpu_has_nx boot_cpu_has(X86_FEATURE_NX)#define cpu_has_k6_mtrr boot_cpu_has(X86_FEATURE_K6_MTRR)
@@ -136,6 +137,7 @@#define cpu_has_xmm2 1#define cpu_has_xmm3 boot_cpu_has(X86_FEATURE_XMM3)#define cpu_has_ht boot_cpu_has(X86_FEATURE_HT) +#define cpu_has_syscall 1#define cpu_has_mp 1#define cpu_has_nx boot_cpu_has(X86_FEATURE_NX)#define cpu_has_k6_mtrr 0
xen/include/asm-x86/hvm/hvm.h +13 -4
@@ -93,14 +93,17 @@ struct hvm_function_table {* 1) determine whether paging is enabled, * 2) determine whether long mode is enabled, * 3) determine whether PAE paging is enabled, -* 4) determine whether interrupts are enabled or not, -* 5) determine the mode the guest is running in, -* 6) return the current guest control-register value -* 7) return the current guest segment descriptor base +* 4) determine whether NX is enabled, +* 5) determine whether interrupts are enabled or not, +* 6) determine the mode the guest is running in, +* 7) return the current guest control-register value +* 8) return the current guest segment descriptor base +* 9) return the current guest segment descriptor */ int (*paging_enabled)(struct vcpu *v);int (*long_mode_enabled)(struct vcpu *v);int (*pae_enabled)(struct vcpu *v); +int (*nx_enabled)(struct vcpu *v);int (*interrupts_enabled)(struct vcpu *v);int (*guest_x86_mode)(struct vcpu *v);unsigned long (*get_guest_ctrl_reg)(struct vcpu *v,unsigned int num);
@@ -199,6 +202,12 @@ hvm_interrupts_enabled(struct vcpu *v) }static inline int +hvm_nx_enabled (struct vcpu *v) +{ +return hvm_funcs.nx_enabled (v); +} + +static inline int hvm_guest_x86_mode (struct vcpu *v) {return hvm_funcs.guest_x86_mode (v);
xen/include/asm-x86/hvm/svm/svm.h +5 -0
@@ -62,6 +62,11 @@ static inline int svm_pae_enabled(structreturn svm_paging_enabled (v) && (guest_cr4 &X86_CR4_PAE ); } +static inline int svm_nx_enabled (struct vcpu *v) +{ +return v->arch.hvm_svm.cpu_shadow_efer &EFER_NX ; +} +static inline int svm_pgbit_test (struct vcpu *v) {return v->arch.hvm_svm.cpu_shadow_cr0 &X86_CR0_PG ;
xen/include/asm-x86/hvm/vmx/vmcs.h +4 -2
@@ -39,7 +39,6 @@ enum {VMX_INDEX_MSR_STAR ,VMX_INDEX_MSR_CSTAR ,VMX_INDEX_MSR_SYSCALL_MASK , -VMX_INDEX_MSR_EFER , VMX_MSR_COUNT };
@@ -47,7 +46,6 @@ enum {struct vmx_msr_state {unsigned long flags;unsigned long msrs[VMX_MSR_COUNT ]; -unsigned long shadow_gs; };struct arch_vmx_struct {
@@ -76,7 +74,11 @@ struct arch_vmx_struct {unsigned long cpu_shadow_cr4;/* copy of guest read shadow CR4 */ unsigned long cpu_cr2;/* save CR2 */ unsigned long cpu_cr3; +#ifdef __x86_64__struct vmx_msr_state msr_state; +unsigned long shadow_gs; +#endif +unsigned long efer; unsigned long vmxassist_enabled:1; };
xen/include/asm-x86/hvm/vmx/vmx.h +2 -4
@@ -261,14 +261,12 @@ static inline int vmx_paging_enabled(strstatic inline int vmx_long_mode_enabled (struct vcpu *v) { -u64 efer = v->arch.hvm_vmx.msr_state.msrs[VMX_INDEX_MSR_EFER ]; -return efer &EFER_LMA ; +return v->arch.hvm_vmx.efer &EFER_LMA ; }static inline int vmx_lme_is_set (struct vcpu *v) { -u64 efer = v->arch.hvm_vmx.msr_state.msrs[VMX_INDEX_MSR_EFER ]; -return efer &EFER_LME ; +return v->arch.hvm_vmx.efer &EFER_LME ; }static inline int vmx_pgbit_test (struct vcpu *v)
xen/include/asm-x86/msr.h +22 -0
@@ -3,6 +3,9 @@#ifndef __ASSEMBLY__ +#include <xen/smp.h> +#include <xen/percpu.h> +#define rdmsr (msr,val1,val2) \ __asm__ __volatile__("rdmsr" \ : "=a" (val1), "=d" (val2) \
@@ -142,6 +145,25 @@ static inline void wrmsrl(unsigned int m#define EFER_NX (1<<_EFER_NX)#define EFER_SVME (1<<_EFER_SVME) +#ifndef __ASSEMBLY__ + +DECLARE_PER_CPU (__u64, efer); + +static inline __u64 read_efer (void ) +{ +if (!this_cpu (efer)) +rdmsrl (MSR_EFER ,this_cpu (efer)); +return this_cpu (efer); +} + +static inline void write_efer (__u64 val) +{ +this_cpu (efer) = val; +wrmsrl (MSR_EFER , val); +} + +#endif +/* Intel MSRs. Some also available on other CPUs */ #define MSR_IA32_PLATFORM_ID 0x17