[PATCH v4 3/3] KVM: SVM: Add support for 12-bit host physical APIC ID
From: Suravee Suthikulpanit
Date: Tue Feb 01 2022 - 23:13:51 EST
The AVIC physical APIC ID table entry contains the host physical
APIC ID field, which the hardware uses to keep track of where each
vCPU is running. Originally, the field is an 8-bit value. For system
w/ maximum physical APIC ID larger than 255, AVIC can support
upto 12-bit value.
However, there is no CPUID bit to help determine the AVIC capability
to support 12-bit host physical APIC ID. Therefore, use the maximum
physical APIC ID available on the system to determine the proper
host physical APIC ID mask size.
Cc: Sean Christopherson <seanjc@xxxxxxxxxx>
Cc: Maxim Levitsky <mlevitsk@xxxxxxxxxx>
Signed-off-by: Suravee Suthikulpanit <suravee.suthikulpanit@xxxxxxx>
---
arch/x86/kvm/svm/avic.c | 33 ++++++++++++++++++++++++---------
arch/x86/kvm/svm/svm.h | 1 -
2 files changed, 24 insertions(+), 10 deletions(-)
diff --git a/arch/x86/kvm/svm/avic.c b/arch/x86/kvm/svm/avic.c
index f5c6cab42d74..3ca5776348a8 100644
--- a/arch/x86/kvm/svm/avic.c
+++ b/arch/x86/kvm/svm/avic.c
@@ -19,6 +19,7 @@
#include <linux/amd-iommu.h>
#include <linux/kvm_host.h>
+#include <asm/apic.h>
#include <asm/irq_remapping.h>
#include "trace.h"
@@ -63,6 +64,7 @@
static DEFINE_HASHTABLE(svm_vm_data_hash, SVM_VM_DATA_HASH_BITS);
static u32 next_vm_id = 0;
static bool next_vm_id_wrapped = 0;
+static u16 avic_host_physical_id_mask;
static DEFINE_SPINLOCK(svm_vm_data_hash_lock);
/*
@@ -133,6 +135,23 @@ void avic_vm_destroy(struct kvm *kvm)
spin_unlock_irqrestore(&svm_vm_data_hash_lock, flags);
}
+static void avic_init_host_physical_apicid_mask(void)
+{
+ u32 count = get_count_order(apic_get_max_phys_apicid());
+
+ /*
+ * Depending on the maximum host physical APIC ID available
+ * on the system, AVIC can support upto 8-bit or 12-bit host
+ * physical APIC ID.
+ */
+ if (count <= 8)
+ avic_host_physical_id_mask = GENMASK(7, 0);
+ else
+ avic_host_physical_id_mask = GENMASK(11, 0);
+ pr_debug("Using AVIC host physical APIC ID mask %#0x\n",
+ avic_host_physical_id_mask);
+}
+
int avic_vm_init(struct kvm *kvm)
{
unsigned long flags;
@@ -974,17 +993,12 @@ avic_update_iommu_vcpu_affinity(struct kvm_vcpu *vcpu, int cpu, bool r)
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);
+ u16 h_physical_id = (u16)kvm_cpu_get_apicid(cpu);
struct vcpu_svm *svm = to_svm(vcpu);
lockdep_assert_preemption_disabled();
- /*
- * 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_host_physical_id_mask) != h_physical_id))
return;
/*
@@ -1000,8 +1014,8 @@ void avic_vcpu_load(struct kvm_vcpu *vcpu, int cpu)
entry = READ_ONCE(*(svm->avic_physical_id_cache));
WARN_ON(entry & AVIC_PHYSICAL_ID_ENTRY_IS_RUNNING_MASK);
- entry &= ~AVIC_PHYSICAL_ID_ENTRY_HOST_PHYSICAL_ID_MASK;
- entry |= (h_physical_id & AVIC_PHYSICAL_ID_ENTRY_HOST_PHYSICAL_ID_MASK);
+ entry &= ~((u64)avic_host_physical_id_mask);
+ entry |= h_physical_id;
entry |= AVIC_PHYSICAL_ID_ENTRY_IS_RUNNING_MASK;
WRITE_ONCE(*(svm->avic_physical_id_cache), entry);
@@ -1076,6 +1090,7 @@ bool avic_hardware_setup(struct kvm_x86_ops *x86_ops)
x86_ops->vcpu_unblocking = avic_vcpu_unblocking,
pr_info("AVIC enabled\n");
+ avic_init_host_physical_apicid_mask();
amd_iommu_register_ga_log_notifier(&avic_ga_log_notifier);
return true;
}
diff --git a/arch/x86/kvm/svm/svm.h b/arch/x86/kvm/svm/svm.h
index f2507d11a31a..70c55f20c0f1 100644
--- a/arch/x86/kvm/svm/svm.h
+++ b/arch/x86/kvm/svm/svm.h
@@ -565,7 +565,6 @@ extern struct kvm_x86_nested_ops svm_nested_ops;
#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_BACKING_PAGE_MASK (0xFFFFFFFFFFULL << 12)
#define AVIC_PHYSICAL_ID_ENTRY_IS_RUNNING_MASK (1ULL << 62)
#define AVIC_PHYSICAL_ID_ENTRY_VALID_MASK (1ULL << 63)
--
2.25.1