Commit 6afbdbb8 authored by Marc Zyngier's avatar Marc Zyngier Committed by Yuntao Liu
Browse files

irqchip/gic-v3: Force propagation of the active state with a read-back

stable inclusion
from stable-v4.19.324
commit a27da2fa0b02e0b5521d6c22fbf5eb8e6944ec56
category: bugfix
bugzilla: https://gitee.com/openeuler/kernel/issues/IB5OOC

Reference: https://git.kernel.org/pub/scm/linux/kernel/git/stable/linux.git/commit/?id=a27da2fa0b02e0b5521d6c22fbf5eb8e6944ec56



--------------------------------

commit 464cb98f1c07298c4c10e714ae0c36338d18d316 upstream.

Christoffer reports that on some implementations, writing to
GICR_ISACTIVER0 (and similar GICD registers) can race badly with a guest
issuing a deactivation of that interrupt via the system register interface.

There are multiple reasons to this:

 - this uses an early write-acknoledgement memory type (nGnRE), meaning
   that the write may only have made it as far as some interconnect
   by the time the store is considered "done"

 - the GIC itself is allowed to buffer the write until it decides to
   take it into account (as long as it is in finite time)

The effects are that the activation may not have taken effect by the time
the kernel enters the guest, forcing an immediate exit, or that a guest
deactivation occurs before the interrupt is active, doing nothing.

In order to guarantee that the write to the ISACTIVER register has taken
effect, read back from it, forcing the interconnect to propagate the write,
and the GIC to process the write before returning the read.

Reported-by: default avatarChristoffer Dall <christoffer.dall@arm.com>
Signed-off-by: default avatarMarc Zyngier <maz@kernel.org>
Signed-off-by: default avatarThomas Gleixner <tglx@linutronix.de>
Acked-by: default avatarChristoffer Dall <christoffer.dall@arm.com>
Cc: stable@vger.kernel.org
Link: https://lore.kernel.org/all/20241106084418.3794612-1-maz@kernel.org


Signed-off-by: default avatarGreg Kroah-Hartman <gregkh@linuxfoundation.org>
Signed-off-by: default avatarYuntao Liu <liuyuntao12@huawei.com>
parent eb352e9e
Loading
Loading
Loading
Loading
+7 −0
Original line number Diff line number Diff line
@@ -303,6 +303,13 @@ static int gic_irq_set_irqchip_state(struct irq_data *d,
	}

	gic_poke_irq(d, reg);

	/*
	 * Force read-back to guarantee that the active state has taken
	 * effect, and won't race with a guest-driven deactivation.
	 */
	if (reg == GICD_ISACTIVER)
		gic_peek_irq(d, reg);
	return 0;
}