diff options
Diffstat (limited to 'arch/arm/include/asm/barebox-arm.h')
-rw-r--r-- | arch/arm/include/asm/barebox-arm.h | 220 |
1 files changed, 118 insertions, 102 deletions
diff --git a/arch/arm/include/asm/barebox-arm.h b/arch/arm/include/asm/barebox-arm.h index 9277b84a19..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,17 +7,6 @@ * (C) Copyright 2002 * Sysgo Real-Time Solutions, GmbH <www.elinos.com> * Alex Zuepke <azu@sysgo.de> - * - * 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_ @@ -25,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 @@ -113,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) || IS_ENABLED(CONFIG_PBL_OPTEE)) - endmem -= OPTEE_SIZE; + return endmem - OPTEE_SIZE; +} + +static inline unsigned long arm_mem_scratch(unsigned long endmem) +{ + return arm_mem_optee(endmem) - SZ_32K; +} - return endmem - SZ_64K; +static inline unsigned long arm_mem_stack(unsigned long endmem) +{ + return arm_mem_scratch(endmem) - STACK_SIZE; } -static inline unsigned long arm_mem_stack(unsigned long membase, - unsigned long endmem) +static inline unsigned long arm_mem_guard_page(unsigned long endmem) { - return arm_mem_stack_top(membase, endmem) - STACK_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 membase, - unsigned long endmem) +static inline unsigned long arm_mem_ttb(unsigned long endmem) { - endmem = arm_mem_stack(membase, endmem); - endmem = ALIGN_DOWN(endmem, ARM_TTB_SIZE) - ARM_TTB_SIZE; + 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); @@ -161,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); @@ -177,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 |