Commit 6e4933a0 authored by Julien Thierry's avatar Julien Thierry Committed by Marc Zyngier
Browse files

irqdesc: Add domain handler for NMIs



NMI handling code should be executed between calls to nmi_enter and
nmi_exit.

Add a separate domain handler to properly setup NMI context when handling
an interrupt requested as NMI.

Signed-off-by: default avatarJulien Thierry <julien.thierry@arm.com>
Acked-by: default avatarMarc Zyngier <marc.zyngier@arm.com>
Cc: Thomas Gleixner <tglx@linutronix.de>
Cc: Marc Zyngier <marc.zyngier@arm.com>
Cc: Will Deacon <will.deacon@arm.com>
Cc: Peter Zijlstra <peterz@infradead.org>
Signed-off-by: default avatarMarc Zyngier <marc.zyngier@arm.com>
parent 2dcf1fbc
Loading
Loading
Loading
Loading
+5 −0
Original line number Diff line number Diff line
@@ -171,6 +171,11 @@ static inline int handle_domain_irq(struct irq_domain *domain,
{
	return __handle_domain_irq(domain, hwirq, true, regs);
}

#ifdef CONFIG_IRQ_DOMAIN
int handle_domain_nmi(struct irq_domain *domain, unsigned int hwirq,
		      struct pt_regs *regs);
#endif
#endif

/* Test to see if a driver has successfully requested an irq */
+35 −0
Original line number Diff line number Diff line
@@ -669,6 +669,41 @@ int __handle_domain_irq(struct irq_domain *domain, unsigned int hwirq,
	set_irq_regs(old_regs);
	return ret;
}

#ifdef CONFIG_IRQ_DOMAIN
/**
 * handle_domain_nmi - Invoke the handler for a HW irq belonging to a domain
 * @domain:	The domain where to perform the lookup
 * @hwirq:	The HW irq number to convert to a logical one
 * @regs:	Register file coming from the low-level handling code
 *
 * Returns:	0 on success, or -EINVAL if conversion has failed
 */
int handle_domain_nmi(struct irq_domain *domain, unsigned int hwirq,
		      struct pt_regs *regs)
{
	struct pt_regs *old_regs = set_irq_regs(regs);
	unsigned int irq;
	int ret = 0;

	nmi_enter();

	irq = irq_find_mapping(domain, hwirq);

	/*
	 * ack_bad_irq is not NMI-safe, just report
	 * an invalid interrupt.
	 */
	if (likely(irq))
		generic_handle_irq(irq);
	else
		ret = -EINVAL;

	nmi_exit();
	set_irq_regs(old_regs);
	return ret;
}
#endif
#endif

/* Dynamic interrupt handling */