feat(interrupts): support Other S-Int action field

Secure partitions can request SPMC to queue secure interrupts that
are targetted for other SPs through a new field. This patch adds
support for SPs to specify the field `other-s-interrupts-action` in
their manifest.

Change-Id: I6c68b1b7216c5121d3d8e522ede94a9c291c3403
Signed-off-by: Madhukar Pappireddy <madhukar.pappireddy@arm.com>
diff --git a/inc/hf/manifest.h b/inc/hf/manifest.h
index 3f4cd3e..fb8bfc0 100644
--- a/inc/hf/manifest.h
+++ b/inc/hf/manifest.h
@@ -159,8 +159,6 @@
 	bool notification_support;
 	/** optional */
 	bool has_primary_scheduler;
-	/** optional - preemptible / run to completion */
-	uint8_t runtime_model;
 	/** optional - tuples SEPID/SMMUID/streamId */
 	uint32_t stream_ep_ids[1];
 
@@ -170,6 +168,8 @@
 	/** Device regions */
 	uint16_t dev_region_count;
 	struct device_region dev_regions[PARTITION_MAX_DEVICE_REGIONS];
+	/** optional - action in response to Other-Secure interrupt */
+	uint8_t other_s_interrupts_action;
 };
 
 /**
@@ -232,8 +232,9 @@
 	MANIFEST_ERROR_MEM_REGION_OVERLAP,
 	MANIFEST_ERROR_INVALID_MEM_PERM,
 	MANIFEST_ERROR_INTERRUPT_ID_REPEATED,
-	MANIFEST_ILLEGAL_NS_ACTION,
+	MANIFEST_ERROR_ILLEGAL_NS_INT_ACTION,
 	MANIFEST_ERROR_INTERRUPT_ID_NOT_IN_LIST,
+	MANIFEST_ERROR_ILLEGAL_OTHER_S_INT_ACTION,
 };
 
 enum manifest_return_code manifest_init(struct mm_stage1_locked stage1_locked,
diff --git a/inc/hf/vm.h b/inc/hf/vm.h
index 6dd1584..fbb2946 100644
--- a/inc/hf/vm.h
+++ b/inc/hf/vm.h
@@ -24,6 +24,10 @@
 #define LOG_BUFFER_SIZE 256
 #define VM_MANIFEST_MAX_INTERRUPTS 32
 
+/** Action for Other-Secure interrupts by SPMC. */
+#define OTHER_S_INT_ACTION_QUEUED 0
+#define OTHER_S_INT_ACTION_SIGNALED 1
+
 /**
  * The state of an RX buffer.
  *
@@ -225,6 +229,12 @@
 	 * non secure interrupt.
 	 */
 	uint8_t ns_interrupts_action;
+
+	/**
+	 * Action specified by a Partition through the manifest in response to
+	 * Other-S-Int.
+	 */
+	uint8_t other_s_interrupts_action;
 	bool me_signal_virq;
 	struct vm *next_boot;
 
diff --git a/src/load.c b/src/load.c
index 764e4b9..b815e1e 100644
--- a/src/load.c
+++ b/src/load.c
@@ -213,6 +213,9 @@
 		vm_locked.vm->ns_interrupts_action =
 			manifest_vm->partition.ns_interrupts_action;
 
+		vm_locked.vm->other_s_interrupts_action =
+			manifest_vm->partition.other_s_interrupts_action;
+
 		vm_locked.vm->me_signal_virq =
 			manifest_vm->partition.me_signal_virq;
 
diff --git a/src/manifest.c b/src/manifest.c
index 2eeaf98..bac21a5 100644
--- a/src/manifest.c
+++ b/src/manifest.c
@@ -947,7 +947,7 @@
 	if (vm->partition.ns_interrupts_action != NS_ACTION_QUEUED &&
 	    vm->partition.ns_interrupts_action != NS_ACTION_ME &&
 	    vm->partition.ns_interrupts_action != NS_ACTION_SIGNALED) {
-		return MANIFEST_ILLEGAL_NS_ACTION;
+		return MANIFEST_ERROR_ILLEGAL_NS_INT_ACTION;
 	}
 
 	dlog_verbose(
@@ -964,7 +964,7 @@
 			dlog_error(
 				"Managed exit cannot be supported by this "
 				"partition\n");
-			return MANIFEST_ILLEGAL_NS_ACTION;
+			return MANIFEST_ERROR_ILLEGAL_NS_INT_ACTION;
 		}
 
 		TRY(read_bool(&root, "managed-exit-virq",
@@ -980,6 +980,28 @@
 		dlog_verbose("  Notifications Receipt Supported\n");
 	}
 
+	TRY(read_optional_uint8(
+		&root, "other-s-interrupts-action", OTHER_S_INT_ACTION_SIGNALED,
+		(uint8_t *)&vm->partition.other_s_interrupts_action));
+
+	if (vm->partition.other_s_interrupts_action ==
+	    OTHER_S_INT_ACTION_QUEUED) {
+		if (vm->partition.ns_interrupts_action != NS_ACTION_QUEUED) {
+			dlog_error(
+				"Choice of the fields 'ns-interrupts-action' "
+				"and 'other-s-interrupts-action' not "
+				"compatible\n");
+			return MANIFEST_ERROR_NOT_COMPATIBLE;
+		}
+	} else if (vm->partition.other_s_interrupts_action >
+		   OTHER_S_INT_ACTION_SIGNALED) {
+		dlog_error(
+			"Illegal value specified for the field"
+			" 'other-s-interrupts-action': %u\n",
+			vm->partition.other_s_interrupts_action);
+		return MANIFEST_ERROR_ILLEGAL_OTHER_S_INT_ACTION;
+	}
+
 	/* Parse boot info node. */
 	if (boot_info_node != NULL) {
 		ffa_node = root;
@@ -1242,11 +1264,14 @@
 		return "Arguments-list node should have at least one argument";
 	case MANIFEST_ERROR_INTERRUPT_ID_REPEATED:
 		return "Interrupt ID already assigned to another endpoint";
-	case MANIFEST_ILLEGAL_NS_ACTION:
+	case MANIFEST_ERROR_ILLEGAL_NS_INT_ACTION:
 		return "Illegal value specidied for the field: Action in "
 		       "response to NS Interrupt";
 	case MANIFEST_ERROR_INTERRUPT_ID_NOT_IN_LIST:
 		return "Interrupt ID is not in the list of interrupts";
+	case MANIFEST_ERROR_ILLEGAL_OTHER_S_INT_ACTION:
+		return "Illegal value specified for the field: Action in "
+		       "response to Other-S Interrupt";
 	}
 
 	panic("Unexpected manifest return code.");
diff --git a/src/manifest_test.cc b/src/manifest_test.cc
index b3807ea..6271da6 100644
--- a/src/manifest_test.cc
+++ b/src/manifest_test.cc
@@ -879,11 +879,20 @@
 	/* clang-format on */
 	ASSERT_EQ(ffa_manifest_from_vec(&m, dtb),
 		  MANIFEST_ERROR_NOT_COMPATIBLE);
-	manifest_dealloc();
+
+	/*
+	 * No need to invoke manifest_dealloac() since manifest TearDown calls
+	 * it when the test ends.
+	 */
+}
+
+TEST_F(manifest, ffa_validate_interrupt_actions)
+{
+	struct_manifest *m;
 
 	/* Incompatible NS interrupt action */
 	/* clang-format off */
-	dtb = ManifestDtBuilder()
+	std::vector<char>  dtb = ManifestDtBuilder()
 		.Compatible({ "arm,ffa-manifest-1.0" })
 		.Property("ffa-version", "<0x10000>")
 		.Property("uuid", "<0xb4b5671e 0x4a904fe1 0xb81ffb13 0xdae1dacb>")
@@ -897,7 +906,8 @@
 		.Property("ns-interrupts-action", "<4>")
 		.Build();
 	/* clang-format on */
-	ASSERT_EQ(ffa_manifest_from_vec(&m, dtb), MANIFEST_ILLEGAL_NS_ACTION);
+	ASSERT_EQ(ffa_manifest_from_vec(&m, dtb),
+		  MANIFEST_ERROR_ILLEGAL_NS_INT_ACTION);
 }
 
 TEST_F(manifest, ffa_validate_rxtx_info)