diff options
author | David Matlack <dmatlack@google.com> | 2016-11-29 21:14:09 -0500 |
---|---|---|
committer | Paolo Bonzini <pbonzini@redhat.com> | 2016-12-08 09:31:08 -0500 |
commit | 8322ebbb24088c22049ef53cd066c6c220640edb (patch) | |
tree | d91152a0df6fc1700e5f6c296f0f553b6572e439 | |
parent | 3899152ccbf42d7e3d3c7830b1fae75a575a1ed6 (diff) |
KVM: nVMX: generate MSR_IA32_CR{0,4}_FIXED1 from guest CPUID
MSR_IA32_CR{0,4}_FIXED1 define which bits in CR0 and CR4 are allowed to
be 1 during VMX operation. Since the set of allowed-1 bits is the same
in and out of VMX operation, we can generate these MSRs entirely from
the guest's CPUID. This lets userspace avoiding having to save/restore
these MSRs.
This patch also initializes MSR_IA32_CR{0,4}_FIXED1 from the CPU's MSRs
by default. This is a saner than the current default of -1ull, which
includes bits that the host CPU does not support.
Signed-off-by: David Matlack <dmatlack@google.com>
Signed-off-by: Radim Krčmář <rkrcmar@redhat.com>
-rw-r--r-- | arch/x86/kvm/vmx.c | 55 |
1 files changed, 52 insertions, 3 deletions
diff --git a/arch/x86/kvm/vmx.c b/arch/x86/kvm/vmx.c index 2b8d4f5ac246..fa29585c63ff 100644 --- a/arch/x86/kvm/vmx.c +++ b/arch/x86/kvm/vmx.c | |||
@@ -2877,16 +2877,18 @@ static void nested_vmx_setup_ctls_msrs(struct vcpu_vmx *vmx) | |||
2877 | vmx->nested.nested_vmx_basic |= VMX_BASIC_INOUT; | 2877 | vmx->nested.nested_vmx_basic |= VMX_BASIC_INOUT; |
2878 | 2878 | ||
2879 | /* | 2879 | /* |
2880 | * These MSRs specify bits which the guest must keep fixed (on or off) | 2880 | * These MSRs specify bits which the guest must keep fixed on |
2881 | * while L1 is in VMXON mode (in L1's root mode, or running an L2). | 2881 | * while L1 is in VMXON mode (in L1's root mode, or running an L2). |
2882 | * We picked the standard core2 setting. | 2882 | * We picked the standard core2 setting. |
2883 | */ | 2883 | */ |
2884 | #define VMXON_CR0_ALWAYSON (X86_CR0_PE | X86_CR0_PG | X86_CR0_NE) | 2884 | #define VMXON_CR0_ALWAYSON (X86_CR0_PE | X86_CR0_PG | X86_CR0_NE) |
2885 | #define VMXON_CR4_ALWAYSON X86_CR4_VMXE | 2885 | #define VMXON_CR4_ALWAYSON X86_CR4_VMXE |
2886 | vmx->nested.nested_vmx_cr0_fixed0 = VMXON_CR0_ALWAYSON; | 2886 | vmx->nested.nested_vmx_cr0_fixed0 = VMXON_CR0_ALWAYSON; |
2887 | vmx->nested.nested_vmx_cr0_fixed1 = -1ULL; | ||
2888 | vmx->nested.nested_vmx_cr4_fixed0 = VMXON_CR4_ALWAYSON; | 2887 | vmx->nested.nested_vmx_cr4_fixed0 = VMXON_CR4_ALWAYSON; |
2889 | vmx->nested.nested_vmx_cr4_fixed1 = -1ULL; | 2888 | |
2889 | /* These MSRs specify bits which the guest must keep fixed off. */ | ||
2890 | rdmsrl(MSR_IA32_VMX_CR0_FIXED1, vmx->nested.nested_vmx_cr0_fixed1); | ||
2891 | rdmsrl(MSR_IA32_VMX_CR4_FIXED1, vmx->nested.nested_vmx_cr4_fixed1); | ||
2890 | 2892 | ||
2891 | /* highest index: VMX_PREEMPTION_TIMER_VALUE */ | 2893 | /* highest index: VMX_PREEMPTION_TIMER_VALUE */ |
2892 | vmx->nested.nested_vmx_vmcs_enum = 0x2e; | 2894 | vmx->nested.nested_vmx_vmcs_enum = 0x2e; |
@@ -9424,6 +9426,50 @@ static void vmcs_set_secondary_exec_control(u32 new_ctl) | |||
9424 | (new_ctl & ~mask) | (cur_ctl & mask)); | 9426 | (new_ctl & ~mask) | (cur_ctl & mask)); |
9425 | } | 9427 | } |
9426 | 9428 | ||
9429 | /* | ||
9430 | * Generate MSR_IA32_VMX_CR{0,4}_FIXED1 according to CPUID. Only set bits | ||
9431 | * (indicating "allowed-1") if they are supported in the guest's CPUID. | ||
9432 | */ | ||
9433 | static void nested_vmx_cr_fixed1_bits_update(struct kvm_vcpu *vcpu) | ||
9434 | { | ||
9435 | struct vcpu_vmx *vmx = to_vmx(vcpu); | ||
9436 | struct kvm_cpuid_entry2 *entry; | ||
9437 | |||
9438 | vmx->nested.nested_vmx_cr0_fixed1 = 0xffffffff; | ||
9439 | vmx->nested.nested_vmx_cr4_fixed1 = X86_CR4_PCE; | ||
9440 | |||
9441 | #define cr4_fixed1_update(_cr4_mask, _reg, _cpuid_mask) do { \ | ||
9442 | if (entry && (entry->_reg & (_cpuid_mask))) \ | ||
9443 | vmx->nested.nested_vmx_cr4_fixed1 |= (_cr4_mask); \ | ||
9444 | } while (0) | ||
9445 | |||
9446 | entry = kvm_find_cpuid_entry(vcpu, 0x1, 0); | ||
9447 | cr4_fixed1_update(X86_CR4_VME, edx, bit(X86_FEATURE_VME)); | ||
9448 | cr4_fixed1_update(X86_CR4_PVI, edx, bit(X86_FEATURE_VME)); | ||
9449 | cr4_fixed1_update(X86_CR4_TSD, edx, bit(X86_FEATURE_TSC)); | ||
9450 | cr4_fixed1_update(X86_CR4_DE, edx, bit(X86_FEATURE_DE)); | ||
9451 | cr4_fixed1_update(X86_CR4_PSE, edx, bit(X86_FEATURE_PSE)); | ||
9452 | cr4_fixed1_update(X86_CR4_PAE, edx, bit(X86_FEATURE_PAE)); | ||
9453 | cr4_fixed1_update(X86_CR4_MCE, edx, bit(X86_FEATURE_MCE)); | ||
9454 | cr4_fixed1_update(X86_CR4_PGE, edx, bit(X86_FEATURE_PGE)); | ||
9455 | cr4_fixed1_update(X86_CR4_OSFXSR, edx, bit(X86_FEATURE_FXSR)); | ||
9456 | cr4_fixed1_update(X86_CR4_OSXMMEXCPT, edx, bit(X86_FEATURE_XMM)); | ||
9457 | cr4_fixed1_update(X86_CR4_VMXE, ecx, bit(X86_FEATURE_VMX)); | ||
9458 | cr4_fixed1_update(X86_CR4_SMXE, ecx, bit(X86_FEATURE_SMX)); | ||
9459 | cr4_fixed1_update(X86_CR4_PCIDE, ecx, bit(X86_FEATURE_PCID)); | ||
9460 | cr4_fixed1_update(X86_CR4_OSXSAVE, ecx, bit(X86_FEATURE_XSAVE)); | ||
9461 | |||
9462 | entry = kvm_find_cpuid_entry(vcpu, 0x7, 0); | ||
9463 | cr4_fixed1_update(X86_CR4_FSGSBASE, ebx, bit(X86_FEATURE_FSGSBASE)); | ||
9464 | cr4_fixed1_update(X86_CR4_SMEP, ebx, bit(X86_FEATURE_SMEP)); | ||
9465 | cr4_fixed1_update(X86_CR4_SMAP, ebx, bit(X86_FEATURE_SMAP)); | ||
9466 | cr4_fixed1_update(X86_CR4_PKE, ecx, bit(X86_FEATURE_PKU)); | ||
9467 | /* TODO: Use X86_CR4_UMIP and X86_FEATURE_UMIP macros */ | ||
9468 | cr4_fixed1_update(bit(11), ecx, bit(2)); | ||
9469 | |||
9470 | #undef cr4_fixed1_update | ||
9471 | } | ||
9472 | |||
9427 | static void vmx_cpuid_update(struct kvm_vcpu *vcpu) | 9473 | static void vmx_cpuid_update(struct kvm_vcpu *vcpu) |
9428 | { | 9474 | { |
9429 | struct kvm_cpuid_entry2 *best; | 9475 | struct kvm_cpuid_entry2 *best; |
@@ -9465,6 +9511,9 @@ static void vmx_cpuid_update(struct kvm_vcpu *vcpu) | |||
9465 | else | 9511 | else |
9466 | to_vmx(vcpu)->msr_ia32_feature_control_valid_bits &= | 9512 | to_vmx(vcpu)->msr_ia32_feature_control_valid_bits &= |
9467 | ~FEATURE_CONTROL_VMXON_ENABLED_OUTSIDE_SMX; | 9513 | ~FEATURE_CONTROL_VMXON_ENABLED_OUTSIDE_SMX; |
9514 | |||
9515 | if (nested_vmx_allowed(vcpu)) | ||
9516 | nested_vmx_cr_fixed1_bits_update(vcpu); | ||
9468 | } | 9517 | } |
9469 | 9518 | ||
9470 | static void vmx_set_supported_cpuid(u32 func, struct kvm_cpuid_entry2 *entry) | 9519 | static void vmx_set_supported_cpuid(u32 func, struct kvm_cpuid_entry2 *entry) |