From 0108047ae425faa91ddf782f264d7ed67d3351d8 Mon Sep 17 00:00:00 2001 From: Soby Mathew Date: Mon, 1 Feb 2016 14:04:34 +0000 Subject: [PATCH] Allow multi cluster topology definitions for ARM platforms The common topology description helper funtions and macros for ARM Standard platforms assumed a dual cluster system. This is not flexible enough to scale to multi cluster platforms. This patch does the following changes for more flexibility in defining topology: 1. The `plat_get_power_domain_tree_desc()` definition is moved from `arm_topology.c` to platform specific files, that is `fvp_topology.c` and `juno_topology.c`. Similarly the common definition of the porting macro `PLATFORM_CORE_COUNT` in `arm_def.h` is moved to platform specific `platform_def.h` header. 2. The ARM common layer porting macros which were dual cluster specific are now removed and a new macro PLAT_ARM_CLUSTER_COUNT is introduced which must be defined by each ARM standard platform. 3. A new mandatory ARM common layer porting API `plat_arm_get_cluster_core_count()` is introduced to enable the common implementation of `arm_check_mpidr()` to validate MPIDR. 4. For the FVP platforms, a new build option `FVP_NUM_CLUSTERS` has been introduced which allows the user to specify the cluster count to be used to build the topology tree within Trusted Firmare. This enables Trusted Firmware to be built for multi cluster FVP models. Change-Id: Ie7a2e38e5661fe2fdb2c8fdf5641d2b2614c2b6b --- docs/user-guide.md | 5 ++ include/plat/arm/common/arm_def.h | 5 -- include/plat/arm/common/plat_arm.h | 1 + plat/arm/board/fvp/fvp_def.h | 6 +- plat/arm/board/fvp/fvp_topology.c | 54 ++++++++++----- plat/arm/board/fvp/include/platform_def.h | 6 +- plat/arm/board/fvp/platform.mk | 5 ++ plat/arm/board/juno/include/platform_def.h | 9 ++- plat/arm/board/juno/juno_def.h | 7 ++ plat/arm/board/juno/juno_topology.c | 77 ++++++++++++++++++++++ plat/arm/board/juno/platform.mk | 1 + plat/arm/board/juno/tsp/tsp-juno.mk | 5 +- plat/arm/common/arm_topology.c | 23 +------ plat/arm/css/common/css_topology.c | 29 +------- 14 files changed, 153 insertions(+), 80 deletions(-) create mode 100644 plat/arm/board/juno/juno_topology.c diff --git a/docs/user-guide.md b/docs/user-guide.md index 7fd765815..0db622b80 100644 --- a/docs/user-guide.md +++ b/docs/user-guide.md @@ -486,6 +486,11 @@ map is explained in the [Firmware Design]. Trusted Firmware must be compiled with GICv2 only driver using `FVP_USE_GIC_DRIVER=FVP_GICV2` build option. +* `FVP_CLUSTER_COUNT` : Configures the cluster count to be used to + build the topology tree within Trusted Firmware. By default the + Trusted Firmware is configured for dual cluster topology and this option + can be used to override the default value. + ### Creating a Firmware Image Package FIPs are automatically created as part of the build instructions described in diff --git a/include/plat/arm/common/arm_def.h b/include/plat/arm/common/arm_def.h index 4c8435607..f6c090f49 100644 --- a/include/plat/arm/common/arm_def.h +++ b/include/plat/arm/common/arm_def.h @@ -44,7 +44,6 @@ /* Special value used to verify platform parameters from BL2 to BL31 */ #define ARM_BL31_PLAT_PARAM_VAL 0x0f1e2d3c4b5a6978ULL -#define ARM_CLUSTER_COUNT 2 #define ARM_SYSTEM_COUNT 1 #define ARM_CACHE_WRITEBACK_SHIFT 6 @@ -218,10 +217,6 @@ */ #define PLAT_MAX_OFF_STATE ARM_LOCAL_STATE_OFF - -#define PLATFORM_CORE_COUNT (PLAT_ARM_CLUSTER0_CORE_COUNT + \ - PLAT_ARM_CLUSTER1_CORE_COUNT) - /* * Some data must be aligned on the biggest cache line size in the platform. * This is known only to the platform as it might have a combination of diff --git a/include/plat/arm/common/plat_arm.h b/include/plat/arm/common/plat_arm.h index 8d7e83b57..e9eebaa09 100644 --- a/include/plat/arm/common/plat_arm.h +++ b/include/plat/arm/common/plat_arm.h @@ -179,6 +179,7 @@ int arm_io_is_toc_valid(void); /* * Mandatory functions required in ARM standard platforms */ +unsigned int plat_arm_get_cluster_core_count(u_register_t mpidr); void plat_arm_gic_driver_init(void); void plat_arm_gic_init(void); void plat_arm_gic_cpuif_enable(void); diff --git a/plat/arm/board/fvp/fvp_def.h b/plat/arm/board/fvp/fvp_def.h index 41b872af5..dbca280cb 100644 --- a/plat/arm/board/fvp/fvp_def.h +++ b/plat/arm/board/fvp/fvp_def.h @@ -1,5 +1,5 @@ /* - * Copyright (c) 2014-2015, ARM Limited and Contributors. All rights reserved. + * Copyright (c) 2014-2016, ARM Limited and Contributors. All rights reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions are met: @@ -33,7 +33,9 @@ #include - +#ifndef FVP_CLUSTER_COUNT +#define FVP_CLUSTER_COUNT 2 +#endif #define FVP_MAX_CPUS_PER_CLUSTER 4 #define FVP_PRIMARY_CPU 0x0 diff --git a/plat/arm/board/fvp/fvp_topology.c b/plat/arm/board/fvp/fvp_topology.c index a212eda74..741aad645 100644 --- a/plat/arm/board/fvp/fvp_topology.c +++ b/plat/arm/board/fvp/fvp_topology.c @@ -1,5 +1,5 @@ /* - * Copyright (c) 2013-2015, ARM Limited and Contributors. All rights reserved. + * Copyright (c) 2013-2016, ARM Limited and Contributors. All rights reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions are met: @@ -29,27 +29,47 @@ */ #include +#include #include #include #include "drivers/pwrc/fvp_pwrc.h" -/* - * The FVP power domain tree does not have a single system level power domain - * i.e. a single root node. The first entry in the power domain descriptor - * specifies the number of power domains at the highest power level. For the FVP - * this is 2 i.e. the number of cluster power domains. - */ -#define FVP_PWR_DOMAINS_AT_MAX_PWR_LVL ARM_CLUSTER_COUNT - /* The FVP power domain tree descriptor */ -const unsigned char arm_power_domain_tree_desc[] = { - /* No of root nodes */ - FVP_PWR_DOMAINS_AT_MAX_PWR_LVL, - /* No of children for the first node */ - PLAT_ARM_CLUSTER0_CORE_COUNT, - /* No of children for the second node */ - PLAT_ARM_CLUSTER1_CORE_COUNT -}; +unsigned char fvp_power_domain_tree_desc[FVP_CLUSTER_COUNT + 1]; + + +CASSERT(FVP_CLUSTER_COUNT && FVP_CLUSTER_COUNT <= 256, assert_invalid_fvp_cluster_count); + +/******************************************************************************* + * This function dynamically constructs the topology according to + * FVP_CLUSTER_COUNT and returns it. + ******************************************************************************/ +const unsigned char *plat_get_power_domain_tree_desc(void) +{ + int i; + + /* + * The FVP power domain tree does not have a single system level power domain + * i.e. a single root node. The first entry in the power domain descriptor + * specifies the number of power domains at the highest power level. For the FVP + * this is the number of cluster power domains. + */ + fvp_power_domain_tree_desc[0] = FVP_CLUSTER_COUNT; + + for (i = 0; i < FVP_CLUSTER_COUNT; i++) + fvp_power_domain_tree_desc[i + 1] = FVP_MAX_CPUS_PER_CLUSTER; + + return fvp_power_domain_tree_desc; +} + +/******************************************************************************* + * This function returns the core count within the cluster corresponding to + * `mpidr`. + ******************************************************************************/ +unsigned int plat_arm_get_cluster_core_count(u_register_t mpidr) +{ + return FVP_MAX_CPUS_PER_CLUSTER; +} /******************************************************************************* * This function implements a part of the critical interface between the psci diff --git a/plat/arm/board/fvp/include/platform_def.h b/plat/arm/board/fvp/include/platform_def.h index 9c82cbfa2..b912643e6 100644 --- a/plat/arm/board/fvp/include/platform_def.h +++ b/plat/arm/board/fvp/include/platform_def.h @@ -39,9 +39,10 @@ #include "../fvp_def.h" /* Required platform porting definitions */ -#define PLAT_NUM_PWR_DOMAINS (ARM_CLUSTER_COUNT + \ +#define PLAT_NUM_PWR_DOMAINS (FVP_CLUSTER_COUNT + \ PLATFORM_CORE_COUNT) #define PLAT_MAX_PWR_LVL ARM_PWR_LVL1 +#define PLATFORM_CORE_COUNT (FVP_CLUSTER_COUNT * FVP_MAX_CPUS_PER_CLUSTER) /* * Other platform porting definitions are provided by included headers @@ -50,8 +51,7 @@ /* * Required ARM standard platform porting definitions */ -#define PLAT_ARM_CLUSTER0_CORE_COUNT 4 -#define PLAT_ARM_CLUSTER1_CORE_COUNT 4 +#define PLAT_ARM_CLUSTER_COUNT FVP_CLUSTER_COUNT #define PLAT_ARM_TRUSTED_ROM_BASE 0x00000000 #define PLAT_ARM_TRUSTED_ROM_SIZE 0x04000000 /* 64 MB */ diff --git a/plat/arm/board/fvp/platform.mk b/plat/arm/board/fvp/platform.mk index c82c21a8c..aad2e2ef5 100644 --- a/plat/arm/board/fvp/platform.mk +++ b/plat/arm/board/fvp/platform.mk @@ -34,6 +34,11 @@ FVP_USE_GIC_DRIVER := FVP_GICV3_LEGACY # The FVP platform depends on this macro to build with correct GIC driver. $(eval $(call add_define,FVP_USE_GIC_DRIVER)) +# If FVP_CLUSTER_COUNT has been defined, pass it into the build system. +ifdef FVP_CLUSTER_COUNT +$(eval $(call add_define,FVP_CLUSTER_COUNT)) +endif + # Choose the GIC sources depending upon the how the FVP will be invoked ifeq (${FVP_USE_GIC_DRIVER}, FVP_GICV3) FVP_GIC_SOURCES := drivers/arm/gic/common/gic_common.c \ diff --git a/plat/arm/board/juno/include/platform_def.h b/plat/arm/board/juno/include/platform_def.h index deac0fffd..e1e0af67b 100644 --- a/plat/arm/board/juno/include/platform_def.h +++ b/plat/arm/board/juno/include/platform_def.h @@ -41,11 +41,15 @@ #include #include "../juno_def.h" +/* Required platform porting definitions */ /* Juno supports system power domain */ #define PLAT_MAX_PWR_LVL ARM_PWR_LVL2 #define PLAT_NUM_PWR_DOMAINS (ARM_SYSTEM_COUNT + \ - ARM_CLUSTER_COUNT + \ + JUNO_CLUSTER_COUNT + \ PLATFORM_CORE_COUNT) +#define PLATFORM_CORE_COUNT (JUNO_CLUSTER0_CORE_COUNT + \ + JUNO_CLUSTER1_CORE_COUNT) + /* * Other platform porting definitions are provided by included headers */ @@ -53,8 +57,7 @@ /* * Required ARM standard platform porting definitions */ -#define PLAT_ARM_CLUSTER0_CORE_COUNT 2 -#define PLAT_ARM_CLUSTER1_CORE_COUNT 4 +#define PLAT_ARM_CLUSTER_COUNT JUNO_CLUSTER_COUNT /* Use the bypass address */ #define PLAT_ARM_TRUSTED_ROM_BASE V2M_FLASH0_BASE + BL1_ROM_BYPASS_OFFSET diff --git a/plat/arm/board/juno/juno_def.h b/plat/arm/board/juno/juno_def.h index f4e225996..f27bbb22e 100644 --- a/plat/arm/board/juno/juno_def.h +++ b/plat/arm/board/juno/juno_def.h @@ -52,6 +52,13 @@ #define JUNO_SSC_VER_PART_NUM 0x030 +/******************************************************************************* + * Juno topology related constants + ******************************************************************************/ +#define JUNO_CLUSTER_COUNT 2 +#define JUNO_CLUSTER0_CORE_COUNT 2 +#define JUNO_CLUSTER1_CORE_COUNT 4 + /******************************************************************************* * TZC-400 related constants ******************************************************************************/ diff --git a/plat/arm/board/juno/juno_topology.c b/plat/arm/board/juno/juno_topology.c new file mode 100644 index 000000000..ee4ec4419 --- /dev/null +++ b/plat/arm/board/juno/juno_topology.c @@ -0,0 +1,77 @@ +/* + * Copyright (c) 2016, ARM Limited and Contributors. All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are met: + * + * Redistributions of source code must retain the above copyright notice, this + * list of conditions and the following disclaimer. + * + * Redistributions in binary form must reproduce the above copyright notice, + * this list of conditions and the following disclaimer in the documentation + * and/or other materials provided with the distribution. + * + * Neither the name of ARM nor the names of its contributors may be used + * to endorse or promote products derived from this software without specific + * prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" + * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE + * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR + * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF + * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS + * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN + * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) + * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE + * POSSIBILITY OF SUCH DAMAGE. + */ + +#include +#include +#include "juno_def.h" + +/* + * On Juno, the system power level is the highest power level. + * The first entry in the power domain descriptor specifies the + * number of system power domains i.e. 1. + */ +#define JUNO_PWR_DOMAINS_AT_MAX_PWR_LVL ARM_SYSTEM_COUNT + +/* + * The Juno power domain tree descriptor. The cluster power domains + * are arranged so that when the PSCI generic code creates the power + * domain tree, the indices of the CPU power domain nodes it allocates + * match the linear indices returned by plat_core_pos_by_mpidr() + * i.e. CLUSTER1 CPUs are allocated indices from 0 to 3 and the higher + * indices for CLUSTER0 CPUs. + */ +const unsigned char juno_power_domain_tree_desc[] = { + /* No of root nodes */ + JUNO_PWR_DOMAINS_AT_MAX_PWR_LVL, + /* No of children for the root node */ + JUNO_CLUSTER_COUNT, + /* No of children for the first cluster node */ + JUNO_CLUSTER1_CORE_COUNT, + /* No of children for the second cluster node */ + JUNO_CLUSTER0_CORE_COUNT +}; + +/******************************************************************************* + * This function returns the Juno topology tree information. + ******************************************************************************/ +const unsigned char *plat_get_power_domain_tree_desc(void) +{ + return juno_power_domain_tree_desc; +} + +/******************************************************************************* + * This function returns the core count within the cluster corresponding to + * `mpidr`. + ******************************************************************************/ +unsigned int plat_arm_get_cluster_core_count(u_register_t mpidr) +{ + return (((mpidr) & 0x100) ? JUNO_CLUSTER1_CORE_COUNT :\ + JUNO_CLUSTER0_CORE_COUNT); +} diff --git a/plat/arm/board/juno/platform.mk b/plat/arm/board/juno/platform.mk index 3ffc7e773..1876821b1 100644 --- a/plat/arm/board/juno/platform.mk +++ b/plat/arm/board/juno/platform.mk @@ -62,6 +62,7 @@ BL31_SOURCES += lib/cpus/aarch64/cortex_a53.S \ lib/cpus/aarch64/cortex_a57.S \ lib/cpus/aarch64/cortex_a72.S \ plat/arm/board/juno/juno_pm.c \ + plat/arm/board/juno/juno_topology.c \ ${JUNO_GIC_SOURCES} \ ${JUNO_INTERCONNECT_SOURCES} \ ${JUNO_SECURITY_SOURCES} diff --git a/plat/arm/board/juno/tsp/tsp-juno.mk b/plat/arm/board/juno/tsp/tsp-juno.mk index 2ef964e8b..4e8060786 100644 --- a/plat/arm/board/juno/tsp/tsp-juno.mk +++ b/plat/arm/board/juno/tsp/tsp-juno.mk @@ -1,5 +1,5 @@ # -# Copyright (c) 2014-2015, ARM Limited and Contributors. All rights reserved. +# Copyright (c) 2014-2016, ARM Limited and Contributors. All rights reserved. # # Redistribution and use in source and binary forms, with or without # modification, are permitted provided that the following conditions are met: @@ -28,7 +28,8 @@ # POSSIBILITY OF SUCH DAMAGE. # -BL32_SOURCES += plat/arm/css/common/css_topology.c \ +BL32_SOURCES += plat/arm/board/juno/juno_topology.c \ + plat/arm/css/common/css_topology.c \ ${JUNO_GIC_SOURCES} include plat/arm/common/tsp/arm_tsp.mk diff --git a/plat/arm/common/arm_topology.c b/plat/arm/common/arm_topology.c index cb0bb9c9c..4430b1399 100644 --- a/plat/arm/common/arm_topology.c +++ b/plat/arm/common/arm_topology.c @@ -1,5 +1,5 @@ /* - * Copyright (c) 2015, ARM Limited and Contributors. All rights reserved. + * Copyright (c) 2015-2016, ARM Limited and Contributors. All rights reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions are met: @@ -29,26 +29,9 @@ */ #include -#include #include #include -#define get_arm_cluster_core_count(mpidr)\ - (((mpidr) & 0x100) ? PLAT_ARM_CLUSTER1_CORE_COUNT :\ - PLAT_ARM_CLUSTER0_CORE_COUNT) - -/* The power domain tree descriptor which need to be exported by ARM platforms */ -extern const unsigned char arm_power_domain_tree_desc[]; - - -/******************************************************************************* - * This function returns the ARM default topology tree information. - ******************************************************************************/ -const unsigned char *plat_get_power_domain_tree_desc(void) -{ - return arm_power_domain_tree_desc; -} - /******************************************************************************* * This function validates an MPIDR by checking whether it falls within the * acceptable bounds. An error code (-1) is returned if an incorrect mpidr @@ -66,12 +49,12 @@ int arm_check_mpidr(u_register_t mpidr) cluster_id = (mpidr >> MPIDR_AFF1_SHIFT) & MPIDR_AFFLVL_MASK; cpu_id = (mpidr >> MPIDR_AFF0_SHIFT) & MPIDR_AFFLVL_MASK; - if (cluster_id >= ARM_CLUSTER_COUNT) + if (cluster_id >= PLAT_ARM_CLUSTER_COUNT) return -1; /* Validate cpu_id by checking whether it represents a CPU in one of the two clusters present on the platform. */ - if (cpu_id >= get_arm_cluster_core_count(mpidr)) + if (cpu_id >= plat_arm_get_cluster_core_count(mpidr)) return -1; return 0; diff --git a/plat/arm/css/common/css_topology.c b/plat/arm/css/common/css_topology.c index 03f81e615..d5f0275a8 100644 --- a/plat/arm/css/common/css_topology.c +++ b/plat/arm/css/common/css_topology.c @@ -1,5 +1,5 @@ /* - * Copyright (c) 2015, ARM Limited and Contributors. All rights reserved. + * Copyright (c) 2015-2016, ARM Limited and Contributors. All rights reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions are met: @@ -30,33 +30,6 @@ #include -/* - * On ARM CSS platforms, by default, the system power level is treated as the - * highest. The first entry in the power domain descriptor specifies the - * number of system power domains i.e. 1. - */ -#define CSS_PWR_DOMAINS_AT_MAX_PWR_LVL ARM_SYSTEM_COUNT - -/* - * The CSS power domain tree descriptor for dual cluster CSS platforms. - * The cluster power domains are arranged so that when the PSCI generic - * code creates the power domain tree, the indices of the CPU power - * domain nodes it allocates match the linear indices returned by - * plat_core_pos_by_mpidr() i.e. CLUSTER1 CPUs are allocated indices - * from 0 to 3 and the higher indices for CLUSTER0 CPUs. - */ -const unsigned char arm_power_domain_tree_desc[] = { - /* No of root nodes */ - CSS_PWR_DOMAINS_AT_MAX_PWR_LVL, - /* No of children for the root node */ - ARM_CLUSTER_COUNT, - /* No of children for the first cluster node */ - PLAT_ARM_CLUSTER1_CORE_COUNT, - /* No of children for the second cluster node */ - PLAT_ARM_CLUSTER0_CORE_COUNT -}; - - /****************************************************************************** * This function implements a part of the critical interface between the psci * generic layer and the platform that allows the former to query the platform