summaryrefslogtreecommitdiffstats
path: root/arch/arm/cpu
diff options
context:
space:
mode:
authorAndrey Smirnov <andrew.smirnov@gmail.com>2019-09-13 23:11:23 -0700
committerSascha Hauer <s.hauer@pengutronix.de>2019-10-01 22:34:08 +0200
commit1d9cc19aa742bff1aa848c48aad58e8d1166037d (patch)
tree796942ab0be0106bf793518f59d8f3fb5068bbb8 /arch/arm/cpu
parentf56b18cdc7595f981878e6aed21d128b59798e24 (diff)
downloadbarebox-1d9cc19aa742bff1aa848c48aad58e8d1166037d.tar.gz
barebox-1d9cc19aa742bff1aa848c48aad58e8d1166037d.tar.xz
ARM: aarch64: Re-implement most of barebox_arm_entry() in assembly
GCC9 now produces the following warning: common.h:51:2: warning: listing the stack pointer register ‘sp’ in a clobber list is deprecated [-Wdeprecated] 51 | __asm__ __volatile__("mov sp, %0" | ^~~~~~~ common.h:51:2: note: the value of the stack pointer after an ‘asm’ statement must be the same as it was before the statement Stack pointer was added to clobber list in commit f9fc8254b2 ("ARM: Mark SP as being clobbered in arm_setup_stack()") to prevent GCC from generating code that would corrupt 'boarddata' pointer by trying to restore it from invalid stack frame. Interestingly enough, seemingly unrelated change in commit 64d95896cf ("ARM: aarch64: compile with general-regs-only") changed generated code such that adding SP to clobber list became no longer necessary. While the above can probably be a fix by itself, it seems a better and more future proof approach would be to address the problem at its root and re-implement offending startup sequence in assembly. Signed-off-by: Andrey Smirnov <andrew.smirnov@gmail.com> Signed-off-by: Sascha Hauer <s.hauer@pengutronix.de>
Diffstat (limited to 'arch/arm/cpu')
-rw-r--r--arch/arm/cpu/Makefile4
-rw-r--r--arch/arm/cpu/entry.c21
-rw-r--r--arch/arm/cpu/entry_ll.S25
-rw-r--r--arch/arm/cpu/entry_ll_64.S23
4 files changed, 63 insertions, 10 deletions
diff --git a/arch/arm/cpu/Makefile b/arch/arm/cpu/Makefile
index e6a1a321dc..e0b16747ad 100644
--- a/arch/arm/cpu/Makefile
+++ b/arch/arm/cpu/Makefile
@@ -8,7 +8,7 @@ obj-pbl-$(CONFIG_CPU_32v7) += hyp.o
AFLAGS_hyp.o :=-Wa,-march=armv7-a -Wa,-mcpu=all
AFLAGS_pbl-hyp.o :=-Wa,-march=armv7-a -Wa,-mcpu=all
-obj-y += start.o entry.o
+obj-y += start.o entry.o entry_ll$(S64).o
pbl-$(CONFIG_BOARD_ARM_GENERIC_DT) += board-dt-2nd.o
pbl-$(CONFIG_BOARD_ARM_GENERIC_DT_AARCH64) += board-dt-2nd-aarch64.o
@@ -47,7 +47,7 @@ AFLAGS_cache-armv8.o :=-Wa,-march=armv8-a
obj-pbl-$(CONFIG_CPU_64v8) += cache-armv8.o
AFLAGS_pbl-cache-armv8.o :=-Wa,-march=armv8-a
-pbl-y += entry.o
+pbl-y += entry.o entry_ll$(S64).o
pbl-y += uncompress.o
obj-pbl-y += common.o sections.o
diff --git a/arch/arm/cpu/entry.c b/arch/arm/cpu/entry.c
index 8b17179437..0b447de801 100644
--- a/arch/arm/cpu/entry.c
+++ b/arch/arm/cpu/entry.c
@@ -24,14 +24,19 @@
* be fine.
*/
+/*
+ * It can be hard to convince GCC to not use old stack pointer after
+ * we modify it with arm_setup_stack() on ARM64, so we implement the
+ * low level details in assembly
+ */
+void __noreturn __barebox_arm_entry(unsigned long membase,
+ unsigned long memsize,
+ void *boarddata,
+ unsigned long sp);
+
void NAKED __noreturn barebox_arm_entry(unsigned long membase,
- unsigned long memsize, void *boarddata)
+ unsigned long memsize, void *boarddata)
{
- arm_setup_stack(arm_mem_stack_top(membase, membase + memsize));
- arm_early_mmu_cache_invalidate();
-
- if (IS_ENABLED(CONFIG_PBL_IMAGE))
- barebox_pbl_start(membase, memsize, boarddata);
- else
- barebox_non_pbl_start(membase, memsize, boarddata);
+ __barebox_arm_entry(membase, memsize, boarddata,
+ arm_mem_stack_top(membase, membase + memsize));
}
diff --git a/arch/arm/cpu/entry_ll.S b/arch/arm/cpu/entry_ll.S
new file mode 100644
index 0000000000..8cc7a84f10
--- /dev/null
+++ b/arch/arm/cpu/entry_ll.S
@@ -0,0 +1,25 @@
+#include <linux/linkage.h>
+#include <asm/sections.h>
+
+/*
+ * r0: memory base
+ * r1: memory size
+ * r2: board data
+ * r3: new value for SP
+ */
+.section .text.__barebox_arm_entry
+ENTRY(__barebox_arm_entry)
+ mov sp, r3
+ mov r4, r0
+ mov r5, r1
+ mov r6, r2
+ bl arm_early_mmu_cache_invalidate
+ mov r0, r4
+ mov r1, r5
+ mov r2, r6
+#if IS_ENABLED(CONFIG_PBL_IMAGE)
+ b barebox_pbl_start
+#else
+ b barebox_non_pbl_start
+#endif
+ENDPROC(__barebox_arm_entry)
diff --git a/arch/arm/cpu/entry_ll_64.S b/arch/arm/cpu/entry_ll_64.S
new file mode 100644
index 0000000000..37e0cb66b5
--- /dev/null
+++ b/arch/arm/cpu/entry_ll_64.S
@@ -0,0 +1,23 @@
+#include <linux/linkage.h>
+#include <asm/sections.h>
+
+/*
+ * x0: memory base
+ * x1: memory size
+ * x2: board data
+ * x3: new value for SP
+ */
+.section .text.__barebox_arm_entry
+ENTRY(__barebox_arm_entry)
+ mov sp, x3
+ /*
+ * arm_early_mmu_cache_invalidate is jsut a call to
+ * v8_invalidate_icache_all() which doesn't clobber x0, x1 or x2
+ */
+ bl arm_early_mmu_cache_invalidate
+#if IS_ENABLED(CONFIG_PBL_IMAGE)
+ b barebox_pbl_start
+#else
+ b barebox_non_pbl_start
+#endif
+ENDPROC(__barebox_arm_entry) \ No newline at end of file