Skip to content

Commit

Permalink
irqchip/gic-v3: Handle pseudo-NMIs
Browse files Browse the repository at this point in the history
Provide a higher priority to be used for pseudo-NMIs. When such an
interrupt is received, keep interrupts fully disabled at CPU level to
prevent receiving other pseudo-NMIs while handling the current one.

Signed-off-by: Julien Thierry <julien.thierry@arm.com>
Acked-by: Marc Zyngier <marc.zyngier@arm.com>
Cc: Thomas Gleixner <tglx@linutronix.de>
Cc: Jason Cooper <jason@lakedaemon.net>
Cc: Marc Zyngier <marc.zyngier@arm.com>
Signed-off-by: Catalin Marinas <catalin.marinas@arm.com>
  • Loading branch information
Julien Thierry authored and ctmarinas committed Feb 6, 2019
1 parent d98d0a9 commit f32c926
Showing 1 changed file with 36 additions and 6 deletions.
42 changes: 36 additions & 6 deletions drivers/irqchip/irq-gic-v3.c
Original file line number Diff line number Diff line change
Expand Up @@ -41,6 +41,8 @@

#include "irq-gic-common.h"

#define GICD_INT_NMI_PRI (GICD_INT_DEF_PRI & ~0x80)

#define FLAGS_WORKAROUND_GICR_WAKER_MSM8996 (1ULL << 0)

struct redist_region {
Expand Down Expand Up @@ -381,12 +383,45 @@ static u64 gic_mpidr_to_affinity(unsigned long mpidr)
return aff;
}

static void gic_deactivate_unhandled(u32 irqnr)
{
if (static_branch_likely(&supports_deactivate_key)) {
if (irqnr < 8192)
gic_write_dir(irqnr);
} else {
gic_write_eoir(irqnr);
}
}

static inline void gic_handle_nmi(u32 irqnr, struct pt_regs *regs)
{
int err;

if (static_branch_likely(&supports_deactivate_key))
gic_write_eoir(irqnr);
/*
* Leave the PSR.I bit set to prevent other NMIs to be
* received while handling this one.
* PSR.I will be restored when we ERET to the
* interrupted context.
*/
err = handle_domain_nmi(gic_data.domain, irqnr, regs);
if (err)
gic_deactivate_unhandled(irqnr);
}

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

irqnr = gic_read_iar();

if (gic_supports_nmi() &&
unlikely(gic_read_rpr() == GICD_INT_NMI_PRI)) {
gic_handle_nmi(irqnr, regs);
return;
}

if (gic_prio_masking_enabled()) {
gic_pmr_mask_irqs();
gic_arch_enable_irqs();
Expand All @@ -403,12 +438,7 @@ static asmlinkage void __exception_irq_entry gic_handle_irq(struct pt_regs *regs
err = handle_domain_irq(gic_data.domain, irqnr, regs);
if (err) {
WARN_ONCE(true, "Unexpected interrupt received!\n");
if (static_branch_likely(&supports_deactivate_key)) {
if (irqnr < 8192)
gic_write_dir(irqnr);
} else {
gic_write_eoir(irqnr);
}
gic_deactivate_unhandled(irqnr);
}
return;
}
Expand Down

0 comments on commit f32c926

Please sign in to comment.