[RFC PATCH 00/36] arm64: Add support for FEAT_NMI

Vladimir Murzin vladimir.murzin at arm.com
Tue Jul 14 08:18:09 PDT 2026


On 7/14/26 11:32, Vladimir Murzin wrote:
>> Hi Vladimir,
>>
>> Even if PE supports FEAT_NMI, the GIC may not be able to generate a
>> super-priority interrupt.
>>
>> The following patch can fix it, we should use
>> gic_supports_v3_3_nmi() instead of system_uses_nmi() in
>> ipi_should_be_nmi() because the GIC.
>>
> Thanks for the report!
> 
> I think it would be better for me to spend some time making the arch
> IPI code tolerate both the presence and absence of NMI support,
> perhaps similar to how perf handles this, rather than creating a
> strong dependency between the architecture code and the interrupt
> controller. At least, I’ll give that a try!

The diff below appears to work and doesn't require any knowledge
of GIC internals

diff --git a/arch/arm64/kernel/smp.c b/arch/arm64/kernel/smp.c
index 80e35a8e5c8f..a7f894e82491 100644
--- a/arch/arm64/kernel/smp.c
+++ b/arch/arm64/kernel/smp.c
@@ -67,6 +67,8 @@ static int cpus_stuck_in_kernel;
 static int ipi_irq_base __ro_after_init;
 static int nr_ipi __ro_after_init = NR_IPI;
 
+static DECLARE_BITMAP(ipi_nmi_bitmap, MAX_IPI) __ro_after_init;
+
 struct ipi_descs {
 	struct irq_desc *descs[MAX_IPI];
 };
@@ -1057,7 +1059,7 @@ static void ipi_setup(int cpu)
 
 	for (i = 0; i < nr_ipi; i++) {
 		if (!percpu_ipi_descs) {
-			if (ipi_should_be_nmi(i)) {
+			if (test_bit(i, ipi_nmi_bitmap)) {
 				prepare_percpu_nmi(ipi_irq_base + i);
 				enable_percpu_nmi(ipi_irq_base + i, 0);
 			} else {
@@ -1079,7 +1081,7 @@ static void ipi_teardown(int cpu)
 
 	for (i = 0; i < nr_ipi; i++) {
 		if (!percpu_ipi_descs) {
-			if (ipi_should_be_nmi(i)) {
+			if (test_bit(i, ipi_nmi_bitmap)) {
 				disable_percpu_nmi(ipi_irq_base + i);
 				teardown_percpu_nmi(ipi_irq_base + i);
 			} else {
@@ -1098,10 +1100,24 @@ static void ipi_setup_sgi(int ipi)
 
 	irq = ipi_irq_base + ipi;
 
-	if (ipi_should_be_nmi(ipi)) {
-		err = request_percpu_nmi(irq, ipi_handler, "IPI", NULL, &irq_stat);
-		WARN(err, "Could not request IRQ %d as NMI, err=%d\n", irq, err);
-	} else {
+	if (ipi_should_be_nmi(ipi))
+		set_bit(ipi, ipi_nmi_bitmap);
+
+	/*
+	 * Try to request NMI if it should be
+	 */
+	if (test_bit(ipi, ipi_nmi_bitmap) &&
+	    request_percpu_nmi(irq, ipi_handler, "IPI", NULL, &irq_stat)) {
+		/*
+		 * Fallback to regular IRQ
+		 */
+		clear_bit(ipi, ipi_nmi_bitmap);
+	}
+
+	/*
+	 * Otherwise regular IRQ
+	 */
+	if (!test_bit(ipi, ipi_nmi_bitmap)) {
 		err = request_percpu_irq(irq, ipi_handler, "IPI", &irq_stat);
 		WARN(err, "Could not request IRQ %d as IRQ, err=%d\n", irq, err);
 	}




More information about the linux-arm-kernel mailing list