When KVM_X2APIC_API_USE_32BIT_IDS is enabled, KVM allows events to target a vCPU by its x2APIC ID even while the vCPU is in xAPIC mode. The optimized physical APIC map also creates an entry for its truncated xAPIC ID. If a vCPU with an ID > 0xff is created before a vCPU whose ID matches that truncated xAPIC ID, the map retains the initial entry and it is not updated to allow reaching the "low" vCPU ID via its xAPIC ID. This can result in INIT/SIPI addressed to the xAPIC ID being delivered to the wrong vCPU. Allow a vCPU in xAPIC mode to replace an existing entry when its vCPU ID exactly matches the xAPIC ID. This ensures vCPUs are reachable via their non-truncated xAPIC IDs, regardless of creation order, and preserves the map entries using the full x2APIC IDs for vCPUs that require them. Update the errata wording to describe this behavior, instead of promising delivery to the vCPU with the lowest ID. Fixes: 5bd5db385b3e ("KVM: x86: allow hotplug of VCPU with APIC ID over 0xff") Suggested-by: Sean Christopherson Assisted-by: Codex:gpt-6-astra Signed-off-by: Partha Sarathi Satapathy Signed-off-by: Alejandro Jimenez --- Documentation/virt/kvm/x86/errata.rst | 9 +++++---- arch/x86/kvm/lapic.c | 7 ++++--- 2 files changed, 9 insertions(+), 7 deletions(-) diff --git a/Documentation/virt/kvm/x86/errata.rst b/Documentation/virt/kvm/x86/errata.rst index a9cf0e004651..58a7adbb221a 100644 --- a/Documentation/virt/kvm/x86/errata.rst +++ b/Documentation/virt/kvm/x86/errata.rst @@ -63,10 +63,11 @@ When KVM_X2APIC_API_USE_32BIT_IDS is enabled, KVM activates a hack/quirk that allows sending events to a single vCPU using its x2APIC ID even if the target vCPU has legacy xAPIC enabled, e.g. to bring up hotplugged vCPUs via INIT-SIPI on VMs with > 255 vCPUs. A side effect of the quirk is that, if multiple vCPUs -have the same physical APIC ID, KVM will deliver events targeting that APIC ID -only to the vCPU with the lowest vCPU ID. If KVM_X2APIC_API_USE_32BIT_IDS is -not enabled, KVM follows x86 architecture when processing interrupts (all vCPUs -matching the target APIC ID receive the interrupt). +have the same physical legacy xAPIC ID, KVM may deliver events targeting that +xAPIC ID only to the vCPU whose vCPU ID matches the aliased x2APIC ID. If +KVM_X2APIC_API_USE_32BIT_IDS is not enabled, KVM follows x86 architecture when +processing interrupts (all vCPUs matching the target APIC ID receive the +interrupt). MTRRs ----- diff --git a/arch/x86/kvm/lapic.c b/arch/x86/kvm/lapic.c index ecf611845fb1..e6bd9be0a107 100644 --- a/arch/x86/kvm/lapic.c +++ b/arch/x86/kvm/lapic.c @@ -297,8 +297,8 @@ static int kvm_recalculate_phys_map(struct kvm_apic_map *new, * Apply KVM's hotplug hack if userspace has enable 32-bit APIC IDs. * Allow sending events to vCPUs by their x2APIC ID even if the target * vCPU is in legacy xAPIC mode, and silently ignore aliased xAPIC IDs - * (the x2APIC ID is truncated to 8 bits, causing IDs > 0xff to wrap - * and collide). + * but make sure the non-truncated xAPIC ID always "wins" (the x2APIC + * ID is truncated to 8 bits, causing IDs > 0xff to wrap and collide). * * Honor the architectural (and KVM's non-optimized) behavior if * userspace has not enabled 32-bit x2APIC IDs. Each APIC is supposed @@ -312,7 +312,8 @@ static int kvm_recalculate_phys_map(struct kvm_apic_map *new, if (apic_x2apic_mode(apic) || x2apic_id > 0xff) new->phys_map[x2apic_id] = apic; - if (!apic_x2apic_mode(apic) && !new->phys_map[xapic_id]) + if (!apic_x2apic_mode(apic) && + (!new->phys_map[xapic_id] || vcpu->vcpu_id == xapic_id)) new->phys_map[xapic_id] = apic; } else { /* -- 2.47.3