diff options
Diffstat (limited to 'arch/arm/include/asm/common.h')
-rw-r--r-- | arch/arm/include/asm/common.h | 19 |
1 files changed, 19 insertions, 0 deletions
diff --git a/arch/arm/include/asm/common.h b/arch/arm/include/asm/common.h index d03ee6273f..9832a6a4d2 100644 --- a/arch/arm/include/asm/common.h +++ b/arch/arm/include/asm/common.h @@ -1,6 +1,10 @@ +/* SPDX-License-Identifier: GPL-2.0-only */ + #ifndef __ASM_ARM_COMMON_H #define __ASM_ARM_COMMON_H +#include <linux/compiler.h> + static inline unsigned long get_pc(void) { unsigned long pc; @@ -46,8 +50,23 @@ static inline unsigned long get_sp(void) return sp; } +extern void __compiletime_error( + "arm_setup_stack() called outside of naked function. On ARM64, " + "stack should be setup in non-inline assembly before branching to C entry point." +) __unsafe_setup_stack(void); + +/* + * Sets up new stack growing down from top within a naked C function. + * The first stack word will be top - sizeof(word). + * + * Avoid interleaving with C code as much as possible and jump + * ASAP to a noinline function. + */ static inline void arm_setup_stack(unsigned long top) { + if (IS_ENABLED(CONFIG_CPU_64)) + __unsafe_setup_stack(); + __asm__ __volatile__("mov sp, %0" : : "r"(top)); |