Although apic initialization will typically clear out the LDR before setting it, the apic cleanup code should reset the LDR.
This was discovered with a 32 bit kvm guest loading the kdump kernel. Stale bits in the LDR exposed a bug in the kvm lapic code that creates logical destination maps for vcpus. If multiple bits are set, kvm could potentially overwrite a valid logical destination with an invalid one. Note that this fix isn't intended to paper over the kvm lapic bug; clear_local_APIC() should correctly clear out any set bits in the LDR when resetting apic registers. Signed-off-by: Bandan Das <b...@redhat.com> --- arch/x86/kernel/apic/apic.c | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/arch/x86/kernel/apic/apic.c b/arch/x86/kernel/apic/apic.c index aa5495d0f478..e75f3782b915 100644 --- a/arch/x86/kernel/apic/apic.c +++ b/arch/x86/kernel/apic/apic.c @@ -1179,6 +1179,10 @@ void clear_local_APIC(void) apic_write(APIC_LVT0, v | APIC_LVT_MASKED); v = apic_read(APIC_LVT1); apic_write(APIC_LVT1, v | APIC_LVT_MASKED); + if (!x2apic_enabled) { + v = apic_read(APIC_LDR) & ~APIC_LDR_MASK; + apic_write(APIC_LDR, v); + } if (maxlvt >= 4) { v = apic_read(APIC_LVTPC); apic_write(APIC_LVTPC, v | APIC_LVT_MASKED); -- 2.20.1