diff options
author | johpow01 <john.powell@arm.com> | 2021-05-20 16:14:12 -0500 |
---|---|---|
committer | Mark Dykes <mark.dykes@arm.com> | 2021-06-10 22:12:19 -0500 |
commit | 6e346fe2104523e79b3295b4575124fe246f6114 (patch) | |
tree | 8cba066feaa4eb9f54cc77de6862b77cce3c6805 | |
parent | 156ed4ce5cf20ca22caa778a0aedc85785bfb8ee (diff) | |
download | trusted-firmware-a-6e346fe2104523e79b3295b4575124fe246f6114.tar.gz |
feat(RME): Run BL2 in root world
This patch enables BL2 to run in root world (EL3) which is
needed as per the security model of RME-enabled systems.
Signed-off-by: John Powell <john.powell@arm.com>
Change-Id: I53ace51e326fcdd44d44c791a7cb9ffaa20ed3f5
-rw-r--r-- | bl1/aarch64/bl1_context_mgmt.c | 31 | ||||
-rw-r--r-- | bl1/aarch64/bl1_entrypoint.S | 44 | ||||
-rw-r--r-- | bl1/bl1_main.c | 14 | ||||
-rw-r--r-- | bl1/bl1_private.h | 4 | ||||
-rw-r--r-- | bl2/aarch64/bl2_el3_entrypoint.S | 38 | ||||
-rw-r--r-- | bl2/bl2.ld.S | 4 | ||||
-rw-r--r-- | bl2/bl2.mk | 14 | ||||
-rw-r--r-- | bl2/bl2_main.c | 29 | ||||
-rw-r--r-- | include/arch/aarch64/el3_common_macros.S | 14 | ||||
-rw-r--r-- | lib/aarch64/misc_helpers.S | 25 | ||||
-rw-r--r-- | lib/cpus/errata_report.c | 4 |
11 files changed, 193 insertions, 28 deletions
diff --git a/bl1/aarch64/bl1_context_mgmt.c b/bl1/aarch64/bl1_context_mgmt.c index 2a8d58efd1..c78f6a9f5e 100644 --- a/bl1/aarch64/bl1_context_mgmt.c +++ b/bl1/aarch64/bl1_context_mgmt.c @@ -93,3 +93,34 @@ void bl1_prepare_next_image(unsigned int image_id) print_entry_point_info(next_bl_ep); } + +#if ENABLE_RME +/******************************************************************************* + * This function prepares the entry point information to run BL2 in Root world + * i.e. EL3. It then jumps into BL2 using this entry point information. + ******************************************************************************/ +void bl1_prepare_for_bl2_in_root(void) +{ + image_desc_t *bl2_desc; + entry_point_info_t *bl2_ep_info; + + /* 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); + + /* 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); + console_flush(); + + bl1_run_bl2_in_root(bl2_ep_info); +} +#endif /* ENABLE_RME */ diff --git a/bl1/aarch64/bl1_entrypoint.S b/bl1/aarch64/bl1_entrypoint.S index 00f27184df..22019478bf 100644 --- a/bl1/aarch64/bl1_entrypoint.S +++ b/bl1/aarch64/bl1_entrypoint.S @@ -1,13 +1,15 @@ /* - * Copyright (c) 2013-2019, ARM Limited and Contributors. All rights reserved. + * 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 /* ----------------------------------------------------- @@ -68,3 +70,43 @@ func bl1_entrypoint */ b el3_exit endfunc bl1_entrypoint + + /* ----------------------------------------------------- + * void bl1_run_bl2_in_root(entry_point_info_t *ep_info); + * This function runs BL2 in root/EL3 when RME is enabled. + * ----------------------------------------------------- + */ + +#if ENABLE_RME +func bl1_run_bl2_in_root + mov x20,x0 + + /* --------------------------------------------- + * 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 + +#if ENABLE_PAUTH + /* --------------------------------------------- + * Disable pointer authentication before jumping + * to next boot image. + * --------------------------------------------- + */ + bl pauth_disable_el3 +#endif /* ENABLE_PAUTH */ + + 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 +#endif /* ENABLE_RME */ diff --git a/bl1/bl1_main.c b/bl1/bl1_main.c index fd602324f7..e85663194c 100644 --- a/bl1/bl1_main.c +++ b/bl1/bl1_main.c @@ -1,5 +1,5 @@ /* - * Copyright (c) 2013-2020, ARM Limited and Contributors. All rights reserved. + * Copyright (c) 2013-2021, Arm Limited and Contributors. All rights reserved. * * SPDX-License-Identifier: BSD-3-Clause */ @@ -142,10 +142,18 @@ void bl1_main(void) * We currently interpret any image id other than * BL2_IMAGE_ID as the start of firmware update. */ - if (image_id == BL2_IMAGE_ID) + if (image_id == BL2_IMAGE_ID) { bl1_load_bl2(); - else + +#if ENABLE_RME + /* Run BL2 in root if RME is enabled. */ + assert(get_armv9_2_feat_rme_support() != 0U); + bl1_prepare_for_bl2_in_root(); +#endif /* ENABLE_RME */ + + } else { NOTICE("BL1-FWU: *******FWU Process Started*******\n"); + } bl1_prepare_next_image(image_id); diff --git a/bl1/bl1_private.h b/bl1/bl1_private.h index 2cfeeea28d..8f18343947 100644 --- a/bl1/bl1_private.h +++ b/bl1/bl1_private.h @@ -1,5 +1,5 @@ /* - * Copyright (c) 2013-2020, ARM Limited and Contributors. All rights reserved. + * Copyright (c) 2013-2021, Arm Limited and Contributors. All rights reserved. * * SPDX-License-Identifier: BSD-3-Clause */ @@ -18,6 +18,8 @@ void bl1_arch_setup(void); void bl1_arch_next_el_setup(void); void bl1_prepare_next_image(unsigned int image_id); +void bl1_prepare_for_bl2_in_root(void); +void bl1_run_bl2_in_root(entry_point_info_t *ep_info); u_register_t bl1_fwu_smc_handler(unsigned int smc_fid, u_register_t x1, diff --git a/bl2/aarch64/bl2_el3_entrypoint.S b/bl2/aarch64/bl2_el3_entrypoint.S index 4eab39cd3b..49e84c3013 100644 --- a/bl2/aarch64/bl2_el3_entrypoint.S +++ b/bl2/aarch64/bl2_el3_entrypoint.S @@ -1,5 +1,5 @@ /* - * Copyright (c) 2017-2020, ARM Limited and Contributors. All rights reserved. + * Copyright (c) 2017-2021, Arm Limited and Contributors. All rights reserved. * * SPDX-License-Identifier: BSD-3-Clause */ @@ -21,6 +21,23 @@ #define FIXUP_SIZE ((BL2_LIMIT) - (BL2_BASE)) #endif +/* + * Notes on ENABLE_RME build option + * + * The purpose of the BL2_IN_EL3 build option is to allow BL2 to + * essentially function as BL1 in systems that don't use a TFA boot ROM. + * For the purposes of RME, we use a normal BL1 image but we also want + * to run BL2 in EL3/root as normally as possible, so rather than use the + * special bl2_el3_setup function here we use the standard bl2_setup and we + * don't need reset or mailbox initialization code seen in the + * el3_entrypoint_common macro. This functionality could be split off into its + * own file if more separation between code paths is desired. + * + * See https://trustedfirmware-a.readthedocs.io/en/latest/design/ + * firmware-design.html?highlight=BL2_AT_EL3 + * #running-bl2-at-el3-execution-level + */ + func bl2_entrypoint /* Save arguments x0-x3 from previous Boot loader */ mov x20, x0 @@ -28,6 +45,18 @@ func bl2_entrypoint mov x22, x2 mov x23, x3 +#if ENABLE_RME + /* RME support is enabled. */ + el3_entrypoint_common \ + _init_sctlr=0 \ + _warm_boot_mailbox=0 \ + _secondary_cold_boot=0 \ + _init_memory=0 \ + _init_c_runtime=1 \ + _exception_vectors=bl2_el3_exceptions \ + _pie_fixup_size=FIXUP_SIZE +#else /* ENABLE_RME */ + /* RME support is disabled. */ el3_entrypoint_common \ _init_sctlr=1 \ _warm_boot_mailbox=!PROGRAMMABLE_RESET_ADDRESS \ @@ -36,6 +65,7 @@ func bl2_entrypoint _init_c_runtime=1 \ _exception_vectors=bl2_el3_exceptions \ _pie_fixup_size=FIXUP_SIZE +#endif /* ENABLE_RME */ /* --------------------------------------------- * Restore parameters of boot rom @@ -50,7 +80,13 @@ func bl2_entrypoint * Perform BL2 setup * --------------------------------------------- */ +#if ENABLE_RME + /* RME is a special case, use normal bl2_setup. */ + bl bl2_setup +#else + /* Otherwise, use the normal bl2 in el3 setup function. */ bl bl2_el3_setup +#endif /* ENABLE_RME */ #if ENABLE_PAUTH /* --------------------------------------------- diff --git a/bl2/bl2.ld.S b/bl2/bl2.ld.S index 37849c3124..1ae8fb368e 100644 --- a/bl2/bl2.ld.S +++ b/bl2/bl2.ld.S @@ -25,7 +25,11 @@ SECTIONS #if SEPARATE_CODE_AND_RODATA .text . : { __TEXT_START__ = .; +#if ENABLE_RME + *bl2_el3_entrypoint.o(.text*) +#else /* ENABLE_RME */ *bl2_entrypoint.o(.text*) +#endif /* ENABLE_RME */ *(SORT_BY_ALIGNMENT(.text*)) *(.vectors) . = ALIGN(PAGE_SIZE); diff --git a/bl2/bl2.mk b/bl2/bl2.mk index 735e7e04fb..07bfa23a08 100644 --- a/bl2/bl2.mk +++ b/bl2/bl2.mk @@ -1,5 +1,5 @@ # -# Copyright (c) 2013-2020, ARM Limited and Contributors. All rights reserved. +# Copyright (c) 2013-2021, Arm Limited and Contributors. All rights reserved. # # SPDX-License-Identifier: BSD-3-Clause # @@ -15,11 +15,21 @@ ifeq (${ARCH},aarch64) BL2_SOURCES += common/aarch64/early_exceptions.S endif -ifeq (${BL2_AT_EL3},0) +ifeq (${ENABLE_RME},1) +include lib/gpt/gpt.mk +# Using RME, run BL2 at EL3 +BL2_SOURCES += bl2/${ARCH}/bl2_el3_entrypoint.S \ + bl2/${ARCH}/bl2_el3_exceptions.S \ + ${GPT_LIB_SRCS} +BL2_LINKERFILE := bl2/bl2.ld.S + +else ifeq (${BL2_AT_EL3},0) +# Normal operation, no RME, no BL2 at EL3 BL2_SOURCES += bl2/${ARCH}/bl2_entrypoint.S BL2_LINKERFILE := bl2/bl2.ld.S else +# BL2 at EL3, no RME BL2_SOURCES += bl2/${ARCH}/bl2_el3_entrypoint.S \ bl2/${ARCH}/bl2_el3_exceptions.S \ lib/cpus/${ARCH}/cpu_helpers.S \ diff --git a/bl2/bl2_main.c b/bl2/bl2_main.c index 203e1d4b1d..37839993d4 100644 --- a/bl2/bl2_main.c +++ b/bl2/bl2_main.c @@ -1,5 +1,5 @@ /* - * Copyright (c) 2013-2020, ARM Limited and Contributors. All rights reserved. + * Copyright (c) 2013-2021, Arm Limited and Contributors. All rights reserved. * * SPDX-License-Identifier: BSD-3-Clause */ @@ -28,18 +28,18 @@ #define NEXT_IMAGE "BL32" #endif -#if !BL2_AT_EL3 +#if BL2_AT_EL3 /******************************************************************************* - * Setup function for BL2. + * Setup function for BL2 when BL2_AT_EL3=1 ******************************************************************************/ -void bl2_setup(u_register_t arg0, u_register_t arg1, u_register_t arg2, - u_register_t arg3) +void bl2_el3_setup(u_register_t arg0, u_register_t arg1, u_register_t arg2, + u_register_t arg3) { /* Perform early platform-specific setup */ - bl2_early_platform_setup2(arg0, arg1, arg2, arg3); + bl2_el3_early_platform_setup(arg0, arg1, arg2, arg3); /* Perform late platform-specific setup */ - bl2_plat_arch_setup(); + bl2_el3_plat_arch_setup(); #if CTX_INCLUDE_PAUTH_REGS /* @@ -49,19 +49,18 @@ void bl2_setup(u_register_t arg0, u_register_t arg1, u_register_t arg2, assert(is_armv8_3_pauth_present()); #endif /* CTX_INCLUDE_PAUTH_REGS */ } - -#else /* if BL2_AT_EL3 */ +#else /* BL2_AT_EL3 */ /******************************************************************************* - * Setup function for BL2 when BL2_AT_EL3=1. + * Setup function for BL2. This function is used when ENABLE_RME=1 ******************************************************************************/ -void bl2_el3_setup(u_register_t arg0, u_register_t arg1, u_register_t arg2, - u_register_t arg3) +void bl2_setup(u_register_t arg0, u_register_t arg1, u_register_t arg2, + u_register_t arg3) { /* Perform early platform-specific setup */ - bl2_el3_early_platform_setup(arg0, arg1, arg2, arg3); + bl2_early_platform_setup2(arg0, arg1, arg2, arg3); /* Perform late platform-specific setup */ - bl2_el3_plat_arch_setup(); + bl2_plat_arch_setup(); #if CTX_INCLUDE_PAUTH_REGS /* @@ -110,7 +109,7 @@ void bl2_main(void) measured_boot_finish(); #endif /* MEASURED_BOOT */ -#if !BL2_AT_EL3 +#if !BL2_AT_EL3 && !ENABLE_RME #ifndef __aarch64__ /* * For AArch32 state BL1 and BL2 share the MMU setup. diff --git a/include/arch/aarch64/el3_common_macros.S b/include/arch/aarch64/el3_common_macros.S index f75998351b..fa0baec48d 100644 --- a/include/arch/aarch64/el3_common_macros.S +++ b/include/arch/aarch64/el3_common_macros.S @@ -1,5 +1,5 @@ /* - * Copyright (c) 2015-2020, ARM Limited and Contributors. All rights reserved. + * Copyright (c) 2015-2021, Arm Limited and Contributors. All rights reserved. * * SPDX-License-Identifier: BSD-3-Clause */ @@ -88,6 +88,13 @@ */ orr x0, x0, #(SCR_API_BIT | SCR_APK_BIT) #endif +#if ENABLE_RME + /* + * Current RME-enabled model does not run in R-EL2 unless EEL2 is enabled. + * EL3 cannot access ICC_SRE_EL2 either. + */ + orr x0, x0, #SCR_EEL2_BIT +#endif msr scr_el3, x0 /* --------------------------------------------------------------------- @@ -324,6 +331,7 @@ msr vbar_el3, x0 isb +#if !(defined(IMAGE_BL2) && ENABLE_RME) /* --------------------------------------------------------------------- * It is a cold boot. * Perform any processor specific actions upon reset e.g. cache, TLB @@ -331,6 +339,7 @@ * --------------------------------------------------------------------- */ bl reset_handler +#endif el3_arch_init_common @@ -373,7 +382,8 @@ * --------------------------------------------------------------------- */ .if \_init_c_runtime -#if defined(IMAGE_BL31) || (defined(IMAGE_BL2) && BL2_AT_EL3 && BL2_INV_DCACHE) +#if defined(IMAGE_BL31) || (defined(IMAGE_BL2) && \ + ((BL2_AT_EL3 && BL2_INV_DCACHE) || ENABLE_RME)) /* ------------------------------------------------------------- * Invalidate the RW memory used by the BL31 image. This * includes the data and NOBITS sections. This is done to diff --git a/lib/aarch64/misc_helpers.S b/lib/aarch64/misc_helpers.S index b6f6c9d881..1f7f93d449 100644 --- a/lib/aarch64/misc_helpers.S +++ b/lib/aarch64/misc_helpers.S @@ -15,6 +15,7 @@ .globl zero_normalmem .globl zeromem .globl memcpy16 + .globl tlbi_by_pa .globl disable_mmu_el1 .globl disable_mmu_el3 @@ -162,7 +163,8 @@ func zeromem_dczva * Check for M bit (MMU enabled) of the current SCTLR_EL(1|3) * register value and panic if the MMU is disabled. */ -#if defined(IMAGE_BL1) || defined(IMAGE_BL31) || (defined(IMAGE_BL2) && BL2_AT_EL3) +#if defined(IMAGE_BL1) || defined(IMAGE_BL31) || (defined(IMAGE_BL2) && \ + (BL2_AT_EL3 || ENABLE_RME)) mrs tmp1, sctlr_el3 #else mrs tmp1, sctlr_el1 @@ -592,3 +594,24 @@ func fixup_gdt_reloc b.lo 1b ret endfunc fixup_gdt_reloc + +func tlbi_by_pa +// @TODO The following code invalidates the entire TLB cache. Replace it with +// "tlbi by pa" instruction once it is made available by the model. + tlbi alle3is + mrs x1, scr_el3 + mov_imm x2, SCR_NS_BIT | SCR_NSE_BIT + orr x0, x1, x2 + msr scr_el3, x0 + tlbi alle2is + tlbi alle1is + orr x0, x1, #SCR_NS_BIT + msr scr_el3, x0 + tlbi alle2is + tlbi alle1is + msr scr_el3, x1 + dsb sy + ret +endfunc tlbi_by_pa + + diff --git a/lib/cpus/errata_report.c b/lib/cpus/errata_report.c index 5d1e3c5cc8..efff57c3ed 100644 --- a/lib/cpus/errata_report.c +++ b/lib/cpus/errata_report.c @@ -1,5 +1,5 @@ /* - * Copyright (c) 2017-2020, ARM Limited and Contributors. All rights reserved. + * Copyright (c) 2017-2021, Arm Limited and Contributors. All rights reserved. * * SPDX-License-Identifier: BSD-3-Clause */ @@ -21,7 +21,7 @@ # define BL_STRING "BL31" #elif !defined(__arch64__) && defined(IMAGE_BL32) # define BL_STRING "BL32" -#elif defined(IMAGE_BL2) && BL2_AT_EL3 +#elif defined(IMAGE_BL2) && (BL2_AT_EL3 || ENABLE_RME) # define BL_STRING "BL2" #else # error This image should not be printing errata status |