Message ID | 427a5562-e2f1-0572-7e74-18425bf01126@suse.com (mailing list archive) |
---|---|
State | New, archived |
Headers | show |
Series | x86: (largely) LAPIC related cleanup | expand |
On 06/09/2019 15:01, Jan Beulich wrote: > 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 jumping into a kdump > kernel. The stale bits in the LDR triggered a bug in the KVM APIC > implementation which caused the destination mapping for VCPUs to be > corrupted. > > Note that this isn't intended to paper over the KVM APIC bug. The kernel > has to clear the LDR when resetting the APIC registers except when X2APIC > is enabled. > > Signed-off-by: Bandan Das <bsd@redhat.com> > [Linux commit 558682b5291937a70748d36fd9ba757fb25b99ae] > Signed-off-by: Jan Beulich <jbeulich@suse.com> Acked-by: Andrew Cooper <andrew.cooper3@citrix.com>
On 06.09.2019 16:01, Jan Beulich wrote: > 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 jumping into a kdump > kernel. The stale bits in the LDR triggered a bug in the KVM APIC > implementation which caused the destination mapping for VCPUs to be > corrupted. > > Note that this isn't intended to paper over the KVM APIC bug. The kernel > has to clear the LDR when resetting the APIC registers except when X2APIC > is enabled. > > Signed-off-by: Bandan Das <bsd@redhat.com> > [Linux commit 558682b5291937a70748d36fd9ba757fb25b99ae] > Signed-off-by: Jan Beulich <jbeulich@suse.com> FTR, commit 950b07c14e8c59444e2359f15fd70ed5112e11a0 reverts this in Linux, but only for breaking offlining and then re- onlining the BSP. Since we don't support this (yet), I don't see a reason for us to revert as well. Jan
--- a/xen/arch/x86/apic.c +++ b/xen/arch/x86/apic.c @@ -212,6 +212,10 @@ void clear_local_APIC(void) apic_write(APIC_LVTTHMR, APIC_LVT_MASKED); if (maxlvt >= 6) apic_write(APIC_CMCI, APIC_LVT_MASKED); + if (!x2apic_enabled) { + v = apic_read(APIC_LDR) & ~APIC_LDR_MASK; + apic_write(APIC_LDR, v); + } if (maxlvt > 3) /* Due to Pentium errata 3AP and 11AP. */ apic_write(APIC_ESR, 0);