struct kvm_vcpu *vcpu;
unsigned long i;
u32 max_id = 255; /* enough space for any xAPIC ID */
+ bool xapic_id_mismatch = false;
/* Read kvm->arch.apic_map_dirty before kvm->arch.apic_map. */
if (atomic_read_acquire(&kvm->arch.apic_map_dirty) == CLEAN)
xapic_id = kvm_xapic_id(apic);
x2apic_id = kvm_x2apic_id(apic);
+ /*
+ * Deliberately truncate the vCPU ID when detecting a mismatched
+ * APIC ID to avoid false positives if the vCPU ID, i.e. x2APIC
+ * ID, is a 32-bit value. Any unwanted aliasing due to
+ * truncation results will be detected below.
+ */
+ if (!apic_x2apic_mode(apic) && xapic_id != (u8)vcpu->vcpu_id)
+ xapic_id_mismatch = true;
+
/*
* Apply KVM's hotplug hack if userspace has enable 32-bit APIC
* IDs. Allow sending events to vCPUs by their x2APIC ID even
else
kvm_clear_apicv_inhibit(kvm, APICV_INHIBIT_REASON_LOGICAL_ID_ALIASED);
+ if (xapic_id_mismatch)
+ kvm_set_apicv_inhibit(kvm, APICV_INHIBIT_REASON_APIC_ID_MODIFIED);
+ else
+ kvm_clear_apicv_inhibit(kvm, APICV_INHIBIT_REASON_APIC_ID_MODIFIED);
+
old = rcu_dereference_protected(kvm->arch.apic_map,
lockdep_is_held(&kvm->arch.apic_map_lock));
rcu_assign_pointer(kvm->arch.apic_map, new);
}
}
-static void kvm_lapic_xapic_id_updated(struct kvm_lapic *apic)
-{
- struct kvm *kvm = apic->vcpu->kvm;
-
- if (!kvm_apic_hw_enabled(apic))
- return;
-
- if (KVM_BUG_ON(apic_x2apic_mode(apic), kvm))
- return;
-
- /*
- * Deliberately truncate the vCPU ID when detecting a modified APIC ID
- * to avoid false positives if the vCPU ID, i.e. x2APIC ID, is a 32-bit
- * value. If the wrap/truncation results in unwanted aliasing, APICv
- * will be inhibited as part of updating KVM's optimized APIC maps.
- */
- if (kvm_xapic_id(apic) == (u8)apic->vcpu->vcpu_id)
- return;
-
- kvm_set_apicv_inhibit(apic->vcpu->kvm, APICV_INHIBIT_REASON_APIC_ID_MODIFIED);
-}
-
static int get_lvt_index(u32 reg)
{
if (reg == APIC_LVTCMCI)
case APIC_ID: /* Local APIC ID */
if (!apic_x2apic_mode(apic)) {
kvm_apic_set_xapic_id(apic, val >> 24);
- kvm_lapic_xapic_id_updated(apic);
} else {
ret = 1;
}
}
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);