arm64: scs: Add shadow stacks for SDEI
authorSami Tolvanen <samitolvanen@google.com>
Mon, 27 Apr 2020 16:00:17 +0000 (09:00 -0700)
committerWill Deacon <will@kernel.org>
Fri, 15 May 2020 15:35:50 +0000 (16:35 +0100)
This change adds per-CPU shadow call stacks for the SDEI handler.
Similarly to how the kernel stacks are handled, we add separate shadow
stacks for normal and critical events.

Signed-off-by: Sami Tolvanen <samitolvanen@google.com>
Reviewed-by: James Morse <james.morse@arm.com>
Tested-by: James Morse <james.morse@arm.com>
Signed-off-by: Will Deacon <will@kernel.org>
arch/arm64/kernel/entry.S
arch/arm64/kernel/scs.c

index 244268d..cb0516e 100644 (file)
@@ -1049,13 +1049,16 @@ SYM_CODE_START(__sdei_asm_handler)
 
        mov     x19, x1
 
+#if defined(CONFIG_VMAP_STACK) || defined(CONFIG_SHADOW_CALL_STACK)
+       ldrb    w4, [x19, #SDEI_EVENT_PRIORITY]
+#endif
+
 #ifdef CONFIG_VMAP_STACK
        /*
         * entry.S may have been using sp as a scratch register, find whether
         * this is a normal or critical event and switch to the appropriate
         * stack for this CPU.
         */
-       ldrb    w4, [x19, #SDEI_EVENT_PRIORITY]
        cbnz    w4, 1f
        ldr_this_cpu dst=x5, sym=sdei_stack_normal_ptr, tmp=x6
        b       2f
@@ -1065,6 +1068,15 @@ SYM_CODE_START(__sdei_asm_handler)
        mov     sp, x5
 #endif
 
+#ifdef CONFIG_SHADOW_CALL_STACK
+       /* Use a separate shadow call stack for normal and critical events */
+       cbnz    w4, 3f
+       adr_this_cpu dst=x18, sym=sdei_shadow_call_stack_normal, tmp=x6
+       b       4f
+3:     adr_this_cpu dst=x18, sym=sdei_shadow_call_stack_critical, tmp=x6
+4:
+#endif
+
        /*
         * We may have interrupted userspace, or a guest, or exit-from or
         * return-to either of these. We can't trust sp_el0, restore it.
index acc6741..adc97f8 100644 (file)
@@ -13,3 +13,8 @@
        DEFINE_PER_CPU(unsigned long [SCS_SIZE/sizeof(long)], name)     \
 
 DEFINE_SCS(irq_shadow_call_stack);
+
+#ifdef CONFIG_ARM_SDE_INTERFACE
+DEFINE_SCS(sdei_shadow_call_stack_normal);
+DEFINE_SCS(sdei_shadow_call_stack_critical);
+#endif