TFTF: get FVP platform's topology from build options
This patch extends passing FVP topology parameters with
FVP_CLUSTER_COUNT and FVP_MAX_CPUS_PER_CLUSTER build
options to match TF-A. The change adds more test options,
make FVP platform configuration more flexible and eliminates
test errors when the platform is configured with number
of CPUs less than default values in the makefile.
These build options are documented in 'Arm FVP Platform
Specific Build Options' section of 'build-options.rst'
document.
Signed-off-by: Alexei Fedorov <Alexei.Fedorov@arm.com>
Change-Id: I01c6437d468885755a5415804b3688e4c878170d
diff --git a/Makefile b/Makefile
index 1851775..fea13db 100644
--- a/Makefile
+++ b/Makefile
@@ -94,6 +94,17 @@
$(and $(patsubst 0,,$(value $(1))),$(patsubst 1,,$(value $(1))),$(error $(1) must be boolean))
endef
+# CREATE_SEQ is a recursive function to create sequence of numbers from 1 to
+# $(2) and assign the sequence to $(1)
+define CREATE_SEQ
+$(if $(word $(2), $($(1))),\
+ $(eval $(1) += $(words $($(1))))\
+ $(eval $(1) := $(filter-out 0,$($(1)))),\
+ $(eval $(1) += $(words $($(1))))\
+ $(call CREATE_SEQ,$(1),$(2))\
+)
+endef
+
ifeq (${PLAT},)
$(error "Error: Unknown platform. Please use PLAT=<platform name> to specify the platform")
endif
diff --git a/docs/getting_started/build-options.rst b/docs/getting_started/build-options.rst
index 2e608e2..95724e7 100644
--- a/docs/getting_started/build-options.rst
+++ b/docs/getting_started/build-options.rst
@@ -70,6 +70,23 @@
- ``V``: Verbose build. If assigned anything other than 0, the build commands
are printed. Default is 0.
+Arm FVP Platform Specific Build Options
+---------------------------------------
+
+- ``FVP_CLUSTER_COUNT`` : Configures the cluster count to be used to build the
+ topology tree within TFTF. By default TFTF is configured for dual cluster for
+ CPUs with single thread (ST) and single cluster for SMT CPUs.
+ For ST CPUs this option can be used to override the default number of clusters
+ with a value in the range 1-4.
+
+- ``FVP_MAX_CPUS_PER_CLUSTER``: Sets the maximum number of CPUs implemented in
+ a single cluster. This option defaults to the maximum value of 4 for ST CPUs
+ and maximum value of 8 for SMT CPUs.
+
+- ``FVP_MAX_PE_PER_CPU``: Sets the maximum number of PEs implemented on any CPU
+ in the system. This option defaults to 1 to select ST CPUs. For platforms with
+ SMT CPUs this value must be set to 2.
+
TFTF-specific Build Options
---------------------------
@@ -107,4 +124,4 @@
--------------
-*Copyright (c) 2019, Arm Limited. All rights reserved.*
+*Copyright (c) 2019-2020, Arm Limited. All rights reserved.*
diff --git a/plat/arm/fvp/fvp_def.h b/plat/arm/fvp/fvp_def.h
index 3f01678..bcd3a7c 100644
--- a/plat/arm/fvp/fvp_def.h
+++ b/plat/arm/fvp/fvp_def.h
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2018-2019, Arm Limited. All rights reserved.
+ * Copyright (c) 2018-2020, Arm Limited. All rights reserved.
*
* SPDX-License-Identifier: BSD-3-Clause
*/
@@ -16,9 +16,13 @@
/*******************************************************************************
* Cluster Topology definitions
******************************************************************************/
-#define FVP_MAX_CPUS_PER_CLUSTER 8
-/* Currently the highest cluster count on the FVP is 4 (Quad cluster) */
-#define FVP_CLUSTER_COUNT 4
+#ifndef FVP_CLUSTER_COUNT
+#error "FVP_CLUSTER_COUNT is not set in makefile"
+#endif
+
+#ifndef FVP_MAX_CPUS_PER_CLUSTER
+#error "FVP_MAX_CPUS_PER_CLUSTER is not set in makefile"
+#endif
/*******************************************************************************
* FVP memory map related constants
diff --git a/plat/arm/fvp/fvp_topology.c b/plat/arm/fvp/fvp_topology.c
index e13e801..6dece28 100644
--- a/plat/arm/fvp/fvp_topology.c
+++ b/plat/arm/fvp/fvp_topology.c
@@ -22,13 +22,60 @@
#define CPU_DEF(cluster, cpu) \
{ cluster, cpu, 0 }, \
{ cluster, cpu, 1 }
-
#else
+/* ST: 1 thread per CPU */
#define CPU_DEF(cluster, cpu) \
{ cluster, cpu }
-#endif
+#endif /* FVP_MAX_PE_PER_CPU */
-/* 8 CPUs per cluster */
+/*
+ * Max CPUs per cluster:
+ * ST: 4
+ * SMT: 8
+ */
+#if (FVP_MAX_CPUS_PER_CLUSTER == 1)
+#define CLUSTER_DEF(cluster) \
+ CPU_DEF(cluster, 0)
+#elif (FVP_MAX_CPUS_PER_CLUSTER == 2)
+#define CLUSTER_DEF(cluster) \
+ CPU_DEF(cluster, 0), \
+ CPU_DEF(cluster, 1)
+#elif (FVP_MAX_CPUS_PER_CLUSTER == 3)
+#define CLUSTER_DEF(cluster) \
+ CPU_DEF(cluster, 0), \
+ CPU_DEF(cluster, 1), \
+ CPU_DEF(cluster, 2)
+#elif (FVP_MAX_CPUS_PER_CLUSTER == 4)
+#define CLUSTER_DEF(cluster) \
+ CPU_DEF(cluster, 0), \
+ CPU_DEF(cluster, 1), \
+ CPU_DEF(cluster, 2), \
+ CPU_DEF(cluster, 3)
+#elif (FVP_MAX_CPUS_PER_CLUSTER == 5)
+#define CLUSTER_DEF(cluster) \
+ CPU_DEF(cluster, 0), \
+ CPU_DEF(cluster, 1), \
+ CPU_DEF(cluster, 2), \
+ CPU_DEF(cluster, 3), \
+ CPU_DEF(cluster, 4)
+#elif (FVP_MAX_CPUS_PER_CLUSTER == 6)
+#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)
+#elif (FVP_MAX_CPUS_PER_CLUSTER == 7)
+#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)
+#else
#define CLUSTER_DEF(cluster) \
CPU_DEF(cluster, 0), \
CPU_DEF(cluster, 1), \
@@ -38,6 +85,7 @@
CPU_DEF(cluster, 5), \
CPU_DEF(cluster, 6), \
CPU_DEF(cluster, 7)
+#endif /* FVP_MAX_CPUS_PER_CLUSTER */
static const struct {
unsigned int cluster_id;
@@ -48,9 +96,15 @@
} fvp_base_aemv8a_aemv8a_cores[] = {
/* Clusters 0...3 */
CLUSTER_DEF(0),
+#if (FVP_CLUSTER_COUNT > 1)
CLUSTER_DEF(1),
+#if (FVP_CLUSTER_COUNT > 2)
CLUSTER_DEF(2),
+#if (FVP_CLUSTER_COUNT > 3)
CLUSTER_DEF(3)
+#endif
+#endif
+#endif
};
/*
@@ -70,12 +124,18 @@
FVP_CLUSTER_COUNT,
/* Number of children for the first node */
FVP_MAX_CPUS_PER_CLUSTER * FVP_MAX_PE_PER_CPU,
+#if (FVP_CLUSTER_COUNT > 1)
/* Number of children for the second node */
FVP_MAX_CPUS_PER_CLUSTER * FVP_MAX_PE_PER_CPU,
+#if (FVP_CLUSTER_COUNT > 2)
/* Number of children for the third node */
FVP_MAX_CPUS_PER_CLUSTER * FVP_MAX_PE_PER_CPU,
+#if (FVP_CLUSTER_COUNT > 3)
/* Number of children for the fourth node */
FVP_MAX_CPUS_PER_CLUSTER * FVP_MAX_PE_PER_CPU
+#endif
+#endif
+#endif
};
const unsigned char *tftf_plat_get_pwr_domain_tree_desc(void)
diff --git a/plat/arm/fvp/platform.mk b/plat/arm/fvp/platform.mk
index 34f6051..b993d72 100644
--- a/plat/arm/fvp/platform.mk
+++ b/plat/arm/fvp/platform.mk
@@ -1,20 +1,61 @@
#
-# Copyright (c) 2018-2019, Arm Limited. All rights reserved.
+# Copyright (c) 2018-2020, 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
+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")
+$(error "Incorrect FVP_MAX_PE_PER_CPU = ${FVP_MAX_PE_PER_CPU} \
+ specified for FVP port")
endif
-# Pass FVP_MAX_PE_PER_CPU to the build system
+# Default cluster count and number of CPUs per cluster for FVP
+ifeq ($(FVP_MAX_PE_PER_CPU),1)
+FVP_CLUSTER_COUNT := 2
+FVP_MAX_CPUS_PER_CLUSTER := 4
+else
+FVP_CLUSTER_COUNT := 1
+FVP_MAX_CPUS_PER_CLUSTER := 8
+endif
+
+# Check cluster count and number of CPUs per cluster
+ifeq ($(FVP_MAX_PE_PER_CPU),2)
+# Multithreaded CPU: 1 cluster with up to 8 CPUs
+$(eval $(call CREATE_SEQ,CLS,1))
+$(eval $(call CREATE_SEQ,CPU,8))
+else
+# CPU with single thread: max 4 clusters with up to 4 CPUs
+$(eval $(call CREATE_SEQ,CLS,4))
+$(eval $(call CREATE_SEQ,CPU,4))
+endif
+
+# Check cluster count
+ifneq ($(FVP_CLUSTER_COUNT),$(filter $(FVP_CLUSTER_COUNT),$(CLS)))
+ $(error "Incorrect FVP_CLUSTER_COUNT = ${FVP_CLUSTER_COUNT} \
+ specified for FVP port with FVP_MAX_PE_PER_CPU = ${FVP_MAX_PE_PER_CPU}")
+endif
+
+# Check number of CPUs per cluster
+ifneq ($(FVP_MAX_CPUS_PER_CLUSTER),$(filter $(FVP_MAX_CPUS_PER_CLUSTER),$(CPU)))
+ $(error "Incorrect FVP_MAX_CPUS_PER_CLUSTER = ${FVP_MAX_CPUS_PER_CLUSTER} \
+ specified for FVP port with FVP_MAX_PE_PER_CPU = ${FVP_MAX_PE_PER_CPU}")
+endif
+
+# Pass FVP topology definitions to the build system
+$(eval $(call add_define,TFTF_DEFINES,FVP_CLUSTER_COUNT))
+$(eval $(call add_define,TFTF_DEFINES,FVP_MAX_CPUS_PER_CLUSTER))
$(eval $(call add_define,TFTF_DEFINES,FVP_MAX_PE_PER_CPU))
+
+$(eval $(call add_define,NS_BL1U_DEFINES,FVP_CLUSTER_COUNT))
+$(eval $(call add_define,NS_BL1U_DEFINES,FVP_MAX_CPUS_PER_CLUSTER))
$(eval $(call add_define,NS_BL1U_DEFINES,FVP_MAX_PE_PER_CPU))
+
+$(eval $(call add_define,NS_BL2U_DEFINES,FVP_CLUSTER_COUNT))
+$(eval $(call add_define,NS_BL2U_DEFINES,FVP_MAX_CPUS_PER_CLUSTER))
$(eval $(call add_define,NS_BL2U_DEFINES,FVP_MAX_PE_PER_CPU))
PLAT_INCLUDES := -Iplat/arm/fvp/include/
diff --git a/plat/common/plat_topology.c b/plat/common/plat_topology.c
index 33b6e57..5ff7a31 100644
--- a/plat/common/plat_topology.c
+++ b/plat/common/plat_topology.c
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2018-2019, Arm Limited. All rights reserved.
+ * Copyright (c) 2018-2020, Arm Limited. All rights reserved.
*
* SPDX-License-Identifier: BSD-3-Clause
*/
@@ -364,6 +364,9 @@
unsigned int tftf_find_random_cpu_other_than(unsigned int exclude_mpid)
{
+#if (PLATFORM_CORE_COUNT == 1)
+ return INVALID_MPID;
+#else
unsigned int cpu_node, mpidr;
unsigned int possible_cpus_cnt = 0;
unsigned int possible_cpus[PLATFORM_CORE_COUNT];
@@ -378,4 +381,5 @@
return INVALID_MPID;
return possible_cpus[rand() % possible_cpus_cnt];
+#endif
}
diff --git a/spm/cactus/cactus.mk b/spm/cactus/cactus.mk
index a32d3d3..ffdfbe8 100644
--- a/spm/cactus/cactus.mk
+++ b/spm/cactus/cactus.mk
@@ -52,6 +52,8 @@
CACTUS_DEFINES :=
$(eval $(call add_define,CACTUS_DEFINES,DEBUG))
+$(eval $(call add_define,CACTUS_DEFINES,FVP_CLUSTER_COUNT))
+$(eval $(call add_define,CACTUS_DEFINES,FVP_MAX_CPUS_PER_CLUSTER))
$(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))
diff --git a/spm/cactus_mm/cactus_mm.mk b/spm/cactus_mm/cactus_mm.mk
index b96580c..6d69061 100644
--- a/spm/cactus_mm/cactus_mm.mk
+++ b/spm/cactus_mm/cactus_mm.mk
@@ -1,5 +1,5 @@
#
-# Copyright (c) 2018-2019, Arm Limited. All rights reserved.
+# Copyright (c) 2018-2020, Arm Limited. All rights reserved.
#
# SPDX-License-Identifier: BSD-3-Clause
#
@@ -53,6 +53,9 @@
CACTUS_MM_DEFINES += -DENABLE_ASSERTIONS=0
$(eval $(call add_define,CACTUS_MM_DEFINES,DEBUG))
+$(eval $(call add_define,CACTUS_MM_DEFINES,FVP_CLUSTER_COUNT))
+$(eval $(call add_define,CACTUS_MM_DEFINES,FVP_MAX_CPUS_PER_CLUSTER))
+$(eval $(call add_define,CACTUS_MM_DEFINES,FVP_MAX_PE_PER_CPU))
$(eval $(call add_define,CACTUS_MM_DEFINES,LOG_LEVEL))
$(eval $(call add_define,CACTUS_MM_DEFINES,PLAT_${PLAT}))
diff --git a/spm/ivy/ivy.mk b/spm/ivy/ivy.mk
index 8d5475a..afc89f4 100644
--- a/spm/ivy/ivy.mk
+++ b/spm/ivy/ivy.mk
@@ -1,5 +1,5 @@
#
-# Copyright (c) 2018, Arm Limited. All rights reserved.
+# Copyright (c) 2018-2020, Arm Limited. All rights reserved.
#
# SPDX-License-Identifier: BSD-3-Clause
#
@@ -52,6 +52,9 @@
$(eval $(call add_define,IVY_DEFINES,DEBUG))
$(eval $(call add_define,IVY_DEFINES,ENABLE_ASSERTIONS))
+$(eval $(call add_define,IVY_DEFINES,FVP_CLUSTER_COUNT))
+$(eval $(call add_define,IVY_DEFINES,FVP_MAX_CPUS_PER_CLUSTER))
+$(eval $(call add_define,IVY_DEFINES,FVP_MAX_PE_PER_CPU))
$(eval $(call add_define,IVY_DEFINES,LOG_LEVEL))
$(eval $(call add_define,IVY_DEFINES,PLAT_${PLAT}))
diff --git a/spm/quark/quark.mk b/spm/quark/quark.mk
index 20ddd1f..ec4a3ed 100644
--- a/spm/quark/quark.mk
+++ b/spm/quark/quark.mk
@@ -1,5 +1,5 @@
#
-# Copyright (c) 2018-2019, Arm Limited. All rights reserved.
+# Copyright (c) 2018-2020, Arm Limited. All rights reserved.
#
# SPDX-License-Identifier: BSD-3-Clause
#
@@ -49,6 +49,9 @@
$(eval $(call add_define,QUARK_DEFINES,DEBUG))
$(eval $(call add_define,QUARK_DEFINES,ENABLE_ASSERTIONS))
+$(eval $(call add_define,QUARK_DEFINES,FVP_CLUSTER_COUNT))
+$(eval $(call add_define,QUARK_DEFINES,FVP_MAX_CPUS_PER_CLUSTER))
+$(eval $(call add_define,QUARK_DEFINES,FVP_MAX_PE_PER_CPU))
$(eval $(call add_define,QUARK_DEFINES,PLAT_${PLAT}))
$(QUARK_DTB) : $(BUILD_PLAT)/quark $(BUILD_PLAT)/quark/quark.elf