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>
This commit is contained in:
Родитель
37451bc95d
Коммит
bf5a71d538
|
@ -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;
|
||||
}
|
||||
|
|
|
@ -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;
|
||||
|
|
Загрузка…
Ссылка в новой задаче