OSDN Git Service

KVM: SVM: Introduce hybrid-AVIC mode
authorSuravee Suthikulpanit <suravee.suthikulpanit@amd.com>
Thu, 19 May 2022 10:27:05 +0000 (05:27 -0500)
committerPaolo Bonzini <pbonzini@redhat.com>
Fri, 24 Jun 2022 16:51:00 +0000 (12:51 -0400)
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: Maxim Levitsky <mlevitsk@redhat.com>
Reviewed-by: Maxim Levitsky <mlevitsk@redhat.com>
Signed-off-by: Suravee Suthikulpanit <suravee.suthikulpanit@amd.com>
Message-Id: <20220519102709.24125-14-suravee.suthikulpanit@amd.com>
Signed-off-by: Paolo Bonzini <pbonzini@redhat.com>
arch/x86/include/asm/kvm_host.h
arch/x86/kvm/svm/avic.c
arch/x86/kvm/svm/svm.c

index 88a3026..de5a149 100644 (file)
@@ -1130,11 +1130,6 @@ enum kvm_apicv_inhibit {
        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.
         */
        APICV_INHIBIT_REASON_SEV,
index fcff249..a8db5d2 100644 (file)
@@ -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.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.avic_physical_id |= X2AVIC_MAX_PHYSICAL_ID;
                /* Disabling MSR intercept for x2APIC registers */
                svm_set_x2apic_msr_interception(svm, false);
        } else {
+               /* For xAVIC and hybrid-xAVIC modes */
                vmcb->control.avic_physical_id |= AVIC_MAX_PHYSICAL_ID;
                /* Enabling MSR intercept for x2APIC registers */
                svm_set_x2apic_msr_interception(svm, true);
@@ -968,7 +978,6 @@ bool avic_check_apicv_inhibit_reasons(enum kvm_apicv_inhibit reason)
                          BIT(APICV_INHIBIT_REASON_NESTED) |
                          BIT(APICV_INHIBIT_REASON_IRQWIN) |
                          BIT(APICV_INHIBIT_REASON_PIT_REINJ) |
-                         BIT(APICV_INHIBIT_REASON_X2APIC) |
                          BIT(APICV_INHIBIT_REASON_BLOCKIRQ) |
                          BIT(APICV_INHIBIT_REASON_SEV)      |
                          BIT(APICV_INHIBIT_REASON_APIC_ID_MODIFIED) |
index 491e4d5..bb0457c 100644 (file)
@@ -4160,7 +4160,6 @@ static void svm_vcpu_after_set_cpuid(struct kvm_vcpu *vcpu)
 {
        struct vcpu_svm *svm = to_svm(vcpu);
        struct kvm_cpuid_entry2 *best;
-       struct kvm *kvm = vcpu->kvm;
 
        vcpu->arch.xsaves_enabled = guest_cpuid_has(vcpu, X86_FEATURE_XSAVE) &&
                                    boot_cpu_has(X86_FEATURE_XSAVE) &&
@@ -4192,14 +4191,6 @@ static void svm_vcpu_after_set_cpuid(struct kvm_vcpu *vcpu)
                        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);
 }