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: 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>
This commit is contained in:
Родитель
c0caeee65a
Коммит
0e311d33bf
|
@ -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.
|
||||
*/
|
||||
|
|
|
@ -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) |
|
||||
|
|
|
@ -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);
|
||||
}
|
||||
|
||||
|
|
Загрузка…
Ссылка в новой задаче