aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorjohpow01 <john.powell@arm.com>2021-05-20 16:14:12 -0500
committerMark Dykes <mark.dykes@arm.com>2021-06-10 22:12:19 -0500
commit6e346fe2104523e79b3295b4575124fe246f6114 (patch)
tree8cba066feaa4eb9f54cc77de6862b77cce3c6805
parent156ed4ce5cf20ca22caa778a0aedc85785bfb8ee (diff)
downloadtrusted-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.c31
-rw-r--r--bl1/aarch64/bl1_entrypoint.S44
-rw-r--r--bl1/bl1_main.c14
-rw-r--r--bl1/bl1_private.h4
-rw-r--r--bl2/aarch64/bl2_el3_entrypoint.S38
-rw-r--r--bl2/bl2.ld.S4
-rw-r--r--bl2/bl2.mk14
-rw-r--r--bl2/bl2_main.c29
-rw-r--r--include/arch/aarch64/el3_common_macros.S14
-rw-r--r--lib/aarch64/misc_helpers.S25
-rw-r--r--lib/cpus/errata_report.c4
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