linux/arch/powerpc/kvm
Paul Mackerras da15c03b04 powerpc/xive: Implement get_irqchip_state method for XIVE to fix shutdown race
Testing has revealed the existence of a race condition where a XIVE
interrupt being shut down can be in one of the XIVE interrupt queues
(of which there are up to 8 per CPU, one for each priority) at the
point where free_irq() is called.  If this happens, can return an
interrupt number which has been shut down.  This can lead to various
symptoms:

- irq_to_desc(irq) can be NULL.  In this case, no end-of-interrupt
  function gets called, resulting in the CPU's elevated interrupt
  priority (numerically lowered CPPR) never gets reset.  That then
  means that the CPU stops processing interrupts, causing device
  timeouts and other errors in various device drivers.

- The irq descriptor or related data structures can be in the process
  of being freed as the interrupt code is using them.  This typically
  leads to crashes due to bad pointer dereferences.

This race is basically what commit 62e0468650 ("genirq: Add optional
hardware synchronization for shutdown", 2019-06-28) is intended to
fix, given a get_irqchip_state() method for the interrupt controller
being used.  It works by polling the interrupt controller when an
interrupt is being freed until the controller says it is not pending.

With XIVE, the PQ bits of the interrupt source indicate the state of
the interrupt source, and in particular the P bit goes from 0 to 1 at
the point where the hardware writes an entry into the interrupt queue
that this interrupt is directed towards.  Normally, the code will then
process the interrupt and do an end-of-interrupt (EOI) operation which
will reset PQ to 00 (assuming another interrupt hasn't been generated
in the meantime).  However, there are situations where the code resets
P even though a queue entry exists (for example, by setting PQ to 01,
which disables the interrupt source), and also situations where the
code leaves P at 1 after removing the queue entry (for example, this
is done for escalation interrupts so they cannot fire again until
they are explicitly re-enabled).

The code already has a 'saved_p' flag for the interrupt source which
indicates that a queue entry exists, although it isn't maintained
consistently.  This patch adds a 'stale_p' flag to indicate that
P has been left at 1 after processing a queue entry, and adds code
to set and clear saved_p and stale_p as necessary to maintain a
consistent indication of whether a queue entry may or may not exist.

With this, we can implement xive_get_irqchip_state() by looking at
stale_p, saved_p and the ESB PQ bits for the interrupt.

There is some additional code to handle escalation interrupts
properly; because they are enabled and disabled in KVM assembly code,
which does not have access to the xive_irq_data struct for the
escalation interrupt.  Hence, stale_p may be incorrect when the
escalation interrupt is freed in kvmppc_xive_{,native_}cleanup_vcpu().
Fortunately, we can fix it up by looking at vcpu->arch.xive_esc_on,
with some careful attention to barriers in order to ensure the correct
result if xive_esc_irq() races with kvmppc_xive_cleanup_vcpu().

Finally, this adds code to make noise on the console (pr_crit and
WARN_ON(1)) if we find an interrupt queue entry for an interrupt
which does not have a descriptor.  While this won't catch the race
reliably, if it does get triggered it will be an indication that
the race is occurring and needs to be debugged.

Fixes: 243e25112d ("powerpc/xive: Native exploitation of the XIVE interrupt controller")
Cc: stable@vger.kernel.org # v4.12+
Signed-off-by: Paul Mackerras <paulus@ozlabs.org>
Signed-off-by: Michael Ellerman <mpe@ellerman.id.au>
Link: https://lore.kernel.org/r/20190813100648.GE9567@blackberry
2019-08-16 14:16:59 +10:00
..
Kconfig powerpc/Kconfig: Clean up formatting 2019-07-04 16:55:10 +10:00
Makefile KVM: PPC: Book3S HV: Add a new KVM device for the XIVE native exploitation mode 2019-04-30 19:35:16 +10:00
book3s.c treewide: Replace GPLv2 boilerplate/reference with SPDX - rule 500 2019-06-19 17:09:55 +02:00
book3s.h treewide: Replace GPLv2 boilerplate/reference with SPDX - rule 98 2019-05-24 17:37:54 +02:00
book3s_32_mmu.c treewide: Replace GPLv2 boilerplate/reference with SPDX - rule 266 2019-06-05 17:30:28 +02:00
book3s_32_mmu_host.c treewide: Replace GPLv2 boilerplate/reference with SPDX - rule 266 2019-06-05 17:30:28 +02:00
book3s_32_sr.S treewide: Replace GPLv2 boilerplate/reference with SPDX - rule 266 2019-06-05 17:30:28 +02:00
book3s_64_mmu.c treewide: Replace GPLv2 boilerplate/reference with SPDX - rule 266 2019-06-05 17:30:28 +02:00
book3s_64_mmu_host.c treewide: Replace GPLv2 boilerplate/reference with SPDX - rule 266 2019-06-05 17:30:28 +02:00
book3s_64_mmu_hv.c treewide: Replace GPLv2 boilerplate/reference with SPDX - rule 266 2019-06-05 17:30:28 +02:00
book3s_64_mmu_radix.c powerpc updates for 5.3 2019-07-13 16:08:36 -07:00
book3s_64_slb.S treewide: Replace GPLv2 boilerplate/reference with SPDX - rule 266 2019-06-05 17:30:28 +02:00
book3s_64_vio.c mm: add account_locked_vm utility function 2019-07-16 19:23:25 -07:00
book3s_64_vio_hv.c treewide: Replace GPLv2 boilerplate/reference with SPDX - rule 266 2019-06-05 17:30:28 +02:00
book3s_emulate.c treewide: Replace GPLv2 boilerplate/reference with SPDX - rule 266 2019-06-05 17:30:28 +02:00
book3s_exports.c treewide: Replace GPLv2 boilerplate/reference with SPDX - rule 266 2019-06-05 17:30:28 +02:00
book3s_hv.c KVM: PPC: Book3S HV: Save and restore guest visible PSSCR bits on pseries 2019-07-15 12:43:36 +10:00
book3s_hv_builtin.c powerpc updates for 5.3 2019-07-13 16:08:36 -07:00
book3s_hv_hmi.c treewide: Replace GPLv2 boilerplate/reference with SPDX - rule 114 2019-05-24 17:39:01 +02:00
book3s_hv_interrupts.S treewide: Replace GPLv2 boilerplate/reference with SPDX - rule 266 2019-06-05 17:30:28 +02:00
book3s_hv_nested.c KVM: PPC: Book3S HV: Introduce kvmhv_update_nest_rmap_rc_list() 2018-12-21 14:39:35 +11:00
book3s_hv_ras.c treewide: Replace GPLv2 boilerplate/reference with SPDX - rule 500 2019-06-19 17:09:55 +02:00
book3s_hv_rm_mmu.c treewide: Replace GPLv2 boilerplate/reference with SPDX - rule 500 2019-06-19 17:09:55 +02:00
book3s_hv_rm_xics.c treewide: Replace GPLv2 boilerplate/reference with SPDX - rule 500 2019-06-19 17:09:55 +02:00
book3s_hv_rm_xive.c License cleanup: add SPDX GPL-2.0 license identifier to files with no license 2017-11-02 11:10:55 +01:00
book3s_hv_rmhandlers.S KVM: PPC: Book3S HV: Don't push XIVE context when not using XIVE device 2019-08-16 14:16:08 +10:00
book3s_hv_tm.c powerpc updates for 5.3 2019-07-13 16:08:36 -07:00
book3s_hv_tm_builtin.c treewide: Replace GPLv2 boilerplate/reference with SPDX - rule 500 2019-06-19 17:09:55 +02:00
book3s_interrupts.S treewide: Replace GPLv2 boilerplate/reference with SPDX - rule 266 2019-06-05 17:30:28 +02:00
book3s_mmu_hpte.c treewide: Replace GPLv2 boilerplate/reference with SPDX - rule 266 2019-06-05 17:30:28 +02:00
book3s_paired_singles.c treewide: Replace GPLv2 boilerplate/reference with SPDX - rule 266 2019-06-05 17:30:28 +02:00
book3s_pr.c treewide: Replace GPLv2 boilerplate/reference with SPDX - rule 500 2019-06-19 17:09:55 +02:00
book3s_pr_papr.c treewide: Replace GPLv2 boilerplate/reference with SPDX - rule 500 2019-06-19 17:09:55 +02:00
book3s_rmhandlers.S treewide: Replace GPLv2 boilerplate/reference with SPDX - rule 266 2019-06-05 17:30:28 +02:00
book3s_rtas.c treewide: Replace GPLv2 boilerplate/reference with SPDX - rule 500 2019-06-19 17:09:55 +02:00
book3s_segment.S treewide: Replace GPLv2 boilerplate/reference with SPDX - rule 266 2019-06-05 17:30:28 +02:00
book3s_xics.c scripts/spelling.txt: drop "sepc" from the misspelling list 2019-07-12 11:05:41 -07:00
book3s_xics.h treewide: Replace GPLv2 boilerplate/reference with SPDX - rule 500 2019-06-19 17:09:55 +02:00
book3s_xive.c powerpc/xive: Implement get_irqchip_state method for XIVE to fix shutdown race 2019-08-16 14:16:59 +10:00
book3s_xive.h powerpc/xive: Implement get_irqchip_state method for XIVE to fix shutdown race 2019-08-16 14:16:59 +10:00
book3s_xive_native.c powerpc/xive: Implement get_irqchip_state method for XIVE to fix shutdown race 2019-08-16 14:16:59 +10:00
book3s_xive_template.c treewide: Replace GPLv2 boilerplate/reference with SPDX - rule 500 2019-06-19 17:09:55 +02:00
booke.c treewide: Replace GPLv2 boilerplate/reference with SPDX - rule 266 2019-06-05 17:30:28 +02:00
booke.h treewide: Replace GPLv2 boilerplate/reference with SPDX - rule 266 2019-06-05 17:30:28 +02:00
booke_emulate.c treewide: Replace GPLv2 boilerplate/reference with SPDX - rule 266 2019-06-05 17:30:28 +02:00
booke_interrupts.S treewide: Replace GPLv2 boilerplate/reference with SPDX - rule 266 2019-06-05 17:30:28 +02:00
bookehv_interrupts.S treewide: Replace GPLv2 boilerplate/reference with SPDX - rule 266 2019-06-05 17:30:28 +02:00
e500.c treewide: Replace GPLv2 boilerplate/reference with SPDX - rule 500 2019-06-19 17:09:55 +02:00
e500.h treewide: Replace GPLv2 boilerplate/reference with SPDX - rule 500 2019-06-19 17:09:55 +02:00
e500_emulate.c treewide: Replace GPLv2 boilerplate/reference with SPDX - rule 500 2019-06-19 17:09:55 +02:00
e500_mmu.c treewide: Replace GPLv2 boilerplate/reference with SPDX - rule 500 2019-06-19 17:09:55 +02:00
e500_mmu_host.c treewide: Replace GPLv2 boilerplate/reference with SPDX - rule 500 2019-06-19 17:09:55 +02:00
e500_mmu_host.h treewide: Replace GPLv2 boilerplate/reference with SPDX - rule 500 2019-06-19 17:09:55 +02:00
e500mc.c treewide: Replace GPLv2 boilerplate/reference with SPDX - rule 500 2019-06-19 17:09:55 +02:00
emulate.c treewide: Replace GPLv2 boilerplate/reference with SPDX - rule 266 2019-06-05 17:30:28 +02:00
emulate_loadstore.c treewide: Replace GPLv2 boilerplate/reference with SPDX - rule 266 2019-06-05 17:30:28 +02:00
fpu.S treewide: Replace GPLv2 boilerplate/reference with SPDX - rule 152 2019-05-30 11:26:32 -07:00
irq.h License cleanup: add SPDX GPL-2.0 license identifier to files with no license 2017-11-02 11:10:55 +01:00
mpic.c Replace <asm/uaccess.h> with <linux/uaccess.h> globally 2016-12-24 11:46:01 -08:00
powerpc.c KVM/arm updates for 5.3 2019-07-11 15:14:16 +02:00
timing.c treewide: Replace GPLv2 boilerplate/reference with SPDX - rule 266 2019-06-05 17:30:28 +02:00
timing.h treewide: Replace GPLv2 boilerplate/reference with SPDX - rule 266 2019-06-05 17:30:28 +02:00
tm.S treewide: Replace GPLv2 boilerplate/reference with SPDX - rule 174 2019-05-30 11:26:41 -07:00
trace.h KVM: PPC: Move and undef TRACE_INCLUDE_PATH/FILE 2018-11-07 23:04:38 +11:00
trace_book3s.h KVM: PPC: Book3S: Simplify external interrupt handling 2018-10-09 16:04:27 +11:00
trace_booke.h KVM: PPC: Move and undef TRACE_INCLUDE_PATH/FILE 2018-11-07 23:04:38 +11:00
trace_hv.h KVM: PPC: Move and undef TRACE_INCLUDE_PATH/FILE 2018-11-07 23:04:38 +11:00
trace_pr.h KVM: PPC: Move and undef TRACE_INCLUDE_PATH/FILE 2018-11-07 23:04:38 +11:00