diff options
author | Julien Thierry <julien.thierry@arm.com> | 2019-01-31 09:54:01 -0500 |
---|---|---|
committer | Marc Zyngier <marc.zyngier@arm.com> | 2019-02-05 09:37:05 -0500 |
commit | 6e4933a006616343f66c4702dc4fc56bb25e7b02 (patch) | |
tree | d5637427d41431971b2037ccbff2c5bf9cdca3f0 /kernel/irq/irqdesc.c | |
parent | 2dcf1fbcad352baaa5f47b17e57c5743c8eedbad (diff) |
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: Julien Thierry <julien.thierry@arm.com>
Acked-by: Marc 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: Marc Zyngier <marc.zyngier@arm.com>
Diffstat (limited to 'kernel/irq/irqdesc.c')
-rw-r--r-- | kernel/irq/irqdesc.c | 35 |
1 files changed, 35 insertions, 0 deletions
diff --git a/kernel/irq/irqdesc.c b/kernel/irq/irqdesc.c index ee062b7939d3..a1d7a7d484e0 100644 --- a/kernel/irq/irqdesc.c +++ b/kernel/irq/irqdesc.c | |||
@@ -669,6 +669,41 @@ int __handle_domain_irq(struct irq_domain *domain, unsigned int hwirq, | |||
669 | set_irq_regs(old_regs); | 669 | set_irq_regs(old_regs); |
670 | return ret; | 670 | return ret; |
671 | } | 671 | } |
672 | |||
673 | #ifdef CONFIG_IRQ_DOMAIN | ||
674 | /** | ||
675 | * handle_domain_nmi - Invoke the handler for a HW irq belonging to a domain | ||
676 | * @domain: The domain where to perform the lookup | ||
677 | * @hwirq: The HW irq number to convert to a logical one | ||
678 | * @regs: Register file coming from the low-level handling code | ||
679 | * | ||
680 | * Returns: 0 on success, or -EINVAL if conversion has failed | ||
681 | */ | ||
682 | int handle_domain_nmi(struct irq_domain *domain, unsigned int hwirq, | ||
683 | struct pt_regs *regs) | ||
684 | { | ||
685 | struct pt_regs *old_regs = set_irq_regs(regs); | ||
686 | unsigned int irq; | ||
687 | int ret = 0; | ||
688 | |||
689 | nmi_enter(); | ||
690 | |||
691 | irq = irq_find_mapping(domain, hwirq); | ||
692 | |||
693 | /* | ||
694 | * ack_bad_irq is not NMI-safe, just report | ||
695 | * an invalid interrupt. | ||
696 | */ | ||
697 | if (likely(irq)) | ||
698 | generic_handle_irq(irq); | ||
699 | else | ||
700 | ret = -EINVAL; | ||
701 | |||
702 | nmi_exit(); | ||
703 | set_irq_regs(old_regs); | ||
704 | return ret; | ||
705 | } | ||
706 | #endif | ||
672 | #endif | 707 | #endif |
673 | 708 | ||
674 | /* Dynamic interrupt handling */ | 709 | /* Dynamic interrupt handling */ |