From: Maxim Levitsky <mlevitsk@xxxxxxxxxx> Neither of these settings should be changed by the guest and it is a burden to support it in the acceleration code, so just inhibit APICv/AVIC in case such rare cases happen. Signed-off-by: Maxim Levitsky <mlevitsk@xxxxxxxxxx> Signed-off-by: Zeng Guang <guang.zeng@xxxxxxxxx> --- arch/x86/include/asm/kvm_host.h | 1 + arch/x86/kvm/lapic.c | 25 +++++++++++++++++++++---- arch/x86/kvm/lapic.h | 8 ++++++++ arch/x86/kvm/svm/avic.c | 3 ++- arch/x86/kvm/vmx/vmx.c | 3 ++- 5 files changed, 34 insertions(+), 6 deletions(-) diff --git a/arch/x86/include/asm/kvm_host.h b/arch/x86/include/asm/kvm_host.h index 4ff36610af6a..408cf88351dd 100644 --- a/arch/x86/include/asm/kvm_host.h +++ b/arch/x86/include/asm/kvm_host.h @@ -1051,6 +1051,7 @@ enum kvm_apicv_inhibit { APICV_INHIBIT_REASON_BLOCKIRQ, APICV_INHIBIT_REASON_ABSENT, APICV_INHIBIT_REASON_SEV, + APICV_INHIBIT_REASON_RO_SETTINGS, }; struct kvm_arch { diff --git a/arch/x86/kvm/lapic.c b/arch/x86/kvm/lapic.c index 66b0eb0bda94..f256fa974ea3 100644 --- a/arch/x86/kvm/lapic.c +++ b/arch/x86/kvm/lapic.c @@ -2038,6 +2038,17 @@ static void apic_manage_nmi_watchdog(struct kvm_lapic *apic, u32 lvt0_val) } } +static void kvm_lapic_check_initial_apic_id(struct kvm_lapic *apic) +{ + if (kvm_apic_has_initial_apic_id(apic)) + return; + + pr_warn_once("APIC ID change is unexpected by KVM"); + + kvm_set_apicv_inhibit(apic->vcpu->kvm, + APICV_INHIBIT_REASON_RO_SETTINGS); +} + static int kvm_lapic_reg_write(struct kvm_lapic *apic, u32 reg, u32 val) { int ret = 0; @@ -2046,9 +2057,11 @@ static int kvm_lapic_reg_write(struct kvm_lapic *apic, u32 reg, u32 val) switch (reg) { case APIC_ID: /* Local APIC ID */ - if (!apic_x2apic_mode(apic)) + if (!apic_x2apic_mode(apic)) { + kvm_apic_set_xapic_id(apic, val >> 24); - else + kvm_lapic_check_initial_apic_id(apic); + } else ret = 1; break; @@ -2335,8 +2348,11 @@ void kvm_lapic_set_base(struct kvm_vcpu *vcpu, u64 value) MSR_IA32_APICBASE_BASE; if ((value & MSR_IA32_APICBASE_ENABLE) && - apic->base_address != APIC_DEFAULT_PHYS_BASE) - pr_warn_once("APIC base relocation is unsupported by KVM"); + apic->base_address != APIC_DEFAULT_PHYS_BASE) { + kvm_set_apicv_inhibit(apic->vcpu->kvm, + APICV_INHIBIT_REASON_RO_SETTINGS); + pr_warn_once("APIC base relocation is unexpected by KVM"); + } } void kvm_apic_update_apicv(struct kvm_vcpu *vcpu) @@ -2649,6 +2665,7 @@ static int kvm_apic_state_fixup(struct kvm_vcpu *vcpu, } } + kvm_lapic_check_initial_apic_id(vcpu->arch.apic); return 0; } diff --git a/arch/x86/kvm/lapic.h b/arch/x86/kvm/lapic.h index 4e4f8a22754f..b9c406d38308 100644 --- a/arch/x86/kvm/lapic.h +++ b/arch/x86/kvm/lapic.h @@ -252,4 +252,12 @@ static inline u8 kvm_xapic_id(struct kvm_lapic *apic) return kvm_lapic_get_reg(apic, APIC_ID) >> 24; } +static inline bool kvm_apic_has_initial_apic_id(struct kvm_lapic *apic) +{ + if (apic_x2apic_mode(apic)) + return true; + + return kvm_xapic_id(apic) == apic->vcpu->vcpu_id; +} + #endif diff --git a/arch/x86/kvm/svm/avic.c b/arch/x86/kvm/svm/avic.c index 421619540ff9..04a07b82b1a4 100644 --- a/arch/x86/kvm/svm/avic.c +++ b/arch/x86/kvm/svm/avic.c @@ -838,7 +838,8 @@ bool avic_check_apicv_inhibit_reasons(enum kvm_apicv_inhibit reason) 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_SEV) | + BIT(APICV_INHIBIT_REASON_RO_SETTINGS); return supported & BIT(reason); } diff --git a/arch/x86/kvm/vmx/vmx.c b/arch/x86/kvm/vmx/vmx.c index 610355b9ccce..b31f858cacf2 100644 --- a/arch/x86/kvm/vmx/vmx.c +++ b/arch/x86/kvm/vmx/vmx.c @@ -7710,7 +7710,8 @@ static bool vmx_check_apicv_inhibit_reasons(enum kvm_apicv_inhibit reason) ulong supported = BIT(APICV_INHIBIT_REASON_DISABLE) | BIT(APICV_INHIBIT_REASON_ABSENT) | BIT(APICV_INHIBIT_REASON_HYPERV) | - BIT(APICV_INHIBIT_REASON_BLOCKIRQ); + BIT(APICV_INHIBIT_REASON_BLOCKIRQ) | + BIT(APICV_INHIBIT_REASON_RO_SETTINGS); return supported & BIT(reason); } -- 2.27.0