diff options
author | Daniel Baumann <daniel.baumann@progress-linux.org> | 2024-04-28 09:13:47 +0000 |
---|---|---|
committer | Daniel Baumann <daniel.baumann@progress-linux.org> | 2024-04-28 09:13:47 +0000 |
commit | 102b0d2daa97dae68d3eed54d8fe37a9cc38a892 (patch) | |
tree | bcf648efac40ca6139842707f0eba5a4496a6dd2 /bl1/aarch64 | |
parent | Initial commit. (diff) | |
download | arm-trusted-firmware-upstream.tar.xz arm-trusted-firmware-upstream.zip |
Adding upstream version 2.8.0+dfsg.upstream/2.8.0+dfsgupstream
Signed-off-by: Daniel Baumann <daniel.baumann@progress-linux.org>
Diffstat (limited to 'bl1/aarch64')
-rw-r--r-- | bl1/aarch64/bl1_arch_setup.c | 35 | ||||
-rw-r--r-- | bl1/aarch64/bl1_context_mgmt.c | 131 | ||||
-rw-r--r-- | bl1/aarch64/bl1_entrypoint.S | 108 | ||||
-rw-r--r-- | bl1/aarch64/bl1_exceptions.S | 289 |
4 files changed, 563 insertions, 0 deletions
diff --git a/bl1/aarch64/bl1_arch_setup.c b/bl1/aarch64/bl1_arch_setup.c new file mode 100644 index 0000000..0a1cb30 --- /dev/null +++ b/bl1/aarch64/bl1_arch_setup.c @@ -0,0 +1,35 @@ +/* + * Copyright (c) 2013-2019, ARM Limited and Contributors. All rights reserved. + * + * SPDX-License-Identifier: BSD-3-Clause + */ + +#include <arch.h> +#include <arch_helpers.h> +#include "../bl1_private.h" + +/******************************************************************************* + * Function that does the first bit of architectural setup that affects + * execution in the non-secure address space. + ******************************************************************************/ +void bl1_arch_setup(void) +{ + /* Set the next EL to be AArch64 */ + write_scr_el3(read_scr_el3() | SCR_RW_BIT); +} + +/******************************************************************************* + * Set the Secure EL1 required architectural state + ******************************************************************************/ +void bl1_arch_next_el_setup(void) +{ + u_register_t next_sctlr; + + /* Use the same endianness than the current BL */ + next_sctlr = (read_sctlr_el3() & SCTLR_EE_BIT); + + /* Set SCTLR Secure EL1 */ + next_sctlr |= SCTLR_EL1_RES1; + + write_sctlr_el1(next_sctlr); +} diff --git a/bl1/aarch64/bl1_context_mgmt.c b/bl1/aarch64/bl1_context_mgmt.c new file mode 100644 index 0000000..b9a7e5b --- /dev/null +++ b/bl1/aarch64/bl1_context_mgmt.c @@ -0,0 +1,131 @@ +/* + * Copyright (c) 2015-2021, Arm Limited and Contributors. All rights reserved. + * + * SPDX-License-Identifier: BSD-3-Clause + */ + +#include <assert.h> + +#include <arch_helpers.h> +#include <context.h> +#include <common/debug.h> +#include <lib/el3_runtime/context_mgmt.h> +#include <plat/common/platform.h> + +#include "../bl1_private.h" + +/* Following contains the cpu context pointers. */ +static void *bl1_cpu_context_ptr[2]; +entry_point_info_t *bl2_ep_info; + + +void *cm_get_context(uint32_t security_state) +{ + assert(sec_state_is_valid(security_state)); + return bl1_cpu_context_ptr[security_state]; +} + +void cm_set_context(void *context, uint32_t security_state) +{ + assert(sec_state_is_valid(security_state)); + bl1_cpu_context_ptr[security_state] = context; +} + +#if ENABLE_RME +/******************************************************************************* + * This function prepares the entry point information to run BL2 in Root world, + * i.e. EL3, for the case when FEAT_RME is enabled. + ******************************************************************************/ +void bl1_prepare_next_image(unsigned int image_id) +{ + image_desc_t *bl2_desc; + + assert(image_id == BL2_IMAGE_ID); + + /* Get the image descriptor. */ + bl2_desc = bl1_plat_get_image_desc(BL2_IMAGE_ID); + assert(bl2_desc != NULL); + + /* Get the entry point info. */ + bl2_ep_info = &bl2_desc->ep_info; + + bl2_ep_info->spsr = (uint32_t)SPSR_64(MODE_EL3, MODE_SP_ELX, + DISABLE_ALL_EXCEPTIONS); + + /* + * Flush cache since bl2_ep_info is accessed after MMU is disabled + * before jumping to BL2. + */ + flush_dcache_range((uintptr_t)bl2_ep_info, sizeof(entry_point_info_t)); + + /* Indicate that image is in execution state. */ + bl2_desc->state = IMAGE_STATE_EXECUTED; + + /* Print debug info and flush the console before running BL2. */ + print_entry_point_info(bl2_ep_info); +} +#else +/******************************************************************************* + * This function prepares the context for Secure/Normal world images. + * Normal world images are transitioned to EL2(if supported) else EL1. + ******************************************************************************/ +void bl1_prepare_next_image(unsigned int image_id) +{ + + /* + * Following array will be used for context management. + * There are 2 instances, for the Secure and Non-Secure contexts. + */ + static cpu_context_t bl1_cpu_context[2]; + + unsigned int security_state, mode = MODE_EL1; + image_desc_t *desc; + entry_point_info_t *next_bl_ep; + +#if CTX_INCLUDE_AARCH32_REGS + /* + * Ensure that the build flag to save AArch32 system registers in CPU + * context is not set for AArch64-only platforms. + */ + if (el_implemented(1) == EL_IMPL_A64ONLY) { + ERROR("EL1 supports AArch64-only. Please set build flag " + "CTX_INCLUDE_AARCH32_REGS = 0\n"); + panic(); + } +#endif + + /* Get the image descriptor. */ + desc = bl1_plat_get_image_desc(image_id); + assert(desc != NULL); + + /* Get the entry point info. */ + next_bl_ep = &desc->ep_info; + + /* Get the image security state. */ + security_state = GET_SECURITY_STATE(next_bl_ep->h.attr); + + /* Setup the Secure/Non-Secure context if not done already. */ + if (cm_get_context(security_state) == NULL) + cm_set_context(&bl1_cpu_context[security_state], security_state); + + /* Prepare the SPSR for the next BL image. */ + if ((security_state != SECURE) && (el_implemented(2) != EL_IMPL_NONE)) { + mode = MODE_EL2; + } + + next_bl_ep->spsr = (uint32_t)SPSR_64((uint64_t) mode, + (uint64_t)MODE_SP_ELX, DISABLE_ALL_EXCEPTIONS); + + /* Allow platform to make change */ + bl1_plat_set_ep_info(image_id, next_bl_ep); + + /* Prepare the context for the next BL image. */ + cm_init_my_context(next_bl_ep); + cm_prepare_el3_exit(security_state); + + /* Indicate that image is in execution state. */ + desc->state = IMAGE_STATE_EXECUTED; + + print_entry_point_info(next_bl_ep); +} +#endif /* ENABLE_RME */ diff --git a/bl1/aarch64/bl1_entrypoint.S b/bl1/aarch64/bl1_entrypoint.S new file mode 100644 index 0000000..f61c060 --- /dev/null +++ b/bl1/aarch64/bl1_entrypoint.S @@ -0,0 +1,108 @@ +/* + * Copyright (c) 2013-2021, Arm Limited and Contributors. All rights reserved. + * + * SPDX-License-Identifier: BSD-3-Clause + */ + +#include <arch.h> +#include <common/bl_common.h> +#include <el3_common_macros.S> + + .globl bl1_entrypoint + .globl bl1_run_bl2_in_root + + + /* ----------------------------------------------------- + * bl1_entrypoint() is the entry point into the trusted + * firmware code when a cpu is released from warm or + * cold reset. + * ----------------------------------------------------- + */ + +func bl1_entrypoint + /* --------------------------------------------------------------------- + * If the reset address is programmable then bl1_entrypoint() is + * executed only on the cold boot path. Therefore, we can skip the warm + * boot mailbox mechanism. + * --------------------------------------------------------------------- + */ + 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=bl1_exceptions \ + _pie_fixup_size=0 + + /* -------------------------------------------------------------------- + * Perform BL1 setup + * -------------------------------------------------------------------- + */ + bl bl1_setup + +#if ENABLE_PAUTH + /* -------------------------------------------------------------------- + * Program APIAKey_EL1 and enable pointer authentication. + * -------------------------------------------------------------------- + */ + bl pauth_init_enable_el3 +#endif /* ENABLE_PAUTH */ + + /* -------------------------------------------------------------------- + * Initialize platform and jump to our c-entry point + * for this type of reset. + * -------------------------------------------------------------------- + */ + bl bl1_main + +#if ENABLE_PAUTH + /* -------------------------------------------------------------------- + * Disable pointer authentication before jumping to next boot image. + * -------------------------------------------------------------------- + */ + bl pauth_disable_el3 +#endif /* ENABLE_PAUTH */ + + /* -------------------------------------------------- + * Do the transition to next boot image. + * -------------------------------------------------- + */ +#if ENABLE_RME + b bl1_run_bl2_in_root +#else + b el3_exit +#endif +endfunc bl1_entrypoint + + /* ----------------------------------------------------- + * void bl1_run_bl2_in_root(); + * This function runs BL2 in root/EL3 when RME is enabled. + * ----------------------------------------------------- + */ + +func bl1_run_bl2_in_root + /* read bl2_ep_info */ + adrp x20, bl2_ep_info + add x20, x20, :lo12:bl2_ep_info + ldr x20, [x20] + + /* --------------------------------------------- + * MMU needs to be disabled because BL2 executes + * in EL3. It will initialize the address space + * according to its own requirements. + * --------------------------------------------- + */ + bl disable_mmu_icache_el3 + tlbi alle3 + + 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)] + exception_return +endfunc bl1_run_bl2_in_root diff --git a/bl1/aarch64/bl1_exceptions.S b/bl1/aarch64/bl1_exceptions.S new file mode 100644 index 0000000..c54219f --- /dev/null +++ b/bl1/aarch64/bl1_exceptions.S @@ -0,0 +1,289 @@ +/* + * Copyright (c) 2013-2022, ARM Limited and Contributors. All rights reserved. + * + * SPDX-License-Identifier: BSD-3-Clause + */ + +#include <arch.h> +#include <asm_macros.S> +#include <bl1/bl1.h> +#include <common/bl_common.h> +#include <context.h> + +/* ----------------------------------------------------------------------------- + * Very simple stackless exception handlers used by BL1. + * ----------------------------------------------------------------------------- + */ + .globl bl1_exceptions + +vector_base bl1_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 +end_vector_entry SynchronousExceptionSP0 + +vector_entry IrqSP0 + mov x0, #IRQ_SP_EL0 + bl plat_report_exception + no_ret plat_panic_handler +end_vector_entry IrqSP0 + +vector_entry FiqSP0 + mov x0, #FIQ_SP_EL0 + bl plat_report_exception + no_ret plat_panic_handler +end_vector_entry FiqSP0 + +vector_entry SErrorSP0 + mov x0, #SERROR_SP_EL0 + bl plat_report_exception + no_ret plat_panic_handler +end_vector_entry 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 +end_vector_entry SynchronousExceptionSPx + +vector_entry IrqSPx + mov x0, #IRQ_SP_ELX + bl plat_report_exception + no_ret plat_panic_handler +end_vector_entry IrqSPx + +vector_entry FiqSPx + mov x0, #FIQ_SP_ELX + bl plat_report_exception + no_ret plat_panic_handler +end_vector_entry FiqSPx + +vector_entry SErrorSPx + mov x0, #SERROR_SP_ELX + bl plat_report_exception + no_ret plat_panic_handler +end_vector_entry SErrorSPx + + /* ----------------------------------------------------- + * Lower EL using AArch64 : 0x400 - 0x600 + * ----------------------------------------------------- + */ +vector_entry SynchronousExceptionA64 + /* Enable the SError interrupt */ + msr daifclr, #DAIF_ABT_BIT + + str x30, [sp, #CTX_GPREGS_OFFSET + CTX_GPREG_LR] + + /* Expect only SMC exceptions */ + mrs x30, esr_el3 + ubfx x30, x30, #ESR_EC_SHIFT, #ESR_EC_LENGTH + cmp x30, #EC_AARCH64_SMC + b.ne unexpected_sync_exception + + b smc_handler64 +end_vector_entry SynchronousExceptionA64 + +vector_entry IrqA64 + mov x0, #IRQ_AARCH64 + bl plat_report_exception + no_ret plat_panic_handler +end_vector_entry IrqA64 + +vector_entry FiqA64 + mov x0, #FIQ_AARCH64 + bl plat_report_exception + no_ret plat_panic_handler +end_vector_entry FiqA64 + +vector_entry SErrorA64 + mov x0, #SERROR_AARCH64 + bl plat_report_exception + no_ret plat_panic_handler +end_vector_entry SErrorA64 + + /* ----------------------------------------------------- + * Lower EL using AArch32 : 0x600 - 0x800 + * ----------------------------------------------------- + */ +vector_entry SynchronousExceptionA32 + mov x0, #SYNC_EXCEPTION_AARCH32 + bl plat_report_exception + no_ret plat_panic_handler +end_vector_entry SynchronousExceptionA32 + +vector_entry IrqA32 + mov x0, #IRQ_AARCH32 + bl plat_report_exception + no_ret plat_panic_handler +end_vector_entry IrqA32 + +vector_entry FiqA32 + mov x0, #FIQ_AARCH32 + bl plat_report_exception + no_ret plat_panic_handler +end_vector_entry FiqA32 + +vector_entry SErrorA32 + mov x0, #SERROR_AARCH32 + bl plat_report_exception + no_ret plat_panic_handler +end_vector_entry SErrorA32 + + +func smc_handler64 + + /* ---------------------------------------------- + * Detect if this is a RUN_IMAGE or other SMC. + * ---------------------------------------------- + */ + mov x30, #BL1_SMC_RUN_IMAGE + cmp x30, x0 + b.ne smc_handler + + /* ------------------------------------------------ + * Make sure only Secure world reaches here. + * ------------------------------------------------ + */ + mrs x30, scr_el3 + tst x30, #SCR_NS_BIT + b.ne unexpected_sync_exception + + /* ---------------------------------------------- + * Handling RUN_IMAGE SMC. First switch back to + * SP_EL0 for the C runtime stack. + * ---------------------------------------------- + */ + ldr x30, [sp, #CTX_EL3STATE_OFFSET + CTX_RUNTIME_SP] + msr spsel, #MODE_SP_EL0 + mov sp, x30 + + /* --------------------------------------------------------------------- + * Pass EL3 control to next BL image. + * Here it expects X1 with the address of a entry_point_info_t + * structure describing the next BL image entrypoint. + * --------------------------------------------------------------------- + */ + mov x20, x1 + + mov x0, x20 + bl bl1_print_next_bl_ep_info + + ldp x0, x1, [x20, #ENTRY_POINT_INFO_PC_OFFSET] + msr elr_el3, x0 + msr spsr_el3, x1 + ubfx x0, x1, #MODE_EL_SHIFT, #2 + cmp x0, #MODE_EL3 + b.ne unexpected_sync_exception + + bl disable_mmu_icache_el3 + tlbi alle3 + dsb ish /* ERET implies ISB, so it is not needed here */ + +#if SPIN_ON_BL1_EXIT + bl print_debug_loop_message +debug_loop: + b debug_loop +#endif + + mov x0, x20 + bl bl1_plat_prepare_exit + + 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)] + exception_return +endfunc smc_handler64 + +unexpected_sync_exception: + mov x0, #SYNC_EXCEPTION_AARCH64 + bl plat_report_exception + no_ret plat_panic_handler + + /* ----------------------------------------------------- + * Save Secure/Normal world context and jump to + * BL1 SMC handler. + * ----------------------------------------------------- + */ +smc_handler: + /* ----------------------------------------------------- + * Save x0-x29 and ARMv8.3-PAuth (if enabled) registers. + * If Secure Cycle Counter is not disabled in MDCR_EL3 + * when ARMv8.5-PMU is implemented, save PMCR_EL0 and + * disable Cycle Counter. + * TODO: Revisit to store only SMCCC specified registers. + * ----------------------------------------------------- + */ + bl prepare_el3_entry + +#if ENABLE_PAUTH + /* ----------------------------------------------------- + * Load and program stored APIAKey firmware key. + * Re-enable pointer authentication in EL3, as it was + * disabled before jumping to the next boot image. + * ----------------------------------------------------- + */ + bl pauth_load_bl1_apiakey_enable +#endif + /* ----------------------------------------------------- + * Populate the parameters for the SMC handler. We + * already have x0-x4 in place. x5 will point to a + * cookie (not used now). x6 will point to the context + * structure (SP_EL3) and x7 will contain flags we need + * to pass to the handler. + * ----------------------------------------------------- + */ + mov x5, xzr + mov x6, sp + + /* ----------------------------------------------------- + * Restore the saved C runtime stack value which will + * become the new SP_EL0 i.e. EL3 runtime stack. It was + * saved in the 'cpu_context' structure prior to the last + * ERET from EL3. + * ----------------------------------------------------- + */ + ldr x12, [x6, #CTX_EL3STATE_OFFSET + CTX_RUNTIME_SP] + + /* --------------------------------------------- + * Switch back to SP_EL0 for the C runtime stack. + * --------------------------------------------- + */ + msr spsel, #MODE_SP_EL0 + mov sp, x12 + + /* ----------------------------------------------------- + * Save the SPSR_EL3, ELR_EL3, & SCR_EL3 in case there + * is a world switch during SMC handling. + * ----------------------------------------------------- + */ + mrs x16, spsr_el3 + mrs x17, elr_el3 + mrs x18, scr_el3 + stp x16, x17, [x6, #CTX_EL3STATE_OFFSET + CTX_SPSR_EL3] + str x18, [x6, #CTX_EL3STATE_OFFSET + CTX_SCR_EL3] + + /* Copy SCR_EL3.NS bit to the flag to indicate caller's security */ + bfi x7, x18, #0, #1 + + /* ----------------------------------------------------- + * Go to BL1 SMC handler. + * ----------------------------------------------------- + */ + bl bl1_smc_handler + + /* ----------------------------------------------------- + * Do the transition to next BL image. + * ----------------------------------------------------- + */ + b el3_exit |