feat(spmd): add spmd logical partitions

Add header file to help with creation of SPMD logical partitions. Also
update linker files to create sections to record SPMD logical partitions
declared. This follows the same pattern as the EL3 SPMC's logical
partitions. This patch also adds initialization of SPMD logical
partitions when the SPMD comes up.
ENABLE_SPMD_LP is a build flag that is used to enable support for
SPMD logical partitions.
Note that the approach chosen is to keep SPMD and SPMC logical
partition support separate, as opposed to extend the existing SPMC
logical partition support since the code would need to have a number of
ifdefs and the interactions with various build options such as
SPMC_AT_EL3 needs to be accounted for, which would make code more
complicated.

Signed-off-by: Raghu Krishnamurthy <raghu.ncstate@gmail.com>
Change-Id: I9642ddbf6ea26dd3f4a283baec598d61c07e3661
diff --git a/include/common/bl_common.h b/include/common/bl_common.h
index 539280e..4c8a17c 100644
--- a/include/common/bl_common.h
+++ b/include/common/bl_common.h
@@ -85,6 +85,10 @@
 #define __EL3_LP_DESCS_START__		Load$$__EL3_LP_DESCS__$$Base
 #define __EL3_LP_DESCS_END__		Load$$__EL3_LP_DESCS__$$Limit
 #endif
+#if ENABLE_SPMD_LP
+#define __SPMD_LP_DESCS_START__	Load$$__SPMD_LP_DESCS__$$Base
+#define __SPMD_LP_DESCS_END__		Load$$__SPMD_LP_DESCS__$$Limit
+#endif
 #define __RW_START__			Load$$LR$$LR_RW_DATA$$Base
 #define __RW_END__			Load$$LR$$LR_END$$Base
 #define __SPM_SHIM_EXCEPTIONS_START__	Load$$__SPM_SHIM_EXCEPTIONS__$$Base
diff --git a/include/common/bl_common.ld.h b/include/common/bl_common.ld.h
index c9bed1a..b6dd0f0 100644
--- a/include/common/bl_common.ld.h
+++ b/include/common/bl_common.ld.h
@@ -49,6 +49,15 @@
 #define EL3_LP_DESCS
 #endif
 
+#if ENABLE_SPMD_LP
+#define SPMD_LP_DESCS					\
+	. = ALIGN(STRUCT_ALIGN);			\
+	__SPMD_LP_DESCS_START__ = .;			\
+	KEEP(*(.spmd_lp_descs))			\
+	__SPMD_LP_DESCS_END__ = .;
+#else
+#define SPMD_LP_DESCS
+#endif
 #define PMF_SVC_DESCS					\
 	. = ALIGN(STRUCT_ALIGN);			\
 	__PMF_SVC_DESCS_START__ = .;			\
@@ -100,7 +109,8 @@
 	CPU_OPS						\
 	GOT						\
 	BASE_XLAT_TABLE_RO				\
-	EL3_LP_DESCS
+	EL3_LP_DESCS					\
+	SPMD_LP_DESCS
 
 /*
  * .data must be placed at a lower address than the stacks if the stack
diff --git a/include/services/el3_spmd_logical_sp.h b/include/services/el3_spmd_logical_sp.h
new file mode 100644
index 0000000..4725c15
--- /dev/null
+++ b/include/services/el3_spmd_logical_sp.h
@@ -0,0 +1,63 @@
+/*
+ * Copyright (c) 2023, ARM Limited and Contributors. All rights reserved.
+ * SPDX-License-Identifier: BSD-3-Clause
+ */
+#ifndef EL3_SPMD_LOGICAL_SP_H
+#define EL3_SPMD_LOGICAL_SP_H
+
+#include <common/bl_common.h>
+#include <lib/cassert.h>
+#include <services/ffa_svc.h>
+
+/*******************************************************************************
+ * Structure definition, typedefs & constants for the SPMD Logical Partitions.
+ ******************************************************************************/
+
+/* Prototype for SPMD logical partition initializing function. */
+typedef int32_t (*ffa_spmd_lp_init_t)(void);
+
+/* SPMD Logical Partition Descriptor. */
+struct spmd_lp_desc {
+	ffa_spmd_lp_init_t init;
+	uint16_t sp_id;
+	uint32_t properties;
+	uint32_t uuid[4];  /* Little Endian. */
+	const char *debug_name;
+};
+
+/* Convenience macro to declare a SPMD logical partition descriptor. */
+#define DECLARE_SPMD_LOGICAL_PARTITION(_name, _init, _sp_id, _uuid, _properties) \
+	static const struct spmd_lp_desc __partition_desc_ ## _name	    \
+		__section(".spmd_lp_descs") __used = {			    \
+			.debug_name = #_name,				    \
+			.init = (_init),				    \
+			.sp_id = (_sp_id),				    \
+			.uuid = _uuid,					    \
+			.properties = (_properties),			    \
+		}
+
+IMPORT_SYM(uintptr_t, __SPMD_LP_DESCS_START__,	SPMD_LP_DESCS_START);
+IMPORT_SYM(uintptr_t, __SPMD_LP_DESCS_END__,	SPMD_LP_DESCS_END);
+
+#define SPMD_LP_DESCS_COUNT ((SPMD_LP_DESCS_END - SPMD_LP_DESCS_START) \
+			  / sizeof(struct spmd_lp_desc))
+CASSERT(sizeof(struct spmd_lp_desc) == 40, assert_spmd_lp_desc_size_mismatch);
+
+/*
+ * Reserve 63 IDs for SPMD Logical Partitions. Currently, 0xFFC0 to 0xFFFE
+ * is reserved.
+ */
+#define SPMD_LP_ID_END		(SPMD_DIRECT_MSG_ENDPOINT_ID - 1)
+#define SPMD_LP_ID_START	(SPMD_LP_ID_END - 62)
+
+static inline bool is_spmd_lp_id(unsigned int id)
+{
+	return (id >= SPMD_LP_ID_START && id <= SPMD_LP_ID_END);
+}
+
+void spmd_logical_sp_set_spmc_initialized(void);
+void spmc_logical_sp_set_spmc_failure(void);
+
+int32_t spmd_logical_sp_init(void);
+
+#endif /* EL3_SPMD_LOGICAL_SP_H */