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

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
Loading
Loading
Loading
Loading
+0 −5
Original line number Diff line number Diff line
@@ -1129,11 +1129,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.
	 */
+11 −2
Original line number Diff line number Diff line
@@ -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) |
+0 −9
Original line number Diff line number Diff line
@@ -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);
}