diff --git a/docs/components/secure-partition-manager.rst b/docs/components/secure-partition-manager.rst index a5e7e8ed5..0b8008306 100644 --- a/docs/components/secure-partition-manager.rst +++ b/docs/components/secure-partition-manager.rst @@ -414,13 +414,17 @@ SPMC boot The SPMC is loaded by BL2 as the BL32 image. -The SPMC manifest is loaded by BL2 as the ``TOS_FW_CONFIG`` image. +The SPMC manifest is loaded by BL2 as the ``TOS_FW_CONFIG`` image `[9]`_. BL2 passes the SPMC manifest address to BL31 through a register. At boot time, the SPMD in BL31 runs from the primary core, initializes the core -contexts and launches the SPMC (BL32) passing the SPMC manifest address through -a register. +contexts and launches the SPMC (BL32) passing the following information through +registers: + +- X0 holds the ``TOS_FW_CONFIG`` physical address (or SPMC manifest blob). +- X1 holds the ``HW_CONFIG`` physical address. +- X4 holds the currently running core linear id. Loading of SPs ~~~~~~~~~~~~~~ @@ -951,6 +955,10 @@ Client `__ [8] https://lists.trustedfirmware.org/pipermail/tf-a/2020-February/000296.html +.. _[9]: + +[9] https://trustedfirmware-a.readthedocs.io/en/latest/design/firmware-design.html#dynamic-configuration-during-cold-boot + -------------- *Copyright (c) 2020-2021, Arm Limited and Contributors. All rights reserved.* diff --git a/services/std_svc/spmd/spmd_main.c b/services/std_svc/spmd/spmd_main.c index dda127fd4..0706c45db 100644 --- a/services/std_svc/spmd/spmd_main.c +++ b/services/std_svc/spmd/spmd_main.c @@ -64,14 +64,6 @@ spmd_spm_core_context_t *spmd_get_context(void) return spmd_get_context_by_mpidr(read_mpidr()); } -/******************************************************************************* - * SPM Core entry point information get helper. - ******************************************************************************/ -entry_point_info_t *spmd_spmc_ep_info_get(void) -{ - return spmc_ep_info; -} - /******************************************************************************* * SPM Core ID getter. ******************************************************************************/ @@ -156,18 +148,11 @@ static int32_t spmd_init(void) { spmd_spm_core_context_t *ctx = spmd_get_context(); uint64_t rc; - unsigned int linear_id = plat_my_core_pos(); - unsigned int core_id; VERBOSE("SPM Core init start.\n"); - ctx->state = SPMC_STATE_ON_PENDING; - /* Set the SPMC context state on other CPUs to OFF */ - for (core_id = 0U; core_id < PLATFORM_CORE_COUNT; core_id++) { - if (core_id != linear_id) { - spm_core_context[core_id].state = SPMC_STATE_OFF; - } - } + /* Primary boot core enters the SPMC for initialization. */ + ctx->state = SPMC_STATE_ON_PENDING; rc = spmd_spm_core_sync_entry(ctx); if (rc != 0ULL) { @@ -187,7 +172,8 @@ static int32_t spmd_init(void) ******************************************************************************/ static int spmd_spmc_init(void *pm_addr) { - spmd_spm_core_context_t *spm_ctx = spmd_get_context(); + cpu_context_t *cpu_ctx; + unsigned int core_id; uint32_t ep_attr; int rc; @@ -280,13 +266,21 @@ static int spmd_spmc_init(void *pm_addr) DISABLE_ALL_EXCEPTIONS); } - /* Initialise SPM Core context with this entry point information */ - cm_setup_context(&spm_ctx->cpu_ctx, spmc_ep_info); + /* Set an initial SPMC context state for all cores. */ + for (core_id = 0U; core_id < PLATFORM_CORE_COUNT; core_id++) { + spm_core_context[core_id].state = SPMC_STATE_OFF; - /* Reuse PSCI affinity states to mark this SPMC context as off */ - spm_ctx->state = AFF_STATE_OFF; + /* Setup an initial cpu context for the SPMC. */ + cpu_ctx = &spm_core_context[core_id].cpu_ctx; + cm_setup_context(cpu_ctx, spmc_ep_info); - INFO("SPM Core setup done.\n"); + /* + * Pass the core linear ID to the SPMC through x4. + * (TF-A implementation defined behavior helping + * a legacy TOS migration to adopt FF-A). + */ + write_ctx_reg(get_gpregs_ctx(cpu_ctx), CTX_GPREG_X4, core_id); + } /* Register power management hooks with PSCI */ psci_register_spd_pm_hook(&spmd_pm); @@ -294,6 +288,8 @@ static int spmd_spmc_init(void *pm_addr) /* Register init function for deferred init. */ bl31_register_bl32_init(&spmd_init); + INFO("SPM Core setup done.\n"); + return 0; } diff --git a/services/std_svc/spmd/spmd_pm.c b/services/std_svc/spmd/spmd_pm.c index 074609c89..ac962eaa2 100644 --- a/services/std_svc/spmd/spmd_pm.c +++ b/services/std_svc/spmd/spmd_pm.c @@ -75,14 +75,14 @@ out: ******************************************************************************/ static void spmd_cpu_on_finish_handler(u_register_t unused) { - entry_point_info_t *spmc_ep_info = spmd_spmc_ep_info_get(); spmd_spm_core_context_t *ctx = spmd_get_context(); unsigned int linear_id = plat_my_core_pos(); + el3_state_t *el3_state; + uintptr_t entry_point; uint64_t rc; assert(ctx != NULL); assert(ctx->state != SPMC_STATE_ON); - assert(spmc_ep_info != NULL); spin_lock(&g_spmd_pm.lock); @@ -92,14 +92,20 @@ static void spmd_cpu_on_finish_handler(u_register_t unused) * primary core address for booting secondary cores. */ if (g_spmd_pm.secondary_ep_locked == true) { - spmc_ep_info->pc = g_spmd_pm.secondary_ep; + /* + * The CPU context has already been initialized at boot time + * (in spmd_spmc_init by a call to cm_setup_context). Adjust + * below the target core entry point based on the address + * passed to by FFA_SECONDARY_EP_REGISTER. + */ + entry_point = g_spmd_pm.secondary_ep; + el3_state = get_el3state_ctx(&ctx->cpu_ctx); + write_ctx_reg(el3_state, CTX_ELR_EL3, entry_point); } spin_unlock(&g_spmd_pm.lock); - cm_setup_context(&ctx->cpu_ctx, spmc_ep_info); - - /* Mark CPU as initiating ON operation */ + /* Mark CPU as initiating ON operation. */ ctx->state = SPMC_STATE_ON_PENDING; rc = spmd_spm_core_sync_entry(ctx);