TFTF: Add support for FVP platforms with SMT capabilities

This patch adds support for Simultaneously MultiThreaded (SMT)
cores on FVP models. Number of threads per CPU is passed in
FVP_MAX_PE_PER_CPU build parameter which can be set either to
1 or 2. This option defaults to 1.

Signed-off-by: Alexei Fedorov <Alexei.Fedorov@arm.com>
Change-Id: Ib0e2afe429e8f24b8a74ad6ee98750ed1ac121fb
diff --git a/docs/user-guide.rst b/docs/user-guide.rst
index 2e6f7ba..d6e1ae5 100644
--- a/docs/user-guide.rst
+++ b/docs/user-guide.rst
@@ -430,6 +430,12 @@
    platform makefile is free to override this value if Firmware Update is
    supported on this platform.
 
+Arm FVP platform specific build options
+'''''''''''''''''''''''''''''''''''''''
+
+-  ``FVP_MAX_PE_PER_CPU``: Sets the maximum number of PEs implemented on any CPU
+   in the system. It can take either 1 or 2 values. This option defaults to 1.
+
 Checking source code style
 --------------------------
 
diff --git a/el3_payload/Makefile b/el3_payload/Makefile
index 984f60d..188731c 100644
--- a/el3_payload/Makefile
+++ b/el3_payload/Makefile
@@ -1,9 +1,25 @@
 #
-# Copyright (c) 2018, Arm Limited. All rights reserved.
+# Copyright (c) 2018-2019, Arm Limited. All rights reserved.
 #
 # SPDX-License-Identifier: BSD-3-Clause
 #
 
+# Default number of threads per CPU on FVP
+FVP_MAX_PE_PER_CPU	:= 1
+
+# Check the PE per core count
+ifneq ($(FVP_MAX_PE_PER_CPU),$(filter $(FVP_MAX_PE_PER_CPU),1 2))
+$(error "Incorrect FVP_MAX_PE_PER_CPU specified for FVP port")
+endif
+
+# Convenience function for adding build definitions
+# $(eval $(call add_define,BAR_DEFINES,FOO)) will have:
+# -DFOO if $(FOO) is empty; -DFOO=$(FOO) otherwise
+# inside the BAR_DEFINES variable.
+define add_define
+$(1) += -D$(2)$(if $(value $(2)),=$(value $(2)),)
+endef
+
 CC		:=	${CROSS_COMPILE}gcc
 AS		:=	${CROSS_COMPILE}as
 LD		:=	${CROSS_COMPILE}ld
@@ -27,6 +43,9 @@
 
 include plat/${PLAT}/platform.mk
 
+# Pass FVP_MAX_PE_PER_CPU to the build system
+$(eval $(call add_define,ASFLAGS,FVP_MAX_PE_PER_CPU))
+
 all: ${BIN}
 
 ${PLAT_BUILD_DIR}:
diff --git a/el3_payload/plat/fvp/platform.h b/el3_payload/plat/fvp/platform.h
index 809ae7e..657b9db 100644
--- a/el3_payload/plat/fvp/platform.h
+++ b/el3_payload/plat/fvp/platform.h
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2018, Arm Limited. All rights reserved.
+ * Copyright (c) 2018-2019, Arm Limited. All rights reserved.
  *
  * SPDX-License-Identifier: BSD-3-Clause
  */
@@ -15,7 +15,5 @@
 #define UART_BASE		0x1c090000
 
 #define FVP_MAX_CPUS_PER_CLUSTER        4
-/* Currently multi-threaded CPUs only have a single thread */
-#define FVP_MAX_PE_PER_CPU              1
 
 #endif /* __PLATFORM_H__ */
diff --git a/include/lib/tftf_lib.h b/include/lib/tftf_lib.h
index 3f60fec..091497a 100644
--- a/include/lib/tftf_lib.h
+++ b/include/lib/tftf_lib.h
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2018, Arm Limited. All rights reserved.
+ * Copyright (c) 2018-2019, Arm Limited. All rights reserved.
  *
  * SPDX-License-Identifier: BSD-3-Clause
  */
@@ -195,7 +195,12 @@
 unsigned int tftf_is_rebooted(void);
 
 static inline unsigned int make_mpid(unsigned int clusterid,
+#if FVP_MAX_PE_PER_CPU > 1
+				     unsigned int coreid,
+				     unsigned int threadid)
+#else
 				     unsigned int coreid)
+#endif
 {
 	/*
 	 * If MT bit is set then need to shift the affinities and also set the
@@ -203,11 +208,14 @@
 	 */
 	if ((read_mpidr_el1() & MPIDR_MT_MASK) != 0)
 		return MPIDR_MT_MASK |
-			((clusterid & MPIDR_AFFLVL_MASK) << MPIDR_AFF2_SHIFT) |
-			((coreid & MPIDR_AFFLVL_MASK) << MPIDR_AFF1_SHIFT);
+#if FVP_MAX_PE_PER_CPU > 1
+			((threadid & MPIDR_AFFLVL_MASK) << MPIDR_AFF0_SHIFT) |
+#endif
+			((coreid & MPIDR_AFFLVL_MASK) << MPIDR_AFF1_SHIFT)   |
+			((clusterid & MPIDR_AFFLVL_MASK) << MPIDR_AFF2_SHIFT);
 	else
-		return ((clusterid & MPIDR_AFFLVL_MASK) << MPIDR_AFF1_SHIFT) |
-			((coreid & MPIDR_AFFLVL_MASK) << MPIDR_AFF0_SHIFT);
+		return ((coreid & MPIDR_AFFLVL_MASK) << MPIDR_AFF0_SHIFT) |
+		       ((clusterid & MPIDR_AFFLVL_MASK) << MPIDR_AFF1_SHIFT);
 
 }
 
diff --git a/plat/arm/fvp/fvp_def.h b/plat/arm/fvp/fvp_def.h
index abaa387..3f01678 100644
--- a/plat/arm/fvp/fvp_def.h
+++ b/plat/arm/fvp/fvp_def.h
@@ -19,8 +19,6 @@
 #define FVP_MAX_CPUS_PER_CLUSTER	8
 /* Currently the highest cluster count on the FVP is 4 (Quad cluster) */
 #define FVP_CLUSTER_COUNT		4
-/* Currently multi-threaded CPUs only have a single thread */
-#define FVP_MAX_PE_PER_CPU		1
 
 /*******************************************************************************
  * FVP memory map related constants
diff --git a/plat/arm/fvp/fvp_topology.c b/plat/arm/fvp/fvp_topology.c
index 751a1b8..dddd25b 100644
--- a/plat/arm/fvp/fvp_topology.c
+++ b/plat/arm/fvp/fvp_topology.c
@@ -17,46 +17,40 @@
 #define PSYSR_OFF		0x10
 #define PSYSR_INVALID		0xffffffff
 
+#if FVP_MAX_PE_PER_CPU == 2
+/* SMT: 2 threads per CPU */
+#define	CPU_DEF(cluster, cpu)	\
+	{ cluster, cpu, 0 },	\
+	{ cluster, cpu, 1 }
+
+#else
+#define	CPU_DEF(cluster, cpu)	\
+	{ cluster, cpu }
+#endif
+
+/* 8 CPUs per cluster */
+#define	CLUSTER_DEF(cluster)	\
+	CPU_DEF(cluster, 0),	\
+	CPU_DEF(cluster, 1),	\
+	CPU_DEF(cluster, 2),	\
+	CPU_DEF(cluster, 3),	\
+	CPU_DEF(cluster, 4),	\
+	CPU_DEF(cluster, 5),	\
+	CPU_DEF(cluster, 6),	\
+	CPU_DEF(cluster, 7)
+
 static const struct {
 	unsigned int cluster_id;
 	unsigned int cpu_id;
+#if FVP_MAX_PE_PER_CPU > 1
+	unsigned int thread_id;
+#endif
 } fvp_base_aemv8a_aemv8a_cores[] = {
-	/* Cluster 0 */
-	{ 0, 0 },
-	{ 0, 1 },
-	{ 0, 2 },
-	{ 0, 3 },
-	{ 0, 4 },
-	{ 0, 5 },
-	{ 0, 6 },
-	{ 0, 7 },
-	/* Cluster 1 */
-	{ 1, 0 },
-	{ 1, 1 },
-	{ 1, 2 },
-	{ 1, 3 },
-	{ 1, 4 },
-	{ 1, 5 },
-	{ 1, 6 },
-	{ 1, 7 },
-	/* Cluster 2 */
-	{ 2, 0 },
-	{ 2, 1 },
-	{ 2, 2 },
-	{ 2, 3 },
-	{ 2, 4 },
-	{ 2, 5 },
-	{ 2, 6 },
-	{ 2, 7 },
-	/* Cluster 3 */
-	{ 3, 0 },
-	{ 3, 1 },
-	{ 3, 2 },
-	{ 3, 3 },
-	{ 3, 4 },
-	{ 3, 5 },
-	{ 3, 6 },
-	{ 3, 7 },
+	/* Clusters 0...3 */
+	CLUSTER_DEF(0),
+	CLUSTER_DEF(1),
+	CLUSTER_DEF(2),
+	CLUSTER_DEF(3)
 };
 
 /*
@@ -105,7 +99,12 @@
 
 	mpid = make_mpid(
 			fvp_base_aemv8a_aemv8a_cores[core_pos].cluster_id,
+#if FVP_MAX_PE_PER_CPU > 1
+			fvp_base_aemv8a_aemv8a_cores[core_pos].cpu_id,
+			fvp_base_aemv8a_aemv8a_cores[core_pos].thread_id);
+#else
 			fvp_base_aemv8a_aemv8a_cores[core_pos].cpu_id);
+#endif
 
 	if (fvp_pwrc_read_psysr(mpid) != PSYSR_INVALID)
 		return mpid;
diff --git a/plat/arm/fvp/platform.mk b/plat/arm/fvp/platform.mk
index c014d6d..27874e2 100644
--- a/plat/arm/fvp/platform.mk
+++ b/plat/arm/fvp/platform.mk
@@ -4,6 +4,19 @@
 # SPDX-License-Identifier: BSD-3-Clause
 #
 
+# Default number of threads per CPU on FVP
+FVP_MAX_PE_PER_CPU	:= 1
+
+# Check the PE per core count
+ifneq ($(FVP_MAX_PE_PER_CPU),$(filter $(FVP_MAX_PE_PER_CPU),1 2))
+$(error "Incorrect FVP_MAX_PE_PER_CPU specified for FVP port")
+endif
+
+# Pass FVP_MAX_PE_PER_CPU to the build system
+$(eval $(call add_define,TFTF_DEFINES,FVP_MAX_PE_PER_CPU))
+$(eval $(call add_define,NS_BL1U_DEFINES,FVP_MAX_PE_PER_CPU))
+$(eval $(call add_define,NS_BL2U_DEFINES,FVP_MAX_PE_PER_CPU))
+
 PLAT_INCLUDES	:=	-Iplat/arm/fvp/include/
 
 PLAT_SOURCES	:=	drivers/arm/gic/arm_gic_v2v3.c			\
diff --git a/spm/cactus/cactus.mk b/spm/cactus/cactus.mk
index d964ab1..4acc715 100644
--- a/spm/cactus/cactus.mk
+++ b/spm/cactus/cactus.mk
@@ -1,5 +1,5 @@
 #
-# Copyright (c) 2018, Arm Limited. All rights reserved.
+# Copyright (c) 2018-2019, Arm Limited. All rights reserved.
 #
 # SPDX-License-Identifier: BSD-3-Clause
 #
@@ -53,6 +53,7 @@
 CACTUS_DEFINES	:=
 
 $(eval $(call add_define,CACTUS_DEFINES,DEBUG))
+$(eval $(call add_define,CACTUS_DEFINES,FVP_MAX_PE_PER_CPU))
 $(eval $(call add_define,CACTUS_DEFINES,ENABLE_ASSERTIONS))
 $(eval $(call add_define,CACTUS_DEFINES,LOG_LEVEL))
 $(eval $(call add_define,CACTUS_DEFINES,PLAT_${PLAT}))
diff --git a/tftf/tests/runtime_services/standard_service/psci/api_tests/affinity_info/test_psci_affinity_info.c b/tftf/tests/runtime_services/standard_service/psci/api_tests/affinity_info/test_psci_affinity_info.c
index 9afd910..cc4ad19 100644
--- a/tftf/tests/runtime_services/standard_service/psci/api_tests/affinity_info/test_psci_affinity_info.c
+++ b/tftf/tests/runtime_services/standard_service/psci/api_tests/affinity_info/test_psci_affinity_info.c
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2018, Arm Limited. All rights reserved.
+ * Copyright (c) 2018-2019, Arm Limited. All rights reserved.
  *
  * SPDX-License-Identifier: BSD-3-Clause
  */
@@ -214,7 +214,11 @@
 	 * CPU on the platform. The PSCI implementation should ignore the
 	 * affinity 0 field.
 	 */
+#if FVP_MAX_PE_PER_CPU > 1
+	target_mpid = make_mpid(cluster_id, 0, 0xE1);
+#else
 	target_mpid = make_mpid(cluster_id, 0xE1);
+#endif
 	aff_info = tftf_psci_affinity_info(target_mpid, MPIDR_AFFLVL1);
 	return get_test_result(expected_values, aff_info);
 }