diff options
author | Li Zhong <zhong@linux.vnet.ibm.com> | 2016-11-11 12:57:34 +0800 |
---|---|---|
committer | Paul Mackerras <paulus@ozlabs.org> | 2017-01-27 10:26:09 +1100 |
commit | bf5a71d53835110d46d33eb5335713ffdbff9ab6 (patch) | |
tree | 21f09dcc3174c68e861d1b433ee57d3c0cb4c4c4 /arch/powerpc/kvm/book3s_hv_rm_xics.c | |
parent | 37451bc95dee0e666927d6ffdda302dbbaaae6fa (diff) | |
download | linux-bf5a71d53835110d46d33eb5335713ffdbff9ab6.tar.bz2 |
KVM: PPC: Book 3S: XICS: Fix potential issue with duplicate IRQ resends
It is possible that in the following order, one irq is resent twice:
CPU 1 CPU 2
ics_check_resend()
lock ics_lock
see resend set
unlock ics_lock
/* change affinity of the irq */
kvmppc_xics_set_xive()
write_xive()
lock ics_lock
see resend set
unlock ics_lock
icp_deliver_irq() /* resend */
icp_deliver_irq() /* resend again */
It doesn't have any user-visible effect at present, but needs to be avoided
when the following patch implementing the P/Q stuff is applied.
This patch clears the resend flag before releasing the ics lock, when we
know we will do a re-delivery after checking the flag, or setting the flag.
Signed-off-by: Li Zhong <zhong@linux.vnet.ibm.com>
Signed-off-by: Paul Mackerras <paulus@ozlabs.org>
Diffstat (limited to 'arch/powerpc/kvm/book3s_hv_rm_xics.c')
-rw-r--r-- | arch/powerpc/kvm/book3s_hv_rm_xics.c | 3 |
1 files changed, 3 insertions, 0 deletions
diff --git a/arch/powerpc/kvm/book3s_hv_rm_xics.c b/arch/powerpc/kvm/book3s_hv_rm_xics.c index 9f6c8fe88db6..16349c9e86ba 100644 --- a/arch/powerpc/kvm/book3s_hv_rm_xics.c +++ b/arch/powerpc/kvm/book3s_hv_rm_xics.c @@ -52,6 +52,8 @@ static void ics_rm_check_resend(struct kvmppc_xics *xics, if (!state->resend) continue; + state->resend = 0; + arch_spin_unlock(&ics->lock); icp_rm_deliver_irq(xics, icp, state->number); arch_spin_lock(&ics->lock); @@ -400,6 +402,7 @@ static void icp_rm_deliver_irq(struct kvmppc_xics *xics, struct kvmppc_icp *icp, */ smp_mb(); if (!icp->state.need_resend) { + state->resend = 0; arch_spin_unlock(&ics->lock); goto again; } |