aboutsummaryrefslogtreecommitdiff
path: root/services/std_svc/rmmd/rmmd_main.c
diff options
context:
space:
mode:
Diffstat (limited to 'services/std_svc/rmmd/rmmd_main.c')
-rw-r--r--services/std_svc/rmmd/rmmd_main.c151
1 files changed, 109 insertions, 42 deletions
diff --git a/services/std_svc/rmmd/rmmd_main.c b/services/std_svc/rmmd/rmmd_main.c
index 746419e9c..6bd9fdf30 100644
--- a/services/std_svc/rmmd/rmmd_main.c
+++ b/services/std_svc/rmmd/rmmd_main.c
@@ -33,6 +33,11 @@
#include "rmmd_private.h"
/*******************************************************************************
+ * RMM boot failure flag
+ ******************************************************************************/
+static bool rmm_boot_failed;
+
+/*******************************************************************************
* RMM context information.
******************************************************************************/
rmmd_rmm_context_t rmm_context[PLATFORM_CORE_COUNT];
@@ -132,13 +137,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 +149,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;
@@ -163,9 +166,13 @@ static int32_t rmm_init(void)
******************************************************************************/
int rmmd_setup(void)
{
+ size_t shared_buf_size __unused;
+ uintptr_t shared_buf_base;
uint32_t ep_attr;
unsigned int linear_id = plat_my_core_pos();
rmmd_rmm_context_t *rmm_ctx = &rmm_context[linear_id];
+ rmm_manifest_t *manifest;
+ int rc;
/* Make sure RME is supported. */
assert(get_armv9_2_feat_rme_support() != 0U);
@@ -192,6 +199,34 @@ 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));
+
+ /* Load the boot manifest at the beginning of the shared area */
+ manifest = (rmm_manifest_t *)shared_buf_base;
+ rc = plat_rmmd_load_manifest(manifest);
+ if (rc != 0) {
+ ERROR("Error loading RMM Boot Manifest (%i)\n", rc);
+ return rc;
+ }
+ flush_dcache_range((uintptr_t)shared_buf_base, shared_buf_size);
+
+ /*
+ * 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);
@@ -207,10 +242,12 @@ int rmmd_setup(void)
* Forward SMC to the other security state
******************************************************************************/
static uint64_t rmmd_smc_forward(uint32_t src_sec_state,
- uint32_t dst_sec_state, uint64_t x0,
- uint64_t x1, uint64_t x2, uint64_t x3,
- uint64_t x4, void *handle)
+ uint32_t dst_sec_state, uint64_t x0,
+ uint64_t x1, uint64_t x2, uint64_t x3,
+ uint64_t x4, void *handle)
{
+ cpu_context_t *ctx = cm_get_context(dst_sec_state);
+
/* Save incoming security state */
cm_el1_sysregs_context_save(src_sec_state);
cm_el2_sysregs_context_save(src_sec_state);
@@ -221,19 +258,21 @@ static uint64_t rmmd_smc_forward(uint32_t src_sec_state,
cm_set_next_eret_context(dst_sec_state);
/*
- * As per SMCCCv1.1, we need to preserve x4 to x7 unless
+ * As per SMCCCv1.2, we need to preserve x4 to x7 unless
* being used as return args. Hence we differentiate the
* onward and backward path. Support upto 8 args in the
* onward path and 4 args in return path.
+ * Register x4 will be preserved by RMM in case it is not
+ * used in return path.
*/
if (src_sec_state == NON_SECURE) {
- SMC_RET8(cm_get_context(dst_sec_state), x0, x1, x2, x3, x4,
- SMC_GET_GP(handle, CTX_GPREG_X5),
- SMC_GET_GP(handle, CTX_GPREG_X6),
- SMC_GET_GP(handle, CTX_GPREG_X7));
- } else {
- SMC_RET4(cm_get_context(dst_sec_state), x0, x1, x2, x3);
+ SMC_RET8(ctx, x0, x1, x2, x3, x4,
+ SMC_GET_GP(handle, CTX_GPREG_X5),
+ SMC_GET_GP(handle, CTX_GPREG_X6),
+ SMC_GET_GP(handle, CTX_GPREG_X7));
}
+
+ SMC_RET5(ctx, x0, x1, x2, x3, x4);
}
/*******************************************************************************
@@ -241,12 +280,17 @@ static uint64_t rmmd_smc_forward(uint32_t src_sec_state,
* either forwarded to the other security state or handled by the RMM dispatcher
******************************************************************************/
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)
+ 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);
@@ -271,15 +315,12 @@ 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);
- }
+ case RMM_RMI_REQ_COMPLETE: {
+ uint64_t x5 = SMC_GET_GP(handle, CTX_GPREG_X5);
return rmmd_smc_forward(REALM, NON_SECURE, x1,
- x2, x3, x4, 0, handle);
-
+ x2, x3, x4, x5, handle);
+ }
default:
WARN("RMMD: Unsupported RMM call 0x%08x\n", smc_fid);
SMC_RET1(handle, SMC_UNK);
@@ -293,11 +334,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 +365,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;
}
@@ -328,15 +384,15 @@ static int gpt_to_gts_error(int error, uint32_t smc_fid, uint64_t address)
int ret;
if (error == 0) {
- return RMMD_OK;
+ return E_RMM_OK;
}
if (error == -EINVAL) {
- ret = RMMD_ERR_BAD_ADDR;
+ ret = E_RMM_BAD_ADDR;
} else {
/* This is the only other error code we expect */
assert(error == -EPERM);
- ret = RMMD_ERR_BAD_PAS;
+ ret = E_RMM_BAD_PAS;
}
ERROR("RMMD: PAS Transition failed. GPT ret = %d, PA: 0x%"PRIx64 ", FID = 0x%x\n",
@@ -354,6 +410,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);
@@ -363,18 +425,23 @@ uint64_t rmmd_rmm_el3_handler(uint32_t smc_fid, uint64_t x1, uint64_t x2,
}
switch (smc_fid) {
- case RMMD_GTSI_DELEGATE:
+ case RMM_GTSI_DELEGATE:
ret = gpt_delegate_pas(x1, PAGE_SIZE_4KB, SMC_FROM_REALM);
SMC_RET1(handle, gpt_to_gts_error(ret, smc_fid, x1));
- case RMMD_GTSI_UNDELEGATE:
+ case RMM_GTSI_UNDELEGATE:
ret = gpt_undelegate_pas(x1, PAGE_SIZE_4KB, SMC_FROM_REALM);
SMC_RET1(handle, gpt_to_gts_error(ret, smc_fid, x1));
- case RMMD_ATTEST_GET_PLAT_TOKEN:
+ case RMM_ATTEST_GET_PLAT_TOKEN:
ret = rmmd_attest_get_platform_token(x1, &x2, x3);
SMC_RET2(handle, ret, x2);
- case RMMD_ATTEST_GET_REALM_KEY:
+ case RMM_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);