feat(rme): run BL2 in root world when FEAT_RME is enabled

This patch enables BL2 to run in root world (EL3) which is
needed as per the security model of RME-enabled systems.

Using the existing BL2_AT_EL3 TF-A build option is not convenient
because that option assumes TF-A BL1 doesn't exist, which is not
the case for RME-enabled systems. For the purposes of RME, we use
a normal BL1 image but we also want to run BL2 in EL3 as normally as
possible, therefore rather than use the special bl2_entrypoint
function in bl2_el3_entrypoint.S, we use a new bl2_entrypoint
function (in bl2_rme_entrypoint.S) which doesn't need reset or
mailbox initialization code seen in the el3_entrypoint_common macro.

The patch also cleans up bl2_el3_entrypoint.S, moving the
bl2_run_next_image function to its own file to avoid duplicating
code.

Signed-off-by: Zelalem Aweke <zelalem.aweke@arm.com>
Change-Id: I99821b4cd550cadcb701f4c0c4dc36da81c7ef55
This commit is contained in:
Zelalem Aweke 2021-07-09 11:37:10 -05:00
parent 362182386b
commit 6c09af9f8b
13 changed files with 298 additions and 108 deletions

View File

@ -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
*/
@ -16,6 +16,7 @@
/* 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)
@ -30,6 +31,40 @@ void cm_set_context(void *context, uint32_t 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.
@ -93,3 +128,4 @@ void bl1_prepare_next_image(unsigned int image_id)
print_entry_point_info(next_bl_ep);
}
#endif /* ENABLE_RME */

View File

@ -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
/* -----------------------------------------------------
@ -66,5 +68,41 @@ func bl1_entrypoint
* 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

View File

@ -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
*/
@ -11,6 +11,8 @@
#include <common/bl_common.h>
extern entry_point_info_t *bl2_ep_info;
/******************************************
* Function prototypes
*****************************************/
@ -18,6 +20,7 @@ void bl1_arch_setup(void);
void bl1_arch_next_el_setup(void);
void bl1_prepare_next_image(unsigned int image_id);
void bl1_run_bl2_in_root(void);
u_register_t bl1_fwu_smc_handler(unsigned int smc_fid,
u_register_t x1,

View File

@ -1,5 +1,5 @@
/*
* Copyright (c) 2017-2021, ARM Limited and Contributors. All rights reserved.
* Copyright (c) 2017-2021, Arm Limited and Contributors. All rights reserved.
*
* SPDX-License-Identifier: BSD-3-Clause
*/
@ -10,7 +10,6 @@
#include <el3_common_macros.S>
.globl bl2_entrypoint
.globl bl2_run_next_image
func bl2_entrypoint
@ -56,37 +55,3 @@ func bl2_entrypoint
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_xc, r1
/* Some BL32 stages expect lr_svc to provide the BL33 entry address */
cps #MODE32_svc
ldr lr, [r8, #ENTRY_POINT_INFO_LR_SVC_OFFSET]
cps #MODE32_mon
add r8, r8, #ENTRY_POINT_INFO_ARGS_OFFSET
ldm r8, {r0, r1, r2, r3}
exception_return
endfunc bl2_run_next_image

View File

@ -0,0 +1,46 @@
/*
* Copyright (c) 2021, Arm Limited. All rights reserved.
*
* SPDX-License-Identifier: BSD-3-Clause
*/
#include <arch.h>
#include <asm_macros.S>
#include <common/bl_common.h>
.globl bl2_run_next_image
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_xc, r1
/* Some BL32 stages expect lr_svc to provide the BL33 entry address */
cps #MODE32_svc
ldr lr, [r8, #ENTRY_POINT_INFO_LR_SVC_OFFSET]
cps #MODE32_mon
add r8, r8, #ENTRY_POINT_INFO_ARGS_OFFSET
ldm r8, {r0, r1, r2, r3}
exception_return
endfunc bl2_run_next_image

View File

@ -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
*/
@ -12,8 +12,6 @@
#include <el3_common_macros.S>
.globl bl2_entrypoint
.globl bl2_el3_run_image
.globl bl2_run_next_image
#if BL2_IN_XIP_MEM
#define FIXUP_SIZE 0
@ -72,36 +70,3 @@ func bl2_entrypoint
*/
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
#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 bl2_run_next_image

View File

@ -0,0 +1,67 @@
/*
* Copyright (c) 2021, Arm Limited. All rights reserved.
*
* SPDX-License-Identifier: BSD-3-Clause
*/
#include <platform_def.h>
#include <arch.h>
#include <asm_macros.S>
#include <common/bl_common.h>
#include <el3_common_macros.S>
.globl bl2_entrypoint
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=0 \
_warm_boot_mailbox=0 \
_secondary_cold_boot=0 \
_init_memory=0 \
_init_c_runtime=1 \
_exception_vectors=bl2_el3_exceptions \
_pie_fixup_size=0
/* ---------------------------------------------
* Restore parameters of boot rom
* ---------------------------------------------
*/
mov x0, x20
mov x1, x21
mov x2, x22
mov x3, x23
/* ---------------------------------------------
* Perform BL2 setup
* ---------------------------------------------
*/
bl bl2_setup
#if ENABLE_PAUTH
/* ---------------------------------------------
* Program APIAKey_EL1 and enable pointer authentication.
* ---------------------------------------------
*/
bl pauth_init_enable_el3
#endif /* ENABLE_PAUTH */
/* ---------------------------------------------
* Jump to main function.
* ---------------------------------------------
*/
bl bl2_main
/* ---------------------------------------------
* Should never reach this point.
* ---------------------------------------------
*/
no_ret plat_panic_handler
endfunc bl2_entrypoint

View File

@ -0,0 +1,45 @@
/*
* Copyright (c) 2021, Arm Limited. All rights reserved.
*
* SPDX-License-Identifier: BSD-3-Clause
*/
#include <arch.h>
#include <asm_macros.S>
#include <common/bl_common.h>
.globl bl2_run_next_image
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
#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 bl2_run_next_image

View File

@ -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
*/
@ -25,7 +25,11 @@ SECTIONS
#if SEPARATE_CODE_AND_RODATA
.text . : {
__TEXT_START__ = .;
#if ENABLE_RME
*bl2_rme_entrypoint.o(.text*)
#else /* ENABLE_RME */
*bl2_entrypoint.o(.text*)
#endif /* ENABLE_RME */
*(SORT_BY_ALIGNMENT(.text*))
*(.vectors)
. = ALIGN(PAGE_SIZE);

View File

@ -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,13 +15,24 @@ ifeq (${ARCH},aarch64)
BL2_SOURCES += common/aarch64/early_exceptions.S
endif
ifeq (${BL2_AT_EL3},0)
ifeq (${ENABLE_RME},1)
# Using RME, run BL2 at EL3
BL2_SOURCES += bl2/${ARCH}/bl2_rme_entrypoint.S \
bl2/${ARCH}/bl2_el3_exceptions.S \
bl2/${ARCH}/bl2_run_next_image.S \
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 \
bl2/${ARCH}/bl2_run_next_image.S \
lib/cpus/${ARCH}/cpu_helpers.S \
lib/cpus/errata_report.c

View File

@ -29,31 +29,9 @@
#define NEXT_IMAGE "BL32"
#endif
#if !BL2_AT_EL3
#if BL2_AT_EL3
/*******************************************************************************
* Setup function for BL2.
******************************************************************************/
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_early_platform_setup2(arg0, arg1, arg2, arg3);
/* Perform late platform-specific setup */
bl2_plat_arch_setup();
#if CTX_INCLUDE_PAUTH_REGS
/*
* Assert that the ARMv8.3-PAuth registers are present or an access
* fault will be triggered when they are being saved or restored.
*/
assert(is_armv8_3_pauth_present());
#endif /* CTX_INCLUDE_PAUTH_REGS */
}
#else /* if BL2_AT_EL3 */
/*******************************************************************************
* Setup function for BL2 when BL2_AT_EL3=1.
* Setup function for BL2 when BL2_AT_EL3=1
******************************************************************************/
void bl2_el3_setup(u_register_t arg0, u_register_t arg1, u_register_t arg2,
u_register_t arg3)
@ -64,6 +42,27 @@ void bl2_el3_setup(u_register_t arg0, u_register_t arg1, u_register_t arg2,
/* Perform late platform-specific setup */
bl2_el3_plat_arch_setup();
#if CTX_INCLUDE_PAUTH_REGS
/*
* Assert that the ARMv8.3-PAuth registers are present or an access
* fault will be triggered when they are being saved or restored.
*/
assert(is_armv8_3_pauth_present());
#endif /* CTX_INCLUDE_PAUTH_REGS */
}
#else /* BL2_AT_EL3 */
/*******************************************************************************
* Setup function for BL2 when BL2_AT_EL3=0
******************************************************************************/
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_early_platform_setup2(arg0, arg1, arg2, arg3);
/* Perform late platform-specific setup */
bl2_plat_arch_setup();
#if CTX_INCLUDE_PAUTH_REGS
/*
* Assert that the ARMv8.3-PAuth registers are present or an access
@ -115,7 +114,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.
@ -140,7 +139,7 @@ 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 /* if BL2_AT_EL3 */
#else /* if BL2_AT_EL3 || ENABLE_RME */
NOTICE("BL2: Booting " NEXT_IMAGE "\n");
print_entry_point_info(next_bl_ep_info);
console_flush();
@ -153,5 +152,5 @@ void bl2_main(void)
#endif /* ENABLE_PAUTH */
bl2_run_next_image(next_bl_ep_info);
#endif /* BL2_AT_EL3 */
#endif /* BL2_AT_EL3 && ENABLE_RME */
}

View File

@ -1,5 +1,5 @@
/*
* Copyright (c) 2015-2021, ARM Limited and Contributors. All rights reserved.
* Copyright (c) 2015-2021, Arm Limited and Contributors. All rights reserved.
*
* SPDX-License-Identifier: BSD-3-Clause
*/
@ -87,6 +87,13 @@
* do so.
*/
orr x0, x0, #(SCR_API_BIT | SCR_APK_BIT)
#endif
#if ENABLE_RME
/*
* TODO: Settting the EEL2 bit to allow EL3 access to secure only registers
* in context management. This will need to be refactored.
*/
orr x0, x0, #SCR_EEL2_BIT
#endif
msr scr_el3, x0
@ -365,6 +372,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
@ -372,6 +380,7 @@
* ---------------------------------------------------------------------
*/
bl reset_handler
#endif
el3_arch_init_common
@ -414,7 +423,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

View File

@ -163,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