fix(ffa): add check for 'Address Range Alignemnt Hint'

FFA_MEM_RETRIEVE_REQ ABI defines a 'Address Range Alignment Hint'
which is curently not supported by Hafnium.

Adding a check to ensure the field is 0, returning
FFA_INVALID_PARAMETERS otherwise.

Improving the already existing `ffa_validate_retrieve_req_mbz` unit
test to take into account this field as well.

Change-Id: I1827b929c7b5a26cd874b5984c7de198f1d6be25
Signed-off-by: Federico Recanati <federico.recanati@arm.com>
diff --git a/inc/vmapi/hf/ffa.h b/inc/vmapi/hf/ffa.h
index 82c742e..e7a626c 100644
--- a/inc/vmapi/hf/ffa.h
+++ b/inc/vmapi/hf/ffa.h
@@ -616,6 +616,9 @@
 #define FFA_MEMORY_REGION_TRANSACTION_TYPE_LEND ((0x2U) << 3)
 #define FFA_MEMORY_REGION_TRANSACTION_TYPE_DONATE ((0x3U) << 3)
 
+#define FFA_MEMORY_REGION_ADDRESS_RANGE_HINT_VALID ((0x1U) << 9)
+#define FFA_MEMORY_REGION_ADDRESS_RANGE_HINT_MASK ((0xFU) << 5)
+
 /**
  * This corresponds to table 42 of the FF-A 1.0 EAC specification, "Endpoint
  * memory access descriptor".
diff --git a/src/ffa_memory.c b/src/ffa_memory.c
index f51bbd8..d68636c 100644
--- a/src/ffa_memory.c
+++ b/src/ffa_memory.c
@@ -1460,6 +1460,7 @@
 			*permissions);
 		return ffa_error(FFA_INVALID_PARAMETERS);
 	}
+
 	if (share_func == FFA_MEM_DONATE_32 &&
 	    data_access != FFA_DATA_ACCESS_NOT_SPECIFIED) {
 		dlog_verbose(
@@ -2250,6 +2251,23 @@
 		goto out;
 	}
 
+	if ((retrieve_request->flags &
+	     FFA_MEMORY_REGION_ADDRESS_RANGE_HINT_VALID) != 0) {
+		dlog_verbose(
+			"Retriever specified 'address range alignment hint'"
+			" not supported.\n");
+		ret = ffa_error(FFA_INVALID_PARAMETERS);
+		goto out;
+	}
+	if ((retrieve_request->flags &
+	     FFA_MEMORY_REGION_ADDRESS_RANGE_HINT_MASK) != 0) {
+		dlog_verbose(
+			"Bits 8-5 must be zero in memory region's flags "
+			"(address range alignment hint not supported).\n");
+		ret = ffa_error(FFA_INVALID_PARAMETERS);
+		goto out;
+	}
+
 	if ((retrieve_request->flags & ~0x7FF) != 0U) {
 		dlog_verbose(
 			"Bits 31-10 must be zero in memory region's flags.\n");
diff --git a/test/vmapi/primary_with_secondaries/memory_sharing.c b/test/vmapi/primary_with_secondaries/memory_sharing.c
index c8de2bc..66b9b5e 100644
--- a/test/vmapi/primary_with_secondaries/memory_sharing.c
+++ b/test/vmapi/primary_with_secondaries/memory_sharing.c
@@ -2192,6 +2192,13 @@
 	SERVICE_SELECT(SERVICE_VM1, "ffa_memory_share_fail_invalid_parameters",
 		       mb.send);
 
+	unsigned invalid_flags[] = {
+		0xFFFFFFFF, /* Incorrect transaction type [4:3]*/
+		0xFFFFFFE0, /* Unsupported address range limit hint [9] */
+		0xFFFFFDE0, /* [8:5] MBZ when not asking for address range */
+		0xFFFFFC00  /* [31:10] MBZ */
+	};
+
 	for (unsigned int i = 0; i < ARRAY_SIZE(send_function); i++) {
 		/* Prepare memory region, and set all flags */
 		EXPECT_EQ(ffa_memory_region_init(
@@ -2210,21 +2217,24 @@
 
 		handle = ffa_mem_success_handle(ret);
 
-		msg_size = ffa_memory_retrieve_request_init(
-			mb.send, handle, HF_PRIMARY_VM_ID, SERVICE_VM1, 0,
-			0xFFFFFFFF, FFA_DATA_ACCESS_RW,
-			FFA_INSTRUCTION_ACCESS_NOT_SPECIFIED,
-			FFA_MEMORY_NORMAL_MEM, FFA_MEMORY_CACHE_WRITE_BACK,
-			FFA_MEMORY_INNER_SHAREABLE);
+		for (unsigned int j = 0; j < ARRAY_SIZE(invalid_flags); ++j) {
+			msg_size = ffa_memory_retrieve_request_init(
+				mb.send, handle, HF_PRIMARY_VM_ID, SERVICE_VM1,
+				0, invalid_flags[j], FFA_DATA_ACCESS_RW,
+				FFA_INSTRUCTION_ACCESS_NOT_SPECIFIED,
+				FFA_MEMORY_NORMAL_MEM,
+				FFA_MEMORY_CACHE_WRITE_BACK,
+				FFA_MEMORY_INNER_SHAREABLE);
 
-		EXPECT_LE(msg_size, HF_MAILBOX_SIZE);
+			EXPECT_LE(msg_size, HF_MAILBOX_SIZE);
 
-		EXPECT_EQ(
-			ffa_msg_send(HF_PRIMARY_VM_ID, SERVICE_VM1, msg_size, 0)
-				.func,
-			FFA_SUCCESS_32);
+			EXPECT_EQ(ffa_msg_send(HF_PRIMARY_VM_ID, SERVICE_VM1,
+					       msg_size, 0)
+					  .func,
+				  FFA_SUCCESS_32);
 
-		ffa_run(SERVICE_VM1, 0);
+			ffa_run(SERVICE_VM1, 0);
+		}
 
 		EXPECT_EQ(ffa_mem_reclaim(handle, 0).func, FFA_SUCCESS_32);
 	}