feat(interrupts): resume interrupted target vCPU

An SP could be interrupted by a NS interrupt whilst handling a direct
message request from another SP. The target SP could send a managed
exit response, if supported.

Consequently, the sender of the direct message request resumes the
target SP by allocating CPU cycles using dummy direct message request.

Signed-off-by: Madhukar Pappireddy <madhukar.pappireddy@arm.com>
Change-Id: I697aeb189da12850af9a1db4c3e3e550b5b36541
diff --git a/spm/cactus/cactus_tests/cactus_test_interrupts.c b/spm/cactus/cactus_tests/cactus_test_interrupts.c
index 31ba7ca..13a5e59 100644
--- a/spm/cactus/cactus_tests/cactus_test_interrupts.c
+++ b/spm/cactus/cactus_tests/cactus_test_interrupts.c
@@ -54,12 +54,34 @@
 
 	ffa_ret = cactus_sleep_cmd(vm_id, fwd_dest, sleep_ms);
 
-	while (ffa_func_id(ffa_ret) == FFA_INTERRUPT) {
-		/* Received FFA_INTERRUPT in blocked state. */
-		VERBOSE("Processing FFA_INTERRUPT while blocked on direct response\n");
-		unsigned int my_core_pos = platform_get_core_pos(read_mpidr_el1());
+	/*
+	 * The target of the direct request could be pre-empted any number of
+	 * times. Moreover, the target SP may or may not support managed exit.
+	 * Hence, the target is allocated cpu cycles in this while loop.
+	 */
+	while ((ffa_func_id(ffa_ret) == FFA_INTERRUPT) ||
+		is_expected_cactus_response(ffa_ret, MANAGED_EXIT_INTERRUPT_ID,
+					    0)) {
 
-		ffa_ret = ffa_run(fwd_dest, my_core_pos);
+		if (ffa_func_id(ffa_ret) == FFA_INTERRUPT) {
+			/* Received FFA_INTERRUPT in blocked state. */
+			VERBOSE("Processing FFA_INTERRUPT while"
+				" blocked on direct response\n");
+			unsigned int my_core_pos =
+				platform_get_core_pos(read_mpidr_el1());
+
+			ffa_ret = ffa_run(fwd_dest, my_core_pos);
+		} else {
+			/*
+			 * Destination sent managed exit response. Allocate
+			 * dummy cycles through direct request message to
+			 * destination SP.
+			 */
+			VERBOSE("SP%x: received Managed Exit as response\n",
+				vm_id);
+			ffa_ret = ffa_msg_send_direct_req64(vm_id, fwd_dest,
+							    0, 0, 0, 0, 0);
+		}
 	}
 
 	if (!is_ffa_direct_response(ffa_ret)) {
@@ -68,7 +90,7 @@
 					 CACTUS_ERROR_FFA_CALL);
 	}
 
-	if (cactus_get_response(ffa_ret) != sleep_ms) {
+	if (cactus_get_response(ffa_ret) < sleep_ms) {
 		ERROR("Request returned: %u ms!\n",
 		      cactus_get_response(ffa_ret));
 		return cactus_error_resp(vm_id, ffa_dir_msg_source(*args),