Commit a13d0f8d authored by Thomas Gleixner's avatar Thomas Gleixner
Browse files

Merge tag 'irqchip-fixes-5.13-2' of...

Merge tag 'irqchip-fixes-5.13-2' of git://git.kernel.org/pub/scm/linux/kernel/git/maz/arm-platforms into irq/urgent

Pull irqchip fixes from Marc Zyngier:

- Fix GICv3 NMI handling where an IRQ could be mistakenly handled
  as a NMI, with disatrous effects

Link: https://lore.kernel.org/r/20210610171127.2404752-1-maz@kernel.org
parents 009c9aa5 382e6e17
Loading
Loading
Loading
Loading
+35 −1
Original line number Diff line number Diff line
@@ -642,11 +642,45 @@ static inline void gic_handle_nmi(u32 irqnr, struct pt_regs *regs)
		nmi_exit();
}

static u32 do_read_iar(struct pt_regs *regs)
{
	u32 iar;

	if (gic_supports_nmi() && unlikely(!interrupts_enabled(regs))) {
		u64 pmr;

		/*
		 * We were in a context with IRQs disabled. However, the
		 * entry code has set PMR to a value that allows any
		 * interrupt to be acknowledged, and not just NMIs. This can
		 * lead to surprising effects if the NMI has been retired in
		 * the meantime, and that there is an IRQ pending. The IRQ
		 * would then be taken in NMI context, something that nobody
		 * wants to debug twice.
		 *
		 * Until we sort this, drop PMR again to a level that will
		 * actually only allow NMIs before reading IAR, and then
		 * restore it to what it was.
		 */
		pmr = gic_read_pmr();
		gic_pmr_mask_irqs();
		isb();

		iar = gic_read_iar();

		gic_write_pmr(pmr);
	} else {
		iar = gic_read_iar();
	}

	return iar;
}

static asmlinkage void __exception_irq_entry gic_handle_irq(struct pt_regs *regs)
{
	u32 irqnr;

	irqnr = gic_read_iar();
	irqnr = do_read_iar(regs);

	/* Check for special IDs first */
	if ((irqnr >= 1020 && irqnr <= 1023))