| From 4a204f7895878363ca8211f50ec610408c8c70aa Mon Sep 17 00:00:00 2001 |
| From: Suravee Suthikulpanit <suravee.suthikulpanit@amd.com> |
| Date: Thu, 10 Feb 2022 18:08:51 -0600 |
| Subject: KVM: SVM: Allow AVIC support on system w/ physical APIC ID > 255 |
| |
| From: Suravee Suthikulpanit <suravee.suthikulpanit@amd.com> |
| |
| commit 4a204f7895878363ca8211f50ec610408c8c70aa upstream. |
| |
| Expand KVM's mask for the AVIC host physical ID to the full 12 bits defined |
| by the architecture. The number of bits consumed by hardware is model |
| specific, e.g. early CPUs ignored bits 11:8, but there is no way for KVM |
| to enumerate the "true" size. So, KVM must allow using all bits, else it |
| risks rejecting completely legal x2APIC IDs on newer CPUs. |
| |
| This means KVM relies on hardware to not assign x2APIC IDs that exceed the |
| "true" width of the field, but presumably hardware is smart enough to tie |
| the width to the max x2APIC ID. KVM also relies on hardware to support at |
| least 8 bits, as the legacy xAPIC ID is writable by software. But, those |
| assumptions are unavoidable due to the lack of any way to enumerate the |
| "true" width. |
| |
| Cc: stable@vger.kernel.org |
| Cc: Maxim Levitsky <mlevitsk@redhat.com> |
| Suggested-by: Sean Christopherson <seanjc@google.com> |
| Reviewed-by: Sean Christopherson <seanjc@google.com> |
| Fixes: 44a95dae1d22 ("KVM: x86: Detect and Initialize AVIC support") |
| Signed-off-by: Suravee Suthikulpanit <suravee.suthikulpanit@amd.com> |
| Message-Id: <20220211000851.185799-1-suravee.suthikulpanit@amd.com> |
| Signed-off-by: Paolo Bonzini <pbonzini@redhat.com> |
| [modified due to the conflict caused by the commit 391503528257 ("KVM: |
| x86: SVM: move avic definitions from AMD's spec to svm.h")] |
| Signed-off-by: Suravee Suthikulpanit <suravee.suthikulpanit@amd.com> |
| Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org> |
| --- |
| arch/x86/kvm/svm/avic.c | 7 +------ |
| arch/x86/kvm/svm/svm.h | 2 +- |
| 2 files changed, 2 insertions(+), 7 deletions(-) |
| |
| --- a/arch/x86/kvm/svm/avic.c |
| +++ b/arch/x86/kvm/svm/avic.c |
| @@ -949,15 +949,10 @@ out: |
| void avic_vcpu_load(struct kvm_vcpu *vcpu, int cpu) |
| { |
| u64 entry; |
| - /* ID = 0xff (broadcast), ID > 0xff (reserved) */ |
| int h_physical_id = kvm_cpu_get_apicid(cpu); |
| struct vcpu_svm *svm = to_svm(vcpu); |
| |
| - /* |
| - * Since the host physical APIC id is 8 bits, |
| - * we can support host APIC ID upto 255. |
| - */ |
| - if (WARN_ON(h_physical_id > AVIC_PHYSICAL_ID_ENTRY_HOST_PHYSICAL_ID_MASK)) |
| + if (WARN_ON(h_physical_id & ~AVIC_PHYSICAL_ID_ENTRY_HOST_PHYSICAL_ID_MASK)) |
| return; |
| |
| entry = READ_ONCE(*(svm->avic_physical_id_cache)); |
| --- a/arch/x86/kvm/svm/svm.h |
| +++ b/arch/x86/kvm/svm/svm.h |
| @@ -510,7 +510,7 @@ extern struct kvm_x86_nested_ops svm_nes |
| #define AVIC_LOGICAL_ID_ENTRY_VALID_BIT 31 |
| #define AVIC_LOGICAL_ID_ENTRY_VALID_MASK (1 << 31) |
| |
| -#define AVIC_PHYSICAL_ID_ENTRY_HOST_PHYSICAL_ID_MASK (0xFFULL) |
| +#define AVIC_PHYSICAL_ID_ENTRY_HOST_PHYSICAL_ID_MASK GENMASK_ULL(11, 0) |
| #define AVIC_PHYSICAL_ID_ENTRY_BACKING_PAGE_MASK (0xFFFFFFFFFFULL << 12) |
| #define AVIC_PHYSICAL_ID_ENTRY_IS_RUNNING_MASK (1ULL << 62) |
| #define AVIC_PHYSICAL_ID_ENTRY_VALID_MASK (1ULL << 63) |