feat(rmmd): add support for RMM Boot interface

This patch adds the infrastructure needed to pass boot arguments from
EL3 to RMM and allocates a shared buffer between both worlds that can
be used, among others, to pass a boot manifest to RMM. The buffer is
composed a single memory page be used by a later EL3 <-> RMM interface
by all CPUs.

The RMM boot manifest is not implemented by this patch.

In addition to that, this patch also enables support for RMM when
RESET_TO_BL31 is enabled.

Signed-off-by: Javier Almansa Sobrino <javier.almansasobrino@arm.com>
Change-Id: I855cd4758ee3843eadd9fb482d70a6d18954d82a
This commit is contained in:
Javier Almansa Sobrino 2021-11-24 18:37:37 +00:00
parent caca0e57b8
commit 8c980a4a46
19 changed files with 336 additions and 75 deletions

View file

@ -563,6 +563,9 @@ subsections:
- title: TRP
scope: trp
- title: RMMD
scope: rmmd
- title: SPM
scope: spm

View file

@ -2017,7 +2017,7 @@ state. This function must return a pointer to the ``entry_point_info`` structure
(that was copied during ``bl31_early_platform_setup()``) if the image exists. It
should return NULL otherwise.
Function : plat_get_cca_attest_token() [mandatory when ENABLE_RME == 1]
Function : plat_rmmd_get_cca_attest_token() [mandatory when ENABLE_RME == 1]
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
::
@ -2043,8 +2043,8 @@ The parameters of the function are:
The function returns 0 on success, -EINVAL on failure.
Function : plat_get_cca_realm_attest_key() [mandatory when ENABLE_RME == 1]
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
Function : plat_rmmd_get_cca_realm_attest_key() [mandatory when ENABLE_RME == 1]
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
::
@ -2069,6 +2069,18 @@ The parameters of the function are:
The function returns 0 on success, -EINVAL on failure.
Function : plat_rmmd_get_el3_rmm_shared_mem() [when ENABLE_RME == 1]
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
::
Argument : uintptr_t *
Return : size_t
This function returns the size of the shared area between EL3 and RMM (or 0 on
failure). A pointer to the shared area (or a NULL pointer on failure) is stored
in the pointer passed as argument.
Function : bl31_plat_enable_mmu [optional]
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~

View file

@ -79,6 +79,7 @@
* - SCP TZC DRAM: If present, DRAM reserved for SCP use
* - L1 GPT DRAM: Reserved for L1 GPT if RME is enabled
* - REALM DRAM: Reserved for Realm world if RME is enabled
* - TF-A <-> RMM SHARED: Area shared for communication between TF-A and RMM
* - AP TZC DRAM: The remaining TZC secured DRAM reserved for AP use
*
* RME enabled(64MB) RME not enabled(16MB)
@ -87,11 +88,16 @@
* | AP TZC (~28MB) | | AP TZC (~14MB) |
* -------------------- -------------------
* | | | |
* | REALM (32MB) | | EL3 TZC (2MB) |
* -------------------- -------------------
* | | | |
* | EL3 TZC (3MB) | | SCP TZC |
* -------------------- 0xFFFF_FFFF-------------------
* | REALM (RMM) | | EL3 TZC (2MB) |
* | (32MB - 4KB) | -------------------
* -------------------- | |
* | | | SCP TZC |
* | TF-A <-> RMM | 0xFFFF_FFFF-------------------
* | SHARED (4KB) |
* --------------------
* | |
* | EL3 TZC (3MB) |
* --------------------
* | L1 GPT + SCP TZC |
* | (~1MB) |
* 0xFFFF_FFFF --------------------
@ -106,12 +112,17 @@
*/
#define ARM_EL3_TZC_DRAM1_SIZE UL(0x00300000) /* 3MB */
#define ARM_L1_GPT_SIZE UL(0x00100000) /* 1MB */
#define ARM_REALM_SIZE UL(0x02000000) /* 32MB */
/* 32MB - ARM_EL3_RMM_SHARED_SIZE */
#define ARM_REALM_SIZE (UL(0x02000000) - \
ARM_EL3_RMM_SHARED_SIZE)
#define ARM_EL3_RMM_SHARED_SIZE (PAGE_SIZE) /* 4KB */
#else
#define ARM_TZC_DRAM1_SIZE UL(0x01000000) /* 16MB */
#define ARM_EL3_TZC_DRAM1_SIZE UL(0x00200000) /* 2MB */
#define ARM_L1_GPT_SIZE UL(0)
#define ARM_REALM_SIZE UL(0)
#define ARM_EL3_RMM_SHARED_SIZE UL(0)
#endif /* ENABLE_RME */
#define ARM_SCP_TZC_DRAM1_BASE (ARM_DRAM1_BASE + \
@ -128,13 +139,20 @@
#define ARM_L1_GPT_END (ARM_L1_GPT_ADDR_BASE + \
ARM_L1_GPT_SIZE - 1U)
#define ARM_REALM_BASE (ARM_DRAM1_BASE + \
ARM_DRAM1_SIZE - \
(ARM_SCP_TZC_DRAM1_SIZE + \
ARM_EL3_TZC_DRAM1_SIZE + \
ARM_REALM_SIZE + \
ARM_L1_GPT_SIZE))
#define ARM_REALM_BASE (ARM_EL3_RMM_SHARED_BASE - \
ARM_REALM_SIZE)
#define ARM_REALM_END (ARM_REALM_BASE + ARM_REALM_SIZE - 1U)
#define ARM_EL3_RMM_SHARED_BASE (ARM_DRAM1_BASE + \
ARM_DRAM1_SIZE - \
(ARM_SCP_TZC_DRAM1_SIZE + \
ARM_L1_GPT_SIZE + \
ARM_EL3_RMM_SHARED_SIZE + \
ARM_EL3_TZC_DRAM1_SIZE))
#define ARM_EL3_RMM_SHARED_END (ARM_EL3_RMM_SHARED_BASE + \
ARM_EL3_RMM_SHARED_SIZE - 1U)
#endif /* ENABLE_RME */
#define ARM_EL3_TZC_DRAM1_BASE (ARM_SCP_TZC_DRAM1_BASE - \
@ -148,6 +166,7 @@
#define ARM_AP_TZC_DRAM1_SIZE (ARM_TZC_DRAM1_SIZE - \
(ARM_SCP_TZC_DRAM1_SIZE + \
ARM_EL3_TZC_DRAM1_SIZE + \
ARM_EL3_RMM_SHARED_SIZE + \
ARM_REALM_SIZE + \
ARM_L1_GPT_SIZE))
#define ARM_AP_TZC_DRAM1_END (ARM_AP_TZC_DRAM1_BASE + \
@ -197,6 +216,7 @@
#define ARM_NS_DRAM1_BASE ARM_DRAM1_BASE
#define ARM_NS_DRAM1_SIZE (ARM_DRAM1_SIZE - \
ARM_TZC_DRAM1_SIZE)
#define ARM_NS_DRAM1_END (ARM_NS_DRAM1_BASE + \
ARM_NS_DRAM1_SIZE - 1U)
#ifdef PLAT_ARM_DRAM1_BASE
@ -301,6 +321,12 @@
ARM_L1_GPT_SIZE, \
MT_MEMORY | MT_RW | EL3_PAS)
#define ARM_MAP_EL3_RMM_SHARED_MEM \
MAP_REGION_FLAT( \
ARM_EL3_RMM_SHARED_BASE, \
ARM_EL3_RMM_SHARED_SIZE, \
MT_MEMORY | MT_RW | MT_REALM)
#endif /* ENABLE_RME */
/*
@ -595,6 +621,8 @@
#if ENABLE_RME
#define RMM_BASE (ARM_REALM_BASE)
#define RMM_LIMIT (RMM_BASE + ARM_REALM_SIZE)
#define RMM_SHARED_BASE (ARM_EL3_RMM_SHARED_BASE)
#define RMM_SHARED_SIZE (ARM_EL3_RMM_SHARED_SIZE)
#endif
#if !defined(__aarch64__) || JUNO_AARCH32_EL3_RUNTIME

View file

@ -1,5 +1,5 @@
/*
* Copyright (c) 2021, ARM Limited and Contributors. All rights reserved.
* Copyright (c) 2021-2022, ARM Limited and Contributors. All rights reserved.
*
* SPDX-License-Identifier: BSD-3-Clause
*/
@ -61,6 +61,10 @@
#define ARM_PAS_2_BASE (ARM_PAS_1_BASE + ARM_PAS_1_SIZE)
#define ARM_PAS_2_SIZE (ARM_NS_DRAM1_SIZE)
/* Shared area between EL3 and RMM */
#define ARM_PAS_SHARED_BASE (ARM_EL3_RMM_SHARED_BASE)
#define ARM_PAS_SHARED_SIZE (ARM_EL3_RMM_SHARED_SIZE)
/* Secure TZC region */
#define ARM_PAS_3_BASE (ARM_AP_TZC_DRAM1_BASE)
#define ARM_PAS_3_SIZE (ARM_AP_TZC_DRAM1_SIZE)
@ -76,8 +80,13 @@
ARM_PAS_3_SIZE, \
GPT_GPI_SECURE)
/*
* REALM and Shared area share the same PAS, so consider them a single
* PAS region to configure in GPT.
*/
#define ARM_PAS_REALM GPT_MAP_REGION_GRANULE(ARM_REALM_BASE, \
ARM_REALM_SIZE, \
(ARM_PAS_SHARED_SIZE + \
ARM_REALM_SIZE), \
GPT_GPI_REALM)
#define ARM_PAS_EL3_DRAM GPT_MAP_REGION_GRANULE(ARM_EL3_TZC_DRAM1_BASE, \

View file

@ -1,5 +1,5 @@
/*
* Copyright (c) 2015-2021, ARM Limited and Contributors. All rights reserved.
* Copyright (c) 2015-2022, ARM Limited and Contributors. All rights reserved.
*
* SPDX-License-Identifier: BSD-3-Clause
*/
@ -57,7 +57,8 @@ typedef struct arm_tzc_regions_info {
{ARM_EL3_TZC_DRAM1_BASE, ARM_L1_GPT_END, TZC_REGION_S_RDWR, 0}, \
{ARM_NS_DRAM1_BASE, ARM_NS_DRAM1_END, ARM_TZC_NS_DRAM_S_ACCESS, \
PLAT_ARM_TZC_NS_DEV_ACCESS}, \
{ARM_REALM_BASE, ARM_REALM_END, ARM_TZC_NS_DRAM_S_ACCESS, \
/* Realm and Shared area share the same PAS */ \
{ARM_REALM_BASE, ARM_EL3_RMM_SHARED_END, ARM_TZC_NS_DRAM_S_ACCESS, \
PLAT_ARM_TZC_NS_DEV_ACCESS}, \
{ARM_DRAM2_BASE, ARM_DRAM2_END, ARM_TZC_NS_DRAM_S_ACCESS, \
PLAT_ARM_TZC_NS_DEV_ACCESS}

View file

@ -305,11 +305,11 @@ plat_local_state_t plat_get_target_pwr_state(unsigned int lvl,
/*******************************************************************************
* Mandatory BL31 functions when ENABLE_RME=1
******************************************************************************/
int plat_get_cca_attest_token(uintptr_t buf, size_t *len,
uintptr_t hash, size_t hash_size);
int plat_get_cca_realm_attest_key(uintptr_t buf, size_t *len,
unsigned int type);
int plat_rmmd_get_cca_attest_token(uintptr_t buf, size_t *len,
uintptr_t hash, size_t hash_size);
int plat_rmmd_get_cca_realm_attest_key(uintptr_t buf, size_t *len,
unsigned int type);
size_t plat_rmmd_get_el3_rmm_shared_mem(uintptr_t *shared);
/*******************************************************************************
* Optional BL31 functions (may be overridden)
******************************************************************************/

View file

@ -40,7 +40,17 @@
/* 0x18F */
#define RMMD_RMI_REQ_COMPLETE SMC64_RMI_FID(U(0x3F))
/* The SMC in the range 0x8400 0190 - 0x8400 01AF are reserved for RSIs.*/
/* RMM_BOOT_COMPLETE arg0 error codes */
#define E_RMM_BOOT_SUCCESS (0)
#define E_RMM_BOOT_UNKNOWN (-1)
#define E_RMM_BOOT_VERSION_MISMATCH (-2)
#define E_RMM_BOOT_CPUS_OUT_OF_RANGE (-3)
#define E_RMM_BOOT_CPU_ID_OUT_OF_RANGE (-4)
#define E_RMM_BOOT_INVALID_SHARED_BUFFER (-5)
#define E_RMM_BOOT_MANIFEST_VERSION_NOT_SUPPORTED (-6)
#define E_RMM_BOOT_MANIFEST_DATA_ERROR (-7)
/* The SMC in the range 0x8400 0191 - 0x8400 01AF are reserved for RSIs.*/
/*
* EL3 - RMM SMCs used for requesting RMMD services. These SMCs originate in Realm
@ -121,6 +131,36 @@
/* ECC Curve types for attest key generation */
#define ATTEST_KEY_CURVE_ECC_SECP384R1 0
/*
* RMM_BOOT_COMPLETE originates on RMM when the boot finishes (either cold
* or warm boot). This is handled by the RMM-EL3 interface SMC handler.
*
* RMM_BOOT_COMPLETE FID is located at the end of the available range.
*/
/* 0x1CF */
#define RMM_BOOT_COMPLETE SMC64_RMMD_EL3_FID(U(0x1F))
/*
* The major version number of the RMM Boot Interface implementation.
* Increase this whenever the semantics of the boot arguments change making it
* backwards incompatible.
*/
#define RMM_EL3_IFC_VERSION_MAJOR (U(0))
/*
* The minor version number of the RMM Boot Interface implementation.
* Increase this when a bug is fixed, or a feature is added without
* breaking compatibility.
*/
#define RMM_EL3_IFC_VERSION_MINOR (U(1))
#define RMM_EL3_INTERFACE_VERSION \
(((RMM_EL3_IFC_VERSION_MAJOR << 16) & 0x7FFFF) | \
RMM_EL3_IFC_VERSION_MINOR)
#define RMM_EL3_IFC_VERSION_GET_MAJOR(_version) (((_version) >> 16) \
& 0x7FFF)
#define RMM_EL3_IFC_VERSION_GET_MAJOR_MINOR(_version) ((_version) & 0xFFFF)
#ifndef __ASSEMBLER__
#include <stdint.h>

View file

@ -169,6 +169,7 @@ const mmap_region_t plat_arm_mmap[] = {
#endif
#if ENABLE_RME
ARM_MAP_GPT_L1_DRAM,
ARM_MAP_EL3_RMM_SHARED_MEM,
#endif
{0}
};
@ -512,3 +513,18 @@ int32_t plat_get_soc_revision(void)
return (int32_t)(((sys_id >> V2M_SYS_ID_REV_SHIFT) &
V2M_SYS_ID_REV_MASK) & SOC_ID_REV_MASK);
}
#if ENABLE_RME
/*
* Get a pointer to the RMM-EL3 Shared buffer and return it
* through the pointer passed as parameter.
*
* This function returns the size of the shared buffer.
*/
size_t plat_rmmd_get_el3_rmm_shared_mem(uintptr_t *shared)
{
*shared = (uintptr_t)RMM_SHARED_BASE;
return (size_t)RMM_SHARED_SIZE;
}
#endif

View file

@ -300,8 +300,8 @@ static uint8_t platform_token[] = {
0xB0, 0x3A
};
int plat_get_cca_attest_token(uintptr_t buf, size_t *len,
uintptr_t hash, size_t hash_size)
int plat_rmmd_get_cca_attest_token(uintptr_t buf, size_t *len,
uintptr_t hash, size_t hash_size)
{
(void)hash;
(void)hash_size;

View file

@ -19,7 +19,8 @@ static uint8_t sample_attest_priv_key[] = {
0xEB, 0x1A, 0x41, 0x85, 0xBD, 0x11, 0x7F, 0x68
};
int plat_get_cca_realm_attest_key(uintptr_t buf, size_t *len, unsigned int type)
int plat_rmmd_get_cca_realm_attest_key(uintptr_t buf, size_t *len,
unsigned int type)
{
assert(type == ATTEST_KEY_CURVE_ECC_SECP384R1);

View file

@ -127,11 +127,7 @@
#if defined(IMAGE_BL31)
# if SPM_MM
# define PLAT_ARM_MMAP_ENTRIES 10
# if ENABLE_RME
# define MAX_XLAT_TABLES 11
# else
# define MAX_XLAT_TABLES 9
# endif
# define MAX_XLAT_TABLES 9
# define PLAT_SP_IMAGE_MMAP_REGIONS 30
# define PLAT_SP_IMAGE_MAX_XLAT_TABLES 10
# elif SPMC_AT_EL3

View file

@ -341,10 +341,6 @@ ifeq ($(filter 1,${BL2_AT_EL3} ${ARM_XLAT_TABLES_LIB_V1}),)
endif
endif
ifeq (${ENABLE_RME},1)
BL31_CPPFLAGS += -DPLAT_XLAT_TABLES_DYNAMIC
endif
ifeq (${ALLOW_RO_XLAT_TABLES}, 1)
ifeq (${ARCH},aarch32)
BL32_CPPFLAGS += -DPLAT_RO_XLAT_TABLES

View file

@ -1,5 +1,5 @@
/*
* Copyright (c) 2015-2021, ARM Limited and Contributors. All rights reserved.
* Copyright (c) 2015-2022, ARM Limited and Contributors. All rights reserved.
*
* SPDX-License-Identifier: BSD-3-Clause
*/
@ -164,6 +164,14 @@ void __init arm_bl31_early_platform_setup(void *from_bl2, uintptr_t soc_fw_confi
bl33_image_ep_info.spsr = arm_get_spsr_for_bl33_entry();
SET_SECURITY_STATE(bl33_image_ep_info.h.attr, NON_SECURE);
#if ENABLE_RME
/*
* Populate entry point information for RMM.
* Only PC needs to be set as other fields are determined by RMMD.
*/
rmm_image_ep_info.pc = RMM_BASE;
#endif /* ENABLE_RME */
#else /* RESET_TO_BL31 */
/*

View file

@ -101,7 +101,7 @@ int rmmd_attest_get_platform_token(uint64_t buf_pa, uint64_t *buf_len, uint64_t
print_challenge((uint8_t *)temp_buf, challenge_hash_len);
/* Get the platform token. */
err = plat_get_cca_attest_token(va,
err = plat_rmmd_get_cca_attest_token(va,
buf_len, (uintptr_t)temp_buf, challenge_hash_len);
if (err != 0) {
@ -152,7 +152,7 @@ int rmmd_attest_get_signing_key(uint64_t buf_pa, uint64_t *buf_len,
}
/* Get the Realm attestation key. */
err = plat_get_cca_realm_attest_key(va, buf_len, (unsigned int)ecc_curve);
err = plat_rmmd_get_cca_realm_attest_key(va, buf_len, (unsigned int)ecc_curve);
if (err != 0) {
ERROR("Failed to get attestation key: %d.\n", err);
err = RMMD_ERR_UNK;

View file

@ -32,6 +32,17 @@
#include "rmmd_initial_context.h"
#include "rmmd_private.h"
/*******************************************************************************
* RMM <-> EL3 shared buffer information.
******************************************************************************/
static size_t shared_buf_size;
static uintptr_t shared_buf_base;
/*******************************************************************************
* RMM boot failure flag
******************************************************************************/
static bool rmm_boot_failed;
/*******************************************************************************
* RMM context information.
******************************************************************************/
@ -132,13 +143,10 @@ static void manage_extensions_realm(cpu_context_t *ctx)
******************************************************************************/
static int32_t rmm_init(void)
{
uint64_t rc;
long rc;
rmmd_rmm_context_t *ctx = &rmm_context[plat_my_core_pos()];
INFO("RMM init start.\n");
ctx->state = RMM_STATE_RESET;
/* Enable architecture extensions */
manage_extensions_realm(&ctx->cpu_ctx);
@ -147,12 +155,13 @@ static int32_t rmm_init(void)
rmm_el2_context_init(&ctx->cpu_ctx.el2_sysregs_ctx);
rc = rmmd_rmm_sync_entry(ctx);
if (rc != 0ULL) {
ERROR("RMM initialisation failed 0x%" PRIx64 "\n", rc);
panic();
if (rc != E_RMM_BOOT_SUCCESS) {
ERROR("RMM init failed: %ld\n", rc);
/* Mark the boot as failed for all the CPUs */
rmm_boot_failed = true;
return 0;
}
ctx->state = RMM_STATE_IDLE;
INFO("RMM init end.\n");
return 1;
@ -192,6 +201,25 @@ int rmmd_setup(void)
MODE_SP_ELX,
DISABLE_ALL_EXCEPTIONS);
shared_buf_size =
plat_rmmd_get_el3_rmm_shared_mem(&shared_buf_base);
assert((shared_buf_size == SZ_4K) &&
((void *)shared_buf_base != NULL));
/*
* Prepare coldboot arguments for RMM:
* arg0: This CPUID (primary processor).
* arg1: Version for this Boot Interface.
* arg2: PLATFORM_CORE_COUNT.
* arg3: Base address for the EL3 <-> RMM shared area. The boot
* manifest will be stored at the beginning of this area.
*/
rmm_ep_info->args.arg0 = linear_id;
rmm_ep_info->args.arg1 = RMM_EL3_INTERFACE_VERSION;
rmm_ep_info->args.arg2 = PLATFORM_CORE_COUNT;
rmm_ep_info->args.arg3 = shared_buf_base;
/* Initialise RMM context with this entry point information */
cm_setup_context(&rmm_ctx->cpu_ctx, rmm_ep_info);
@ -244,9 +272,14 @@ uint64_t rmmd_rmi_handler(uint32_t smc_fid, uint64_t x1, uint64_t x2,
uint64_t x3, uint64_t x4, void *cookie,
void *handle, uint64_t flags)
{
rmmd_rmm_context_t *ctx = &rmm_context[plat_my_core_pos()];
uint32_t src_sec_state;
/* If RMM failed to boot, treat any RMI SMC as unknown */
if (rmm_boot_failed) {
WARN("RMMD: Failed to boot up RMM. Ignoring RMI call\n");
SMC_RET1(handle, SMC_UNK);
}
/* Determine which security state this SMC originated from */
src_sec_state = caller_sec_state(flags);
@ -272,11 +305,6 @@ uint64_t rmmd_rmi_handler(uint32_t smc_fid, uint64_t x1, uint64_t x2,
switch (smc_fid) {
case RMMD_RMI_REQ_COMPLETE:
if (ctx->state == RMM_STATE_RESET) {
VERBOSE("RMMD: running rmmd_rmm_sync_exit\n");
rmmd_rmm_sync_exit(x1);
}
return rmmd_smc_forward(REALM, NON_SECURE, x1,
x2, x3, x4, 0, handle);
@ -293,11 +321,26 @@ uint64_t rmmd_rmi_handler(uint32_t smc_fid, uint64_t x1, uint64_t x2,
******************************************************************************/
static void *rmmd_cpu_on_finish_handler(const void *arg)
{
int32_t rc;
long rc;
uint32_t linear_id = plat_my_core_pos();
rmmd_rmm_context_t *ctx = &rmm_context[linear_id];
ctx->state = RMM_STATE_RESET;
if (rmm_boot_failed) {
/* RMM Boot failed on a previous CPU. Abort. */
ERROR("RMM Failed to initialize. Ignoring for CPU%d\n",
linear_id);
return NULL;
}
/*
* Prepare warmboot arguments for RMM:
* arg0: This CPUID.
* arg1 to arg3: Not used.
*/
rmm_ep_info->args.arg0 = linear_id;
rmm_ep_info->args.arg1 = 0ULL;
rmm_ep_info->args.arg2 = 0ULL;
rmm_ep_info->args.arg3 = 0ULL;
/* Initialise RMM context with this entry point information */
cm_setup_context(&ctx->cpu_ctx, rmm_ep_info);
@ -309,13 +352,13 @@ static void *rmmd_cpu_on_finish_handler(const void *arg)
rmm_el2_context_init(&ctx->cpu_ctx.el2_sysregs_ctx);
rc = rmmd_rmm_sync_entry(ctx);
if (rc != 0) {
ERROR("RMM initialisation failed (%d) on CPU%d\n", rc,
linear_id);
panic();
if (rc != E_RMM_BOOT_SUCCESS) {
ERROR("RMM init failed on CPU%d: %ld\n", linear_id, rc);
/* Mark the boot as failed for any other booting CPU */
rmm_boot_failed = true;
}
ctx->state = RMM_STATE_IDLE;
return NULL;
}
@ -354,6 +397,12 @@ uint64_t rmmd_rmm_el3_handler(uint32_t smc_fid, uint64_t x1, uint64_t x2,
uint32_t src_sec_state;
int ret;
/* If RMM failed to boot, treat any RMM-EL3 interface SMC as unknown */
if (rmm_boot_failed) {
WARN("RMMD: Failed to boot up RMM. Ignoring RMM-EL3 call\n");
SMC_RET1(handle, SMC_UNK);
}
/* Determine which security state this SMC originated from */
src_sec_state = caller_sec_state(flags);
@ -375,6 +424,11 @@ uint64_t rmmd_rmm_el3_handler(uint32_t smc_fid, uint64_t x1, uint64_t x2,
case RMMD_ATTEST_GET_REALM_KEY:
ret = rmmd_attest_get_signing_key(x1, &x2, x3);
SMC_RET2(handle, ret, x2);
case RMM_BOOT_COMPLETE:
VERBOSE("RMMD: running rmmd_rmm_sync_exit\n");
rmmd_rmm_sync_exit(x1);
default:
WARN("RMMD: Unsupported RMM-EL3 call 0x%08x\n", smc_fid);
SMC_RET1(handle, SMC_UNK);

View file

@ -32,11 +32,6 @@
#ifndef __ASSEMBLER__
#include <stdint.h>
typedef enum rmm_state {
RMM_STATE_RESET = 0,
RMM_STATE_IDLE
} rmm_state_t;
/*
* Data structure used by the RMM dispatcher (RMMD) in EL3 to track context of
* the RMM at R-EL2.
@ -44,7 +39,6 @@ typedef enum rmm_state {
typedef struct rmmd_rmm_context {
uint64_t c_rt_ctx;
cpu_context_t cpu_ctx;
rmm_state_t state;
} rmmd_rmm_context_t;
/* Functions used to enter/exit the RMM synchronously */

View file

@ -6,6 +6,8 @@
#include <asm_macros.S>
#include <services/rmmd_svc.h>
#include <platform_def.h>
#include "trp_private.h"
.global trp_head
@ -31,6 +33,28 @@
* ---------------------------------------------
*/
trp_head:
/*
* Stash arguments from previous boot stage
*/
mov x20, x0
mov x21, x1
mov x22, x2
mov x23, x3
/*
* Validate CPUId before allocating a stack.
*/
cmp x20, #PLATFORM_CORE_COUNT
b.lo 1f
mov_imm x0, RMM_BOOT_COMPLETE
mov_imm x1, E_RMM_BOOT_CPU_ID_OUT_OF_RANGE
smc #0
/* EL3 should never return back here, so panic if it does */
b trp_panic
1:
bl plat_set_my_stack
/*
@ -45,7 +69,6 @@ trp_head:
adr x2, cold_boot_flag
str xzr, [x2]
/* ---------------------------------------------
* Zero out BSS section
* ---------------------------------------------
@ -54,15 +77,21 @@ trp_head:
ldr x1, =__BSS_SIZE__
bl zeromem
mov x0, x20
mov x1, x21
mov x2, x22
mov x3, x23
bl trp_setup
bl trp_main
warm_boot:
mov_imm x0, RMMD_RMI_REQ_COMPLETE
mov x1, xzr
mov_imm x0, RMM_BOOT_COMPLETE
mov x1, xzr /* RMM_BOOT_SUCCESS */
smc #0
b trp_handler
trp_panic:
no_ret plat_panic_handler
/*
* Flag to mark if it is a cold boot.
* 1: cold boot, 0: warmboot.

View file

@ -13,6 +13,10 @@
#include <platform_def.h>
#include "trp_private.h"
/* Parameters received from the previous image */
static unsigned int trp_boot_abi_version;
static uintptr_t trp_shared_region_start;
/*******************************************************************************
* Per cpu data structure to populate parameters for an SMC in C code and use
* a pointer to this structure in assembler code to populate x0-x7
@ -52,11 +56,55 @@ static trp_args_t *set_smc_args(uint64_t arg0,
return pcpu_smc_args;
}
/*
* Abort the boot process with the reason given in err.
*/
__dead2 static void trp_boot_abort(uint64_t err)
{
(void)trp_smc(set_smc_args(RMM_BOOT_COMPLETE, err, 0, 0, 0, 0, 0, 0));
panic();
}
/*******************************************************************************
* Setup function for TRP.
******************************************************************************/
void trp_setup(void)
void trp_setup(uint64_t x0,
uint64_t x1,
uint64_t x2,
uint64_t x3)
{
/*
* Validate boot parameters.
*
* According to the Boot Interface ABI v.0.1, the
* parameters recived from EL3 are:
* x0: CPUID (verified earlier so not used)
* x1: Boot Interface version
* x2: PLATFORM_CORE_COUNT
* x3: Pointer to the shared memory area.
*/
(void)x0;
if (TRP_RMM_EL3_VERSION_GET_MAJOR(x1) != TRP_RMM_EL3_ABI_VERS_MAJOR) {
trp_boot_abort(E_RMM_BOOT_VERSION_MISMATCH);
}
if ((void *)x3 == NULL) {
trp_boot_abort(E_RMM_BOOT_INVALID_SHARED_BUFFER);
}
if (x2 > TRP_PLATFORM_CORE_COUNT) {
trp_boot_abort(E_RMM_BOOT_CPUS_OUT_OF_RANGE);
}
trp_boot_abi_version = x1;
trp_shared_region_start = x3;
flush_dcache_range((uintptr_t)&trp_boot_abi_version,
sizeof(trp_boot_abi_version));
flush_dcache_range((uintptr_t)&trp_shared_region_start,
sizeof(trp_shared_region_start));
/* Perform early platform-specific setup */
trp_early_platform_setup();
}
@ -66,9 +114,16 @@ void trp_main(void)
{
NOTICE("TRP: %s\n", version_string);
NOTICE("TRP: %s\n", build_message);
NOTICE("TRP: Supported RMM-EL3 Interface ABI: v.%u.%u\n",
TRP_RMM_EL3_ABI_VERS_MAJOR, TRP_RMM_EL3_ABI_VERS_MINOR);
INFO("TRP: Memory base : 0x%lx\n", (unsigned long)RMM_BASE);
INFO("TRP: Base address for the shared region : 0x%lx\n",
(unsigned long)trp_shared_region_start);
INFO("TRP: Total size : 0x%lx bytes\n", (unsigned long)(RMM_END
- RMM_BASE));
INFO("TRP: RMM-EL3 Interface ABI reported by EL3: v.%u.%u\n",
TRP_RMM_EL3_VERSION_GET_MAJOR(trp_boot_abi_version),
TRP_RMM_EL3_VERSION_GET_MINOR(trp_boot_abi_version));
}
/*******************************************************************************

View file

@ -7,6 +7,8 @@
#ifndef TRP_PRIVATE_H
#define TRP_PRIVATE_H
#include <services/rmmd_svc.h>
/* Definitions to help the assembler access the SMC/ERET args structure */
#define TRP_ARGS_SIZE TRP_ARGS_END
#define TRP_ARG0 0x0
@ -19,6 +21,14 @@
#define TRP_ARG7 0x38
#define TRP_ARGS_END 0x40
/* Definitions for RMM-EL3 Interface ABI VERSION */
#define TRP_RMM_EL3_ABI_VERS_MAJOR RMM_EL3_IFC_VERSION_MAJOR
#define TRP_RMM_EL3_ABI_VERS_MINOR RMM_EL3_IFC_VERSION_MINOR
#define TRP_RMM_EL3_ABI_VERS (((TRP_RMM_EL3_ABI_VERS_MAJOR & 0x7FFF) << 16) | \
(TRP_RMM_EL3_ABI_VERS_MINOR & 0xFFFF))
#define TRP_PLATFORM_CORE_COUNT PLATFORM_CORE_COUNT
#ifndef __ASSEMBLER__
#include <stdint.h>
@ -38,8 +48,14 @@ typedef struct trp_args {
/* Definitions for RMI VERSION */
#define RMI_ABI_VERSION_MAJOR U(0x0)
#define RMI_ABI_VERSION_MINOR U(0x0)
#define RMI_ABI_VERSION ((RMI_ABI_VERSION_MAJOR << 16) | \
RMI_ABI_VERSION_MINOR)
#define RMI_ABI_VERSION (((RMI_ABI_VERSION_MAJOR & 0x7FFF) \
<< 16) | \
(RMI_ABI_VERSION_MINOR & 0xFFFF))
#define TRP_RMM_EL3_VERSION_GET_MAJOR(x) \
RMM_EL3_IFC_VERSION_GET_MAJOR((x))
#define TRP_RMM_EL3_VERSION_GET_MINOR(x) \
RMM_EL3_IFC_VERSION_GET_MAJOR_MINOR((x))
/* Helper to issue SMC calls to BL31 */
uint64_t trp_smc(trp_args_t *);
@ -48,7 +64,10 @@ uint64_t trp_smc(trp_args_t *);
void trp_main(void);
/* Setup TRP. Executed only by Primary CPU */
void trp_setup(void);
void trp_setup(uint64_t x0,
uint64_t x1,
uint64_t x2,
uint64_t x3);
#endif /* __ASSEMBLER__ */
#endif /* TRP_PRIVATE_H */