[RFC 07/12] riscv: Handle pseudo NMI in arch irq handler

From: Xu Lu
Date: Mon Oct 23 2023 - 04:30:48 EST


This commit handles pseudo NMI in arch irq handler. We enter NMI context
before handling NMI and keeps all interrupts disabled during NMI handling
to avoid interrupt nesting.

Signed-off-by: Xu Lu <luxu.kernel@xxxxxxxxxxxxx>
Signed-off-by: Hangjing Li <lihangjing@xxxxxxxxxxxxx>
---
drivers/irqchip/irq-riscv-intc.c | 22 ++++++++++++++++++++++
1 file changed, 22 insertions(+)

diff --git a/drivers/irqchip/irq-riscv-intc.c b/drivers/irqchip/irq-riscv-intc.c
index 83a0a744fce6..c672c0c64d5d 100644
--- a/drivers/irqchip/irq-riscv-intc.c
+++ b/drivers/irqchip/irq-riscv-intc.c
@@ -20,6 +20,26 @@

static struct irq_domain *intc_domain;

+#ifdef CONFIG_RISCV_PSEUDO_NMI
+
+static asmlinkage void riscv_intc_irq(struct pt_regs *regs)
+{
+ unsigned long cause = regs->cause & ~CAUSE_IRQ_FLAG;
+
+ if (unlikely(cause >= BITS_PER_LONG))
+ panic("unexpected interrupt cause");
+
+ if (is_nmi(cause)) {
+ nmi_enter();
+ generic_handle_domain_nmi(intc_domain, cause);
+ nmi_exit();
+ } else {
+ generic_handle_domain_irq(intc_domain, cause);
+ }
+}
+
+#else /* CONFIG_RISCV_PSEUDO_NMI */
+
static asmlinkage void riscv_intc_irq(struct pt_regs *regs)
{
unsigned long cause = regs->cause & ~CAUSE_IRQ_FLAG;
@@ -30,6 +50,8 @@ static asmlinkage void riscv_intc_irq(struct pt_regs *regs)
generic_handle_domain_irq(intc_domain, cause);
}

+#endif /* CONFIG_RISCV_PSEUDO_NMI */
+
/*
* On RISC-V systems local interrupts are masked or unmasked by writing
* the SIE (Supervisor Interrupt Enable) CSR. As CSRs can only be written
--
2.20.1