Merge "refactor(spmd): boot interface and pass core id" into integration

This commit is contained in:
Olivier Deprez 2021-09-24 08:47:40 +02:00 committed by TrustedFirmware Code Review
commit 2245bb8a77
3 changed files with 42 additions and 32 deletions

View file

@ -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 <https://developer.arm.com/documentation/den0006/d/>`__
[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.*

View file

@ -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;
}

View file

@ -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);