OSDN Git Service

KVM: x86: fix APICv/x2AVIC disabled when vm reboot by itself
authorYuan ZhaoXiong <yuanzhaoxiong@baidu.com>
Fri, 2 Dec 2022 12:36:14 +0000 (20:36 +0800)
committerPaolo Bonzini <pbonzini@redhat.com>
Fri, 2 Dec 2022 18:08:16 +0000 (13:08 -0500)
When a VM reboots itself, the reset process will result in
an ioctl(KVM_SET_LAPIC, ...) to disable x2APIC mode and set
the xAPIC id of the vCPU to its default value, which is the
vCPU id.

That will be handled in KVM as follows:

     kvm_vcpu_ioctl_set_lapic
       kvm_apic_set_state
  kvm_lapic_set_base  =>  disable X2APIC mode
    kvm_apic_state_fixup
      kvm_lapic_xapic_id_updated
        kvm_xapic_id(apic) != apic->vcpu->vcpu_id
kvm_set_apicv_inhibit(APICV_INHIBIT_REASON_APIC_ID_MODIFIED)
   memcpy(vcpu->arch.apic->regs, s->regs, sizeof(*s))  => update APIC_ID

When kvm_apic_set_state invokes kvm_lapic_set_base to disable
x2APIC mode, the old 32-bit x2APIC id is still present rather
than the 8-bit xAPIC id.  kvm_lapic_xapic_id_updated will set the
APICV_INHIBIT_REASON_APIC_ID_MODIFIED bit and disable APICv/x2AVIC.

Instead, kvm_lapic_xapic_id_updated must be called after APIC_ID is
changed.

In fact, this fixes another small issue in the code in that
potential changes to a vCPU's xAPIC ID need not be tracked for
KVM_GET_LAPIC.

Fixes: 3743c2f02517 ("KVM: x86: inhibit APICv/AVIC on changes to APIC ID or APIC base")
Signed-off-by: Yuan ZhaoXiong <yuanzhaoxiong@baidu.com>
Message-Id: <1669984574-32692-1-git-send-email-yuanzhaoxiong@baidu.com>
Cc: stable@vger.kernel.org
Reported-by: Alejandro Jimenez <alejandro.j.jimenez@oracle.com>
Signed-off-by: Paolo Bonzini <pbonzini@redhat.com>
arch/x86/kvm/lapic.c

index 1bb6374..8224ac8 100644 (file)
@@ -2724,8 +2724,6 @@ static int kvm_apic_state_fixup(struct kvm_vcpu *vcpu,
                        icr = __kvm_lapic_get_reg64(s->regs, APIC_ICR);
                        __kvm_lapic_set_reg(s->regs, APIC_ICR2, icr >> 32);
                }
-       } else {
-               kvm_lapic_xapic_id_updated(vcpu->arch.apic);
        }
 
        return 0;
@@ -2761,6 +2759,9 @@ int kvm_apic_set_state(struct kvm_vcpu *vcpu, struct kvm_lapic_state *s)
        }
        memcpy(vcpu->arch.apic->regs, s->regs, sizeof(*s));
 
+       if (!apic_x2apic_mode(apic))
+               kvm_lapic_xapic_id_updated(apic);
+
        atomic_set_release(&apic->vcpu->kvm->arch.apic_map_dirty, DIRTY);
        kvm_recalculate_apic_map(vcpu->kvm);
        kvm_apic_set_version(vcpu);