diff options
| author | Manish V Badarkhe <Manish.Badarkhe@arm.com> | 2026-03-05 22:45:36 +0000 |
|---|---|---|
| committer | John Powell <john.powell@arm.com> | 2026-06-30 20:25:11 +0000 |
| commit | 7196825ce71266d6656165657d4936d185bd439b (patch) | |
| tree | cb08336180e5168637032f0c4e42a126deb41cb5 | |
| parent | 7a5b0839b5b95b21c82cd0a5d10dc13901e53185 (diff) | |
| download | arm-trusted-firmware-7196825ce71266d6656165657d4936d185bd439b.tar.gz arm-trusted-firmware-7196825ce71266d6656165657d4936d185bd439b.zip | |
feat(lfa): harden cancel handling and lock around LFA_CANCEL
- block cancel once all active CPUs have entered ACTIVATE
- take lfa_lock during cancel SMC handling
Change-Id: I1443644845d19e0322f5d188461a1c4083c57707
Signed-off-by: Manish V Badarkhe <Manish.Badarkhe@arm.com>
Signed-off-by: John Powell <john.powell@arm.com>
| -rw-r--r-- | services/std_svc/lfa/lfa_main.c | 26 |
1 files changed, 26 insertions, 0 deletions
diff --git a/services/std_svc/lfa/lfa_main.c b/services/std_svc/lfa/lfa_main.c index 2f76756bc..31c05bf58 100644 --- a/services/std_svc/lfa/lfa_main.c +++ b/services/std_svc/lfa/lfa_main.c @@ -31,6 +31,7 @@ static volatile bool activation_in_progress; static volatile bool activation_skip_cpu_rendezvous; static volatile uint32_t activation_users; static volatile bool activation_failed; +static volatile bool activation_cancel_locked; /* * Spinlock to serialize LFA operations (PRIME, ACTIVATE). @@ -49,6 +50,7 @@ void lfa_reset_activation(void) activation_skip_cpu_rendezvous = false; activation_users = 0U; activation_failed = false; + activation_cancel_locked = false; } static int convert_to_lfa_error(int ret) @@ -112,6 +114,14 @@ static int lfa_cancel(uint32_t component_id) return LFA_INVALID_PARAMETERS; } + /* + * Deny cancellation once the activation round is no longer cancellable. + */ + if (activation_in_progress && + (activation_cancel_locked || activation_skip_cpu_rendezvous)) { + return LFA_BUSY; + } + activator = lfa_components[component_id].activator; if (activator->cancel != NULL) { ret = activator->cancel(¤t_activation); @@ -122,6 +132,10 @@ static int lfa_cancel(uint32_t component_id) ret = plat_lfa_cancel(component_id); if (ret != LFA_SUCCESS) { + /* + * Cancellation can fail when activation cannot be stopped + * (e.g. activation requested with skip_cpu_rendezvous=1). + */ return LFA_BUSY; } @@ -271,6 +285,7 @@ static int lfa_activate_prepare(uint32_t component_id, uint64_t flags, (*activator)->cpu_rendezvous_required; } activation_skip_cpu_rendezvous = false; + activation_cancel_locked = false; } /* * Pass skip_cpu_rendezvous (flag[0]) only if flag[0]==1 @@ -310,6 +325,9 @@ static int lfa_activate_prepare(uint32_t component_id, uint64_t flags, /* Track how many CPUs have entered LFA_ACTIVATE for this round. */ activation_users += 1U; + if (activation_users >= psci_num_cpus_running_on_safe(plat_my_core_pos())) { + activation_cancel_locked = true; + } return LFA_SUCCESS; } @@ -328,6 +346,7 @@ static void lfa_activate_finish(uint32_t component_id, bool activation_complete) if (activation_users == 0U) { activation_in_progress = false; activation_skip_cpu_rendezvous = false; + activation_cancel_locked = false; if (!activation_failed) { lfa_components[component_id].activation_pending = false; } @@ -524,7 +543,14 @@ uint64_t lfa_smc_handler(uint32_t smc_fid, u_register_t x1, u_register_t x2, break; case LFA_CANCEL: + if (!spin_trylock(&lfa_lock)) { + SMC_RET1(handle, LFA_BUSY); + } + ret = lfa_cancel(x1); + + spin_unlock(&lfa_lock); + SMC_RET1(handle, ret); break; |
