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
diff --git a/changelog.yaml b/changelog.yaml
index 37a9c6d..01e91b4 100644
--- a/changelog.yaml
+++ b/changelog.yaml
@@ -563,6 +563,9 @@
- title: TRP
scope: trp
+ - title: RMMD
+ scope: rmmd
+
- title: SPM
scope: spm
diff --git a/docs/getting_started/porting-guide.rst b/docs/getting_started/porting-guide.rst
index 2c6a005..87c4ccb 100644
--- a/docs/getting_started/porting-guide.rst
+++ b/docs/getting_started/porting-guide.rst
@@ -2017,7 +2017,7 @@
(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 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 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]
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
diff --git a/include/plat/arm/common/arm_def.h b/include/plat/arm/common/arm_def.h
index caab14e..47fbe76 100644
--- a/include/plat/arm/common/arm_def.h
+++ b/include/plat/arm/common/arm_def.h
@@ -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
diff --git a/include/plat/arm/common/arm_pas_def.h b/include/plat/arm/common/arm_pas_def.h
index 4fee41b..c199302 100644
--- a/include/plat/arm/common/arm_pas_def.h
+++ b/include/plat/arm/common/arm_pas_def.h
@@ -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, \
diff --git a/include/plat/arm/common/plat_arm.h b/include/plat/arm/common/plat_arm.h
index 9618700..d060332 100644
--- a/include/plat/arm/common/plat_arm.h
+++ b/include/plat/arm/common/plat_arm.h
@@ -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 @@
{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}
diff --git a/include/plat/common/platform.h b/include/plat/common/platform.h
index b62a631..479a48b 100644
--- a/include/plat/common/platform.h
+++ b/include/plat/common/platform.h
@@ -305,11 +305,11 @@
/*******************************************************************************
* 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)
******************************************************************************/
diff --git a/include/services/rmmd_svc.h b/include/services/rmmd_svc.h
index 156d89c..8e9bdab 100644
--- a/include/services/rmmd_svc.h
+++ b/include/services/rmmd_svc.h
@@ -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>
diff --git a/plat/arm/board/fvp/fvp_common.c b/plat/arm/board/fvp/fvp_common.c
index a7028f6..45a4721 100644
--- a/plat/arm/board/fvp/fvp_common.c
+++ b/plat/arm/board/fvp/fvp_common.c
@@ -169,6 +169,7 @@
#endif
#if ENABLE_RME
ARM_MAP_GPT_L1_DRAM,
+ ARM_MAP_EL3_RMM_SHARED_MEM,
#endif
{0}
};
@@ -512,3 +513,18 @@
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
diff --git a/plat/arm/board/fvp/fvp_plat_attest_token.c b/plat/arm/board/fvp/fvp_plat_attest_token.c
index 5463f33..1b0854b 100644
--- a/plat/arm/board/fvp/fvp_plat_attest_token.c
+++ b/plat/arm/board/fvp/fvp_plat_attest_token.c
@@ -300,8 +300,8 @@
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;
diff --git a/plat/arm/board/fvp/fvp_realm_attest_key.c b/plat/arm/board/fvp/fvp_realm_attest_key.c
index b32f557..1af1f0d 100644
--- a/plat/arm/board/fvp/fvp_realm_attest_key.c
+++ b/plat/arm/board/fvp/fvp_realm_attest_key.c
@@ -19,7 +19,8 @@
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);
diff --git a/plat/arm/board/fvp/include/platform_def.h b/plat/arm/board/fvp/include/platform_def.h
index c75aca7..73d7ada 100644
--- a/plat/arm/board/fvp/include/platform_def.h
+++ b/plat/arm/board/fvp/include/platform_def.h
@@ -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
diff --git a/plat/arm/board/fvp/platform.mk b/plat/arm/board/fvp/platform.mk
index f9053a8..a7e27e8 100644
--- a/plat/arm/board/fvp/platform.mk
+++ b/plat/arm/board/fvp/platform.mk
@@ -341,10 +341,6 @@
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
diff --git a/plat/arm/common/arm_bl31_setup.c b/plat/arm/common/arm_bl31_setup.c
index a6f7df5..cf403b1 100644
--- a/plat/arm/common/arm_bl31_setup.c
+++ b/plat/arm/common/arm_bl31_setup.c
@@ -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 @@
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 */
/*
diff --git a/services/std_svc/rmmd/rmmd_attest.c b/services/std_svc/rmmd/rmmd_attest.c
index 0432ec3..6c5f368 100644
--- a/services/std_svc/rmmd/rmmd_attest.c
+++ b/services/std_svc/rmmd/rmmd_attest.c
@@ -101,7 +101,7 @@
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 @@
}
/* 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;
diff --git a/services/std_svc/rmmd/rmmd_main.c b/services/std_svc/rmmd/rmmd_main.c
index 746419e..d128e3e 100644
--- a/services/std_svc/rmmd/rmmd_main.c
+++ b/services/std_svc/rmmd/rmmd_main.c
@@ -33,6 +33,17 @@
#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.
******************************************************************************/
rmmd_rmm_context_t rmm_context[PLATFORM_CORE_COUNT];
@@ -132,13 +143,10 @@
******************************************************************************/
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 @@
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 @@
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 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 @@
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 @@
******************************************************************************/
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 @@
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 @@
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 @@
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);
diff --git a/services/std_svc/rmmd/rmmd_private.h b/services/std_svc/rmmd/rmmd_private.h
index 73df2b8..e964ead 100644
--- a/services/std_svc/rmmd/rmmd_private.h
+++ b/services/std_svc/rmmd/rmmd_private.h
@@ -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 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 */
diff --git a/services/std_svc/rmmd/trp/trp_entry.S b/services/std_svc/rmmd/trp/trp_entry.S
index 1b03c9f..47c1df1 100644
--- a/services/std_svc/rmmd/trp/trp_entry.S
+++ b/services/std_svc/rmmd/trp/trp_entry.S
@@ -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 @@
adr x2, cold_boot_flag
str xzr, [x2]
-
/* ---------------------------------------------
* Zero out BSS section
* ---------------------------------------------
@@ -54,15 +77,21 @@
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.
diff --git a/services/std_svc/rmmd/trp/trp_main.c b/services/std_svc/rmmd/trp/trp_main.c
index 2e3f076..7df128b 100644
--- a/services/std_svc/rmmd/trp/trp_main.c
+++ b/services/std_svc/rmmd/trp/trp_main.c
@@ -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 @@
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 @@
{
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));
}
/*******************************************************************************
diff --git a/services/std_svc/rmmd/trp/trp_private.h b/services/std_svc/rmmd/trp/trp_private.h
index 4c5222e..f3a4876 100644
--- a/services/std_svc/rmmd/trp/trp_private.h
+++ b/services/std_svc/rmmd/trp/trp_private.h
@@ -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 @@
/* 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 @@
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 */