Thread (35 messages) 35 messages, 5 authors, 2021-10-09

[PATCHv2 2/5] irqchip/GICv3: expose handle_nmi() directly

From: Pingfan Liu <hidden>
Date: 2021-09-24 13:33:10
Also in: lkml
Subsystem: arm generic interrupt controller drivers, arm64 port (aarch64 architecture), irqchip drivers, the rest · Maintainers: Marc Zyngier, Catalin Marinas, Will Deacon, Thomas Gleixner, Linus Torvalds

With the previous patch, the NMI should be dispatched at irqentry level.
Accordingly adjust GICv3 to utilize the hooks, so NMI handler can be
dispatched.

Signed-off-by: Pingfan Liu <redacted>
Cc: Catalin Marinas <catalin.marinas@arm.com>
Cc: Will Deacon <will@kernel.org>
Cc: Mark Rutland <mark.rutland@arm.com>
Cc: Marc Zyngier <maz@kernel.org>
Cc: Joey Gouly <joey.gouly@arm.com>
Cc: Sami Tolvanen <samitolvanen@google.com>
Cc: Julien Thierry <redacted>
Cc: Thomas Gleixner <redacted>
Cc: Yuichi Ito <redacted>
Cc: linux-kernel@vger.kernel.org
To: linux-arm-kernel@lists.infradead.org
---
 arch/arm64/include/asm/irq.h |  2 ++
 drivers/irqchip/irq-gic-v3.c | 53 +++++++++++++++++++-----------------
 2 files changed, 30 insertions(+), 25 deletions(-)
diff --git a/arch/arm64/include/asm/irq.h b/arch/arm64/include/asm/irq.h
index a59b1745f458..c39627290a60 100644
--- a/arch/arm64/include/asm/irq.h
+++ b/arch/arm64/include/asm/irq.h
@@ -11,6 +11,8 @@ struct pt_regs;
 int set_handle_irq(void (*handle_irq)(struct pt_regs *));
 #define set_handle_irq	set_handle_irq
 int set_handle_fiq(void (*handle_fiq)(struct pt_regs *));
+int set_handle_nmi(void (*handle_nmi)(struct pt_regs *));
+int set_nmi_discriminator(bool (*discriminator)(void));
 
 extern void (*handle_arch_irq)(struct pt_regs *regs);
 extern void (*handle_arch_fiq)(struct pt_regs *regs);
diff --git a/drivers/irqchip/irq-gic-v3.c b/drivers/irqchip/irq-gic-v3.c
index fd4e9a37fea6..89dcec902a82 100644
--- a/drivers/irqchip/irq-gic-v3.c
+++ b/drivers/irqchip/irq-gic-v3.c
@@ -644,28 +644,12 @@ static void gic_deactivate_unhandled(u32 irqnr)
 	}
 }
 
-static inline void gic_handle_nmi(u32 irqnr, struct pt_regs *regs)
+static bool gic_is_in_nmi(void)
 {
-	bool irqs_enabled = interrupts_enabled(regs);
-	int err;
-
-	if (irqs_enabled)
-		nmi_enter();
-
-	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);
+	if (gic_supports_nmi() && unlikely(gic_read_rpr() == GICD_INT_NMI_PRI))
+		return true;
 
-	if (irqs_enabled)
-		nmi_exit();
+	return false;
 }
 
 static u32 do_read_iar(struct pt_regs *regs)
@@ -702,21 +686,38 @@ static u32 do_read_iar(struct pt_regs *regs)
 	return iar;
 }
 
-static asmlinkage void __exception_irq_entry gic_handle_irq(struct pt_regs *regs)
+static void gic_handle_nmi(struct pt_regs *regs)
 {
 	u32 irqnr;
+	int err;
 
 	irqnr = do_read_iar(regs);
 
 	/* Check for special IDs first */
 	if ((irqnr >= 1020 && irqnr <= 1023))
 		return;
+	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);
+}
 
-	if (gic_supports_nmi() &&
-	    unlikely(gic_read_rpr() == GICD_INT_RPR_PRI(GICD_INT_NMI_PRI))) {
-		gic_handle_nmi(irqnr, regs);
+static asmlinkage void __exception_irq_entry gic_handle_irq(struct pt_regs *regs)
+{
+	u32 irqnr;
+
+	irqnr = do_read_iar(regs);
+
+	/* Check for special IDs first */
+	if ((irqnr >= 1020 && irqnr <= 1023))
 		return;
-	}
 
 	if (gic_prio_masking_enabled()) {
 		gic_pmr_mask_irqs();
@@ -1791,6 +1792,8 @@ static int __init gic_init_bases(void __iomem *dist_base,
 	}
 
 	set_handle_irq(gic_handle_irq);
+	set_handle_nmi(gic_handle_nmi);
+	set_nmi_discriminator(gic_is_in_nmi);
 
 	gic_update_rdist_properties();
 
-- 
2.31.1


_______________________________________________
linux-arm-kernel mailing list
linux-arm-kernel@lists.infradead.org
http://lists.infradead.org/mailman/listinfo/linux-arm-kernel
Keyboard shortcuts
hback out one level
jnext message in thread
kprevious message in thread
ldrill in
Escclose help / fold thread tree
?toggle this help