test(interrupts): hint fwd destination SP could be interrupted

TFTF can send a hint to the destination SP to expect that the
forwarded sleep command could be preempted by a non-secure interrupt.

This can make the tests exercising SP's response to non-secure
interrupt robust by allowing the destination SP to check if the
forward destination SP has indeed been preempted.

Signed-off-by: Madhukar Pappireddy <madhukar.pappireddy@arm.com>
Change-Id: I808ee6c63687438d0092a53389f11bf9b3dd532d
diff --git a/include/runtime_services/cactus_test_cmds.h b/include/runtime_services/cactus_test_cmds.h
index d86aa61..bbf0187 100644
--- a/include/runtime_services/cactus_test_cmds.h
+++ b/include/runtime_services/cactus_test_cmds.h
@@ -301,15 +301,17 @@
  *
  * The sender of this command expects to receive CACTUS_SUCCESS if the requested
  * echo interaction happened successfully, or CACTUS_ERROR otherwise.
+ * Moreover, the sender can send a hint to the destination SP to expect that
+ * the forwaded sleep command could be preempted by a non-secure interrupt.
  */
 #define CACTUS_FWD_SLEEP_CMD (CACTUS_SLEEP_CMD + 1)
 
 static inline struct ffa_value cactus_fwd_sleep_cmd(
 	ffa_id_t source, ffa_id_t dest, ffa_id_t fwd_dest,
-	uint32_t sleep_time)
+	uint32_t sleep_time, bool hint_interrupted)
 {
 	return cactus_send_cmd(source, dest, CACTUS_FWD_SLEEP_CMD, sleep_time,
-			       fwd_dest, 0, 0);
+			       fwd_dest, hint_interrupted, 0);
 }
 
 static inline uint32_t cactus_get_sleep_time(struct ffa_value ret)
@@ -322,6 +324,11 @@
 	return (ffa_id_t)ret.arg5;
 }
 
+static inline bool cactus_get_fwd_sleep_interrupted_hint(struct ffa_value ret)
+{
+	return (bool)ret.arg6;
+}
+
 /**
  * Command to request cactus to sleep for half the given time in ms, trigger
  * trusted watchdog timer and then sleep again for another half the given time.
diff --git a/spm/cactus/cactus_tests/cactus_test_interrupts.c b/spm/cactus/cactus_tests/cactus_test_interrupts.c
index 13a5e59..c438050 100644
--- a/spm/cactus/cactus_tests/cactus_test_interrupts.c
+++ b/spm/cactus/cactus_tests/cactus_test_interrupts.c
@@ -48,6 +48,8 @@
 	ffa_id_t vm_id = ffa_dir_msg_dest(*args);
 	ffa_id_t fwd_dest = cactus_get_fwd_sleep_dest(*args);
 	uint32_t sleep_ms = cactus_get_sleep_time(*args);
+	bool hint_interrupted = cactus_get_fwd_sleep_interrupted_hint(*args);
+	bool fwd_dest_interrupted;
 
 	VERBOSE("VM%x requested %x to sleep for value %u\n",
 		ffa_dir_msg_source(*args), fwd_dest, sleep_ms);
@@ -62,6 +64,7 @@
 	while ((ffa_func_id(ffa_ret) == FFA_INTERRUPT) ||
 		is_expected_cactus_response(ffa_ret, MANAGED_EXIT_INTERRUPT_ID,
 					    0)) {
+		fwd_dest_interrupted = true;
 
 		if (ffa_func_id(ffa_ret) == FFA_INTERRUPT) {
 			/* Received FFA_INTERRUPT in blocked state. */
@@ -84,6 +87,13 @@
 		}
 	}
 
+	if (hint_interrupted && !fwd_dest_interrupted) {
+		ERROR("Forwaded destination of the sleep command was not"
+		      " interrupted as anticipated\n");
+		return cactus_error_resp(vm_id, ffa_dir_msg_source(*args),
+					 CACTUS_ERROR_TEST);
+	}
+
 	if (!is_ffa_direct_response(ffa_ret)) {
 		ERROR("Encountered error in CACTUS_FWD_SLEEP_CMD response\n");
 		return cactus_error_resp(vm_id, ffa_dir_msg_source(*args),
diff --git a/tftf/tests/runtime_services/secure_service/test_ffa_interrupts.c b/tftf/tests/runtime_services/secure_service/test_ffa_interrupts.c
index 0aaf5e3..fa850c7 100644
--- a/tftf/tests/runtime_services/secure_service/test_ffa_interrupts.c
+++ b/tftf/tests/runtime_services/secure_service/test_ffa_interrupts.c
@@ -299,7 +299,7 @@
 	 * SP to sleep.
 	 */
 	ret_values = cactus_fwd_sleep_cmd(SENDER, RECEIVER, RECEIVER_3,
-					  SLEEP_TIME_FWD);
+					  SLEEP_TIME_FWD, true);
 
 	if (!is_ffa_direct_response(ret_values)) {
 		return TEST_RESULT_FAIL;
@@ -401,7 +401,7 @@
 	 * SP to sleep.
 	 */
 	ret_values = cactus_fwd_sleep_cmd(SENDER, RECEIVER, RECEIVER_2,
-					  SLEEP_TIME_FWD);
+					  SLEEP_TIME_FWD, true);
 
 	if (!is_ffa_direct_response(ret_values)) {
 		return TEST_RESULT_FAIL;
@@ -508,7 +508,7 @@
 	 */
 	VERBOSE("Forward sleep command\n");
 	ret_values = cactus_fwd_sleep_cmd(SENDER, RECEIVER_2, RECEIVER,
-					  SLEEP_TIME_FWD);
+					  SLEEP_TIME_FWD, true);
 
 	if (check_timer_interrupt() == 0) {
 		ERROR("Timer interrupt hasn't actually been handled.\n");
diff --git a/tftf/tests/runtime_services/secure_service/test_ffa_secure_interrupts.c b/tftf/tests/runtime_services/secure_service/test_ffa_secure_interrupts.c
index ac19c06..89c9b40 100644
--- a/tftf/tests/runtime_services/secure_service/test_ffa_secure_interrupts.c
+++ b/tftf/tests/runtime_services/secure_service/test_ffa_secure_interrupts.c
@@ -320,7 +320,7 @@
 	 * SP to sleep
 	 */
 	ret_values = cactus_fwd_sleep_cmd(SENDER, RECEIVER, RECEIVER_2,
-					 SP_SLEEP_TIME);
+					 SP_SLEEP_TIME, false);
 
 	/*
 	 * Secure interrupt should trigger during this time, Cactus
@@ -380,7 +380,7 @@
  *    deactivate HVC and invoke FFA_MSG_WAIT ABI to perform interrupt signal
  *    completion.
  *
- * 7. SPM then resumes the second SP which was pre-empted by secure interrupt.
+ * 7. SPM then resumes the second SP which was preempted by secure interrupt.
  *
  * 8. Second SP will complete the busy sleep loop and send a direct response
  *    message with the elapsed time back to the first SP.