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)