feat(manifest): support FF-A v1.2 direct messages
Add additional messaging method parsing to indicate whether a partition
can send/receive messages via FFA_MSG_SEND_DIRECT_REQ2.
Also enforce that a manifest declaring an FF-A version < FF-A v1.2
cannot declare usage of FFA_MSG_SEND_DIRECT_REQ2.
Signed-off-by: Kathleen Capella <kathleen.capella@arm.com>
Change-Id: I56f8e15dd00f16932ab7059dc585e12a9ca28f09
diff --git a/src/arch/aarch64/hypervisor/other_world.c b/src/arch/aarch64/hypervisor/other_world.c
index 5f80ab3..1457148 100644
--- a/src/arch/aarch64/hypervisor/other_world.c
+++ b/src/arch/aarch64/hypervisor/other_world.c
@@ -31,7 +31,18 @@
/* Enabling all communication methods for the other world. */
other_world_vm->messaging_method =
- FFA_PARTITION_DIRECT_REQ_RECV | FFA_PARTITION_DIRECT_REQ_SEND;
+ FFA_PARTITION_DIRECT_REQ_SEND | FFA_PARTITION_DIRECT_REQ2_SEND;
+
+ /*
+ * If Hafnium is NWd Hypervisor, allow other_world_VM (SPMC) to
+ * receive requests.
+ * When Hafnium is SPMC, other_world_vm not allowed to receive requests
+ * from SPs.
+ */
+#if SECURE_WORLD == 0
+ other_world_vm->messaging_method |= FFA_PARTITION_DIRECT_REQ2_RECV;
+ other_world_vm->messaging_method |= FFA_PARTITION_DIRECT_REQ_RECV;
+#endif
/* Map NS mem ranges to "Other world VM" Stage-2 PTs. */
for (i = 0; i < params->ns_mem_ranges_count; i++) {
diff --git a/src/manifest.c b/src/manifest.c
index 3065c72..6be414a 100644
--- a/src/manifest.c
+++ b/src/manifest.c
@@ -895,6 +895,9 @@
enum manifest_return_code ret_code = MANIFEST_SUCCESS;
const char *error_string = "specified in manifest is unsupported";
uint32_t k = 0;
+ bool using_req2 = (vm->partition.messaging_method &
+ (FFA_PARTITION_DIRECT_REQ2_RECV |
+ FFA_PARTITION_DIRECT_REQ2_SEND)) != 0;
/* ensure that the SPM version is compatible */
ffa_version_major = (vm->partition.ffa_version & 0xffff0000) >>
@@ -929,9 +932,16 @@
ret_code = MANIFEST_ERROR_NOT_COMPATIBLE;
}
+ if (vm->partition.ffa_version < MAKE_FFA_VERSION(1, 2) && using_req2) {
+ dlog_error("Messaging method %s: %x\n", error_string,
+ vm->partition.messaging_method);
+ ret_code = MANIFEST_ERROR_NOT_COMPATIBLE;
+ }
+
if ((vm->partition.messaging_method &
~(FFA_PARTITION_DIRECT_REQ_RECV | FFA_PARTITION_DIRECT_REQ_SEND |
- FFA_PARTITION_INDIRECT_MSG)) != 0U) {
+ FFA_PARTITION_INDIRECT_MSG | FFA_PARTITION_DIRECT_REQ2_RECV |
+ FFA_PARTITION_DIRECT_REQ2_SEND)) != 0U) {
dlog_error("Messaging method %s: %x\n", error_string,
vm->partition.messaging_method);
ret_code = MANIFEST_ERROR_NOT_COMPATIBLE;
@@ -1089,8 +1099,8 @@
vm->partition.rxtx.available = true;
}
- TRY(read_uint8(&root, "messaging-method",
- (uint8_t *)&vm->partition.messaging_method));
+ TRY(read_uint16(&root, "messaging-method",
+ (uint16_t *)&vm->partition.messaging_method));
dlog_verbose(" Messaging method %u\n", vm->partition.messaging_method);
TRY(read_bool(&root, "managed-exit", &managed_exit_field_present));
diff --git a/src/manifest_test.cc b/src/manifest_test.cc
index 3554e47..1adaa0e 100644
--- a/src/manifest_test.cc
+++ b/src/manifest_test.cc
@@ -243,7 +243,7 @@
Property("entrypoint-offset", "<0x00002000>");
Property("xlat-granule", "<0>");
Property("boot-order", "<0>");
- Property("messaging-method", "<4>");
+ Property("messaging-method", "<0x4>");
Property("ns-interrupts-action", "<1>");
return *this;
}
@@ -911,7 +911,29 @@
MANIFEST_ERROR_NOT_COMPATIBLE);
manifest_dealloc();
- /* Incompatible messaging method */
+ /* Incompatible messaging method - unrecognized messaging-method. */
+ /* clang-format off */
+ dtb = ManifestDtBuilder()
+ .Compatible({ "arm,ffa-manifest-1.0" })
+ .Property("ffa-version", "<0x10002>")
+ .Property("uuid", "<0xb4b5671e 0x4a904fe1 0xb81ffb13 0xdae1dacb>")
+ .Property("execution-ctx-count", "<1>")
+ .Property("exception-level", "<2>")
+ .Property("execution-state", "<0>")
+ .Property("entrypoint-offset", "<0x00002000>")
+ .Property("xlat-granule", "<0>")
+ .Property("boot-order", "<0>")
+ .Property("messaging-method", "<0x272>")
+ .Property("ns-interrupts-action", "<0>")
+ .Build();
+ /* clang-format on */
+ ASSERT_EQ(ffa_manifest_from_vec(&m, dtb),
+ MANIFEST_ERROR_NOT_COMPATIBLE);
+ manifest_dealloc();
+
+ /* Incompatible messaging method - only endpoints using FF-A version >=
+ * FF-A v1.2 are allowed to set FFA_PARTITION_DIRECT_REQ2_RECV and
+ * FFA_PARTITION_DIRECT_REQ2_SEND. */
/* clang-format off */
dtb = ManifestDtBuilder()
.Compatible({ "arm,ffa-manifest-1.0" })
@@ -923,7 +945,7 @@
.Property("entrypoint-offset", "<0x00002000>")
.Property("xlat-granule", "<0>")
.Property("boot-order", "<0>")
- .Property("messaging-method", "<16>")
+ .Property("messaging-method", "<0x204>")
.Property("ns-interrupts-action", "<0>")
.Build();
/* clang-format on */
diff --git a/src/vm.c b/src/vm.c
index 8a91a2b..d2f6ce6 100644
--- a/src/vm.c
+++ b/src/vm.c
@@ -955,7 +955,7 @@
/**
* Checks VM's messaging method support.
*/
-bool vm_supports_messaging_method(struct vm *vm, uint8_t msg_method)
+bool vm_supports_messaging_method(struct vm *vm, uint16_t msg_method)
{
return (vm->messaging_method & msg_method) != 0;
}