feat(fvp): spmd logical partition smc handler

This patch adds a basic el3 spmd logical partition to the fvp platform
via a platform specific smc handler. One of the use cases for el3
logical partitions is to have the ability to translate sip calls into
ff-a direct requests via the use of spmd logical partitions. The smc
handler creates a direct request based on the incoming smc parameters
and forwards the call as a direct request from the spmd logical
partition to the target secure partition.

Change-Id: If8ba9aab8203924bd00fc1dcdf9cd05a9a04a147
diff --git a/include/services/el3_spmd_logical_sp.h b/include/services/el3_spmd_logical_sp.h
index 670474a..1f9ef0d 100644
--- a/include/services/el3_spmd_logical_sp.h
+++ b/include/services/el3_spmd_logical_sp.h
@@ -156,4 +156,13 @@
 				 void *handle,
 				 struct ffa_value *retval);
 
+uintptr_t plat_spmd_logical_sp_smc_handler(unsigned int smc_fid,
+		u_register_t x1,
+		u_register_t x2,
+		u_register_t x3,
+		u_register_t x4,
+		void *cookie,
+		void *handle,
+		u_register_t flags);
+
 #endif /* EL3_SPMD_LOGICAL_SP_H */
diff --git a/plat/arm/board/fvp/fvp_spmd_logical_sp.c b/plat/arm/board/fvp/fvp_spmd_logical_sp.c
index 4f8ce1e..37b4466 100644
--- a/plat/arm/board/fvp/fvp_spmd_logical_sp.c
+++ b/plat/arm/board/fvp/fvp_spmd_logical_sp.c
@@ -14,12 +14,81 @@
 /* SPMD Logical SP currently only supports sending direct message. */
 #define SPMD_PARTITION_PROPERTIES FFA_PARTITION_DIRECT_REQ_SEND
 
+#define SPMD_LP_MAX_SUPPORTED_SP 10
+static void fvp_get_partition_info(void)
+{
+	struct ffa_value ret = { 0 };
+	uint32_t target_uuid[4] = { 0 };
+	static struct ffa_partition_info_v1_1
+		part_info[SPMD_LP_MAX_SUPPORTED_SP] = { 0 };
+
+	uint16_t num_partitions = 0;
+
+	if (!spmd_el3_invoke_partition_info_get(target_uuid, 0, 0, &ret)) {
+		panic();
+	}
+
+	if (is_ffa_error(&ret)) {
+		panic();
+	}
+
+	num_partitions = ffa_partition_info_regs_get_last_idx(ret) + 1;
+	if (num_partitions > SPMD_LP_MAX_SUPPORTED_SP) {
+		panic();
+	}
+
+	INFO("Number of secure partitions = %d\n", num_partitions);
+
+	for (uint16_t i = 0; i < num_partitions; i++) {
+		INFO("***Start Partition***\n");
+		if (!ffa_partition_info_regs_get_part_info(ret, i, &part_info[i]))
+			panic();
+		INFO("\tPartition ID: 0x%x\n", part_info[i].ep_id);
+		INFO("\tvCPU count:0x%x\n", part_info[i].execution_ctx_count);
+		INFO("\tProperties: 0x%x\n", part_info[i].properties);
+		INFO("\tUUID: 0x%x 0x%x 0x%x 0x%x\n", part_info[i].uuid[0],
+				part_info[i].uuid[1], part_info[i].uuid[2],
+				part_info[i].uuid[3]);
+		INFO("***End Partition***\n");
+	}
+
+}
+
 static int32_t fvp_spmd_logical_partition_init(void)
 {
 	INFO("FVP SPMD LSP: Init function called.\n");
+
+	fvp_get_partition_info();
 	return 0;
 }
 
+/*
+ * Platform specific SMC handler used to translate SIP SMCs or other platform
+ * specific SMCs into FF-A direct messages.
+ */
+uintptr_t plat_spmd_logical_sp_smc_handler(unsigned int smc_fid,
+			u_register_t x1,
+			u_register_t x2,
+			u_register_t x3,
+			u_register_t x4,
+			void *cookie,
+			void *handle,
+			u_register_t flags)
+{
+	struct ffa_value retval = { 0 };
+	uint64_t send_recv_id = SPMD_LP_PARTITION_ID << 16 | 0x8001;
+
+	/*
+	 * Forward the SMC as direct request.
+	 */
+	if (!spmd_el3_ffa_msg_direct_req(send_recv_id, x2, x3, x4, handle, &retval)) {
+		panic();
+	}
+
+	SMC_RET8(handle, retval.func, retval.arg1, retval.arg2, retval.arg3,
+			retval.arg4, retval.arg5, retval.arg6, retval.arg7);
+}
+
 /* Register SPMD logical partition  */
 DECLARE_SPMD_LOGICAL_PARTITION(
 	fvp_spmd_logical_partition,
diff --git a/plat/arm/common/arm_sip_svc.c b/plat/arm/common/arm_sip_svc.c
index af8a02f..7c3e13d 100644
--- a/plat/arm/common/arm_sip_svc.c
+++ b/plat/arm/common/arm_sip_svc.c
@@ -13,6 +13,9 @@
 #include <lib/pmf/pmf.h>
 #include <plat/arm/common/arm_sip_svc.h>
 #include <plat/arm/common/plat_arm.h>
+#if ENABLE_SPMD_LP
+#include <services/el3_spmd_logical_sp.h>
+#endif
 #include <tools_share/uuid.h>
 
 /* ARM SiP Service UUID */
@@ -133,8 +136,13 @@
 		SMC_RET2(handle, ARM_SIP_SVC_VERSION_MAJOR, ARM_SIP_SVC_VERSION_MINOR);
 
 	default:
+#if ENABLE_SPMD_LP
+		return plat_spmd_logical_sp_smc_handler(smc_fid, x1, x2, x3, x4,
+				cookie, handle, flags);
+#else
 		WARN("Unimplemented ARM SiP Service Call: 0x%x \n", smc_fid);
 		SMC_RET1(handle, SMC_UNK);
+#endif
 	}
 
 }