No normal guest has any reason to change physical APIC IDs, and
allowing this introduces bugs into APIC acceleration code.

Signed-off-by: Maxim Levitsky <mlevi...@redhat.com>
---
 arch/x86/kvm/lapic.c | 28 ++++++++++++++++++++++------
 1 file changed, 22 insertions(+), 6 deletions(-)

diff --git a/arch/x86/kvm/lapic.c b/arch/x86/kvm/lapic.c
index dd4e2888c244b..7ff695cab27b2 100644
--- a/arch/x86/kvm/lapic.c
+++ b/arch/x86/kvm/lapic.c
@@ -2002,10 +2002,20 @@ 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))
-                       kvm_apic_set_xapic_id(apic, val >> 24);
-               else
+               if (apic_x2apic_mode(apic)) {
                        ret = 1;
+                       break;
+               }
+               /*
+                * Don't allow setting APIC ID with any APIC acceleration
+                * enabled to avoid unexpected issues
+                */
+               if (enable_apicv && ((val >> 24) != apic->vcpu->vcpu_id)) {
+                       kvm_vm_bugged(apic->vcpu->kvm);
+                       break;
+               }
+
+               kvm_apic_set_xapic_id(apic, val >> 24);
                break;
 
        case APIC_TASKPRI:
@@ -2572,10 +2582,16 @@ int kvm_get_apic_interrupt(struct kvm_vcpu *vcpu)
 static int kvm_apic_state_fixup(struct kvm_vcpu *vcpu,
                struct kvm_lapic_state *s, bool set)
 {
-       if (apic_x2apic_mode(vcpu->arch.apic)) {
-               u32 *id = (u32 *)(s->regs + APIC_ID);
-               u32 *ldr = (u32 *)(s->regs + APIC_LDR);
+       u32 *id = (u32 *)(s->regs + APIC_ID);
+       u32 *ldr = (u32 *)(s->regs + APIC_LDR);
 
+       if (!apic_x2apic_mode(vcpu->arch.apic)) {
+               /* Don't allow setting APIC ID with any APIC acceleration
+                * enabled to avoid unexpected issues
+                */
+               if (enable_apicv && (*id >> 24) != vcpu->vcpu_id)
+                       return -EINVAL;
+       } else {
                if (vcpu->kvm->arch.x2apic_format) {
                        if (*id != vcpu->vcpu_id)
                                return -EINVAL;
-- 
2.26.3

Reply via email to