refactor(ff-a): direct messaging
Some functions from `src/ffa/{hypervisor,spmc}.c` were missed in the
refactoring.
Move them to `src/ffa/{hypervisor,spmc}/direct_messaging.c`.
Change-Id: Ic0a238fe676c8aa77110f539ccf9cdb9638b85e9
Signed-off-by: Karl Meakin <karl.meakin@arm.com>
diff --git a/inc/hf/ffa.h b/inc/hf/ffa.h
index 1a33d6c..936e2eb 100644
--- a/inc/hf/ffa.h
+++ b/inc/hf/ffa.h
@@ -15,9 +15,4 @@
void plat_ffa_set_tee_enabled(bool tee_enabled);
void plat_ffa_init(struct mpool *ppool);
-bool plat_ffa_is_spmd_lp_id(ffa_id_t vm_id);
-
void plat_save_ns_simd_context(struct vcpu *vcpu);
-
-bool plat_ffa_handle_framework_msg(struct ffa_value args,
- struct ffa_value *ret);
diff --git a/inc/hf/ffa/direct_messaging.h b/inc/hf/ffa/direct_messaging.h
index eb87da8..968a2e9 100644
--- a/inc/hf/ffa/direct_messaging.h
+++ b/inc/hf/ffa/direct_messaging.h
@@ -35,3 +35,8 @@
void ffa_direct_msg_unwind_call_chain_ffa_direct_resp(
struct vcpu_locked current_locked, struct vcpu_locked next_locked);
+
+bool plat_ffa_handle_framework_msg(struct ffa_value args,
+ struct ffa_value *ret);
+
+bool plat_ffa_is_spmd_lp_id(ffa_id_t vm_id);
diff --git a/src/ffa/hypervisor.c b/src/ffa/hypervisor.c
index 1b87bca..07adb9b 100644
--- a/src/ffa/hypervisor.c
+++ b/src/ffa/hypervisor.c
@@ -116,17 +116,3 @@
dlog_verbose("TEE finished setting up buffers.\n");
}
-
-bool plat_ffa_is_spmd_lp_id(ffa_id_t vm_id)
-{
- (void)vm_id;
- return false;
-}
-
-bool plat_ffa_handle_framework_msg(struct ffa_value args, struct ffa_value *ret)
-{
- (void)args;
- (void)ret;
-
- return false;
-}
diff --git a/src/ffa/hypervisor/direct_messaging.c b/src/ffa/hypervisor/direct_messaging.c
index c5b5292..cfa663f 100644
--- a/src/ffa/hypervisor/direct_messaging.c
+++ b/src/ffa/hypervisor/direct_messaging.c
@@ -119,3 +119,17 @@
(void)current_locked;
(void)next_locked;
}
+
+bool plat_ffa_handle_framework_msg(struct ffa_value args, struct ffa_value *ret)
+{
+ (void)args;
+ (void)ret;
+
+ return false;
+}
+
+bool plat_ffa_is_spmd_lp_id(ffa_id_t vm_id)
+{
+ (void)vm_id;
+ return false;
+}
diff --git a/src/ffa/spmc.c b/src/ffa/spmc.c
index 6d28b77..ff69e29 100644
--- a/src/ffa/spmc.c
+++ b/src/ffa/spmc.c
@@ -7,17 +7,14 @@
*/
#include "hf/arch/ffa.h"
-#include "hf/arch/gicv3.h"
#include "hf/arch/sve.h"
#include "hf/api.h"
#include "hf/bits.h"
-#include "hf/check.h"
#include "hf/dlog.h"
#include "hf/ffa.h"
#include "hf/ffa/vm.h"
#include "hf/ffa_internal.h"
-#include "hf/plat/interrupts.h"
#include "hf/vcpu.h"
#include "hf/vm.h"
@@ -40,212 +37,3 @@
arch_ffa_init();
ffa_vm_init(ppool);
}
-
-bool plat_ffa_is_spmd_lp_id(ffa_id_t vm_id)
-{
- return (vm_id >= EL3_SPMD_LP_ID_START && vm_id <= EL3_SPMD_LP_ID_END);
-}
-
-/**
- * Enforce action of an SP in response to non-secure or other-secure interrupt
- * by changing the priority mask. Effectively, physical interrupts shall not
- * trigger which has the same effect as queueing interrupts.
- */
-static void plat_ffa_vcpu_queue_interrupts(
- struct vcpu_locked receiver_vcpu_locked)
-{
- struct vcpu *receiver_vcpu = receiver_vcpu_locked.vcpu;
- uint8_t current_priority;
-
- /* Save current value of priority mask. */
- current_priority = plat_interrupts_get_priority_mask();
- receiver_vcpu->prev_interrupt_priority = current_priority;
-
- if (receiver_vcpu->vm->other_s_interrupts_action ==
- OTHER_S_INT_ACTION_QUEUED ||
- receiver_vcpu->scheduling_mode == SPMC_MODE) {
- /*
- * If secure interrupts not masked yet, mask them now. We could
- * enter SPMC scheduled mode when an EL3 SPMD Logical partition
- * sends a direct request, and we are making the IMPDEF choice
- * to mask interrupts when such a situation occurs. This keeps
- * design simple.
- */
- if (current_priority > SWD_MASK_ALL_INT) {
- plat_interrupts_set_priority_mask(SWD_MASK_ALL_INT);
- }
- } else if (receiver_vcpu->vm->ns_interrupts_action ==
- NS_ACTION_QUEUED) {
- /* If non secure interrupts not masked yet, mask them now. */
- if (current_priority > SWD_MASK_NS_INT) {
- plat_interrupts_set_priority_mask(SWD_MASK_NS_INT);
- }
- }
-}
-
-/**
- * If the interrupts were indeed masked by SPMC before an SP's vCPU was resumed,
- * restore the priority mask thereby allowing the interrupts to be delivered.
- */
-void plat_ffa_vcpu_allow_interrupts(struct vcpu *current)
-{
- plat_interrupts_set_priority_mask(current->prev_interrupt_priority);
-}
-
-/*
- * Start winding the call chain or continue to wind the present one upon the
- * invocation of FFA_MSG_SEND_DIRECT_REQ or FFA_MSG_SEND_DIRECT_REQ2 (FF-A v1.2)
- * ABI.
- */
-void ffa_direct_msg_wind_call_chain_ffa_direct_req(
- struct vcpu_locked current_locked,
- struct vcpu_locked receiver_vcpu_locked, ffa_id_t sender_vm_id)
-{
- struct vcpu *current = current_locked.vcpu;
- struct vcpu *receiver_vcpu = receiver_vcpu_locked.vcpu;
-
- CHECK(receiver_vcpu->scheduling_mode == NONE);
- CHECK(receiver_vcpu->call_chain.prev_node == NULL);
- CHECK(receiver_vcpu->call_chain.next_node == NULL);
- CHECK(receiver_vcpu->rt_model == RTM_NONE);
-
- receiver_vcpu->rt_model = RTM_FFA_DIR_REQ;
-
- if (!vm_id_is_current_world(sender_vm_id)) {
- /* Start of NWd scheduled call chain. */
- receiver_vcpu->scheduling_mode = NWD_MODE;
- } else if (plat_ffa_is_spmd_lp_id(sender_vm_id)) {
- receiver_vcpu->scheduling_mode = SPMC_MODE;
- } else {
- /* Adding a new node to an existing call chain. */
- vcpu_call_chain_extend(current_locked, receiver_vcpu_locked);
- receiver_vcpu->scheduling_mode = current->scheduling_mode;
- }
- plat_ffa_vcpu_queue_interrupts(receiver_vcpu_locked);
-}
-
-/*
- * Unwind the present call chain upon the invocation of
- * FFA_MSG_SEND_DIRECT_RESP ABI. The function also returns
- * the partition ID to which the caller must return to. In
- * case the call chain was started by an SPMD logical
- * partition direct message, at the end of the call chain,
- * we need to return other world's id so that the SPMC can
- * return to the SPMD.
- */
-void ffa_direct_msg_unwind_call_chain_ffa_direct_resp(
- struct vcpu_locked current_locked, struct vcpu_locked next_locked)
-{
- struct vcpu *next = next_locked.vcpu;
- ffa_id_t receiver_vm_id = next->vm->id;
- struct vcpu *current = current_locked.vcpu;
-
- assert(current->call_chain.next_node == NULL);
- current->scheduling_mode = NONE;
- current->rt_model = RTM_NONE;
-
- /* Allow interrupts if they were masked earlier. */
- plat_ffa_vcpu_allow_interrupts(current);
-
- if (!vm_id_is_current_world(receiver_vm_id)) {
- /* End of NWd scheduled call chain. */
- assert(current->call_chain.prev_node == NULL);
- } else {
- /* Removing a node from an existing call chain. */
- vcpu_call_chain_remove_node(current_locked, next_locked);
- }
-}
-
-/**
- * Check that the arguments to a VM availability message are correct.
- * Returns `FFA_SUCCESS_32` if the arguments are correct.
- * Returns `FFA_INVALID_PARAMETERS` if:
- * - the receiver is not a valid VM
- * - the receiver has not subscribed to the message type
- */
-static struct ffa_value check_vm_availability_message(struct ffa_value args)
-{
- struct ffa_value ret = ffa_error(FFA_INVALID_PARAMETERS);
- enum ffa_framework_msg_func func = ffa_framework_msg_func(args);
- ffa_id_t receiver_id = ffa_receiver(args);
- struct vm_locked receiver = vm_find_locked(receiver_id);
-
- if (receiver.vm == NULL) {
- dlog_verbose(
- "VM availability messaging: could not find SP %#x\n",
- receiver_id);
- return ret;
- }
-
- /* only valid if receiver has subscribed */
- if (func == FFA_FRAMEWORK_MSG_VM_CREATION_REQ &&
- !receiver.vm->vm_availability_messages.vm_created) {
- dlog_verbose(
- "VM availability messaging: SP %#x is not subscribed "
- "to VM creation messages\n",
- receiver_id);
- goto out;
- }
-
- if (func == FFA_FRAMEWORK_MSG_VM_DESTRUCTION_REQ &&
- !receiver.vm->vm_availability_messages.vm_destroyed) {
- dlog_verbose(
- "VM availability messaging: SP %#x is not subscribed "
- "to VM destruction messages\n",
- receiver_id);
- goto out;
- }
-
- if (ANY_BITS_SET(args.arg5, FFA_VM_AVAILABILITY_MESSAGE_SBZ_HI,
- FFA_VM_AVAILABILITY_MESSAGE_SBZ_LO)) {
- dlog_warning(
- "VM availability messaging: bits[%u:%u] of w5 are "
- "reserved and should be zero (w5=%#lx)\n",
- FFA_VM_AVAILABILITY_MESSAGE_SBZ_HI,
- FFA_VM_AVAILABILITY_MESSAGE_SBZ_LO, args.arg5);
- }
-
- if (args.arg6 != 0) {
- dlog_warning(
- "VM availability messaging: w6 is reserved and should "
- "be zero (w6=%#lx)\n",
- args.arg6);
- }
-
- if (args.arg7 != 0) {
- dlog_warning(
- "VM availability messaging: w7 is reserved and should "
- "be zero (w7=%#lx)\n",
- args.arg7);
- }
-
- ret = (struct ffa_value){.func = FFA_SUCCESS_32};
-
-out:
-
- vm_unlock(&receiver);
- return ret;
-}
-
-/**
- * Handle framework messages: in particular, check VM availability messages are
- * valid.
- */
-bool plat_ffa_handle_framework_msg(struct ffa_value args, struct ffa_value *ret)
-{
- enum ffa_framework_msg_func func = ffa_framework_msg_func(args);
-
- switch (func) {
- case FFA_FRAMEWORK_MSG_VM_CREATION_REQ:
- case FFA_FRAMEWORK_MSG_VM_DESTRUCTION_REQ:
- *ret = check_vm_availability_message(args);
- if (ret->func != FFA_SUCCESS_32) {
- return true;
- }
- break;
- default:
- break;
- }
-
- return false;
-}
diff --git a/src/ffa/spmc/direct_messaging.c b/src/ffa/spmc/direct_messaging.c
index f76987b..79473bc 100644
--- a/src/ffa/spmc/direct_messaging.c
+++ b/src/ffa/spmc/direct_messaging.c
@@ -8,8 +8,11 @@
#include "hf/ffa/direct_messaging.h"
-#include "hf/ffa.h"
-#include "hf/vm.h"
+#include "hf/arch/gicv3.h"
+
+#include "hf/bits.h"
+#include "hf/ffa_internal.h"
+#include "hf/plat/interrupts.h"
bool ffa_direct_msg_is_direct_request_valid(struct vcpu *current,
ffa_id_t sender_vm_id,
@@ -121,3 +124,212 @@
return false;
}
+
+/**
+ * If the interrupts were indeed masked by SPMC before an SP's vCPU was resumed,
+ * restore the priority mask thereby allowing the interrupts to be delivered.
+ */
+void plat_ffa_vcpu_allow_interrupts(struct vcpu *current)
+{
+ plat_interrupts_set_priority_mask(current->prev_interrupt_priority);
+}
+
+/*
+ * Unwind the present call chain upon the invocation of
+ * FFA_MSG_SEND_DIRECT_RESP ABI. The function also returns
+ * the partition ID to which the caller must return to. In
+ * case the call chain was started by an SPMD logical
+ * partition direct message, at the end of the call chain,
+ * we need to return other world's id so that the SPMC can
+ * return to the SPMD.
+ */
+void ffa_direct_msg_unwind_call_chain_ffa_direct_resp(
+ struct vcpu_locked current_locked, struct vcpu_locked next_locked)
+{
+ struct vcpu *next = next_locked.vcpu;
+ ffa_id_t receiver_vm_id = next->vm->id;
+ struct vcpu *current = current_locked.vcpu;
+
+ assert(current->call_chain.next_node == NULL);
+ current->scheduling_mode = NONE;
+ current->rt_model = RTM_NONE;
+
+ /* Allow interrupts if they were masked earlier. */
+ plat_ffa_vcpu_allow_interrupts(current);
+
+ if (!vm_id_is_current_world(receiver_vm_id)) {
+ /* End of NWd scheduled call chain. */
+ assert(current->call_chain.prev_node == NULL);
+ } else {
+ /* Removing a node from an existing call chain. */
+ vcpu_call_chain_remove_node(current_locked, next_locked);
+ }
+}
+
+/**
+ * Enforce action of an SP in response to non-secure or other-secure interrupt
+ * by changing the priority mask. Effectively, physical interrupts shall not
+ * trigger which has the same effect as queueing interrupts.
+ */
+static void plat_ffa_vcpu_queue_interrupts(
+ struct vcpu_locked receiver_vcpu_locked)
+{
+ struct vcpu *receiver_vcpu = receiver_vcpu_locked.vcpu;
+ uint8_t current_priority;
+
+ /* Save current value of priority mask. */
+ current_priority = plat_interrupts_get_priority_mask();
+ receiver_vcpu->prev_interrupt_priority = current_priority;
+
+ if (receiver_vcpu->vm->other_s_interrupts_action ==
+ OTHER_S_INT_ACTION_QUEUED ||
+ receiver_vcpu->scheduling_mode == SPMC_MODE) {
+ /*
+ * If secure interrupts not masked yet, mask them now. We could
+ * enter SPMC scheduled mode when an EL3 SPMD Logical partition
+ * sends a direct request, and we are making the IMPDEF choice
+ * to mask interrupts when such a situation occurs. This keeps
+ * design simple.
+ */
+ if (current_priority > SWD_MASK_ALL_INT) {
+ plat_interrupts_set_priority_mask(SWD_MASK_ALL_INT);
+ }
+ } else if (receiver_vcpu->vm->ns_interrupts_action ==
+ NS_ACTION_QUEUED) {
+ /* If non secure interrupts not masked yet, mask them now. */
+ if (current_priority > SWD_MASK_NS_INT) {
+ plat_interrupts_set_priority_mask(SWD_MASK_NS_INT);
+ }
+ }
+}
+
+/*
+ * Start winding the call chain or continue to wind the present one upon the
+ * invocation of FFA_MSG_SEND_DIRECT_REQ or FFA_MSG_SEND_DIRECT_REQ2 (FF-A v1.2)
+ * ABI.
+ */
+void ffa_direct_msg_wind_call_chain_ffa_direct_req(
+ struct vcpu_locked current_locked,
+ struct vcpu_locked receiver_vcpu_locked, ffa_id_t sender_vm_id)
+{
+ struct vcpu *current = current_locked.vcpu;
+ struct vcpu *receiver_vcpu = receiver_vcpu_locked.vcpu;
+
+ CHECK(receiver_vcpu->scheduling_mode == NONE);
+ CHECK(receiver_vcpu->call_chain.prev_node == NULL);
+ CHECK(receiver_vcpu->call_chain.next_node == NULL);
+ CHECK(receiver_vcpu->rt_model == RTM_NONE);
+
+ receiver_vcpu->rt_model = RTM_FFA_DIR_REQ;
+
+ if (!vm_id_is_current_world(sender_vm_id)) {
+ /* Start of NWd scheduled call chain. */
+ receiver_vcpu->scheduling_mode = NWD_MODE;
+ } else if (plat_ffa_is_spmd_lp_id(sender_vm_id)) {
+ receiver_vcpu->scheduling_mode = SPMC_MODE;
+ } else {
+ /* Adding a new node to an existing call chain. */
+ vcpu_call_chain_extend(current_locked, receiver_vcpu_locked);
+ receiver_vcpu->scheduling_mode = current->scheduling_mode;
+ }
+ plat_ffa_vcpu_queue_interrupts(receiver_vcpu_locked);
+}
+
+/**
+ * Check that the arguments to a VM availability message are correct.
+ * Returns `FFA_SUCCESS_32` if the arguments are correct.
+ * Returns `FFA_INVALID_PARAMETERS` if:
+ * - the receiver is not a valid VM
+ * - the receiver has not subscribed to the message type
+ */
+static struct ffa_value check_vm_availability_message(struct ffa_value args)
+{
+ struct ffa_value ret = ffa_error(FFA_INVALID_PARAMETERS);
+ enum ffa_framework_msg_func func = ffa_framework_msg_func(args);
+ ffa_id_t receiver_id = ffa_receiver(args);
+ struct vm_locked receiver = vm_find_locked(receiver_id);
+
+ if (receiver.vm == NULL) {
+ dlog_verbose(
+ "VM availability messaging: could not find SP %#x\n",
+ receiver_id);
+ return ret;
+ }
+
+ /* only valid if receiver has subscribed */
+ if (func == FFA_FRAMEWORK_MSG_VM_CREATION_REQ &&
+ !receiver.vm->vm_availability_messages.vm_created) {
+ dlog_verbose(
+ "VM availability messaging: SP %#x is not subscribed "
+ "to VM creation messages\n",
+ receiver_id);
+ goto out;
+ }
+
+ if (func == FFA_FRAMEWORK_MSG_VM_DESTRUCTION_REQ &&
+ !receiver.vm->vm_availability_messages.vm_destroyed) {
+ dlog_verbose(
+ "VM availability messaging: SP %#x is not subscribed "
+ "to VM destruction messages\n",
+ receiver_id);
+ goto out;
+ }
+
+ if (ANY_BITS_SET(args.arg5, FFA_VM_AVAILABILITY_MESSAGE_SBZ_HI,
+ FFA_VM_AVAILABILITY_MESSAGE_SBZ_LO)) {
+ dlog_warning(
+ "VM availability messaging: bits[%u:%u] of w5 are "
+ "reserved and should be zero (w5=%#lx)\n",
+ FFA_VM_AVAILABILITY_MESSAGE_SBZ_HI,
+ FFA_VM_AVAILABILITY_MESSAGE_SBZ_LO, args.arg5);
+ }
+
+ if (args.arg6 != 0) {
+ dlog_warning(
+ "VM availability messaging: w6 is reserved and should "
+ "be zero (w6=%#lx)\n",
+ args.arg6);
+ }
+
+ if (args.arg7 != 0) {
+ dlog_warning(
+ "VM availability messaging: w7 is reserved and should "
+ "be zero (w7=%#lx)\n",
+ args.arg7);
+ }
+
+ ret = (struct ffa_value){.func = FFA_SUCCESS_32};
+
+out:
+
+ vm_unlock(&receiver);
+ return ret;
+}
+
+/**
+ * Handle framework messages: in particular, check VM availability messages are
+ * valid.
+ */
+bool plat_ffa_handle_framework_msg(struct ffa_value args, struct ffa_value *ret)
+{
+ enum ffa_framework_msg_func func = ffa_framework_msg_func(args);
+
+ switch (func) {
+ case FFA_FRAMEWORK_MSG_VM_CREATION_REQ:
+ case FFA_FRAMEWORK_MSG_VM_DESTRUCTION_REQ:
+ *ret = check_vm_availability_message(args);
+ if (ret->func != FFA_SUCCESS_32) {
+ return true;
+ }
+ break;
+ default:
+ break;
+ }
+
+ return false;
+}
+
+bool plat_ffa_is_spmd_lp_id(ffa_id_t vm_id)
+{
+ return (vm_id >= EL3_SPMD_LP_ID_START && vm_id <= EL3_SPMD_LP_ID_END);
+}
diff --git a/src/ffa/spmc/notifications.c b/src/ffa/spmc/notifications.c
index d27c76b..a055e5e 100644
--- a/src/ffa/spmc/notifications.c
+++ b/src/ffa/spmc/notifications.c
@@ -13,6 +13,7 @@
#include "hf/check.h"
#include "hf/cpu.h"
#include "hf/ffa.h"
+#include "hf/ffa/direct_messaging.h"
#include "hf/ffa/vm.h"
#include "hf/ffa_internal.h"
#include "hf/plat/interrupts.h"