Commit 0e311d33 authored by Suravee Suthikulpanit's avatar Suravee Suthikulpanit Committed by Paolo Bonzini

KVM: SVM: Introduce hybrid-AVIC mode

Currently, AVIC is inhibited when booting a VM w/ x2APIC support.
because AVIC cannot virtualize x2APIC MSR register accesses.
However, the AVIC doorbell can be used to accelerate interrupt
injection into a running vCPU, while all guest accesses to x2APIC MSRs
will be intercepted and emulated by KVM.

With hybrid-AVIC support, the APICV_INHIBIT_REASON_X2APIC is
no longer enforced.
Suggested-by: default avatarMaxim Levitsky <mlevitsk@redhat.com>
Reviewed-by: default avatarMaxim Levitsky <mlevitsk@redhat.com>
Signed-off-by: default avatarSuravee Suthikulpanit <suravee.suthikulpanit@amd.com>
Message-Id: <20220519102709.24125-14-suravee.suthikulpanit@amd.com>
Signed-off-by: default avatarPaolo Bonzini <pbonzini@redhat.com>
parent c0caeee6
...@@ -1129,11 +1129,6 @@ enum kvm_apicv_inhibit { ...@@ -1129,11 +1129,6 @@ enum kvm_apicv_inhibit {
*/ */
APICV_INHIBIT_REASON_PIT_REINJ, APICV_INHIBIT_REASON_PIT_REINJ,
/*
* AVIC is inhibited because the guest has x2apic in its CPUID.
*/
APICV_INHIBIT_REASON_X2APIC,
/* /*
* AVIC is disabled because SEV doesn't support it. * AVIC is disabled because SEV doesn't support it.
*/ */
......
...@@ -71,12 +71,22 @@ static void avic_activate_vmcb(struct vcpu_svm *svm) ...@@ -71,12 +71,22 @@ static void avic_activate_vmcb(struct vcpu_svm *svm)
vmcb->control.avic_physical_id &= ~AVIC_PHYSICAL_MAX_INDEX_MASK; vmcb->control.avic_physical_id &= ~AVIC_PHYSICAL_MAX_INDEX_MASK;
vmcb->control.int_ctl |= AVIC_ENABLE_MASK; vmcb->control.int_ctl |= AVIC_ENABLE_MASK;
if (apic_x2apic_mode(svm->vcpu.arch.apic)) {
/* Note:
* KVM can support hybrid-AVIC mode, where KVM emulates x2APIC
* MSR accesses, while interrupt injection to a running vCPU
* can be achieved using AVIC doorbell. The AVIC hardware still
* accelerate MMIO accesses, but this does not cause any harm
* as the guest is not supposed to access xAPIC mmio when uses x2APIC.
*/
if (apic_x2apic_mode(svm->vcpu.arch.apic) &&
avic_mode == AVIC_MODE_X2) {
vmcb->control.int_ctl |= X2APIC_MODE_MASK; vmcb->control.int_ctl |= X2APIC_MODE_MASK;
vmcb->control.avic_physical_id |= X2AVIC_MAX_PHYSICAL_ID; vmcb->control.avic_physical_id |= X2AVIC_MAX_PHYSICAL_ID;
/* Disabling MSR intercept for x2APIC registers */ /* Disabling MSR intercept for x2APIC registers */
svm_set_x2apic_msr_interception(svm, false); svm_set_x2apic_msr_interception(svm, false);
} else { } else {
/* For xAVIC and hybrid-xAVIC modes */
vmcb->control.avic_physical_id |= AVIC_MAX_PHYSICAL_ID; vmcb->control.avic_physical_id |= AVIC_MAX_PHYSICAL_ID;
/* Enabling MSR intercept for x2APIC registers */ /* Enabling MSR intercept for x2APIC registers */
svm_set_x2apic_msr_interception(svm, true); svm_set_x2apic_msr_interception(svm, true);
...@@ -968,7 +978,6 @@ bool avic_check_apicv_inhibit_reasons(enum kvm_apicv_inhibit reason) ...@@ -968,7 +978,6 @@ bool avic_check_apicv_inhibit_reasons(enum kvm_apicv_inhibit reason)
BIT(APICV_INHIBIT_REASON_NESTED) | BIT(APICV_INHIBIT_REASON_NESTED) |
BIT(APICV_INHIBIT_REASON_IRQWIN) | BIT(APICV_INHIBIT_REASON_IRQWIN) |
BIT(APICV_INHIBIT_REASON_PIT_REINJ) | BIT(APICV_INHIBIT_REASON_PIT_REINJ) |
BIT(APICV_INHIBIT_REASON_X2APIC) |
BIT(APICV_INHIBIT_REASON_BLOCKIRQ) | BIT(APICV_INHIBIT_REASON_BLOCKIRQ) |
BIT(APICV_INHIBIT_REASON_SEV) | BIT(APICV_INHIBIT_REASON_SEV) |
BIT(APICV_INHIBIT_REASON_APIC_ID_MODIFIED) | BIT(APICV_INHIBIT_REASON_APIC_ID_MODIFIED) |
......
...@@ -4160,7 +4160,6 @@ static void svm_vcpu_after_set_cpuid(struct kvm_vcpu *vcpu) ...@@ -4160,7 +4160,6 @@ static void svm_vcpu_after_set_cpuid(struct kvm_vcpu *vcpu)
{ {
struct vcpu_svm *svm = to_svm(vcpu); struct vcpu_svm *svm = to_svm(vcpu);
struct kvm_cpuid_entry2 *best; struct kvm_cpuid_entry2 *best;
struct kvm *kvm = vcpu->kvm;
vcpu->arch.xsaves_enabled = guest_cpuid_has(vcpu, X86_FEATURE_XSAVE) && vcpu->arch.xsaves_enabled = guest_cpuid_has(vcpu, X86_FEATURE_XSAVE) &&
boot_cpu_has(X86_FEATURE_XSAVE) && boot_cpu_has(X86_FEATURE_XSAVE) &&
...@@ -4192,14 +4191,6 @@ static void svm_vcpu_after_set_cpuid(struct kvm_vcpu *vcpu) ...@@ -4192,14 +4191,6 @@ static void svm_vcpu_after_set_cpuid(struct kvm_vcpu *vcpu)
vcpu->arch.reserved_gpa_bits &= ~(1UL << (best->ebx & 0x3f)); vcpu->arch.reserved_gpa_bits &= ~(1UL << (best->ebx & 0x3f));
} }
if (kvm_vcpu_apicv_active(vcpu)) {
/*
* AVIC does not work with an x2APIC mode guest. If the X2APIC feature
* is exposed to the guest, disable AVIC.
*/
if (guest_cpuid_has(vcpu, X86_FEATURE_X2APIC))
kvm_set_apicv_inhibit(kvm, APICV_INHIBIT_REASON_X2APIC);
}
init_vmcb_after_set_cpuid(vcpu); init_vmcb_after_set_cpuid(vcpu);
} }
......
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