Merge "refactor(spmd): boot interface and pass core id" into integration
diff --git a/docs/components/secure-partition-manager.rst b/docs/components/secure-partition-manager.rst
index f6a8828..fa51fe0 100644
--- a/docs/components/secure-partition-manager.rst
+++ b/docs/components/secure-partition-manager.rst
@@ -414,13 +414,17 @@
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 @@
[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 dda127f..0706c45 100644
--- a/services/std_svc/spmd/spmd_main.c
+++ b/services/std_svc/spmd/spmd_main.c
@@ -65,14 +65,6 @@
}
/*******************************************************************************
- * 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.
******************************************************************************/
uint16_t spmd_spmc_id_get(void)
@@ -156,18 +148,11 @@
{
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 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 @@
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 @@
/* 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 074609c..ac962ea 100644
--- a/services/std_svc/spmd/spmd_pm.c
+++ b/services/std_svc/spmd/spmd_pm.c
@@ -75,14 +75,14 @@
******************************************************************************/
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 @@
* 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);