diff options
| author | John Powell <john.powell@arm.com> | 2026-06-26 13:52:52 -0500 |
|---|---|---|
| committer | John Powell <john.powell@arm.com> | 2026-06-30 15:42:43 +0000 |
| commit | e6bccf43c4f93a25a0e1c7877107022537a17cad (patch) | |
| tree | 23c99170f8f2f431345d7e370c7b7b8826bf5a8b | |
| parent | 567e4357fb29be24ab5917102d2a5ed6f6feba4d (diff) | |
| download | arm-trusted-firmware-e6bccf43c4f93a25a0e1c7877107022537a17cad.tar.gz arm-trusted-firmware-e6bccf43c4f93a25a0e1c7877107022537a17cad.zip | |
feat(lfa): lfa service updates
This patch updates the LFA service components in preparation for
BL31 specific changes.
Change-Id: I6d4dd90b11fa1d8729c4f9026d2ddce0272aea76
Signed-off-by: John Powell <john.powell@arm.com>
| -rw-r--r-- | include/services/lfa_component_desc.h | 37 | ||||
| -rw-r--r-- | include/services/lfa_svc.h | 7 | ||||
| -rw-r--r-- | services/std_svc/lfa/lfa_main.c | 99 | ||||
| -rw-r--r-- | services/std_svc/rmmd/rmmd_rmm_lfa.c | 1 |
4 files changed, 88 insertions, 56 deletions
diff --git a/include/services/lfa_component_desc.h b/include/services/lfa_component_desc.h index aefef953a..d15041e17 100644 --- a/include/services/lfa_component_desc.h +++ b/include/services/lfa_component_desc.h @@ -16,20 +16,55 @@ typedef enum { PRIME_COMPLETE, } lfa_prime_status_t; +/* + * This structure contains the status of a component that is currently in the + * process of being activated. + * + * component_id ID of the activation component currently in progress. + * Can be either RMM or BL31. + * prime_status Current prime status of this component. + * image_size Size of the image file to be activated. + * image_address Address of the image file to be activated. + * reset Flag indicating that the core will warm reset after the + * activation. + * cpu_rendezvous Flag indicating that active CPUs will rendezvous prior + * to activation. This is set to true by default and can + * only be cleared if the caller requests it and the flag + * cpu_rendezvous_required in the component ops structure + * is clear. + */ struct lfa_component_status { uint32_t component_id; lfa_prime_status_t prime_status; - bool cpu_rendezvous_required; + size_t image_size; + uintptr_t image_address; + bool reset; + bool cpu_rendezvous; }; typedef int (*component_prime_fn)(struct lfa_component_status *activation); typedef int (*component_activate_fn)(struct lfa_component_status *activation, uint64_t ep_address, uint64_t context_id); +typedef int (*component_cancel_fn)(struct lfa_component_status *activation); +/* + * This structure is defined per-component and contains pointers to the prime + * and activate functions as well as some basic requirements for activation of + * that component. + * + * prime Pointer to prime function for a component. + * activate Pointer to activate function for a component. + * may_reset_cpu Flag letting the caller know to expect a CPU warm + * reset after activation. + * cpu_rendezvous_required Flag indicating that a CPU reset is not optional. If + * this flag is set, the caller cannot request skipping + * the CPU rendezvous. + */ struct lfa_component_ops { component_prime_fn prime; component_activate_fn activate; + component_cancel_fn cancel; bool may_reset_cpu; bool cpu_rendezvous_required; }; diff --git a/include/services/lfa_svc.h b/include/services/lfa_svc.h index f585cf3e5..3485a7234 100644 --- a/include/services/lfa_svc.h +++ b/include/services/lfa_svc.h @@ -77,6 +77,12 @@ enum lfa_retc { LFA_ACTIVATION_FAILED = -11, }; +typedef struct { + entry_point_info_t ep; + uint64_t spinlock_p; + uintptr_t plat_wr_mailbox; +} lfa_mailbox_message_t; + /* Initialization routine for the LFA service */ int lfa_setup(void); @@ -85,5 +91,6 @@ uint64_t lfa_smc_handler(uint32_t smc_fid, u_register_t x1, u_register_t x2, void *handle, u_register_t flags); void lfa_reset_activation(void); bool lfa_is_prime_complete(uint32_t lfa_component_id); +uint64_t prepare_warm_reset(uintptr_t lfa_ns_ep, uint64_t context_id, uint64_t cpu_spinlock); #endif /* LFA_SVC_H */ diff --git a/services/std_svc/lfa/lfa_main.c b/services/std_svc/lfa/lfa_main.c index 819b169a7..0022e0331 100644 --- a/services/std_svc/lfa/lfa_main.c +++ b/services/std_svc/lfa/lfa_main.c @@ -1,5 +1,5 @@ /* - * Copyright (c) 2025, Arm Limited. All rights reserved. + * Copyright (c) 2025-2026, Arm Limited. All rights reserved. * Copyright (c) 2025, NVIDIA Corporation. All rights reserved. * * SPDX-License-Identifier: BSD-3-Clause @@ -32,7 +32,6 @@ void lfa_reset_activation(void) { current_activation.component_id = LFA_INVALID_COMPONENT; current_activation.prime_status = PRIME_NONE; - current_activation.cpu_rendezvous_required = false; } static int convert_to_lfa_error(int ret) @@ -54,8 +53,7 @@ static bool lfa_initialize_components(void) lfa_component_count = plat_lfa_get_components(&lfa_components); if (lfa_component_count == 0U || lfa_components == NULL) { - /* unlikely to reach here */ - ERROR("Invalid LFA component setup: count = 0 or components are NULL"); + ERROR("Could not retrieve LFA components.\n"); return false; } @@ -64,8 +62,7 @@ static bool lfa_initialize_components(void) static uint64_t get_fw_activation_flags(uint32_t fw_seq_id) { - const plat_lfa_component_info_t *comp = - &lfa_components[fw_seq_id]; + const plat_lfa_component_info_t *comp = &lfa_components[fw_seq_id]; uint64_t flags = 0ULL; flags |= ((comp->activator == NULL ? 0ULL : 1ULL) @@ -86,6 +83,7 @@ static uint64_t get_fw_activation_flags(uint32_t fw_seq_id) static int lfa_cancel(uint32_t component_id) { int ret = LFA_SUCCESS; + struct lfa_component_ops *activator; if (lfa_component_count == 0U) { return LFA_WRONG_STATE; @@ -97,6 +95,14 @@ static int lfa_cancel(uint32_t component_id) return LFA_INVALID_PARAMETERS; } + activator = lfa_components[component_id].activator; + if (activator->cancel != NULL) { + ret = activator->cancel(¤t_activation); + if (ret != LFA_SUCCESS) { + return LFA_BUSY; + } + } + ret = plat_lfa_cancel(component_id); if (ret != LFA_SUCCESS) { return LFA_BUSY; @@ -120,13 +126,13 @@ static int lfa_activate(uint32_t component_id, uint64_t flags, return LFA_COMPONENT_WRONG_STATE; } - /* Check if fw_seq_id is in range. */ if ((component_id >= lfa_component_count) || (current_activation.component_id != component_id)) { return LFA_INVALID_PARAMETERS; } - if (lfa_components[component_id].activator == NULL) { + activator = lfa_components[component_id].activator; + if (activator == NULL) { return LFA_NOT_SUPPORTED; } @@ -135,35 +141,20 @@ static int lfa_activate(uint32_t component_id, uint64_t flags, return LFA_ACTIVATION_FAILED; } - activator = lfa_components[component_id].activator; - if (activator->activate != NULL) { - /* - * Pass skip_cpu_rendezvous (flag[0]) only if flag[0]==1 - * & CPU_RENDEZVOUS is not required. - */ - if (flags & LFA_SKIP_CPU_RENDEZVOUS_BIT) { - if (!activator->cpu_rendezvous_required) { - INFO("Skipping rendezvous requested by caller.\n"); - current_activation.cpu_rendezvous_required = false; - } - /* - * Return error if caller tries to skip rendezvous when - * it is required. - */ - else { - ERROR("CPU Rendezvous is required, can't skip.\n"); - return LFA_INVALID_PARAMETERS; - } + /* If caller requests it, see if we can skip CPU rendezvous. */ + if (flags & LFA_SKIP_CPU_RENDEZVOUS_BIT) { + if (!activator->cpu_rendezvous_required) { + INFO("Caller requested skip CPU rendezvous.\n"); + current_activation.cpu_rendezvous = false; + } else { + ERROR("CPU rendezvous cannot be skipped!\n"); + return LFA_INVALID_PARAMETERS; } - - ret = activator->activate(¤t_activation, ep_address, - context_id); } - /* - * Update the activation pending flag only if the activation was - * successful. - */ + ret = activator->activate(¤t_activation, ep_address, context_id); + + /* Clear pending flag on successful activation. */ if (ret == LFA_SUCCESS) { lfa_components[component_id].activation_pending = false; } @@ -225,7 +216,13 @@ static int lfa_prime(uint32_t component_id, uint64_t *flags) } } + /* + * Update current activation status fields. CPU rendezvous is enabled + * by default but can be disabled if requested and allowed. + */ + current_activation.cpu_rendezvous = true; current_activation.prime_status = PRIME_COMPLETE; + current_activation.reset = lfa_components[component_id].activator->may_reset_cpu; } /* @@ -268,8 +265,9 @@ uint64_t lfa_smc_handler(uint32_t smc_fid, u_register_t x1, u_register_t x2, u_register_t x3, u_register_t x4, void *cookie, void *handle, u_register_t flags) { - uint64_t retx1, retx2; - uint64_t lfa_flags; + uint64_t retx1; + uint64_t retx2; + uint64_t lfa_flags = 0; uint8_t *uuid_p; uint32_t fw_seq_id = (uint32_t)x1; int ret; @@ -292,9 +290,9 @@ uint64_t lfa_smc_handler(uint32_t smc_fid, u_register_t x1, u_register_t x2, break; case LFA_GET_INFO: - /** + /* * The current specification limits this input parameter to be zero for - * version 1.0 of LFA + * version 1.0 of LFA. */ if (x1 == 0ULL) { SMC_RET3(handle, LFA_SUCCESS, lfa_component_count, 0); @@ -309,29 +307,27 @@ uint64_t lfa_smc_handler(uint32_t smc_fid, u_register_t x1, u_register_t x2, } /* - * Check if fw_seq_id is in range. LFA_GET_INFO must be called first to scan - * platform firmware and create a valid number of firmware components. + * Check if fw_seq_id is in range. LFA_GET_INFO must be called + * first to scan platform firmware and create a valid number of + * firmware components. */ if (fw_seq_id >= lfa_component_count) { SMC_RET1(handle, LFA_INVALID_PARAMETERS); } - /* - * grab the UUID of asked fw_seq_id and set the return UUID - * variables - */ + /* Get the UUID of requested fw_seq_id. */ uuid_p = (uint8_t *)&lfa_components[fw_seq_id].uuid; memcpy(&retx1, uuid_p, sizeof(uint64_t)); memcpy(&retx2, uuid_p + sizeof(uint64_t), sizeof(uint64_t)); /* - * check the given fw_seq_id's update available - * and accordingly set the active_pending flag + * Check the given fw_seq_id update available and accordingly + * set the active_pending flag. */ lfa_components[fw_seq_id].activation_pending = is_plat_lfa_activation_pending(fw_seq_id); - INFO("Component %lu %s live activation:\n", x1, + INFO("Component %lu %s live activation.\n", x1, lfa_components[fw_seq_id].activator ? "supports" : "does not support"); @@ -340,10 +336,7 @@ uint64_t lfa_smc_handler(uint32_t smc_fid, u_register_t x1, u_register_t x2, lfa_components[fw_seq_id].activation_pending ? "true" : "false"); } - INFO("x1 = 0x%016lx, x2 = 0x%016lx\n", retx1, retx2); - SMC_RET4(handle, LFA_SUCCESS, retx1, retx2, get_fw_activation_flags(fw_seq_id)); - break; case LFA_PRIME: @@ -372,7 +365,6 @@ uint64_t lfa_smc_handler(uint32_t smc_fid, u_register_t x1, u_register_t x2, ret = lfa_activate(fw_seq_id, x2, x3, x4); /* TODO: implement activate again */ SMC_RET2(handle, ret, 0ULL); - break; case LFA_CANCEL: @@ -383,11 +375,8 @@ uint64_t lfa_smc_handler(uint32_t smc_fid, u_register_t x1, u_register_t x2, default: WARN("Unimplemented LFA Service Call: 0x%x\n", smc_fid); SMC_RET1(handle, SMC_UNK); - break; /* unreachable */ - + break; } - SMC_RET1(handle, SMC_UNK); - return 0; } diff --git a/services/std_svc/rmmd/rmmd_rmm_lfa.c b/services/std_svc/rmmd/rmmd_rmm_lfa.c index 74c8cdddc..23c14e23c 100644 --- a/services/std_svc/rmmd/rmmd_rmm_lfa.c +++ b/services/std_svc/rmmd/rmmd_rmm_lfa.c @@ -78,6 +78,7 @@ static int lfa_rmm_activate(struct lfa_component_status *activation, static struct lfa_component_ops rmm_activator = { .prime = lfa_rmm_prime, .activate = lfa_rmm_activate, + .cancel = NULL, .may_reset_cpu = false, .cpu_rendezvous_required = true, }; |
