fix: check support of direct requests messaging

The FF-A partitions have the supported messaging method configured in
their respective manifest.
This patch adds a check to the sender and receiver support of the
messaging method in the handler of FFA_MSG_SEND_DIRECT_REQ.

Change-Id: Ib3f844caef158ece2ac78fbd477e245f4d690b9c
Signed-off-by: J-Alves <joao.alves@arm.com>
diff --git a/inc/hf/arch/plat/ffa.h b/inc/hf/arch/plat/ffa.h
index ee2a3cc..60a02d7 100644
--- a/inc/hf/arch/plat/ffa.h
+++ b/inc/hf/arch/plat/ffa.h
@@ -64,6 +64,8 @@
 bool plat_ffa_is_direct_response_valid(struct vcpu *current,
 				       ffa_vm_id_t sender_vm_id,
 				       ffa_vm_id_t receiver_vm_id);
+bool plat_ffa_is_direct_request_supported(struct vm *sender_vm,
+					  struct vm *receiver_vm);
 bool plat_ffa_direct_request_forward(ffa_vm_id_t receiver_vm_id,
 				     struct ffa_value args,
 				     struct ffa_value *ret);
diff --git a/inc/hf/vm.h b/inc/hf/vm.h
index 7469113..70cbe2b 100644
--- a/inc/hf/vm.h
+++ b/inc/hf/vm.h
@@ -308,3 +308,4 @@
 			       uint32_t *ids_count, uint32_t *lists_sizes,
 			       uint32_t *lists_count,
 			       const uint32_t ids_max_count);
+bool vm_supports_messaging_method(struct vm *vm, uint8_t messaging_method);
diff --git a/src/api.c b/src/api.c
index 8ce4136..911b1ad 100644
--- a/src/api.c
+++ b/src/api.c
@@ -2074,6 +2074,14 @@
 	}
 
 	/*
+	 * Check if sender supports sending direct message req, and if
+	 * receiver supports receipt of direct message requests.
+	 */
+	if (!plat_ffa_is_direct_request_supported(current->vm, receiver_vm)) {
+		return ffa_error(FFA_DENIED);
+	}
+
+	/*
 	 * Per PSA FF-A EAC spec section 4.4.1 the firmware framework supports
 	 * UP (migratable) or MP partitions with a number of vCPUs matching the
 	 * number of PEs in the system. It further states that MP partitions
diff --git a/src/arch/aarch64/hypervisor/other_world.c b/src/arch/aarch64/hypervisor/other_world.c
index 775f33c..652b645 100644
--- a/src/arch/aarch64/hypervisor/other_world.c
+++ b/src/arch/aarch64/hypervisor/other_world.c
@@ -35,6 +35,10 @@
 		goto out;
 	}
 
+	/* Enabling all communication methods for the other world. */
+	other_world_vm->messaging_method =
+		FFA_PARTITION_DIRECT_REQ_RECV | FFA_PARTITION_DIRECT_REQ_SEND;
+
 	ret = true;
 
 out:
diff --git a/src/arch/aarch64/plat/ffa/absent.c b/src/arch/aarch64/plat/ffa/absent.c
index 15fd844..c6a7d4c 100644
--- a/src/arch/aarch64/plat/ffa/absent.c
+++ b/src/arch/aarch64/plat/ffa/absent.c
@@ -55,6 +55,15 @@
 	return false;
 }
 
+bool plat_ffa_is_direct_request_supported(struct vm *sender_vm,
+					  struct vm *receiver_vm)
+{
+	(void)sender_vm;
+	(void)receiver_vm;
+
+	return false;
+}
+
 /**
  * Check validity of a FF-A direct message response.
  */
diff --git a/src/arch/aarch64/plat/ffa/hypervisor.c b/src/arch/aarch64/plat/ffa/hypervisor.c
index d1f4607..b7361fb 100644
--- a/src/arch/aarch64/plat/ffa/hypervisor.c
+++ b/src/arch/aarch64/plat/ffa/hypervisor.c
@@ -174,6 +174,19 @@
 	return false;
 }
 
+bool plat_ffa_is_direct_request_supported(struct vm *sender_vm,
+					  struct vm *receiver_vm)
+{
+	(void)sender_vm;
+	(void)receiver_vm;
+
+	/*
+	 * As Hypervisor is only meant to be used as a test artifact, allow
+	 * direct messaging for all VMs.
+	 */
+	return true;
+}
+
 /**
  * Check validity of a FF-A direct message response.
  */
diff --git a/src/arch/aarch64/plat/ffa/spmc.c b/src/arch/aarch64/plat/ffa/spmc.c
index 4e0074a..b24ed8a 100644
--- a/src/arch/aarch64/plat/ffa/spmc.c
+++ b/src/arch/aarch64/plat/ffa/spmc.c
@@ -189,6 +189,30 @@
 }
 
 /**
+ * Check that the receiver supports receipt of direct requests, and that the
+ * sender supports sending direct messaging requests, in accordance to their
+ * respective configurations at the partition's FF-A manifest.
+ */
+bool plat_ffa_is_direct_request_supported(struct vm *sender_vm,
+					  struct vm *receiver_vm)
+{
+	if (!vm_supports_messaging_method(sender_vm,
+					  FFA_PARTITION_DIRECT_REQ_SEND)) {
+		dlog_verbose("Sender can't send direct message requests.\n");
+		return false;
+	}
+
+	if (!vm_supports_messaging_method(receiver_vm,
+					  FFA_PARTITION_DIRECT_REQ_RECV)) {
+		dlog_verbose(
+			"Receiver can't receive direct message requests.\n");
+		return false;
+	}
+
+	return true;
+}
+
+/**
  * Check validity of a FF-A direct message response.
  */
 bool plat_ffa_is_direct_response_valid(struct vcpu *current,
diff --git a/src/arch/fake/hypervisor/ffa.c b/src/arch/fake/hypervisor/ffa.c
index d043c6e..91bebd4 100644
--- a/src/arch/fake/hypervisor/ffa.c
+++ b/src/arch/fake/hypervisor/ffa.c
@@ -40,6 +40,15 @@
 	return true;
 }
 
+bool plat_ffa_is_direct_request_supported(struct vm *sender_vm,
+					  struct vm *receiver_vm)
+{
+	(void)sender_vm;
+	(void)receiver_vm;
+
+	return false;
+}
+
 bool plat_ffa_is_direct_response_valid(struct vcpu *current,
 				       ffa_vm_id_t sender_vm_id,
 				       ffa_vm_id_t receiver_vm_id)
diff --git a/src/vm.c b/src/vm.c
index 43a52f2..159c08f 100644
--- a/src/vm.c
+++ b/src/vm.c
@@ -899,3 +899,11 @@
 	 */
 	return current_state == FULL;
 }
+
+/**
+ * Checks VM's messaging method support.
+ */
+bool vm_supports_messaging_method(struct vm *vm, uint8_t msg_method)
+{
+	return (vm->messaging_method & msg_method) != 0;
+}
diff --git a/test/vmapi/el0_partitions/secure_partitions/partition-manifest-nwd-primary.dts b/test/vmapi/el0_partitions/secure_partitions/partition-manifest-nwd-primary.dts
index c75206d..e10e815 100644
--- a/test/vmapi/el0_partitions/secure_partitions/partition-manifest-nwd-primary.dts
+++ b/test/vmapi/el0_partitions/secure_partitions/partition-manifest-nwd-primary.dts
@@ -21,5 +21,5 @@
   load-address = <0x90000000>;
   entrypoint-offset = <0x1000>;
   xlat-granule = <0>; /* 4KiB */
-  messaging-method = <0>; /* Direct messaging only */
+  messaging-method = <0x3>; /* Direct messaging only */
 };
diff --git a/test/vmapi/el0_partitions/secure_partitions/partition_manifest_primary_sel1_sp.dts b/test/vmapi/el0_partitions/secure_partitions/partition_manifest_primary_sel1_sp.dts
index c0c61e6..d82406a 100644
--- a/test/vmapi/el0_partitions/secure_partitions/partition_manifest_primary_sel1_sp.dts
+++ b/test/vmapi/el0_partitions/secure_partitions/partition_manifest_primary_sel1_sp.dts
@@ -21,6 +21,6 @@
   load-address = <0x6280000>;
   entrypoint-offset = <0x1000>;
   xlat-granule = <0>; /* 4KiB */
-  messaging-method = <0>; /* Direct messaging only */
+  messaging-method = <0x3>; /* Direct messaging only */
   boot-order = <1>;
 };
diff --git a/test/vmapi/el0_partitions/secure_partitions/partition_manifest_sel0_sp1.dts b/test/vmapi/el0_partitions/secure_partitions/partition_manifest_sel0_sp1.dts
index f439f23..eeeceae 100644
--- a/test/vmapi/el0_partitions/secure_partitions/partition_manifest_sel0_sp1.dts
+++ b/test/vmapi/el0_partitions/secure_partitions/partition_manifest_sel0_sp1.dts
@@ -21,6 +21,6 @@
   load-address = <0x6290000>;
   entrypoint-offset = <0x1000>;
   xlat-granule = <0>; /* 4KiB */
-  messaging-method = <0>; /* Direct messaging only */
+  messaging-method = <0x3>; /* Direct messaging only */
   boot-order = <1>;
 };
diff --git a/test/vmapi/ffa_secure_partitions/partition_manifest_nwd_primary.dts b/test/vmapi/ffa_secure_partitions/partition_manifest_nwd_primary.dts
index 07567d9..a5ebc77 100644
--- a/test/vmapi/ffa_secure_partitions/partition_manifest_nwd_primary.dts
+++ b/test/vmapi/ffa_secure_partitions/partition_manifest_nwd_primary.dts
@@ -21,6 +21,6 @@
 	load-address = <0x90000000>;
 	entrypoint-offset = <0x1000>;
 	xlat-granule = <0>; /* 4KiB */
-	messaging-method = <0>; /* Direct messaging only */
+	messaging-method = <0x3>; /* Supports sending/receiving direct requests. */
 	notification-support; /* Receipt of notifications. */
 };
diff --git a/test/vmapi/ffa_secure_partitions/partition_manifest_services_secondary_sp.dts b/test/vmapi/ffa_secure_partitions/partition_manifest_services_secondary_sp.dts
index 436ba96..a85e01f 100644
--- a/test/vmapi/ffa_secure_partitions/partition_manifest_services_secondary_sp.dts
+++ b/test/vmapi/ffa_secure_partitions/partition_manifest_services_secondary_sp.dts
@@ -21,7 +21,7 @@
 	load-address = <0x6480000>;
 	entrypoint-offset = <0x1000>;
 	xlat-granule = <0>; /* 4KiB */
-	messaging-method = <0>; /* Direct messaging only */
+	messaging-method = <0x3>; /* Supports sending/receiving direct requests. */
 	boot-order = <3>;
 	notification-support; /* Receipt of notifications. */
 };
diff --git a/test/vmapi/ffa_secure_partitions/partition_manifest_services_sp.dts b/test/vmapi/ffa_secure_partitions/partition_manifest_services_sp.dts
index 01c2c64..9160604 100644
--- a/test/vmapi/ffa_secure_partitions/partition_manifest_services_sp.dts
+++ b/test/vmapi/ffa_secure_partitions/partition_manifest_services_sp.dts
@@ -21,7 +21,7 @@
 	load-address = <0x6380000>;
 	entrypoint-offset = <0x1000>;
 	xlat-granule = <0>; /* 4KiB */
-	messaging-method = <0>; /* Direct messaging only */
+	messaging-method = <0x3>; /* Supports sending/receiving direct requests. */
 	boot-order = <1>; /* This should be the highest priority partition */
 	notification-support; /* Receipt of notifications. */
 };