feat: FFA_FEATURES update for FF-A v1.1 features
Update to handling of FFA_FEATURES to encompass:
- Notifications func IDs.
- Query of interrupt IDs for Schedule Receiver Interrupt, Notification
Pending Interrupt, and Managed Exit Interrupt.
- Tests to FFA_FEATURES to validate aforementioned points.
Change-Id: If6810ea222ce30e40ab0d004e3631ca9fae316a8
Signed-off-by: J-Alves <joao.alves@arm.com>
diff --git a/src/api.c b/src/api.c
index e353bd9..21bec1d 100644
--- a/src/api.c
+++ b/src/api.c
@@ -1811,12 +1811,32 @@
}
/**
+ * Helper for success return of FFA_FEATURES, for when it is used to query
+ * an interrupt ID.
+ */
+struct ffa_value api_ffa_feature_success(uint32_t arg2)
+{
+ return (struct ffa_value){
+ .func = FFA_SUCCESS_32, .arg1 = 0U, .arg2 = arg2};
+}
+
+/**
* Discovery function returning information about the implementation of optional
* FF-A interfaces.
*/
-struct ffa_value api_ffa_features(uint32_t function_id)
+struct ffa_value api_ffa_features(uint32_t feature_function_id)
{
- switch (function_id) {
+ /*
+ * According to table 13.8 of FF-A v1.1 Beta 0 spec, bits [30:8] MBZ
+ * if using a feature ID.
+ */
+ if ((feature_function_id & FFA_FEATURES_FUNC_ID_MASK) == 0U &&
+ (feature_function_id & ~FFA_FEATURES_FEATURE_ID_MASK) != 0) {
+ return ffa_error(FFA_NOT_SUPPORTED);
+ }
+
+ switch (feature_function_id) {
+ /* Check support of the given Function ID. */
case FFA_ERROR_32:
case FFA_SUCCESS_32:
case FFA_INTERRUPT_32:
@@ -1843,10 +1863,26 @@
#if (MAKE_FFA_VERSION(1, 1) <= FFA_VERSION_COMPILED)
/* FF-A v1.1 features. */
case FFA_SPM_ID_GET_32:
+ case FFA_NOTIFICATION_BITMAP_CREATE_32:
+ case FFA_NOTIFICATION_BITMAP_DESTROY_32:
+ case FFA_NOTIFICATION_BIND_32:
+ case FFA_NOTIFICATION_UNBIND_32:
+ case FFA_NOTIFICATION_SET_32:
+ case FFA_NOTIFICATION_GET_32:
+ case FFA_NOTIFICATION_INFO_GET_64:
#endif
return (struct ffa_value){.func = FFA_SUCCESS_32};
+
+#if (MAKE_FFA_VERSION(1, 1) <= FFA_VERSION_COMPILED)
+ /* Check support of a feature provided respective feature ID. */
+ case FFA_FEATURE_NPI:
+ return api_ffa_feature_success(HF_NOTIFICATION_PENDING_INTID);
+ case FFA_FEATURE_SRI:
+ return api_ffa_feature_success(HF_SCHEDULE_RECEIVER_INTID);
+#endif
+ /* Platform specific feature support. */
default:
- return arch_ffa_features(function_id);
+ return arch_ffa_features(feature_function_id);
}
}
@@ -2833,9 +2869,9 @@
vm_get_vcpu(receiver_locked.vm, vcpu_id);
dlog_verbose("Per-vCPU notification, pending NPI.\n");
- internal_interrupt_inject(
- target_vcpu, HF_NOTIFICATION_PENDING_INTERRUPT_INTID,
- current, NULL);
+ internal_interrupt_inject(target_vcpu,
+ HF_NOTIFICATION_PENDING_INTID,
+ current, NULL);
}
ret = (struct ffa_value){.func = FFA_SUCCESS_32};
diff --git a/src/arch/aarch64/hypervisor/ffa.c b/src/arch/aarch64/hypervisor/ffa.c
index 363ac85..b74cabb 100644
--- a/src/arch/aarch64/hypervisor/ffa.c
+++ b/src/arch/aarch64/hypervisor/ffa.c
@@ -20,9 +20,9 @@
/**
* Returns information for features with arch specific implementation.
*/
-struct ffa_value arch_ffa_features(uint32_t function_id)
+struct ffa_value arch_ffa_features(uint32_t function_feature_id)
{
- return plat_ffa_features(function_id);
+ return plat_ffa_features(function_feature_id);
}
/**
diff --git a/src/arch/aarch64/plat/ffa/absent.c b/src/arch/aarch64/plat/ffa/absent.c
index 1aafad2..df0ccb2 100644
--- a/src/arch/aarch64/plat/ffa/absent.c
+++ b/src/arch/aarch64/plat/ffa/absent.c
@@ -11,9 +11,9 @@
#include "hf/vcpu.h"
#include "hf/vm.h"
-struct ffa_value plat_ffa_features(uint32_t function_id)
+struct ffa_value plat_ffa_features(uint32_t function_feature_id)
{
- (void)function_id;
+ (void)function_feature_id;
return ffa_error(FFA_NOT_SUPPORTED);
}
diff --git a/src/arch/aarch64/plat/ffa/hypervisor.c b/src/arch/aarch64/plat/ffa/hypervisor.c
index b4f6df9..86407c2 100644
--- a/src/arch/aarch64/plat/ffa/hypervisor.c
+++ b/src/arch/aarch64/plat/ffa/hypervisor.c
@@ -28,9 +28,9 @@
alignas(FFA_PAGE_SIZE) static uint8_t other_world_recv_buffer[HF_MAILBOX_SIZE];
/** Returns information on features specific to the NWd. */
-struct ffa_value plat_ffa_features(uint32_t function_id)
+struct ffa_value plat_ffa_features(uint32_t function_feature_id)
{
- switch (function_id) {
+ switch (function_feature_id) {
case FFA_MSG_POLL_32:
case FFA_YIELD_32:
case FFA_MSG_SEND_32:
diff --git a/src/arch/aarch64/plat/ffa/spmc.c b/src/arch/aarch64/plat/ffa/spmc.c
index 8b272b9..7f4c4e1 100644
--- a/src/arch/aarch64/plat/ffa/spmc.c
+++ b/src/arch/aarch64/plat/ffa/spmc.c
@@ -107,11 +107,23 @@
}
/** Returns information on features specific to the SWd. */
-struct ffa_value plat_ffa_features(uint32_t function_id)
+struct ffa_value plat_ffa_features(uint32_t function_feature_id)
{
- (void)function_id;
+ struct ffa_value ret;
+
+ switch (function_feature_id) {
+#if (MAKE_FFA_VERSION(1, 1) <= FFA_VERSION_COMPILED)
+ case FFA_FEATURE_MEI:
+ ret = api_ffa_feature_success(HF_MANAGED_EXIT_INTID);
+ break;
+#endif
+ default:
+ ret = ffa_error(FFA_NOT_SUPPORTED);
+ break;
+ }
+
/* There are no features only supported in the SWd */
- return ffa_error(FFA_NOT_SUPPORTED);
+ return ret;
}
struct ffa_value plat_ffa_spmc_id_get(void)
@@ -1118,9 +1130,9 @@
static void plat_ffa_send_schedule_receiver_interrupt(struct cpu *cpu)
{
dlog_verbose("Setting Schedule Receiver SGI %d on core: %d\n",
- FFA_SCHEDULE_RECEIVER_INTERRUPT_ID, cpu_index(cpu));
+ HF_SCHEDULE_RECEIVER_INTID, cpu_index(cpu));
- plat_interrupts_send_sgi(FFA_SCHEDULE_RECEIVER_INTERRUPT_ID, false,
+ plat_interrupts_send_sgi(HF_SCHEDULE_RECEIVER_INTID, false,
(1 << cpu_index(cpu)), false);
}
@@ -1161,7 +1173,7 @@
/* TODO: when supported, make the interrupt driver use cpu structure. */
(void)cpu;
- interrupt_desc_set_id(&sri_desc, FFA_SCHEDULE_RECEIVER_INTERRUPT_ID);
+ interrupt_desc_set_id(&sri_desc, HF_SCHEDULE_RECEIVER_INTID);
interrupt_desc_set_priority(&sri_desc, SRI_PRIORITY);
interrupt_desc_set_valid(&sri_desc, true);
@@ -1198,8 +1210,7 @@
struct vcpu_locked next_locked = vcpu_lock(next);
api_interrupt_inject_locked(
- next_locked,
- HF_NOTIFICATION_PENDING_INTERRUPT_INTID,
+ next_locked, HF_NOTIFICATION_PENDING_INTID,
current, NULL);
vcpu_unlock(&next_locked);