ARM: run softirqs on the per-CPU IRQ stack
authorArd Biesheuvel <ardb@kernel.org>
Tue, 5 Oct 2021 07:15:42 +0000 (09:15 +0200)
committerArd Biesheuvel <ardb@kernel.org>
Fri, 3 Dec 2021 14:11:32 +0000 (15:11 +0100)
Now that we have enabled IRQ stacks, any softIRQs that are handled over
the back of a hard IRQ will run from the IRQ stack as well. However, any
synchronous softirq processing that happens when re-enabling softIRQs
from task context will still execute on that task's stack.

Since any call to local_bh_enable() at any level in the task's call
stack may trigger a softIRQ processing run, which could potentially
cause a task stack overflow if the combined stack footprints exceed the
stack's size, let's run these synchronous invocations of do_softirq() on
the IRQ stack as well.

Signed-off-by: Ard Biesheuvel <ardb@kernel.org>
Reviewed-by: Arnd Bergmann <arnd@arndb.de>
Acked-by: Linus Walleij <linus.walleij@linaro.org>
Tested-by: Keith Packard <keithpac@amazon.com>
Tested-by: Marc Zyngier <maz@kernel.org>
Tested-by: Vladimir Murzin <vladimir.murzin@arm.com> # ARMv7M
arch/arm/Kconfig
arch/arm/kernel/irq.c

index b118466..41849d5 100644 (file)
@@ -1169,6 +1169,8 @@ config CURRENT_POINTER_IN_TPIDRURO
 config IRQSTACKS
        def_bool y
        depends on GENERIC_IRQ_MULTI_HANDLER && THREAD_INFO_IN_TASK
+       select HAVE_IRQ_EXIT_ON_IRQ_STACK
+       select HAVE_SOFTIRQ_ON_OWN_STACK
 
 config ARM_CPU_TOPOLOGY
        bool "Support cpu topology definition"
index abb0aa6..e05219b 100644 (file)
 #include <asm/hardware/cache-l2x0.h>
 #include <asm/hardware/cache-uniphier.h>
 #include <asm/outercache.h>
+#include <asm/softirq_stack.h>
 #include <asm/exception.h>
 #include <asm/mach/arch.h>
 #include <asm/mach/irq.h>
 #include <asm/mach/time.h>
 
+#include "reboot.h"
+
 unsigned long irq_err_count;
 
 #ifdef CONFIG_IRQSTACKS
@@ -60,6 +63,17 @@ static void __init init_irq_stacks(void)
        }
 }
 
+static void ____do_softirq(void *arg)
+{
+       __do_softirq();
+}
+
+void do_softirq_own_stack(void)
+{
+       call_with_stack(____do_softirq, NULL,
+                       __this_cpu_read(irq_stack_ptr));
+}
+
 #endif
 
 int arch_show_interrupts(struct seq_file *p, int prec)