]> www.infradead.org Git - users/dwmw2/linux.git/commitdiff
riscv: Use separate IRQ shadow call stacks
authorSami Tolvanen <samitolvanen@google.com>
Wed, 27 Sep 2023 22:48:03 +0000 (22:48 +0000)
committerPalmer Dabbelt <palmer@rivosinc.com>
Fri, 27 Oct 2023 21:43:09 +0000 (14:43 -0700)
When both CONFIG_IRQ_STACKS and SCS are enabled, also use a separate
per-CPU shadow call stack.

Signed-off-by: Sami Tolvanen <samitolvanen@google.com>
Tested-by: Nathan Chancellor <nathan@kernel.org>
Link: https://lore.kernel.org/r/20230927224757.1154247-13-samitolvanen@google.com
Signed-off-by: Palmer Dabbelt <palmer@rivosinc.com>
arch/riscv/include/asm/scs.h
arch/riscv/kernel/entry.S
arch/riscv/kernel/irq.c

index 94726ea773e3f556dbb9f6fab5e6e82cf2006154..0e45db78b24bf201c7f70c1819d95d258323b8bd 100644 (file)
        XIP_FIXUP_OFFSET gp
 .endm
 
+/* Load the per-CPU IRQ shadow call stack to gp. */
+.macro scs_load_irq_stack tmp
+       load_per_cpu gp, irq_shadow_call_stack_ptr, \tmp
+.endm
+
 /* Load task_scs_sp(current) to gp. */
 .macro scs_load_current
        REG_L   gp, TASK_TI_SCS_SP(tp)
@@ -34,6 +39,8 @@ _skip_scs:
 
 .macro scs_load_init_stack
 .endm
+.macro scs_load_irq_stack tmp
+.endm
 .macro scs_load_current
 .endm
 .macro scs_load_current_if_task_changed prev
index 52793193a763a6b82b35b8d0bca33ac561bac199..3a0db310325a104f26161a1048230938f50bc700 100644 (file)
@@ -237,12 +237,19 @@ SYM_FUNC_START(call_on_irq_stack)
        REG_S   s0, STACKFRAME_FP(sp)
        addi    s0, sp, STACKFRAME_SIZE_ON_STACK
 
+       /* Switch to the per-CPU shadow call stack */
+       scs_save_current
+       scs_load_irq_stack t0
+
        /* Switch to the per-CPU IRQ stack and call the handler */
        load_per_cpu t0, irq_stack_ptr, t1
        li      t1, IRQ_STACK_SIZE
        add     sp, t0, t1
        jalr    a1
 
+       /* Switch back to the thread shadow call stack */
+       scs_load_current
+
        /* Switch back to the thread stack and restore ra and s0 */
        addi    sp, s0, -STACKFRAME_SIZE_ON_STACK
        REG_L   ra, STACKFRAME_RA(sp)
index 95dafdcbd135537354ed8c5c1d0b2c0d7b46648c..7bfea97ee7e7e0033ddb6dd43e0a138efa873c3f 100644 (file)
@@ -9,6 +9,7 @@
 #include <linux/irqchip.h>
 #include <linux/irqdomain.h>
 #include <linux/module.h>
+#include <linux/scs.h>
 #include <linux/seq_file.h>
 #include <asm/sbi.h>
 #include <asm/smp.h>
@@ -34,6 +35,24 @@ EXPORT_SYMBOL_GPL(riscv_get_intc_hwnode);
 #ifdef CONFIG_IRQ_STACKS
 #include <asm/irq_stack.h>
 
+DECLARE_PER_CPU(ulong *, irq_shadow_call_stack_ptr);
+
+#ifdef CONFIG_SHADOW_CALL_STACK
+DEFINE_PER_CPU(ulong *, irq_shadow_call_stack_ptr);
+#endif
+
+static void init_irq_scs(void)
+{
+       int cpu;
+
+       if (!scs_is_enabled())
+               return;
+
+       for_each_possible_cpu(cpu)
+               per_cpu(irq_shadow_call_stack_ptr, cpu) =
+                       scs_alloc(cpu_to_node(cpu));
+}
+
 DEFINE_PER_CPU(ulong *, irq_stack_ptr);
 
 #ifdef CONFIG_VMAP_STACK
@@ -76,6 +95,7 @@ void do_softirq_own_stack(void)
 #endif /* CONFIG_HAVE_SOFTIRQ_ON_OWN_STACK */
 
 #else
+static void init_irq_scs(void) {}
 static void init_irq_stacks(void) {}
 #endif /* CONFIG_IRQ_STACKS */
 
@@ -87,6 +107,7 @@ int arch_show_interrupts(struct seq_file *p, int prec)
 
 void __init init_IRQ(void)
 {
+       init_irq_scs();
        init_irq_stacks();
        irqchip_init();
        if (!handle_arch_irq)