[PATCH 3/3] irqchip/gic-v3: fix priority mask handling
Joey Gouly
joey.gouly at arm.com
Fri May 13 06:45:52 PDT 2022
Hi Mark,
On Fri, May 13, 2022 at 02:30:38PM +0100, Mark Rutland wrote:
> When a kernel is built with CONFIG_ARM64_PSEUDO_NMI=y and pseudo-NMIs
> are enabled at runtime, GICv3's gic_handle_irq() can leave DAIF and
> ICC_PMR_EL1 in an unexpected state in some cases, breaking subsequent
> usage of local_irq_enable() and resulting in softirqs being run with
> IRQs erroneously masked (possibly resulting in deadlocks).
>
> This can happen when an IRQ exception is taken from a context where
> regular IRQs were unmasked, and either:
>
> (1) ICC_IAR1_EL1 indicates a special INTID (e.g. as a result of an IRQ
> being withdrawn since the IRQ exception was taken).
>
> (2) ICC_IAR1_EL1 and ICC_RPR_EL1 indicate an NMI was acknowledged.
>
> When an NMI is taken from a context where regular IRQs were masked,
> there is no problem.
>
[..]
> +/*
> + * An exception has been taken from a context with IRQs enabled, which can only
I think this should be: IRQs *disabled*?
> + * be an NMI.
> + *
> + * The entry code called us with DAIF.IF set to keep NMIs masked. We must leave
> + * DAIF.IF (and ICC_PMR_EL1) unchanged.
> + *
> + * The entry code has performed NMI entry.
> + */
> +static void __gic_handle_irq_from_irqsoff(struct pt_regs *regs)
> +{
> + u64 pmr;
> + u32 irqnr;
> +
> + /*
> + * 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();
> + irqnr = gic_read_iar();
> + gic_write_pmr(pmr);
> +
> + __gic_handle_nmi(irqnr, regs);
> +}
Thanks,
Joey
More information about the linux-arm-kernel
mailing list