refactor(gicv3): clarify redistributor base address usage with USE_GIC_DRIVER=3
The GICv3 driver has 2 methods of discovering the redistributors:
a) via setting gicr_base - done at boot and assumes all GICR frames are
contiguous. This is the original method.
b) via gicv3_rdistif_probe() - called from platform code and requires
gicr_base == 0. It relaxes the requirement for frames to be
contiguous, like in a multichip configuration, and defers the
discovery to core bringup. This was introduced later.
Configurations possible with option a) are also possible with option b)
with only slightly different behaviour. USE_GIC_DRIVER=3 inherited
option b) from plat_gicv3_base.c and as such option a) is unusable.
However, it is unclear from code how this should be used. Clarify this
by requiring platforms initialise with gic_set_gicr_frames() and
adding relevant comments.
Also rename plat_arm_override_gicr_frames() to gic_set_gicr_frames() as
this is not plat arm specific and a part of the generic GIC driver.
Change-Id: I61d77211f8e65dc54cf9904069b500d26a06b5a5
Signed-off-by: Boyan Karatotev <boyan.karatotev@arm.com>
diff --git a/docs/getting_started/build-options.rst b/docs/getting_started/build-options.rst
index 6d3fea1..23de63f 100644
--- a/docs/getting_started/build-options.rst
+++ b/docs/getting_started/build-options.rst
@@ -1336,7 +1336,9 @@
- ``2``: use the GICv2 driver
- ``3``: use the GICv3 driver. See the next section on how to further configure
- it. Use this option for GICv4 implementations.
+ it. Use this option for GICv4 implementations. Requires calling
+ ``gic_set_gicr_frames()``.
+
- ``5``: use the EXPERIMENTAL GICv5 driver. Requires ``ENABLE_FEAT_GCIE=1``.
For GIC driver versions other than ``1``, deciding when to save and restore GIC
diff --git a/drivers/arm/gic/v3/gicv3_base.c b/drivers/arm/gic/v3/gicv3_base.c
index 1a65758..20b2ea8 100644
--- a/drivers/arm/gic/v3/gicv3_base.c
+++ b/drivers/arm/gic/v3/gicv3_base.c
@@ -22,14 +22,8 @@
/* The GICv3 driver only needs to be initialized in EL3 */
uintptr_t rdistif_base_addrs[PLATFORM_CORE_COUNT];
-/* Default GICR base address to be used for GICR probe. */
-static const uintptr_t gicr_base_addrs[2] = {
- PLAT_ARM_GICR_BASE, /* GICR Base address of the primary CPU */
- 0U /* Zero Termination */
-};
-
/* List of zero terminated GICR frame addresses which CPUs will probe */
-static const uintptr_t *gicr_frames = gicr_base_addrs;
+static const uintptr_t *gicr_frames = NULL;
static const interrupt_prop_t arm_interrupt_props[] = {
#ifdef PLAT_ARM_G1S_IRQ_PROPS
@@ -78,6 +72,8 @@
gicv3_driver_data_t gic_data __unused = {
.gicd_base = PLAT_ARM_GICD_BASE,
+ /* unused for USE_GIC_DRIVER=3. Use gic_set_gicr_frames(), passing a ptr
+ * to an array with 2 values - the frame's base and a NULL pointer */
.gicr_base = 0U,
.interrupt_props = arm_interrupt_props,
.interrupt_props_num = ARRAY_SIZE(arm_interrupt_props),
@@ -87,12 +83,12 @@
};
/*
- * By default, gicr_frames will be pointing to gicr_base_addrs. If
- * the platform supports a non-contiguous GICR frames (GICR frames located
- * at uneven offset), plat_arm_override_gicr_frames function can be used by
- * such platform to override the gicr_frames.
+ * Initialises the gicr_frames array. It contains a NULL terminated list of
+ * non-contiguous blocks of GICR frames (located at uneven offsets). Most
+ * platforms will have one such block, except multichip configurations, which
+ * will usually have multiple.
*/
-void plat_arm_override_gicr_frames(const uintptr_t *plat_gicr_frames)
+void gic_set_gicr_frames(const uintptr_t *plat_gicr_frames)
{
assert(plat_gicr_frames != NULL);
gicr_frames = plat_gicr_frames;
@@ -130,18 +126,21 @@
*****************************************************************************/
void gic_pcpu_init(unsigned int cpu_idx)
{
- int result;
- const uintptr_t *plat_gicr_frames = gicr_frames;
+ /* to guard against an empty array */
+ int result = -1;
+
+ /* did the paltform initialise the array with gic_set_gicr_frames() */
+ assert(gicr_frames != NULL);
do {
- result = gicv3_rdistif_probe(*plat_gicr_frames);
+ result = gicv3_rdistif_probe(*gicr_frames);
/* If the probe is successful, no need to proceed further */
if (result == 0)
break;
- plat_gicr_frames++;
- } while (*plat_gicr_frames != 0U);
+ gicr_frames++;
+ } while (*gicr_frames != 0U);
if (result == -1) {
ERROR("No GICR base frame found for CPU 0x%lx\n", read_mpidr());
diff --git a/include/plat/arm/common/plat_arm.h b/include/plat/arm/common/plat_arm.h
index 0573f3b..39a9bc2 100644
--- a/include/plat/arm/common/plat_arm.h
+++ b/include/plat/arm/common/plat_arm.h
@@ -376,7 +376,7 @@
/*
* Optional functions in ARM standard platforms
*/
-void plat_arm_override_gicr_frames(const uintptr_t *plat_gicr_frames);
+void gic_set_gicr_frames(const uintptr_t *plat_gicr_frames);
int arm_get_rotpk_info(void *cookie, void **key_ptr, unsigned int *key_len,
unsigned int *flags);
int arm_get_rotpk_info_regs(void **key_ptr, unsigned int *key_len,
diff --git a/plat/arm/board/fvp/fvp_gicv3.c b/plat/arm/board/fvp/fvp_gicv3.c
index 4167229..9071f41 100644
--- a/plat/arm/board/fvp/fvp_gicv3.c
+++ b/plat/arm/board/fvp/fvp_gicv3.c
@@ -96,6 +96,6 @@
gic_data.interrupt_props = fvp_interrupt_props;
gic_data.interrupt_props_num = ARRAY_SIZE(fvp_interrupt_props);
#endif
- plat_arm_override_gicr_frames(fvp_gicr_base_addrs);
+ gic_set_gicr_frames(fvp_gicr_base_addrs);
#endif /* !(BL2_AT_EL3 || RESET_TO_BL31 || RESET_TO_SP_MIN || RESET_TO_BL2) */
}
diff --git a/plat/arm/board/n1sdp/n1sdp_bl31_setup.c b/plat/arm/board/n1sdp/n1sdp_bl31_setup.c
index d8d60ef..9300c14 100644
--- a/plat/arm/board/n1sdp/n1sdp_bl31_setup.c
+++ b/plat/arm/board/n1sdp/n1sdp_bl31_setup.c
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2018-2024, Arm Limited. All rights reserved.
+ * Copyright (c) 2018-2025, Arm Limited. All rights reserved.
*
* SPDX-License-Identifier: BSD-3-Clause
*/
@@ -124,7 +124,7 @@
void n1sdp_bl31_multichip_setup(void)
{
- plat_arm_override_gicr_frames(n1sdp_multichip_gicr_frames);
+ gic_set_gicr_frames(n1sdp_multichip_gicr_frames);
gic600_multichip_init(&n1sdp_multichip_data);
}
diff --git a/plat/arm/board/neoverse_rd/platform/rdn2/rdn2_plat.c b/plat/arm/board/neoverse_rd/platform/rdn2/rdn2_plat.c
index cf820b8..1f02c77 100644
--- a/plat/arm/board/neoverse_rd/platform/rdn2/rdn2_plat.c
+++ b/plat/arm/board/neoverse_rd/platform/rdn2/rdn2_plat.c
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2020-2024, Arm Limited and Contributors. All rights reserved.
+ * Copyright (c) 2020-2025, Arm Limited and Contributors. All rights reserved.
*
* SPDX-License-Identifier: BSD-3-Clause
*/
@@ -174,7 +174,7 @@
}
}
- plat_arm_override_gicr_frames(
+ gic_set_gicr_frames(
rdn2mc_multichip_gicr_frames);
gic600_multichip_init(&rdn2mc_multichip_data);
}
diff --git a/plat/arm/board/neoverse_rd/platform/rdv3/rdv3_bl31_setup.c b/plat/arm/board/neoverse_rd/platform/rdv3/rdv3_bl31_setup.c
index e32e761..a9c957e 100644
--- a/plat/arm/board/neoverse_rd/platform/rdv3/rdv3_bl31_setup.c
+++ b/plat/arm/board/neoverse_rd/platform/rdv3/rdv3_bl31_setup.c
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2024, Arm Limited and Contributors. All rights reserved.
+ * Copyright (c) 2024-2025, Arm Limited and Contributors. All rights reserved.
*
* SPDX-License-Identifier: BSD-3-Clause
*/
@@ -171,7 +171,7 @@
}
}
- plat_arm_override_gicr_frames(
+ gic_set_gicr_frames(
rdv3mc_multichip_gicr_frames);
gic600_multichip_init(&rdv3mc_multichip_data);
}
diff --git a/plat/arm/common/arm_bl31_setup.c b/plat/arm/common/arm_bl31_setup.c
index 353efac..c38418e 100644
--- a/plat/arm/common/arm_bl31_setup.c
+++ b/plat/arm/common/arm_bl31_setup.c
@@ -28,6 +28,13 @@
struct transfer_list_header *secure_tl;
struct transfer_list_header *ns_tl __unused;
+#if USE_GIC_DRIVER == 3
+const uintptr_t gicr_base_addrs[2] = {
+ PLAT_ARM_GICR_BASE, /* GICR Base address of the primary CPU */
+ 0U /* Zero Termination */
+};
+#endif
+
/*
* Placeholder variables for copying the arguments that have been passed to
* BL31 from BL2.
@@ -427,6 +434,10 @@
#if USE_DEBUGFS
debugfs_init();
#endif /* USE_DEBUGFS */
+
+#if USE_GIC_DRIVER == 3
+ gic_set_gicr_frames(gicr_base_addrs);
+#endif
}
/*******************************************************************************
diff --git a/plat/arm/common/sp_min/arm_sp_min_setup.c b/plat/arm/common/sp_min/arm_sp_min_setup.c
index 2b52a76..f9a884e 100644
--- a/plat/arm/common/sp_min/arm_sp_min_setup.c
+++ b/plat/arm/common/sp_min/arm_sp_min_setup.c
@@ -21,6 +21,13 @@
static entry_point_info_t bl33_image_ep_info;
+#if USE_GIC_DRIVER == 3
+static const uintptr_t gicr_base_addrs[2] = {
+ PLAT_ARM_GICR_BASE, /* GICR Base address of the primary CPU */
+ 0U /* Zero Termination */
+};
+#endif
+
/* Weak definitions may be overridden in specific ARM standard platform */
#pragma weak sp_min_platform_setup
#pragma weak sp_min_plat_arch_setup
@@ -206,6 +213,9 @@
/* Initialize the GIC driver, cpu and distributor interfaces */
unsigned int core_pos = plat_my_core_pos();
+#if USE_GIC_DRIVER == 3
+ gic_set_gicr_frames(gicr_base_addrs);
+#endif
gic_init(core_pos);
gic_pcpu_init(core_pos);
gic_cpuif_enable(core_pos);
diff --git a/plat/xilinx/versal_net/bl31_versal_net_setup.c b/plat/xilinx/versal_net/bl31_versal_net_setup.c
index 907deee..089f9b1 100644
--- a/plat/xilinx/versal_net/bl31_versal_net_setup.c
+++ b/plat/xilinx/versal_net/bl31_versal_net_setup.c
@@ -30,6 +30,11 @@
static entry_point_info_t bl32_image_ep_info;
static entry_point_info_t bl33_image_ep_info;
+static const uintptr_t gicr_base_addrs[2] = {
+ PLAT_ARM_GICR_BASE, /* GICR Base address of the primary CPU */
+ 0U /* Zero Termination */
+};
+
/*
* Return a pointer to the 'entry_point_info' structure of the next image for
* the security state specified. BL33 corresponds to the non-secure image type
@@ -242,6 +247,8 @@
void bl31_platform_setup(void)
{
prepare_dtb();
+
+ gic_set_gicr_frames(gicr_base_addrs);
}
void bl31_plat_runtime_setup(void)