summaryrefslogtreecommitdiff
path: root/arch/powerpc/kvm/book3s_xics.c
diff options
context:
space:
mode:
authorLi Zhong <zhong@linux.vnet.ibm.com>2016-11-11 07:57:34 +0300
committerPaul Mackerras <paulus@ozlabs.org>2017-01-27 02:26:09 +0300
commitbf5a71d53835110d46d33eb5335713ffdbff9ab6 (patch)
tree21f09dcc3174c68e861d1b433ee57d3c0cb4c4c4 /arch/powerpc/kvm/book3s_xics.c
parent37451bc95dee0e666927d6ffdda302dbbaaae6fa (diff)
downloadlinux-bf5a71d53835110d46d33eb5335713ffdbff9ab6.tar.xz
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_xics.c')
-rw-r--r--arch/powerpc/kvm/book3s_xics.c4
1 files changed, 4 insertions, 0 deletions
diff --git a/arch/powerpc/kvm/book3s_xics.c b/arch/powerpc/kvm/book3s_xics.c
index debda779a240..cdfb4ed73601 100644
--- a/arch/powerpc/kvm/book3s_xics.c
+++ b/arch/powerpc/kvm/book3s_xics.c
@@ -125,6 +125,8 @@ static void ics_check_resend(struct kvmppc_xics *xics, struct kvmppc_ics *ics,
if (!state->resend)
continue;
+ state->resend = 0;
+
XICS_DBG("resend %#x prio %#x\n", state->number,
state->priority);
@@ -155,6 +157,7 @@ static bool write_xive(struct kvmppc_xics *xics, struct kvmppc_ics *ics,
deliver = false;
if ((state->masked_pending || state->resend) && priority != MASKED) {
state->masked_pending = 0;
+ state->resend = 0;
deliver = true;
}
@@ -488,6 +491,7 @@ static void icp_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);
local_irq_restore(flags);
goto again;