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/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)