summaryrefslogtreecommitdiffstats
path: root/arch/arm/include/asm/common.h
diff options
context:
space:
mode:
Diffstat (limited to 'arch/arm/include/asm/common.h')
-rw-r--r--arch/arm/include/asm/common.h19
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));