Skip to content

Commit c40fef8

Browse files
samitolvanenpalmer-dabbelt
authored andcommitted
riscv: Use separate IRQ shadow call stacks
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>
1 parent d1584d7 commit c40fef8

File tree

3 files changed

+35
-0
lines changed

3 files changed

+35
-0
lines changed

arch/riscv/include/asm/scs.h

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -13,6 +13,11 @@
1313
XIP_FIXUP_OFFSET gp
1414
.endm
1515

16+
/* Load the per-CPU IRQ shadow call stack to gp. */
17+
.macro scs_load_irq_stack tmp
18+
load_per_cpu gp, irq_shadow_call_stack_ptr, \tmp
19+
.endm
20+
1621
/* Load task_scs_sp(current) to gp. */
1722
.macro scs_load_current
1823
REG_L gp, TASK_TI_SCS_SP(tp)
@@ -34,6 +39,8 @@
3439

3540
.macro scs_load_init_stack
3641
.endm
42+
.macro scs_load_irq_stack tmp
43+
.endm
3744
.macro scs_load_current
3845
.endm
3946
.macro scs_load_current_if_task_changed prev

arch/riscv/kernel/entry.S

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -237,12 +237,19 @@ SYM_FUNC_START(call_on_irq_stack)
237237
REG_S s0, STACKFRAME_FP(sp)
238238
addi s0, sp, STACKFRAME_SIZE_ON_STACK
239239

240+
/* Switch to the per-CPU shadow call stack */
241+
scs_save_current
242+
scs_load_irq_stack t0
243+
240244
/* Switch to the per-CPU IRQ stack and call the handler */
241245
load_per_cpu t0, irq_stack_ptr, t1
242246
li t1, IRQ_STACK_SIZE
243247
add sp, t0, t1
244248
jalr a1
245249

250+
/* Switch back to the thread shadow call stack */
251+
scs_load_current
252+
246253
/* Switch back to the thread stack and restore ra and s0 */
247254
addi sp, s0, -STACKFRAME_SIZE_ON_STACK
248255
REG_L ra, STACKFRAME_RA(sp)

arch/riscv/kernel/irq.c

Lines changed: 21 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -9,6 +9,7 @@
99
#include <linux/irqchip.h>
1010
#include <linux/irqdomain.h>
1111
#include <linux/module.h>
12+
#include <linux/scs.h>
1213
#include <linux/seq_file.h>
1314
#include <asm/sbi.h>
1415
#include <asm/smp.h>
@@ -34,6 +35,24 @@ EXPORT_SYMBOL_GPL(riscv_get_intc_hwnode);
3435
#ifdef CONFIG_IRQ_STACKS
3536
#include <asm/irq_stack.h>
3637

38+
DECLARE_PER_CPU(ulong *, irq_shadow_call_stack_ptr);
39+
40+
#ifdef CONFIG_SHADOW_CALL_STACK
41+
DEFINE_PER_CPU(ulong *, irq_shadow_call_stack_ptr);
42+
#endif
43+
44+
static void init_irq_scs(void)
45+
{
46+
int cpu;
47+
48+
if (!scs_is_enabled())
49+
return;
50+
51+
for_each_possible_cpu(cpu)
52+
per_cpu(irq_shadow_call_stack_ptr, cpu) =
53+
scs_alloc(cpu_to_node(cpu));
54+
}
55+
3756
DEFINE_PER_CPU(ulong *, irq_stack_ptr);
3857

3958
#ifdef CONFIG_VMAP_STACK
@@ -76,6 +95,7 @@ void do_softirq_own_stack(void)
7695
#endif /* CONFIG_HAVE_SOFTIRQ_ON_OWN_STACK */
7796

7897
#else
98+
static void init_irq_scs(void) {}
7999
static void init_irq_stacks(void) {}
80100
#endif /* CONFIG_IRQ_STACKS */
81101

@@ -87,6 +107,7 @@ int arch_show_interrupts(struct seq_file *p, int prec)
87107

88108
void __init init_IRQ(void)
89109
{
110+
init_irq_scs();
90111
init_irq_stacks();
91112
irqchip_init();
92113
if (!handle_arch_irq)

0 commit comments

Comments
 (0)