test: add SP helpers for reconfiguring interrupt

These helpers are useful in creating a test to exercise the newly
introduced paravirtualized ABI that allows an SP to reconfigure
an interrupt in runtime.

Signed-off-by: Madhukar Pappireddy <madhukar.pappireddy@arm.com>
Change-Id: If7096a3a653a65af0a1d820d11aeb18495ce6505
diff --git a/inc/vmapi/hf/call.h b/inc/vmapi/hf/call.h
index 98d1b3f..552dffe 100644
--- a/inc/vmapi/hf/call.h
+++ b/inc/vmapi/hf/call.h
@@ -426,6 +426,25 @@
 		       intid);
 }
 
+/**
+ * Reconfigure the virtual interrupt belonging to the current SP. Note that the
+ * virtual interrupt is identity mapped to the physical interrupt id.
+ *
+ * Returns -1 on failure, or 0 on success.
+ */
+static inline int64_t hf_interrupt_reconfigure(uint32_t intid, uint32_t command,
+					       uint32_t value)
+{
+	return hf_call(HF_INTERRUPT_RECONFIGURE, intid, command, value);
+}
+
+static inline int64_t hf_interrupt_reconfigure_target_cpu(
+	uint32_t intid, ffa_vcpu_index_t target_cpu_index)
+{
+	return hf_interrupt_reconfigure(intid, INT_RECONFIGURE_TARGET_PE,
+					(uint32_t)target_cpu_index);
+}
+
 /** Obtains the Hafnium's version of the implemented FF-A specification. */
 static inline int32_t ffa_version(uint32_t requested_version)
 {
diff --git a/test/vmapi/ffa_secure_partitions/services/arch/aarch64/secure/inc/partition_services.h b/test/vmapi/ffa_secure_partitions/services/arch/aarch64/secure/inc/partition_services.h
index e39e6a1..9dd1df8 100644
--- a/test/vmapi/ffa_secure_partitions/services/arch/aarch64/secure/inc/partition_services.h
+++ b/test/vmapi/ffa_secure_partitions/services/arch/aarch64/secure/inc/partition_services.h
@@ -354,6 +354,20 @@
 struct ffa_value sp_get_last_interrupt_cmd(ffa_id_t source);
 
 /**
+ * Request SP to clear the last serviced secure virtual interrupt.
+ */
+#define SP_CLEAR_LAST_INTERRUPT_CMD (SP_LAST_INTERRUPT_SERVICED_CMD + 1)
+
+static inline struct ffa_value sp_clear_last_interrupt_cmd_send(ffa_id_t source,
+								ffa_id_t dest)
+{
+	return ffa_msg_send_direct_req(source, dest,
+				       SP_CLEAR_LAST_INTERRUPT_CMD, 0, 0, 0, 0);
+}
+
+struct ffa_value sp_clear_last_interrupt_cmd(ffa_id_t source);
+
+/**
  * Command to request SP to sleep for the given time in ms.
  *
  * The command id is the hex representation of string "slep".
@@ -462,3 +476,22 @@
 
 struct ffa_value sp_yield_secure_interrupt_handling_cmd(ffa_id_t source,
 							bool yield);
+
+/**
+ * Command to request an SP to reconfigure the secure interrupt to be targetted
+ * to a given vCPU identified by its linear id.
+ * The command id is the hex representaton of the string "RSTV".
+ */
+#define SP_ROUTE_SEC_INT_TARGET_VCPU_CMD 0x52535456U
+
+static inline struct ffa_value sp_route_interrupt_to_target_vcpu_cmd_send(
+	ffa_id_t source, ffa_id_t dest, ffa_vcpu_index_t target_vcpu_id,
+	uint32_t int_id)
+{
+	return ffa_msg_send_direct_req(source, dest,
+				       SP_ROUTE_SEC_INT_TARGET_VCPU_CMD,
+				       target_vcpu_id, int_id, 0, 0);
+}
+
+struct ffa_value sp_route_interrupt_to_target_vcpu_cmd(
+	ffa_id_t source, ffa_vcpu_index_t target_vcpu_id, uint32_t int_id);
diff --git a/test/vmapi/ffa_secure_partitions/services/arch/aarch64/secure/message_loop.c b/test/vmapi/ffa_secure_partitions/services/arch/aarch64/secure/message_loop.c
index 1b090bf..35d4b17 100644
--- a/test/vmapi/ffa_secure_partitions/services/arch/aarch64/secure/message_loop.c
+++ b/test/vmapi/ffa_secure_partitions/services/arch/aarch64/secure/message_loop.c
@@ -75,6 +75,9 @@
 	case SP_LAST_INTERRUPT_SERVICED_CMD:
 		res = sp_get_last_interrupt_cmd(ffa_sender(res));
 		break;
+	case SP_CLEAR_LAST_INTERRUPT_CMD:
+		res = sp_clear_last_interrupt_cmd(ffa_sender(res));
+		break;
 	case SP_SLEEP_CMD:
 		res = sp_sleep_cmd(ffa_sender(res), sp_get_sleep_time(res));
 		break;
@@ -90,6 +93,11 @@
 		res = sp_yield_secure_interrupt_handling_cmd(ffa_sender(res),
 							     res.arg4);
 		break;
+	case SP_ROUTE_SEC_INT_TARGET_VCPU_CMD:
+		res = sp_route_interrupt_to_target_vcpu_cmd(
+			ffa_sender(res), (ffa_vcpu_index_t)res.arg4,
+			(uint32_t)res.arg5);
+		break;
 	default:
 		HFTEST_LOG_FAILURE();
 		HFTEST_LOG(HFTEST_LOG_INDENT
diff --git a/test/vmapi/ffa_secure_partitions/services/arch/aarch64/secure/secure_interrupts.c b/test/vmapi/ffa_secure_partitions/services/arch/aarch64/secure/secure_interrupts.c
index 59c1741..703889b 100644
--- a/test/vmapi/ffa_secure_partitions/services/arch/aarch64/secure/secure_interrupts.c
+++ b/test/vmapi/ffa_secure_partitions/services/arch/aarch64/secure/secure_interrupts.c
@@ -146,6 +146,14 @@
 			  exception_handler_get_last_interrupt());
 }
 
+struct ffa_value sp_clear_last_interrupt_cmd(ffa_id_t test_source)
+{
+	ffa_id_t own_id = hf_vm_get_id();
+
+	exception_handler_set_last_interrupt(HF_INVALID_INTID);
+	return sp_success(own_id, test_source, 0);
+}
+
 static bool is_expected_sp_response(struct ffa_value ret,
 				    uint32_t expected_resp, uint32_t arg)
 {
@@ -249,3 +257,19 @@
 	yield_while_handling_sec_interrupt = yield;
 	return sp_success(own_id, source, 0);
 }
+
+struct ffa_value sp_route_interrupt_to_target_vcpu_cmd(
+	ffa_id_t source, ffa_vcpu_index_t target_vcpu_id, uint32_t int_id)
+{
+	ffa_id_t own_id = hf_vm_get_id();
+
+	/* Change target vCPU for the trusted watchdog interrupt. */
+	if (hf_interrupt_reconfigure_target_cpu(int_id, target_vcpu_id) == 0) {
+		return sp_success(own_id, source, 0);
+	}
+
+	HFTEST_LOG(
+		"Request to route trusted wdog interrupt to target vCPU "
+		"denied\n");
+	return sp_error(own_id, source, 0);
+}