From b1d27b484f4172542eca074fdac42ffd13736a0f Mon Sep 17 00:00:00 2001 From: Roberto Vargas Date: Mon, 30 Oct 2017 14:43:43 +0000 Subject: bl2-el3: Add BL2_EL3 image This patch enables BL2 to execute at the highest exception level without any dependancy on TF BL1. This enables platforms which already have a non-TF Boot ROM to directly load and execute BL2 and subsequent BL stages without need for BL1. This is not currently possible because BL2 executes at S-EL1 and cannot jump straight to EL3. Change-Id: Ief1efca4598560b1b8c8e61fbe26d1f44e929d69 Signed-off-by: Roberto Vargas --- bl2/aarch32/bl2_el3_entrypoint.S | 84 +++++++++++++++++++ bl2/aarch32/bl2_el3_exceptions.S | 21 +++++ bl2/aarch64/bl2_el3_entrypoint.S | 77 +++++++++++++++++ bl2/aarch64/bl2_el3_exceptions.S | 131 +++++++++++++++++++++++++++++ bl2/bl2.mk | 12 ++- bl2/bl2_el3.ld.S | 175 +++++++++++++++++++++++++++++++++++++++ bl2/bl2_main.c | 14 ++++ bl2/bl2_private.h | 3 +- 8 files changed, 515 insertions(+), 2 deletions(-) create mode 100644 bl2/aarch32/bl2_el3_entrypoint.S create mode 100644 bl2/aarch32/bl2_el3_exceptions.S create mode 100644 bl2/aarch64/bl2_el3_entrypoint.S create mode 100644 bl2/aarch64/bl2_el3_exceptions.S create mode 100644 bl2/bl2_el3.ld.S (limited to 'bl2') diff --git a/bl2/aarch32/bl2_el3_entrypoint.S b/bl2/aarch32/bl2_el3_entrypoint.S new file mode 100644 index 00000000..997b069c --- /dev/null +++ b/bl2/aarch32/bl2_el3_entrypoint.S @@ -0,0 +1,84 @@ +/* + * Copyright (c) 2017, ARM Limited and Contributors. All rights reserved. + * + * SPDX-License-Identifier: BSD-3-Clause + */ + +#include +#include +#include +#include + + + .globl bl2_entrypoint + .globl bl2_run_next_image + + +func bl2_entrypoint + /* Save arguments x0-x3 from previous Boot loader */ + mov r9, r0 + mov r10, r1 + mov r11, r2 + mov r12, r3 + + el3_entrypoint_common \ + _init_sctlr=1 \ + _warm_boot_mailbox=!PROGRAMMABLE_RESET_ADDRESS \ + _secondary_cold_boot=!COLD_BOOT_SINGLE_CPU \ + _init_memory=1 \ + _init_c_runtime=1 \ + _exception_vectors=bl2_vector_table + + /* + * Restore parameters of boot rom + */ + mov r0, r9 + mov r1, r10 + mov r2, r11 + mov r3, r12 + + bl bl2_el3_early_platform_setup + bl bl2_el3_plat_arch_setup + + /* --------------------------------------------- + * Jump to main function. + * --------------------------------------------- + */ + bl bl2_main + + /* --------------------------------------------- + * Should never reach this point. + * --------------------------------------------- + */ + no_ret plat_panic_handler + +endfunc bl2_entrypoint + +func bl2_run_next_image + mov r8,r0 + + /* + * MMU needs to be disabled because both BL2 and BL32 execute + * in PL1, and therefore share the same address space. + * BL32 will initialize the address space according to its + * own requirement. + */ + bl disable_mmu_icache_secure + stcopr r0, TLBIALL + dsb sy + isb + mov r0, r8 + bl bl2_el3_plat_prepare_exit + + /* + * Extract PC and SPSR based on struct `entry_point_info_t` + * and load it in LR and SPSR registers respectively. + */ + ldr lr, [r8, #ENTRY_POINT_INFO_PC_OFFSET] + ldr r1, [r8, #(ENTRY_POINT_INFO_PC_OFFSET + 4)] + msr spsr, r1 + + add r8, r8, #ENTRY_POINT_INFO_ARGS_OFFSET + ldm r8, {r0, r1, r2, r3} + eret +endfunc bl2_run_next_image diff --git a/bl2/aarch32/bl2_el3_exceptions.S b/bl2/aarch32/bl2_el3_exceptions.S new file mode 100644 index 00000000..11ddf371 --- /dev/null +++ b/bl2/aarch32/bl2_el3_exceptions.S @@ -0,0 +1,21 @@ +/* + * Copyright (c) 2017, ARM Limited and Contributors. All rights reserved. + * + * SPDX-License-Identifier: BSD-3-Clause + */ + +#include +#include +#include + + .globl bl2_vector_table + +vector_base bl2_vector_table + b bl2_entrypoint + b report_exception /* Undef */ + b report_exception /* SVC call */ + b report_exception /* Prefetch abort */ + b report_exception /* Data abort */ + b report_exception /* Reserved */ + b report_exception /* IRQ */ + b report_exception /* FIQ */ diff --git a/bl2/aarch64/bl2_el3_entrypoint.S b/bl2/aarch64/bl2_el3_entrypoint.S new file mode 100644 index 00000000..2d3efd1f --- /dev/null +++ b/bl2/aarch64/bl2_el3_entrypoint.S @@ -0,0 +1,77 @@ +/* + * Copyright (c) 2017, ARM Limited and Contributors. All rights reserved. + * + * SPDX-License-Identifier: BSD-3-Clause + */ + +#include +#include +#include +#include + + .globl bl2_entrypoint + .globl bl2_vector_table + .globl bl2_el3_run_image + .globl bl2_run_next_image + +func bl2_entrypoint + /* Save arguments x0-x3 from previous Boot loader */ + mov x20, x0 + mov x21, x1 + mov x22, x2 + mov x23, x3 + + el3_entrypoint_common \ + _init_sctlr=1 \ + _warm_boot_mailbox=!PROGRAMMABLE_RESET_ADDRESS \ + _secondary_cold_boot=!COLD_BOOT_SINGLE_CPU \ + _init_memory=1 \ + _init_c_runtime=1 \ + _exception_vectors=bl2_el3_exceptions + + /* + * Restore parameters of boot rom + */ + mov x0, x20 + mov x1, x21 + mov x2, x22 + mov x3, x23 + + bl bl2_el3_early_platform_setup + bl bl2_el3_plat_arch_setup + + /* --------------------------------------------- + * Jump to main function. + * --------------------------------------------- + */ + bl bl2_main + + /* --------------------------------------------- + * Should never reach this point. + * --------------------------------------------- + */ + no_ret plat_panic_handler +endfunc bl2_entrypoint + +func bl2_run_next_image + mov x20,x0 + /* + * MMU needs to be disabled because both BL2 and BL31 execute + * in EL3, and therefore share the same address space. + * BL31 will initialize the address space according to its + * own requirement. + */ + bl disable_mmu_icache_el3 + tlbi alle3 + bl bl2_el3_plat_prepare_exit + + ldp x0, x1, [x20, #ENTRY_POINT_INFO_PC_OFFSET] + msr elr_el3, x0 + msr spsr_el3, x1 + + ldp x6, x7, [x20, #(ENTRY_POINT_INFO_ARGS_OFFSET + 0x30)] + ldp x4, x5, [x20, #(ENTRY_POINT_INFO_ARGS_OFFSET + 0x20)] + ldp x2, x3, [x20, #(ENTRY_POINT_INFO_ARGS_OFFSET + 0x10)] + ldp x0, x1, [x20, #(ENTRY_POINT_INFO_ARGS_OFFSET + 0x0)] + eret +endfunc bl2_run_next_image diff --git a/bl2/aarch64/bl2_el3_exceptions.S b/bl2/aarch64/bl2_el3_exceptions.S new file mode 100644 index 00000000..987f6e35 --- /dev/null +++ b/bl2/aarch64/bl2_el3_exceptions.S @@ -0,0 +1,131 @@ +/* + * Copyright (c) 2017, ARM Limited and Contributors. All rights reserved. + * + * SPDX-License-Identifier: BSD-3-Clause + */ + +#include +#include +#include +#include +#include + +/* ----------------------------------------------------------------------------- + * Very simple stackless exception handlers used by BL2. + * ----------------------------------------------------------------------------- + */ + .globl bl2_el3_exceptions + +vector_base bl2_el3_exceptions + + /* ----------------------------------------------------- + * Current EL with SP0 : 0x0 - 0x200 + * ----------------------------------------------------- + */ +vector_entry SynchronousExceptionSP0 + mov x0, #SYNC_EXCEPTION_SP_EL0 + bl plat_report_exception + no_ret plat_panic_handler + check_vector_size SynchronousExceptionSP0 + +vector_entry IrqSP0 + mov x0, #IRQ_SP_EL0 + bl plat_report_exception + no_ret plat_panic_handler + check_vector_size IrqSP0 + +vector_entry FiqSP0 + mov x0, #FIQ_SP_EL0 + bl plat_report_exception + no_ret plat_panic_handler + check_vector_size FiqSP0 + +vector_entry SErrorSP0 + mov x0, #SERROR_SP_EL0 + bl plat_report_exception + no_ret plat_panic_handler + check_vector_size SErrorSP0 + + /* ----------------------------------------------------- + * Current EL with SPx: 0x200 - 0x400 + * ----------------------------------------------------- + */ +vector_entry SynchronousExceptionSPx + mov x0, #SYNC_EXCEPTION_SP_ELX + bl plat_report_exception + no_ret plat_panic_handler + check_vector_size SynchronousExceptionSPx + +vector_entry IrqSPx + mov x0, #IRQ_SP_ELX + bl plat_report_exception + no_ret plat_panic_handler + check_vector_size IrqSPx + +vector_entry FiqSPx + mov x0, #FIQ_SP_ELX + bl plat_report_exception + no_ret plat_panic_handler + check_vector_size FiqSPx + +vector_entry SErrorSPx + mov x0, #SERROR_SP_ELX + bl plat_report_exception + no_ret plat_panic_handler + check_vector_size SErrorSPx + + /* ----------------------------------------------------- + * Lower EL using AArch64 : 0x400 - 0x600 + * ----------------------------------------------------- + */ +vector_entry SynchronousExceptionA64 + mov x0, #SYNC_EXCEPTION_AARCH64 + bl plat_report_exception + no_ret plat_panic_handler + check_vector_size SynchronousExceptionA64 + +vector_entry IrqA64 + mov x0, #IRQ_AARCH64 + bl plat_report_exception + no_ret plat_panic_handler + check_vector_size IrqA64 + +vector_entry FiqA64 + mov x0, #FIQ_AARCH64 + bl plat_report_exception + no_ret plat_panic_handler + check_vector_size FiqA64 + +vector_entry SErrorA64 + mov x0, #SERROR_AARCH64 + bl plat_report_exception + no_ret plat_panic_handler + check_vector_size SErrorA64 + + /* ----------------------------------------------------- + * Lower EL using AArch32 : 0x600 - 0x800 + * ----------------------------------------------------- + */ +vector_entry SynchronousExceptionA32 + mov x0, #SYNC_EXCEPTION_AARCH32 + bl plat_report_exception + no_ret plat_panic_handler + check_vector_size SynchronousExceptionA32 + +vector_entry IrqA32 + mov x0, #IRQ_AARCH32 + bl plat_report_exception + no_ret plat_panic_handler + check_vector_size IrqA32 + +vector_entry FiqA32 + mov x0, #FIQ_AARCH32 + bl plat_report_exception + no_ret plat_panic_handler + check_vector_size FiqA32 + +vector_entry SErrorA32 + mov x0, #SERROR_AARCH32 + bl plat_report_exception + no_ret plat_panic_handler + check_vector_size SErrorA32 diff --git a/bl2/bl2.mk b/bl2/bl2.mk index 32e32844..f6d69eb3 100644 --- a/bl2/bl2.mk +++ b/bl2/bl2.mk @@ -5,7 +5,6 @@ # BL2_SOURCES += bl2/bl2_main.c \ - bl2/${ARCH}/bl2_entrypoint.S \ bl2/${ARCH}/bl2_arch_setup.c \ lib/locks/exclusive/${ARCH}/spinlock.S \ plat/common/${ARCH}/platform_up_stack.S @@ -20,4 +19,15 @@ else BL2_SOURCES += bl2/bl2_image_load.c endif +ifeq (${BL2_AT_EL3},0) +BL2_SOURCES += bl2/${ARCH}/bl2_entrypoint.S BL2_LINKERFILE := bl2/bl2.ld.S + +else +BL2_SOURCES += bl2/${ARCH}/bl2_el3_entrypoint.S \ + bl2/${ARCH}/bl2_el3_exceptions.S \ + plat/common/plat_bl2_el3_common.c \ + lib/cpus/${ARCH}/cpu_helpers.S \ + lib/cpus/errata_report.c +BL2_LINKERFILE := bl2/bl2_el3.ld.S +endif diff --git a/bl2/bl2_el3.ld.S b/bl2/bl2_el3.ld.S new file mode 100644 index 00000000..7ec4646f --- /dev/null +++ b/bl2/bl2_el3.ld.S @@ -0,0 +1,175 @@ +/* + * Copyright (c) 2017, ARM Limited and Contributors. All rights reserved. + * + * SPDX-License-Identifier: BSD-3-Clause + */ + +#include +#include + +OUTPUT_FORMAT(PLATFORM_LINKER_FORMAT) +OUTPUT_ARCH(PLATFORM_LINKER_ARCH) +ENTRY(bl2_entrypoint) + +MEMORY { + RAM (rwx): ORIGIN = BL2_BASE, LENGTH = BL2_LIMIT - BL2_BASE +} + + +SECTIONS +{ + . = BL2_BASE; + ASSERT(. == ALIGN(PAGE_SIZE), + "BL2_BASE address is not aligned on a page boundary.") + +#if SEPARATE_CODE_AND_RODATA + .text . : { + __TEXT_START__ = .; + *bl2_el3_entrypoint.o(.text*) + *(.text*) + *(.vectors) + . = NEXT(PAGE_SIZE); + __TEXT_END__ = .; + } >RAM + + .rodata . : { + __RODATA_START__ = .; + *(.rodata*) + + /* Ensure 8-byte alignment for descriptors and ensure inclusion */ + . = ALIGN(8); + __PARSER_LIB_DESCS_START__ = .; + KEEP(*(.img_parser_lib_descs)) + __PARSER_LIB_DESCS_END__ = .; + + /* + * Ensure 8-byte alignment for cpu_ops so that its fields are also + * aligned. Also ensure cpu_ops inclusion. + */ + . = ALIGN(8); + __CPU_OPS_START__ = .; + KEEP(*(cpu_ops)) + __CPU_OPS_END__ = .; + + . = NEXT(PAGE_SIZE); + __RODATA_END__ = .; + } >RAM +#else + ro . : { + __RO_START__ = .; + *bl2_el3_entrypoint.o(.text*) + *(.text*) + *(.rodata*) + + /* + * Ensure 8-byte alignment for cpu_ops so that its fields are also + * aligned. Also ensure cpu_ops inclusion. + */ + . = ALIGN(8); + __CPU_OPS_START__ = .; + KEEP(*(cpu_ops)) + __CPU_OPS_END__ = .; + + /* Ensure 8-byte alignment for descriptors and ensure inclusion */ + . = ALIGN(8); + __PARSER_LIB_DESCS_START__ = .; + KEEP(*(.img_parser_lib_descs)) + __PARSER_LIB_DESCS_END__ = .; + + *(.vectors) + __RO_END_UNALIGNED__ = .; + /* + * Memory page(s) mapped to this section will be marked as + * read-only, executable. No RW data from the next section must + * creep in. Ensure the rest of the current memory page is unused. + */ + . = NEXT(PAGE_SIZE); + + __RO_END__ = .; + } >RAM +#endif + + ASSERT(__CPU_OPS_END__ > __CPU_OPS_START__, + "cpu_ops not defined for this platform.") + + /* + * Define a linker symbol to mark start of the RW memory area for this + * image. + */ + __RW_START__ = . ; + + /* + * .data must be placed at a lower address than the stacks if the stack + * protector is enabled. Alternatively, the .data.stack_protector_canary + * section can be placed independently of the main .data section. + */ + .data . : { + __DATA_START__ = .; + *(.data*) + __DATA_END__ = .; + } >RAM + + stacks (NOLOAD) : { + __STACKS_START__ = .; + *(tzfw_normal_stacks) + __STACKS_END__ = .; + } >RAM + + /* + * The .bss section gets initialised to 0 at runtime. + * Its base address should be 16-byte aligned for better performance of the + * zero-initialization code. + */ + .bss : ALIGN(16) { + __BSS_START__ = .; + *(SORT_BY_ALIGNMENT(.bss*)) + *(COMMON) + __BSS_END__ = .; + } >RAM + + /* + * The xlat_table section is for full, aligned page tables (4K). + * Removing them from .bss avoids forcing 4K alignment on + * the .bss section and eliminates the unnecessary zero init + */ + xlat_table (NOLOAD) : { + *(xlat_table) + } >RAM + +#if USE_COHERENT_MEM + /* + * The base address of the coherent memory section must be page-aligned (4K) + * to guarantee that the coherent data are stored on their own pages and + * are not mixed with normal data. This is required to set up the correct + * memory attributes for the coherent data page tables. + */ + coherent_ram (NOLOAD) : ALIGN(PAGE_SIZE) { + __COHERENT_RAM_START__ = .; + *(tzfw_coherent_mem) + __COHERENT_RAM_END_UNALIGNED__ = .; + /* + * Memory page(s) mapped to this section will be marked + * as device memory. No other unexpected data must creep in. + * Ensure the rest of the current memory page is unused. + */ + . = NEXT(PAGE_SIZE); + __COHERENT_RAM_END__ = .; + } >RAM +#endif + + /* + * Define a linker symbol to mark end of the RW memory area for this + * image. + */ + __RW_END__ = .; + __BL2_END__ = .; + + __BSS_SIZE__ = SIZEOF(.bss); + +#if USE_COHERENT_MEM + __COHERENT_RAM_UNALIGNED_SIZE__ = + __COHERENT_RAM_END_UNALIGNED__ - __COHERENT_RAM_START__; +#endif + + ASSERT(. <= BL2_LIMIT, "BL2 image has exceeded its limit.") +} diff --git a/bl2/bl2_main.c b/bl2/bl2_main.c index 018deb34..c85db2d4 100644 --- a/bl2/bl2_main.c +++ b/bl2/bl2_main.c @@ -13,6 +13,11 @@ #include #include "bl2_private.h" +#ifdef AARCH32 +#define NEXT_IMAGE "BL32" +#else +#define NEXT_IMAGE "BL31" +#endif /******************************************************************************* * The only thing to do in BL2 is to load further images and pass control to @@ -49,6 +54,8 @@ void bl2_main(void) disable_mmu_icache_secure(); #endif /* AARCH32 */ + +#if !BL2_AT_EL3 console_flush(); /* @@ -57,4 +64,11 @@ void bl2_main(void) * be passed to next BL image as an argument. */ smc(BL1_SMC_RUN_IMAGE, (unsigned long)next_bl_ep_info, 0, 0, 0, 0, 0, 0); +#else + NOTICE("BL2: Booting " NEXT_IMAGE "\n"); + print_entry_point_info(next_bl_ep_info); + console_flush(); + + bl2_run_next_image(next_bl_ep_info); +#endif } diff --git a/bl2/bl2_private.h b/bl2/bl2_private.h index 83b8047a..ea2f33aa 100644 --- a/bl2/bl2_private.h +++ b/bl2/bl2_private.h @@ -1,5 +1,5 @@ /* - * Copyright (c) 2013-2016, ARM Limited and Contributors. All rights reserved. + * Copyright (c) 2013-2017, ARM Limited and Contributors. All rights reserved. * * SPDX-License-Identifier: BSD-3-Clause */ @@ -17,5 +17,6 @@ struct entry_point_info; *****************************************/ void bl2_arch_setup(void); struct entry_point_info *bl2_load_images(void); +void bl2_run_next_image(const entry_point_info_t *bl_ep_info); #endif /* __BL2_PRIVATE_H__ */ -- cgit v1.2.3