diff mbox

[3/5] KVM: PPC: Book 3S: XICS: Fix potential issue with duplicate IRQ resends

Message ID 1486591230-11006-4-git-send-email-tim.gardner@canonical.com
State New
Headers show

Commit Message

Tim Gardner Feb. 8, 2017, 10 p.m. UTC
From: Li Zhong <zhong@linux.vnet.ibm.com>

BugLink: http://bugs.launchpad.net/bugs/1651248

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>
(cherry picked from linux-next commit bf5a71d53835110d46d33eb5335713ffdbff9ab6)
Signed-off-by: Tim Gardner <tim.gardner@canonical.com>
---
 arch/powerpc/kvm/book3s_hv_rm_xics.c | 3 +++
 arch/powerpc/kvm/book3s_xics.c       | 4 ++++
 2 files changed, 7 insertions(+)
diff mbox

Patch

diff --git a/arch/powerpc/kvm/book3s_hv_rm_xics.c b/arch/powerpc/kvm/book3s_hv_rm_xics.c
index 9f6c8fe..16349c9 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;
 		}
diff --git a/arch/powerpc/kvm/book3s_xics.c b/arch/powerpc/kvm/book3s_xics.c
index 6f14401..44fda52 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;