summaryrefslogtreecommitdiffstats
path: root/arch/arm/include/asm/barebox-arm.h
diff options
context:
space:
mode:
Diffstat (limited to 'arch/arm/include/asm/barebox-arm.h')
-rw-r--r--arch/arm/include/asm/barebox-arm.h223
1 files changed, 118 insertions, 105 deletions
diff --git a/arch/arm/include/asm/barebox-arm.h b/arch/arm/include/asm/barebox-arm.h
index 8b2ecd9ab2..7a7e5a2403 100644
--- a/arch/arm/include/asm/barebox-arm.h
+++ b/arch/arm/include/asm/barebox-arm.h
@@ -1,3 +1,4 @@
+/* SPDX-License-Identifier: GPL-2.0-or-later */
/*
* (C) Copyright 2002
* Sysgo Real-Time Solutions, GmbH <www.elinos.com>
@@ -6,20 +7,6 @@
* (C) Copyright 2002
* Sysgo Real-Time Solutions, GmbH <www.elinos.com>
* Alex Zuepke <azu@sysgo.de>
- *
- * See file CREDITS for list of people who contributed to this
- * project.
- *
- * This program is free software; you can redistribute it and/or
- * modify it under the terms of the GNU General Public License as
- * published by the Free Software Foundation; either version 2 of
- * the License, or (at your option) any later version.
- *
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
- * GNU General Public License for more details.
- *
*/
#ifndef _BAREBOX_ARM_H_
@@ -28,84 +15,33 @@
#include <linux/sizes.h>
#include <asm-generic/memory_layout.h>
#include <linux/kernel.h>
+#include <linux/pagemap.h>
#include <linux/types.h>
#include <linux/compiler.h>
#include <asm/barebox-arm-head.h>
+#include <asm/common.h>
#include <asm/sections.h>
+#include <asm/reloc.h>
+#include <linux/stringify.h>
+#include <boarddata.h>
-/*
- * We have a 4GiB address space split into 1MiB sections, with each
- * section header taking 4 bytes
- */
-#define ARM_TTB_SIZE (SZ_4G / SZ_1M * sizeof(u32))
-
-unsigned long get_runtime_offset(void);
-
-/* global_variable_offset() - Access global variables when not running at link address
- *
- * Get the offset of global variables when not running at the address we are
- * linked at.
- */
-static inline unsigned long global_variable_offset(void)
-{
-#ifdef CONFIG_CPU_V8
- unsigned long text;
-
- __asm__ __volatile__(
- "adr %0, _text\n"
- : "=r" (text)
- :
- : "memory");
- return text - (unsigned long)_text;
-#else
- return get_runtime_offset();
-#endif
-}
+#define ARM_EARLY_PAGETABLE_SIZE SZ_64K
-void setup_c(void);
-void pbl_barebox_break(void);
-void relocate_to_current_adr(void);
-void relocate_to_adr(unsigned long target);
void __noreturn barebox_arm_entry(unsigned long membase, unsigned long memsize, void *boarddata);
-struct barebox_arm_boarddata {
-#define BAREBOX_ARM_BOARDDATA_MAGIC 0xabe742c3
- u32 magic;
- u32 machine; /* machine number to pass to barebox. This may or may
- * not be a ARM machine number registered on arm.linux.org.uk.
- * It must only be unique across barebox. Please use a number
- * that do not potientially clashes with registered machines,
- * i.e. use a number > 0x10000.
- */
-};
-
-/*
- * Create a boarddata struct at given address. Suitable to be passed
- * as boarddata to barebox_arm_entry(). The machine can be retrieved
- * later with barebox_arm_machine().
- */
-static inline void boarddata_create(void *adr, u32 machine)
-{
- struct barebox_arm_boarddata *bd = adr;
-
- bd->magic = BAREBOX_ARM_BOARDDATA_MAGIC;
- bd->machine = machine;
-}
+#define barebox_arm_boarddata barebox_boarddata
+#define BAREBOX_ARM_BOARDDATA_MAGIC BAREBOX_BOARDDATA_MAGIC
u32 barebox_arm_machine(void);
unsigned long arm_mem_ramoops_get(void);
+unsigned long arm_mem_membase_get(void);
unsigned long arm_mem_endmem_get(void);
-struct barebox_arm_boarddata_compressed_dtb {
-#define BAREBOX_ARM_BOARDDATA_COMPRESSED_DTB_MAGIC 0x7b66bcbd
- u32 magic;
- u32 datalen;
- u32 datalen_uncompressed;
-};
-
struct barebox_arm_boarddata *barebox_arm_get_boarddata(void);
+#define barebox_arm_get_boarddata barebox_get_boarddata
+
#if defined(CONFIG_RELOCATABLE) && defined(CONFIG_ARM_EXCEPTIONS)
void arm_fixup_vectors(void);
#else
@@ -116,46 +52,52 @@ static inline void arm_fixup_vectors(void)
void *barebox_arm_boot_dtb(void);
-static inline unsigned long arm_mem_stack_top(unsigned long membase,
- unsigned long endmem)
+static inline unsigned long arm_mem_optee(unsigned long endmem)
{
- if (IS_ENABLED(CONFIG_BOOTM_OPTEE))
- endmem -= OPTEE_SIZE;
+ return endmem - OPTEE_SIZE;
+}
- return endmem - SZ_64K;
+static inline unsigned long arm_mem_scratch(unsigned long endmem)
+{
+ return arm_mem_optee(endmem) - SZ_32K;
}
-static inline unsigned long arm_mem_stack(unsigned long membase,
- unsigned long endmem)
+static inline unsigned long arm_mem_stack(unsigned long endmem)
{
- return arm_mem_stack_top(membase, endmem) - STACK_SIZE;
+ return arm_mem_scratch(endmem) - STACK_SIZE;
}
-static inline unsigned long arm_mem_ttb(unsigned long membase,
- unsigned long endmem)
+static inline unsigned long arm_mem_guard_page(unsigned long endmem)
{
- endmem = arm_mem_stack(membase, endmem);
- endmem = ALIGN_DOWN(endmem, ARM_TTB_SIZE) - ARM_TTB_SIZE;
+ endmem = arm_mem_stack(endmem);
+
+ if (!IS_ENABLED(CONFIG_STACK_GUARD_PAGE))
+ return endmem;
+
+ return ALIGN_DOWN(endmem, PAGE_SIZE) - PAGE_SIZE;
+}
+
+static inline unsigned long arm_mem_ttb(unsigned long endmem)
+{
+ endmem = arm_mem_guard_page(endmem);
+ endmem = ALIGN_DOWN(endmem, ARM_EARLY_PAGETABLE_SIZE) - ARM_EARLY_PAGETABLE_SIZE;
return endmem;
}
-static inline unsigned long arm_mem_early_malloc(unsigned long membase,
- unsigned long endmem)
+static inline unsigned long arm_mem_early_malloc(unsigned long endmem)
{
- return arm_mem_ttb(membase, endmem) - SZ_128K;
+ return arm_mem_ttb(endmem) - SZ_128K;
}
-static inline unsigned long arm_mem_early_malloc_end(unsigned long membase,
- unsigned long endmem)
+static inline unsigned long arm_mem_early_malloc_end(unsigned long endmem)
{
- return arm_mem_ttb(membase, endmem);
+ return arm_mem_ttb(endmem);
}
-static inline unsigned long arm_mem_ramoops(unsigned long membase,
- unsigned long endmem)
+static inline unsigned long arm_mem_ramoops(unsigned long endmem)
{
- endmem = arm_mem_ttb(membase, endmem);
+ endmem = arm_mem_ttb(endmem);
#ifdef CONFIG_FS_PSTORE_RAMOOPS
endmem -= CONFIG_FS_PSTORE_RAMOOPS_SIZE;
endmem = ALIGN_DOWN(endmem, SZ_4K);
@@ -164,11 +106,26 @@ static inline unsigned long arm_mem_ramoops(unsigned long membase,
return endmem;
}
+static inline unsigned long arm_mem_stack_top(unsigned long endmem)
+{
+ return arm_mem_stack(endmem) + STACK_SIZE;
+}
+
+static inline const void *arm_mem_scratch_get(void)
+{
+ return (const void *)arm_mem_scratch(arm_mem_endmem_get());
+}
+
+static inline unsigned long arm_mem_guard_page_get(void)
+{
+ return arm_mem_guard_page(arm_mem_endmem_get());
+}
+
static inline unsigned long arm_mem_barebox_image(unsigned long membase,
unsigned long endmem,
unsigned long size)
{
- endmem = arm_mem_ramoops(membase, endmem);
+ endmem = arm_mem_ramoops(endmem);
if (IS_ENABLED(CONFIG_RELOCATABLE)) {
return ALIGN_DOWN(endmem - size, SZ_1M);
@@ -180,19 +137,75 @@ static inline unsigned long arm_mem_barebox_image(unsigned long membase,
}
}
+/*
+ * Unlike ENTRY_FUNCTION, this can be used to setup stack for a C entry
+ * point on both ARM32 and ARM64. ENTRY_FUNCTION on ARM64 can only be used
+ * if preceding boot stage has initialized the stack pointer.
+ *
+ * Stack top of 0 means stack is already set up. In that case, the follow-up
+ * code block will not be inlined and may spill to stack right away.
+ */
+#ifdef CONFIG_CPU_64
+
+void __barebox_arm64_head(ulong x0, ulong x1, ulong x2);
+
+#define ENTRY_FUNCTION_WITHSTACK_HEAD(name, stack_top, head, arg0, arg1, arg2) \
+ void name(ulong r0, ulong r1, ulong r2); \
+ \
+ static void __##name(ulong, ulong, ulong); \
+ \
+ void __section(.text_head_entry_##name) name \
+ (ulong r0, ulong r1, ulong r2) \
+ { \
+ static __section(.pbl_board_stack_top_##name) \
+ const ulong __stack_top = (stack_top); \
+ __keep_symbolref(head); \
+ __keep_symbolref(__stack_top); \
+ __##name(r0, r1, r2); \
+ } \
+ static void noinline __##name \
+ (ulong arg0, ulong arg1, ulong arg2)
+
+#define ENTRY_FUNCTION_WITHSTACK(name, stack_top, arg0, arg1, arg2) \
+ ENTRY_FUNCTION_WITHSTACK_HEAD(name, stack_top, \
+ __barebox_arm64_head, arg0, arg1, arg2)
+
#define ENTRY_FUNCTION(name, arg0, arg1, arg2) \
- void name (uint32_t r0, uint32_t r1, uint32_t r2); \
+ ENTRY_FUNCTION_WITHSTACK(name, 0, arg0, arg1, arg2)
+
+#else
+#define ENTRY_FUNCTION_WITHSTACK_HEAD(name, stack_top, head, arg0, arg1, arg2) \
+ static void ____##name(ulong, ulong, ulong); \
+ __ENTRY_FUNCTION_HEAD(name, head, arg0, arg1, arg2) \
+ { \
+ if (stack_top) \
+ arm_setup_stack(stack_top); \
+ ____##name(arg0, arg1, arg2); \
+ } \
+ static void noinline ____##name \
+ (ulong arg0, ulong arg1, ulong arg2)
+
+#define __ENTRY_FUNCTION_HEAD(name, head, arg0, arg1, arg2) \
+ void name(ulong r0, ulong r1, ulong r2); \
\
- static void __##name(uint32_t, uint32_t, uint32_t); \
+ static void __##name(ulong, ulong, ulong); \
\
- void NAKED __section(.text_head_entry_##name) name \
- (uint32_t r0, uint32_t r1, uint32_t r2) \
+ void __naked __section(.text_head_entry_##name) name \
+ (ulong r0, ulong r1, ulong r2) \
{ \
- __barebox_arm_head(); \
+ head(); \
__##name(r0, r1, r2); \
} \
- static void NAKED noinline __##name \
- (uint32_t arg0, uint32_t arg1, uint32_t arg2)
+ static void __naked noinline __##name \
+ (ulong arg0, ulong arg1, ulong arg2)
+
+#define ENTRY_FUNCTION(name, arg0, arg1, arg2) \
+ __ENTRY_FUNCTION_HEAD(name, __barebox_arm_head, arg0, arg1, arg2)
+
+#define ENTRY_FUNCTION_WITHSTACK(name, stack_top, arg0, arg1, arg2) \
+ ENTRY_FUNCTION_WITHSTACK_HEAD(name, stack_top, \
+ __barebox_arm_head, arg0, arg1, arg2)
+#endif
/*
* When using compressed images in conjunction with relocatable images