feat(lfa): add initial implementation for LFA_ACTIVATE
This patch introduces the overall handling of the LFA_ACTIVATE call,
including input validation and invocation flow.
While this covers the core implementation, per-component-specific
handling will be developed in a separate patch. The respective
component callbacks are invoked as part of this logic.
Change-Id: Ie9d4584fc0c0abc9a9faffed62165b4461efed3a
Signed-off-by: Manish V Badarkhe <Manish.Badarkhe@arm.com>
diff --git a/include/services/lfa_component_desc.h b/include/services/lfa_component_desc.h
index ca3b15e..5f198bd 100644
--- a/include/services/lfa_component_desc.h
+++ b/include/services/lfa_component_desc.h
@@ -19,6 +19,7 @@
struct lfa_component_status {
uint32_t component_id;
lfa_prime_status_t prime_status;
+ bool cpu_rendezvous_required;
};
typedef int32_t (*component_prime_fn)(struct lfa_component_status *activation);
diff --git a/include/services/lfa_svc.h b/include/services/lfa_svc.h
index 26dbb7a..69d549c 100644
--- a/include/services/lfa_svc.h
+++ b/include/services/lfa_svc.h
@@ -57,6 +57,8 @@
#define LFA_MAY_RESET_CPU_SHIFT 2
#define LFA_CPU_RENDEZVOUS_OPTIONAL_SHIFT 3
+#define LFA_SKIP_CPU_RENDEZVOUS_BIT BIT(0)
+
/* List of errors as per the specification */
enum lfa_retc {
LFA_SUCCESS = 0,
diff --git a/services/std_svc/lfa/lfa_main.c b/services/std_svc/lfa/lfa_main.c
index d0d3bf4..1cf65ae 100644
--- a/services/std_svc/lfa/lfa_main.c
+++ b/services/std_svc/lfa/lfa_main.c
@@ -4,6 +4,8 @@
* SPDX-License-Identifier: BSD-3-Clause
*/
+#include <errno.h>
+
#include <plat/common/platform.h>
#include <services/bl31_lfa.h>
#include <services/lfa_svc.h>
@@ -19,6 +21,7 @@
{
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)
@@ -94,6 +97,58 @@
return ret;
}
+static int lfa_activate(uint32_t component_id, uint64_t flags,
+ uint64_t ep_address, uint64_t context_id)
+{
+ int ret = LFA_ACTIVATION_FAILED;
+ struct lfa_component_ops *activator;
+
+ if ((lfa_component_count == 0U) ||
+ (!lfa_components[component_id].activation_pending) ||
+ (current_activation.prime_status != PRIME_COMPLETE)) {
+ 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) {
+ return LFA_NOT_SUPPORTED;
+ }
+
+ 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;
+ }
+ }
+
+ ret = activator->activate(¤t_activation, ep_address,
+ context_id);
+ }
+
+ lfa_components[component_id].activation_pending = false;
+
+ return ret;
+}
+
static int lfa_prime(uint32_t component_id, uint64_t *flags)
{
int ret = LFA_SUCCESS;
@@ -258,6 +313,10 @@
break;
case LFA_ACTIVATE:
+ ret = lfa_activate(fw_seq_id, x2, x3, x4);
+ /* TODO: implement activate again */
+ SMC_RET2(handle, ret, 0ULL);
+
break;
case LFA_CANCEL: