Commit 90a2db6d authored by Paolo Bonzini's avatar Paolo Bonzini

KVM: nVMX: INVPCID support

Expose the "Enable INVPCID" secondary execution control to the guest
and properly reflect the exit reason.

In addition, before this patch the guest was always running with
INVPCID enabled, causing pcid.flat's "Test on INVPCID when disabled"
test to fail.
Signed-off-by: default avatarPaolo Bonzini <pbonzini@redhat.com>
parent 72c139ba
...@@ -8219,6 +8219,10 @@ static bool nested_vmx_exit_reflected(struct kvm_vcpu *vcpu, u32 exit_reason) ...@@ -8219,6 +8219,10 @@ static bool nested_vmx_exit_reflected(struct kvm_vcpu *vcpu, u32 exit_reason)
* table is L0's fault. * table is L0's fault.
*/ */
return false; return false;
case EXIT_REASON_INVPCID:
return
nested_cpu_has2(vmcs12, SECONDARY_EXEC_ENABLE_INVPCID) &&
nested_cpu_has(vmcs12, CPU_BASED_INVLPG_EXITING);
case EXIT_REASON_WBINVD: case EXIT_REASON_WBINVD:
return nested_cpu_has2(vmcs12, SECONDARY_EXEC_WBINVD_EXITING); return nested_cpu_has2(vmcs12, SECONDARY_EXEC_WBINVD_EXITING);
case EXIT_REASON_XSETBV: case EXIT_REASON_XSETBV:
...@@ -9469,7 +9473,6 @@ static void nested_vmx_cr_fixed1_bits_update(struct kvm_vcpu *vcpu) ...@@ -9469,7 +9473,6 @@ static void nested_vmx_cr_fixed1_bits_update(struct kvm_vcpu *vcpu)
static void vmx_cpuid_update(struct kvm_vcpu *vcpu) static void vmx_cpuid_update(struct kvm_vcpu *vcpu)
{ {
struct kvm_cpuid_entry2 *best;
struct vcpu_vmx *vmx = to_vmx(vcpu); struct vcpu_vmx *vmx = to_vmx(vcpu);
u32 secondary_exec_ctl = vmx_secondary_exec_control(vmx); u32 secondary_exec_ctl = vmx_secondary_exec_control(vmx);
...@@ -9488,15 +9491,27 @@ static void vmx_cpuid_update(struct kvm_vcpu *vcpu) ...@@ -9488,15 +9491,27 @@ static void vmx_cpuid_update(struct kvm_vcpu *vcpu)
} }
} }
/* Exposing INVPCID only when PCID is exposed */ if (vmx_invpcid_supported()) {
best = kvm_find_cpuid_entry(vcpu, 0x7, 0); /* Exposing INVPCID only when PCID is exposed */
if (vmx_invpcid_supported() && struct kvm_cpuid_entry2 *best = kvm_find_cpuid_entry(vcpu, 0x7, 0);
(!best || !(best->ebx & bit(X86_FEATURE_INVPCID)) || bool invpcid_enabled =
!guest_cpuid_has_pcid(vcpu))) { best && best->ebx & bit(X86_FEATURE_INVPCID) &&
secondary_exec_ctl &= ~SECONDARY_EXEC_ENABLE_INVPCID; guest_cpuid_has_pcid(vcpu);
if (best) if (!invpcid_enabled) {
best->ebx &= ~bit(X86_FEATURE_INVPCID); secondary_exec_ctl &= ~SECONDARY_EXEC_ENABLE_INVPCID;
if (best)
best->ebx &= ~bit(X86_FEATURE_INVPCID);
}
if (nested) {
if (invpcid_enabled)
vmx->nested.nested_vmx_secondary_ctls_high |=
SECONDARY_EXEC_ENABLE_INVPCID;
else
vmx->nested.nested_vmx_secondary_ctls_high &=
~SECONDARY_EXEC_ENABLE_INVPCID;
}
} }
if (cpu_has_secondary_exec_ctrls()) if (cpu_has_secondary_exec_ctrls())
...@@ -10198,6 +10213,7 @@ static int prepare_vmcs02(struct kvm_vcpu *vcpu, struct vmcs12 *vmcs12, ...@@ -10198,6 +10213,7 @@ static int prepare_vmcs02(struct kvm_vcpu *vcpu, struct vmcs12 *vmcs12,
/* Take the following fields only from vmcs12 */ /* Take the following fields only from vmcs12 */
exec_control &= ~(SECONDARY_EXEC_VIRTUALIZE_APIC_ACCESSES | exec_control &= ~(SECONDARY_EXEC_VIRTUALIZE_APIC_ACCESSES |
SECONDARY_EXEC_ENABLE_INVPCID |
SECONDARY_EXEC_RDTSCP | SECONDARY_EXEC_RDTSCP |
SECONDARY_EXEC_VIRTUAL_INTR_DELIVERY | SECONDARY_EXEC_VIRTUAL_INTR_DELIVERY |
SECONDARY_EXEC_APIC_REGISTER_VIRT); SECONDARY_EXEC_APIC_REGISTER_VIRT);
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment