fix(cactus): memory sharing tests failure MP

The last test to share memory functionality tested the FFA_MEMORY_DONATE
interface. After donating the memory, the original owner didn't update
its stage-1 translation at EL1. Hence, when booting a MP setup, there
would be a data abort, as at stage-2 translation the memory region
is now owned by the receiver of the test.
Share memory region was being allocated part of the BSS section, was
being mapped as a static region in the xlat libraries. A static region
is not meant to be unmapped.
To fix the above points:
- allocated a memory region in the partition manifest of all Cactus SPs
for the sake of the memory sharing tests.
- at stage-1 before using it for the first memory share operation, the
 sender would map its segment as a dynamic region.
- if test included a FFA_MEMORY_DONATE call, after donation the owner
unmaps the memory region from its stage-1 translation.

Signed-off-by: J-Alves <joao.alves@arm.com>
Change-Id: I039c0d0d1633688b0e9d6ba1e2bbebfd518fc72b
diff --git a/spm/cactus/cactus_tests/cactus_test_memory_sharing.c b/spm/cactus/cactus_tests/cactus_test_memory_sharing.c
index 604058a..21df55b 100644
--- a/spm/cactus/cactus_tests/cactus_test_memory_sharing.c
+++ b/spm/cactus/cactus_tests/cactus_test_memory_sharing.c
@@ -5,6 +5,7 @@
  */
 
 #include <cactus_def.h>
+#include <cactus_platform_def.h>
 #include "cactus_message_loop.h"
 #include "cactus_test_cmds.h"
 #include "cactus_tests.h"
@@ -14,8 +15,26 @@
 #include <xlat_tables_defs.h>
 #include <lib/xlat_tables/xlat_tables_v2.h>
 
-/* Memory section to be used for memory share operations */
-static __aligned(PAGE_SIZE) uint8_t share_page[PAGE_SIZE];
+/**
+ * Each Cactus SP has a memory region dedicated to memory sharing tests
+ * described in their partition manifest.
+ * This function returns the expected base address depending on the
+ * SP ID (should be the same as the manifest).
+ */
+static void *share_page(ffa_id_t cactus_sp_id)
+{
+	switch (cactus_sp_id) {
+	case SP_ID(1):
+		return (void *)CACTUS_SP1_MEM_SHARE_BASE;
+	case SP_ID(2):
+		return (void *)CACTUS_SP2_MEM_SHARE_BASE;
+	case SP_ID(3):
+		return (void *)CACTUS_SP3_MEM_SHARE_BASE;
+	default:
+		ERROR("Helper function expecting a valid Cactus SP ID!\n");
+		panic();
+	}
+}
 
 CACTUS_CMD_HANDLER(mem_send_cmd, CACTUS_MEM_SEND_CMD)
 {
@@ -58,7 +77,7 @@
 			mem_attrs);
 
 	if (ret != 0) {
-		ERROR("Failed first mmap_add_dynamic_region!\n");
+		ERROR("Failed to map received memory region(%d)!\n", ret);
 		return cactus_error_resp(vm_id, source, CACTUS_ERROR_TEST);
 	}
 
@@ -111,17 +130,35 @@
 	ffa_memory_handle_t handle;
 	ffa_id_t vm_id = ffa_dir_msg_dest(*args);
 	ffa_id_t source = ffa_dir_msg_source(*args);
+	int ret;
+	static bool share_memory_mapped;
 
-	VERBOSE("%x requested to send memory to %x (func: %x)\n",
-		source, receiver, mem_func);
+	VERBOSE("%x requested to send memory to %x (func: %x), page: %llx\n",
+		source, receiver, mem_func, (uint64_t)share_page(vm_id));
 
 	const struct ffa_memory_region_constituent constituents[] = {
-		{(void *)share_page, 1, 0}
+		{share_page(vm_id), 1, 0}
 	};
 
 	const uint32_t constituents_count = (sizeof(constituents) /
 					     sizeof(constituents[0]));
 
+	if (!share_memory_mapped) {
+		ret = mmap_add_dynamic_region(
+			(uint64_t)constituents[0].address,
+			(uint64_t)constituents[0].address,
+			constituents[0].page_count * PAGE_SIZE,
+			MT_RW_DATA);
+
+		if (ret != 0) {
+			ERROR("Failed map share memory before sending (%d)!\n",
+			      ret);
+			return cactus_error_resp(vm_id, source,
+						 CACTUS_ERROR_TEST);
+		}
+		share_memory_mapped = true;
+	}
+
 	handle = memory_init_and_send(
 		(struct ffa_memory_region *)mb->send, PAGE_SIZE,
 		vm_id, receiver, constituents,
@@ -173,6 +210,16 @@
 				VERBOSE("      %u: %x\n", i, ptr[i]);
 			}
 		#endif
+	} else {
+		ret = mmap_remove_dynamic_region(
+			(uint64_t)constituents[0].address,
+			constituents[0].page_count * PAGE_SIZE);
+
+		if (ret != 0) {
+			ERROR("Failed to unmap donated region (%d)!\n", ret);
+			return cactus_error_resp(vm_id, source,
+						 CACTUS_ERROR_TEST);
+		}
 	}
 
 	return cactus_success_resp(vm_id, source, 0);
diff --git a/spm/cactus/plat/arm/fvp/fdts/cactus-secondary.dts b/spm/cactus/plat/arm/fvp/fdts/cactus-secondary.dts
index 42f05fc..17ace6f 100644
--- a/spm/cactus/plat/arm/fvp/fdts/cactus-secondary.dts
+++ b/spm/cactus/plat/arm/fvp/fdts/cactus-secondary.dts
@@ -56,6 +56,14 @@
 			attributes = <0x3>; /* read-write */
 		};
 
+		/* Memory to be shared in memory sharing tests. */
+		share-memory {
+			description = "share-memory";
+			pages-count = <1>;
+			base-address = <0x00000000 0x7501000>;
+			attributes = <0x3>; /* read-write */
+		};
+
 		/* Without optional base-address */
 		test-memory {
 			description = "test-memory";
diff --git a/spm/cactus/plat/arm/fvp/fdts/cactus-tertiary.dts b/spm/cactus/plat/arm/fvp/fdts/cactus-tertiary.dts
index 38f15fe..88a5c3f 100644
--- a/spm/cactus/plat/arm/fvp/fdts/cactus-tertiary.dts
+++ b/spm/cactus/plat/arm/fvp/fdts/cactus-tertiary.dts
@@ -42,6 +42,14 @@
 			pages-count = <4>;
 			attributes = <0x7>; /* read-write-execute */
 		};
+
+		/* Memory to be shared in memory sharing tests. */
+		share-memory {
+			description = "share-memory";
+			pages-count = <1>;
+			base-address = <0x00000000 0x7502000>;
+			attributes = <0x3>; /* read-write */
+		};
 	};
 
 	device-regions {
diff --git a/spm/cactus/plat/arm/fvp/fdts/cactus.dts b/spm/cactus/plat/arm/fvp/fdts/cactus.dts
index 7d74e1e..759adc4 100644
--- a/spm/cactus/plat/arm/fvp/fdts/cactus.dts
+++ b/spm/cactus/plat/arm/fvp/fdts/cactus.dts
@@ -57,6 +57,14 @@
 			attributes = <0x3>; /* read-write */
 		};
 
+		/* Memory to be shared in memory sharing tests. */
+		share-memory {
+			description = "share-memory";
+			pages-count = <1>;
+			base-address =<0x00000000 0x7500000>;
+			attributes = <0x3>; /* read-write */
+		};
+
 		/* Without optional base-address */
 		test-memory {
 			description = "test-memory";
diff --git a/spm/cactus/plat/arm/fvp/include/cactus_platform_def.h b/spm/cactus/plat/arm/fvp/include/cactus_platform_def.h
index d35194d..c48ce96 100644
--- a/spm/cactus/plat/arm/fvp/include/cactus_platform_def.h
+++ b/spm/cactus/plat/arm/fvp/include/cactus_platform_def.h
@@ -26,4 +26,9 @@
 #define USR_BASE_FRAME			ULL(0x2BFE0000)
 #define PRIV_BASE_FRAME			ULL(0x2BFF0000)
 
+/* Base address for memory sharing tests. */
+#define CACTUS_SP1_MEM_SHARE_BASE 0x7500000
+#define CACTUS_SP2_MEM_SHARE_BASE 0x7501000
+#define CACTUS_SP3_MEM_SHARE_BASE 0x7502000
+
 #endif /* CACTUS_PLATFORM_DEF_H */
diff --git a/spm/cactus/plat/arm/tc0/fdts/cactus-secondary.dts b/spm/cactus/plat/arm/tc0/fdts/cactus-secondary.dts
index fe80433..29add4d 100644
--- a/spm/cactus/plat/arm/tc0/fdts/cactus-secondary.dts
+++ b/spm/cactus/plat/arm/tc0/fdts/cactus-secondary.dts
@@ -53,5 +53,13 @@
 			base-address = <0x00000000 0xfe303000>;
 			attributes = <0x3>; /* read-write */
 		};
+
+		/* Memory to be shared in memory sharing tests. */
+		share-memory {
+			description = "share-memory";
+			pages-count = <1>;
+			base-address =<0x00000000 0xfe501000>;
+			attributes = <0x3>; /* read-write */
+		};
 	};
 };
diff --git a/spm/cactus/plat/arm/tc0/fdts/cactus-tertiary.dts b/spm/cactus/plat/arm/tc0/fdts/cactus-tertiary.dts
index 71cd1ed..c051975 100644
--- a/spm/cactus/plat/arm/tc0/fdts/cactus-tertiary.dts
+++ b/spm/cactus/plat/arm/tc0/fdts/cactus-tertiary.dts
@@ -40,6 +40,14 @@
 			pages-count = <4>;
 			attributes = <0x7>; /* read-write-execute */
 		};
+
+		/* Memory to be shared in memory sharing tests. */
+		share-memory {
+			description = "share-memory";
+			pages-count = <1>;
+			base-address =<0x00000000 0xfe502000>;
+			attributes = <0x3>; /* read-write */
+		};
 	};
 
 	device-regions {
diff --git a/spm/cactus/plat/arm/tc0/fdts/cactus.dts b/spm/cactus/plat/arm/tc0/fdts/cactus.dts
index 142535c..bcf9245 100644
--- a/spm/cactus/plat/arm/tc0/fdts/cactus.dts
+++ b/spm/cactus/plat/arm/tc0/fdts/cactus.dts
@@ -54,6 +54,14 @@
 			base-address = <0x00000000 0xfe301000>;
 			attributes = <0x3>; /* read-write */
 		};
+
+		/* Memory to be shared in memory sharing tests. */
+		share-memory {
+			description = "share-memory";
+			pages-count = <1>;
+			base-address =<0x00000000 0xfe500000>;
+			attributes = <0x3>; /* read-write */
+		};
 	};
 
 	device-regions {
diff --git a/spm/cactus/plat/arm/tc0/include/cactus_platform_def.h b/spm/cactus/plat/arm/tc0/include/cactus_platform_def.h
index 62cb3ed..a972440 100644
--- a/spm/cactus/plat/arm/tc0/include/cactus_platform_def.h
+++ b/spm/cactus/plat/arm/tc0/include/cactus_platform_def.h
@@ -28,4 +28,9 @@
 #define USR_BASE_FRAME			ULL(0x0)
 #define PRIV_BASE_FRAME			ULL(0x0)
 
+/* Base address for memory sharing tests. */
+#define CACTUS_SP1_MEM_SHARE_BASE 0xfe500000
+#define CACTUS_SP2_MEM_SHARE_BASE 0xfe501000
+#define CACTUS_SP3_MEM_SHARE_BASE 0xfe502000
+
 #endif /* CACTUS_PLATFORM_DEF_H */