feat(scheduled mode): unwind call chain for FFA_MSG_SEND_DIRECT_RESP

This patch performs the action of unwinding the SP call chain upon
FFA_MSG_SEND_DIRECT_RESP invocation.

Change-Id: I26d1ecae2d4c0d21f8780eff0b99f355ea910914
Signed-off-by: Madhukar Pappireddy <madhukar.pappireddy@arm.com>
diff --git a/src/api.c b/src/api.c
index ab9aa5b..e61c7a6 100644
--- a/src/api.c
+++ b/src/api.c
@@ -2741,6 +2741,8 @@
 		panic("Invalid direct message response invocation");
 	}
 
+	plat_ffa_unwind_call_chain_ffa_direct_resp(current, *next);
+
 	return (struct ffa_value){.func = FFA_INTERRUPT_32};
 }
 
diff --git a/src/arch/aarch64/plat/ffa/absent.c b/src/arch/aarch64/plat/ffa/absent.c
index 6825931..be8c458 100644
--- a/src/arch/aarch64/plat/ffa/absent.c
+++ b/src/arch/aarch64/plat/ffa/absent.c
@@ -478,3 +478,10 @@
 	(void)current_locked;
 	(void)receiver_vcpu_locked;
 }
+
+void plat_ffa_unwind_call_chain_ffa_direct_resp(struct vcpu *current,
+						struct vcpu *next)
+{
+	(void)current;
+	(void)next;
+}
diff --git a/src/arch/aarch64/plat/ffa/hypervisor.c b/src/arch/aarch64/plat/ffa/hypervisor.c
index 8ca0321..467a37a 100644
--- a/src/arch/aarch64/plat/ffa/hypervisor.c
+++ b/src/arch/aarch64/plat/ffa/hypervisor.c
@@ -982,3 +982,11 @@
 	(void)current_locked;
 	(void)receiver_vcpu_locked;
 }
+
+void plat_ffa_unwind_call_chain_ffa_direct_resp(struct vcpu *current,
+						struct vcpu *next)
+{
+	/* Calls chains not supported in the Hypervisor/VMs. */
+	(void)current;
+	(void)next;
+}
diff --git a/src/arch/aarch64/plat/ffa/spmc.c b/src/arch/aarch64/plat/ffa/spmc.c
index c1e46da..dff129d 100644
--- a/src/arch/aarch64/plat/ffa/spmc.c
+++ b/src/arch/aarch64/plat/ffa/spmc.c
@@ -1904,3 +1904,31 @@
 		receiver_vcpu->scheduling_mode = current->scheduling_mode;
 	}
 }
+
+/*
+ * Unwind the present call chain upon the invocation of
+ * FFA_MSG_SEND_DIRECT_RESP ABI.
+ */
+void plat_ffa_unwind_call_chain_ffa_direct_resp(struct vcpu *current,
+						struct vcpu *next)
+{
+	ffa_vm_id_t receiver_vm_id = next->vm->id;
+
+	/* Lock both vCPUs at once. */
+	vcpu_lock_both(current, next);
+
+	assert(current->call_chain.next_node == NULL);
+	current->scheduling_mode = NONE;
+	current->rt_model = RTM_NONE;
+
+	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, next);
+	}
+
+	sl_unlock(&next->lock);
+	sl_unlock(&current->lock);
+}
diff --git a/src/arch/fake/hypervisor/ffa.c b/src/arch/fake/hypervisor/ffa.c
index 3a9e8dd..2983ef3 100644
--- a/src/arch/fake/hypervisor/ffa.c
+++ b/src/arch/fake/hypervisor/ffa.c
@@ -449,3 +449,11 @@
 	(void)current_locked;
 	(void)receiver_vcpu_locked;
 }
+
+void plat_ffa_unwind_call_chain_ffa_direct_resp(struct vcpu *current,
+						struct vcpu *next)
+{
+	/* Calls chains not supported in the Hypervisor/VMs. */
+	(void)current;
+	(void)next;
+}