* [BOOTWRAPPER PATCH v2 0/2] Support GICv5
@ 2026-03-24 12:59 Vladimir Murzin
2026-03-24 12:59 ` [BOOTWRAPPER PATCH v2 1/2] Introduce --with-gic option Vladimir Murzin
2026-03-24 12:59 ` [BOOTWRAPPER PATCH v2 2/2] Add support for GICv5 Vladimir Murzin
0 siblings, 2 replies; 7+ messages in thread
From: Vladimir Murzin @ 2026-03-24 12:59 UTC (permalink / raw)
To: linux-arm-kernel
Cc: vladimir.murzin, mark.rutland, maz, joey.gouly, Sascha.Bischoff
Small series adding GICv5 to the list of supported GIC
versions. Minimal implementation, just enough for Fast Models.
Thanks!
Changelog:
v1 -> v2
- Assign SW_PPI to NS domain (per Sascha)
Vladimir Murzin (2):
Introduce --with-gic option
Add support for GICv5
Makefile.am | 15 +++-
arch/aarch64/include/asm/cpu.h | 11 +++
common/{gic.c => gic-v2.c} | 0
common/gic-v5.c | 134 +++++++++++++++++++++++++++++++++
configure.ac | 24 ++++--
scripts/FDT.pm | 16 ++++
scripts/findbase-by-regname.pl | 44 +++++++++++
7 files changed, 234 insertions(+), 10 deletions(-)
rename common/{gic.c => gic-v2.c} (100%)
create mode 100644 common/gic-v5.c
create mode 100755 scripts/findbase-by-regname.pl
--
2.34.1
^ permalink raw reply [flat|nested] 7+ messages in thread
* [BOOTWRAPPER PATCH v2 1/2] Introduce --with-gic option
2026-03-24 12:59 [BOOTWRAPPER PATCH v2 0/2] Support GICv5 Vladimir Murzin
@ 2026-03-24 12:59 ` Vladimir Murzin
2026-05-28 15:06 ` Sascha Bischoff
2026-03-24 12:59 ` [BOOTWRAPPER PATCH v2 2/2] Add support for GICv5 Vladimir Murzin
1 sibling, 1 reply; 7+ messages in thread
From: Vladimir Murzin @ 2026-03-24 12:59 UTC (permalink / raw)
To: linux-arm-kernel
Cc: vladimir.murzin, mark.rutland, maz, joey.gouly, Sascha.Bischoff
We are about adding support for another GIC version, so introduce a
new --with-gic option to select the desired GIC version at configure
time. The default remains v2, preserving existing behavior. Howevere,
for GICv3, we replace the previous --enable-gicv3 option with
--with-gic=v3 which is backward-incompatible change (yet I hope we can
live with that).
Signed-off-by: Vladimir Murzin <vladimir.murzin@arm•com>
---
Makefile.am | 8 +++++---
common/{gic.c => gic-v2.c} | 0
configure.ac | 23 ++++++++++++++++-------
3 files changed, 21 insertions(+), 10 deletions(-)
rename common/{gic.c => gic-v2.c} (100%)
diff --git a/Makefile.am b/Makefile.am
index 0178e5d..2710494 100644
--- a/Makefile.am
+++ b/Makefile.am
@@ -87,15 +87,17 @@ GIC_DIST_BASE := $(shell perl -I $(SCRIPT_DIR) $(SCRIPT_DIR)/findbase.pl $(KERNE
GIC_RDIST_BASE := $(shell perl -I $(SCRIPT_DIR) $(SCRIPT_DIR)/findbase.pl $(KERNEL_DTB) 1 'arm,gic-v3')
DEFINES += -DGIC_DIST_BASE=$(GIC_DIST_BASE)
DEFINES += -DGIC_RDIST_BASE=$(GIC_RDIST_BASE)
-COMMON_OBJ += gic-v3.o
-else
+endif
+
+if GICV2
GIC_DIST_BASE := $(shell perl -I $(SCRIPT_DIR) $(SCRIPT_DIR)/findbase.pl $(KERNEL_DTB) 0 'arm,cortex-a15-gic')
GIC_CPU_BASE := $(shell perl -I $(SCRIPT_DIR) $(SCRIPT_DIR)/findbase.pl $(KERNEL_DTB) 1 'arm,cortex-a15-gic')
DEFINES += -DGIC_CPU_BASE=$(GIC_CPU_BASE)
DEFINES += -DGIC_DIST_BASE=$(GIC_DIST_BASE)
-COMMON_OBJ += gic.o
endif
+COMMON_OBJ += gic-$(GIC_VERSION).o
+
if KERNEL_32
MBOX_OFFSET := 0x7ff8
TEXT_LIMIT := 0x3000
diff --git a/common/gic.c b/common/gic-v2.c
similarity index 100%
rename from common/gic.c
rename to common/gic-v2.c
diff --git a/configure.ac b/configure.ac
index 42858df..6f486c4 100644
--- a/configure.ac
+++ b/configure.ac
@@ -139,12 +139,21 @@ AC_ARG_WITH([xen-cmdline],
[X_CMDLINE=$withval])
AC_SUBST([XEN_CMDLINE], [$X_CMDLINE])
-# Allow a user to pass --enable-gicv3
-AC_ARG_ENABLE([gicv3],
- AS_HELP_STRING([--enable-gicv3], [enable GICv3 instead of GICv2]),
- [USE_GICV3=$enableval])
-AM_CONDITIONAL([GICV3], [test "x$USE_GICV3" = "xyes"])
-AS_IF([test "x$USE_GICV3" = "xyes"], [], [USE_GICV3=no])
+
+AC_ARG_WITH([gic],
+ AS_HELP_STRING([--with-gic={v2|v3}], [select GIC version]),
+ [GIC_VERSION=$withval],
+ [GIC_VERSION=v2])
+
+AS_CASE([$GIC_VERSION],
+ [v2|v3], [],
+ [AC_MSG_ERROR([Invalid GIC version: $GIC_VERSION (use v2 or v3)])])
+
+AC_SUBST([GIC_VERSION], [$GIC_VERSION])
+
+AM_CONDITIONAL([GICV2], [test "x$GIC_VERSION" = "xv2"])
+AM_CONDITIONAL([GICV3], [test "x$GIC_VERSION" = "xv3"])
+
# Ensure that we have all the needed programs
AC_PROG_CC
@@ -174,7 +183,7 @@ echo " Device tree compiler: ${DTC}"
echo " Linux kernel command line: ${CMDLINE}"
echo " Embedded initrd: ${FILESYSTEM:-NONE}"
echo " Use PSCI? ${USE_PSCI}"
-echo " Use GICv3? ${USE_GICV3}"
+echo " GIC version: ${GIC_VERSION}"
echo " Boot-wrapper execution state: AArch${BOOTWRAPPER_ES}"
echo " Kernel execution state: AArch${KERNEL_ES}"
echo " Xen image ${XEN_IMAGE:-NONE}"
--
2.34.1
^ permalink raw reply related [flat|nested] 7+ messages in thread
* [BOOTWRAPPER PATCH v2 2/2] Add support for GICv5
2026-03-24 12:59 [BOOTWRAPPER PATCH v2 0/2] Support GICv5 Vladimir Murzin
2026-03-24 12:59 ` [BOOTWRAPPER PATCH v2 1/2] Introduce --with-gic option Vladimir Murzin
@ 2026-03-24 12:59 ` Vladimir Murzin
2026-05-28 15:10 ` Sascha Bischoff
1 sibling, 1 reply; 7+ messages in thread
From: Vladimir Murzin @ 2026-03-24 12:59 UTC (permalink / raw)
To: linux-arm-kernel
Cc: vladimir.murzin, mark.rutland, maz, joey.gouly, Sascha.Bischoff
Performs the minimal initialization required for GICv5 support. GICv5
support can be requested with --with-gic=v5.
Signed-off-by: Vladimir Murzin <vladimir.murzin@arm•com>
---
Makefile.am | 7 ++
arch/aarch64/include/asm/cpu.h | 11 +++
common/gic-v5.c | 134 +++++++++++++++++++++++++++++++++
configure.ac | 7 +-
scripts/FDT.pm | 16 ++++
scripts/findbase-by-regname.pl | 44 +++++++++++
6 files changed, 216 insertions(+), 3 deletions(-)
create mode 100644 common/gic-v5.c
create mode 100755 scripts/findbase-by-regname.pl
diff --git a/Makefile.am b/Makefile.am
index 2710494..aacd639 100644
--- a/Makefile.am
+++ b/Makefile.am
@@ -82,6 +82,13 @@ PSCI_NODE :=
CPU_NODES :=
endif
+if GICV5
+GIC_IRS_BASE := $(shell perl -I $(SCRIPT_DIR) $(SCRIPT_DIR)/findbase-by-regname.pl $(KERNEL_DTB) "el3-config" 'arm,gic-v5-irs')
+GIC_IWB_BASE := $(shell perl -I $(SCRIPT_DIR) $(SCRIPT_DIR)/findbase.pl $(KERNEL_DTB) 0 'arm,gic-v5-iwb')
+DEFINES += -DGIC_IRS_BASE=$(GIC_IRS_BASE)
+DEFINES += -DGIC_IWB_BASE=$(GIC_IWB_BASE)
+endif
+
if GICV3
GIC_DIST_BASE := $(shell perl -I $(SCRIPT_DIR) $(SCRIPT_DIR)/findbase.pl $(KERNEL_DTB) 0 'arm,gic-v3')
GIC_RDIST_BASE := $(shell perl -I $(SCRIPT_DIR) $(SCRIPT_DIR)/findbase.pl $(KERNEL_DTB) 1 'arm,gic-v3')
diff --git a/arch/aarch64/include/asm/cpu.h b/arch/aarch64/include/asm/cpu.h
index ac50474..af4191c 100644
--- a/arch/aarch64/include/asm/cpu.h
+++ b/arch/aarch64/include/asm/cpu.h
@@ -128,6 +128,7 @@
#define ID_AA64PFR1_EL1_THE BITS(51, 48)
#define ID_AA64PFR2_EL1 s3_0_c0_c4_2
+#define ID_AA64PFR2_EL1_GCIE BITS(15, 12)
#define ID_AA64PFR2_EL1_FPMR BITS(35, 32)
#define ID_AA64SMFR0_EL1 s3_0_c0_c4_5
@@ -169,6 +170,11 @@
#define ICC_CTLR_EL3 S3_6_C12_C12_4
#define ICC_PMR_EL1 S3_0_C4_C6_0
+#define ICC_PPI_DOMAINR0_EL3 S3_6_C12_C8_4
+#define ICC_PPI_DOMAINR1_EL3 S3_6_C12_C8_5
+#define ICC_PPI_DOMAINR2_EL3 S3_6_C12_C8_6
+#define ICC_PPI_DOMAINR3_EL3 S3_6_C12_C8_7
+
#define VSTCR_EL2 s3_4_c2_c6_2
#define VSCTLR_EL2 s3_4_c2_c0_0
@@ -245,6 +251,11 @@ static inline int has_gicv3_sysreg(void)
return !!mrs_field(ID_AA64PFR0_EL1, GIC);
}
+static inline int has_gicv5_sysreg(void)
+{
+ return !!mrs_field(ID_AA64PFR2_EL1, GCIE);
+}
+
#endif /* !__ASSEMBLY__ */
#endif
diff --git a/common/gic-v5.c b/common/gic-v5.c
new file mode 100644
index 0000000..cef2ece
--- /dev/null
+++ b/common/gic-v5.c
@@ -0,0 +1,134 @@
+/*
+ * gic-v5.c
+ *
+ * Copyright (C) 2025 ARM Limited. All rights reserved.
+ *
+ * Use of this source code is governed by a BSD-style license that can be
+ * found in the LICENSE.txt file.
+ */
+
+#include <stdint.h>
+
+#include <cpu.h>
+#include <gic.h>
+#include <asm/io.h>
+
+#define IWB_IDR0 0x0
+#define IWB_IDR0_IW_RANGE_SHIFT 0x0
+#define IWB_IDR0_IW_RANGE_MASK 0x7ff
+
+#define IWB_CR0 0x80
+#define IWB_CR0_IWBEN (1 << 0)
+#define IWB_CR0_IDLE (1 << 1)
+
+#define IWB_WENABLE_STATUSR 0xc0
+#define IWB_WENABLE_STATUSR_IDLE (1 << 0)
+
+#define IWB_WDOMAIN_STATUSR 0xc4
+#define IWB_WDOMAIN_STATUSR_IDLE (1 << 0)
+
+#define IWB_WENABLER 0x2000
+#define IWB_WDOMAINR 0x8000
+
+#define IRS_IDR6 0x0018
+#define IRS_IDR6_SPI_IRS_RANGE_MASK 0x1ffffff
+
+#define IRS_IDR7 0x001c
+#define IRS_IDR7_SPI_BASE_MASK 0xffffff
+
+#define IRS_SPI_SELR 0x108
+#define IRS_SPI_DOMAINR 0x10c
+
+#define IRS_SPI_STATUSR 0x0118
+#define IRS_SPI_STATUSR_IDLE (1 << 0)
+
+
+static void gic_iwb_init(void) {
+ void *iwb_ptr = (void *)GIC_IWB_BASE;
+ unsigned int num;
+ unsigned int i;
+
+ /* Get number of implemented wires */
+ num = ((raw_readl(iwb_ptr + IWB_IDR0) >> IWB_IDR0_IW_RANGE_SHIFT) & IWB_IDR0_IW_RANGE_MASK) + 1;
+
+ /* Disable all wires */
+ for (i = 0; i < num; i++)
+ raw_writel(0, iwb_ptr + IWB_WENABLER + i * 4);
+
+
+ while (!(raw_readl(iwb_ptr + IWB_WENABLE_STATUSR) & IWB_WENABLE_STATUSR_IDLE));
+
+ /* Asign all wires to Non-Secure domain */
+ for (i = 0; i < num * 2; i++)
+ raw_writel(0x55555555, iwb_ptr + IWB_WDOMAINR + i * 4);
+
+ while (!(raw_readl(iwb_ptr + IWB_WDOMAIN_STATUSR) & IWB_WDOMAIN_STATUSR_IDLE));
+
+ /* Enable IWB */
+ raw_writel(IWB_CR0_IWBEN, iwb_ptr + IWB_CR0);
+
+ while (!(raw_readl(iwb_ptr + IWB_CR0) & IWB_CR0_IDLE));
+}
+
+static void gic_irs_init(void) {
+ void *irs_ptr = (void *)GIC_IRS_BASE;
+ unsigned int range;
+ unsigned int base;
+ unsigned int i;
+
+ /* Get the range of implemented SPI's ids */
+ base = raw_readl(irs_ptr + IRS_IDR7) & IRS_IDR7_SPI_BASE_MASK;
+ range = raw_readl(irs_ptr + IRS_IDR6) & IRS_IDR6_SPI_IRS_RANGE_MASK;
+
+ for (i = base; i < base + range; i++) {
+ /* Select SPI */
+ raw_writel(i, irs_ptr + IRS_SPI_SELR);
+ while (!(raw_readl(irs_ptr + IRS_SPI_STATUSR) & IRS_SPI_STATUSR_IDLE));
+
+ /* Asign SPI to Non-Secure domain */
+ raw_writel(1, irs_ptr + IRS_SPI_DOMAINR);
+ while (!(raw_readl(irs_ptr + IRS_SPI_STATUSR) & IRS_SPI_STATUSR_IDLE));
+ }
+}
+
+static void gic_ppi_init(void) {
+ uint64_t val = 0;
+
+ val |= 1UL << (2 * 31); // Trace Buffer Unit
+ val |= 1UL << (2 * 30); // EL1 Physical Timer
+ val |= 1UL << (2 * 28); // Non-secure EL2 Virtual Timer
+ val |= 1UL << (2 * 27); // EL1 Virtual Timer
+ val |= 1UL << (2 * 26); // Non-secure EL2 Physical Timer
+ val |= 1UL << (2 * 25); // GIC maintenance interrupt
+ val |= 1UL << (2 * 24); // Generic CTI interrupt trigger event
+ val |= 1UL << (2 * 23); // PMU overflow interrupt request
+ val |= 1UL << (2 * 22); // Debug communication channel
+ val |= 1UL << (2 * 21); // Profiling Buffer management interrupt request
+ val |= 1UL << (2 * 15); // Hardware accelerator for cleaning Dirty state interrupt
+ val |= 1UL << (2 * 3); // Reserved for software usage
+
+ /* Asign PPI to Non-Secure domain */
+ msr(ICC_PPI_DOMAINR0_EL3, val);
+ isb();
+}
+
+void gic_secure_init(void)
+{
+ /*
+ * If GICv5 is not available, skip initialisation. The OS will probably
+ * fail with a warning, but this should be easier to debug than a
+ * failure within the boot wrapper.
+ */
+ if (!has_gicv5_sysreg())
+ return;
+
+ if (this_cpu_logical_id() == 0) {
+ gic_iwb_init();
+ gic_irs_init();
+ }
+
+ gic_ppi_init();
+
+ return;
+}
+
diff --git a/configure.ac b/configure.ac
index 6f486c4..f4faff7 100644
--- a/configure.ac
+++ b/configure.ac
@@ -141,18 +141,19 @@ AC_SUBST([XEN_CMDLINE], [$X_CMDLINE])
AC_ARG_WITH([gic],
- AS_HELP_STRING([--with-gic={v2|v3}], [select GIC version]),
+ AS_HELP_STRING([--with-gic={v2|v3|v5}], [select GIC version]),
[GIC_VERSION=$withval],
[GIC_VERSION=v2])
AS_CASE([$GIC_VERSION],
- [v2|v3], [],
- [AC_MSG_ERROR([Invalid GIC version: $GIC_VERSION (use v2 or v3)])])
+ [v2|v3|v5], [],
+ [AC_MSG_ERROR([Invalid GIC version: $GIC_VERSION (use v2, v3, or v5)])])
AC_SUBST([GIC_VERSION], [$GIC_VERSION])
AM_CONDITIONAL([GICV2], [test "x$GIC_VERSION" = "xv2"])
AM_CONDITIONAL([GICV3], [test "x$GIC_VERSION" = "xv3"])
+AM_CONDITIONAL([GICV5], [test "x$GIC_VERSION" = "xv5"])
# Ensure that we have all the needed programs
diff --git a/scripts/FDT.pm b/scripts/FDT.pm
index 9adf70b..3f49ba6 100755
--- a/scripts/FDT.pm
+++ b/scripts/FDT.pm
@@ -322,6 +322,22 @@ sub get_num_reg_cells
return ($ac, $sc);
}
+sub get_regname_idx
+{
+ my $self = shift;
+ my $regname = shift;
+
+ my $prop = $self->get_property("reg-names");
+
+ return undef if (not defined($prop));
+
+ my @names = $prop->read_strings();
+
+ my ($idx) = grep { $names[$_] eq $regname } 0 .. $#names;
+
+ return $idx;
+}
+
sub translate_address
{
my $self = shift;
diff --git a/scripts/findbase-by-regname.pl b/scripts/findbase-by-regname.pl
new file mode 100755
index 0000000..49cd0ce
--- /dev/null
+++ b/scripts/findbase-by-regname.pl
@@ -0,0 +1,44 @@
+#!/usr/bin/perl -w
+# Find device register base addresses.
+#
+# Usage: ./$0 <DTB> <regname> <compatible ...>
+#
+# Copyright (C) 2026 ARM Limited. All rights reserved.
+#
+# Use of this source code is governed by a BSD-style license that can be
+# found in the LICENSE.txt file.
+
+use warnings;
+use strict;
+
+use FDT;
+
+my $filename = shift;
+die("No filename provided") unless defined($filename);
+
+my $regname = shift;
+die("no reg regname provided") unless defined($regname);
+
+my @compats = shift;
+
+open (my $fh, "<:raw", $filename) or die("Unable to open file '$filename'");
+
+my $fdt = FDT->parse($fh) or die("Unable to parse DTB");
+
+my $root = $fdt->get_root();
+
+my @devs = ();
+for my $compat (@compats) {
+ push @devs, $root->find_compatible($compat);
+}
+
+# We only care about finding the first matching device
+my $dev = shift @devs;
+die("No matching devices found") if (not defined($dev));
+
+my $idx = $dev->get_regname_idx($regname);
+die("Cannot find reg name $regname") if (not defined($idx));
+my ($addr, $size) = $dev->get_translated_reg($idx);
+die("Cannot find reg entry $idx") if (not defined($addr) or not defined($size));
+
+printf("0x%016x\n", $addr);
--
2.34.1
^ permalink raw reply related [flat|nested] 7+ messages in thread
* Re: [BOOTWRAPPER PATCH v2 1/2] Introduce --with-gic option
2026-03-24 12:59 ` [BOOTWRAPPER PATCH v2 1/2] Introduce --with-gic option Vladimir Murzin
@ 2026-05-28 15:06 ` Sascha Bischoff
2026-05-29 9:47 ` Vladimir Murzin
0 siblings, 1 reply; 7+ messages in thread
From: Sascha Bischoff @ 2026-05-28 15:06 UTC (permalink / raw)
To: linux-arm-kernel@lists•infradead.org, Vladimir Murzin
Cc: maz@kernel•org, Joey Gouly, Mark Rutland, nd
Hi Vladimir,
Sorry for taking so long to get to this!
On Tue, 2026-03-24 at 12:59 +0000, Vladimir Murzin wrote:
> We are about adding support for another GIC version, so introduce a
nit: We are about to add support
> new --with-gic option to select the desired GIC version at configure
> time. The default remains v2, preserving existing behavior.
> Howevere,
nit: However
Aside from these nits, this looks good to me, so:
Reviewed-by: Sascha Bischoff <sascha.bischoff@arm•com>
Thanks,
Sascha
> for GICv3, we replace the previous --enable-gicv3 option with
> --with-gic=v3 which is backward-incompatible change (yet I hope we
> can
> live with that).
>
> Signed-off-by: Vladimir Murzin <vladimir.murzin@arm•com>
> ---
> Makefile.am | 8 +++++---
> common/{gic.c => gic-v2.c} | 0
> configure.ac | 23 ++++++++++++++++-------
> 3 files changed, 21 insertions(+), 10 deletions(-)
> rename common/{gic.c => gic-v2.c} (100%)
>
> diff --git a/Makefile.am b/Makefile.am
> index 0178e5d..2710494 100644
> --- a/Makefile.am
> +++ b/Makefile.am
> @@ -87,15 +87,17 @@ GIC_DIST_BASE := $(shell perl -I
> $(SCRIPT_DIR) $(SCRIPT_DIR)/findbase.pl $(KERNE
> GIC_RDIST_BASE := $(shell perl -I $(SCRIPT_DIR)
> $(SCRIPT_DIR)/findbase.pl $(KERNEL_DTB) 1 'arm,gic-v3')
> DEFINES += -DGIC_DIST_BASE=$(GIC_DIST_BASE)
> DEFINES += -DGIC_RDIST_BASE=$(GIC_RDIST_BASE)
> -COMMON_OBJ += gic-v3.o
> -else
> +endif
> +
> +if GICV2
> GIC_DIST_BASE := $(shell perl -I $(SCRIPT_DIR)
> $(SCRIPT_DIR)/findbase.pl $(KERNEL_DTB) 0 'arm,cortex-a15-gic')
> GIC_CPU_BASE := $(shell perl -I $(SCRIPT_DIR)
> $(SCRIPT_DIR)/findbase.pl $(KERNEL_DTB) 1 'arm,cortex-a15-gic')
> DEFINES += -DGIC_CPU_BASE=$(GIC_CPU_BASE)
> DEFINES += -DGIC_DIST_BASE=$(GIC_DIST_BASE)
> -COMMON_OBJ += gic.o
> endif
>
> +COMMON_OBJ += gic-$(GIC_VERSION).o
> +
> if KERNEL_32
> MBOX_OFFSET := 0x7ff8
> TEXT_LIMIT := 0x3000
> diff --git a/common/gic.c b/common/gic-v2.c
> similarity index 100%
> rename from common/gic.c
> rename to common/gic-v2.c
> diff --git a/configure.ac b/configure.ac
> index 42858df..6f486c4 100644
> --- a/configure.ac
> +++ b/configure.ac
> @@ -139,12 +139,21 @@ AC_ARG_WITH([xen-cmdline],
> [X_CMDLINE=$withval])
> AC_SUBST([XEN_CMDLINE], [$X_CMDLINE])
>
> -# Allow a user to pass --enable-gicv3
> -AC_ARG_ENABLE([gicv3],
> - AS_HELP_STRING([--enable-gicv3], [enable GICv3 instead of
> GICv2]),
> - [USE_GICV3=$enableval])
> -AM_CONDITIONAL([GICV3], [test "x$USE_GICV3" = "xyes"])
> -AS_IF([test "x$USE_GICV3" = "xyes"], [], [USE_GICV3=no])
> +
> +AC_ARG_WITH([gic],
> + AS_HELP_STRING([--with-gic={v2|v3}], [select GIC version]),
> + [GIC_VERSION=$withval],
> + [GIC_VERSION=v2])
> +
> +AS_CASE([$GIC_VERSION],
> + [v2|v3], [],
> + [AC_MSG_ERROR([Invalid GIC version: $GIC_VERSION (use v2 or
> v3)])])
> +
> +AC_SUBST([GIC_VERSION], [$GIC_VERSION])
> +
> +AM_CONDITIONAL([GICV2], [test "x$GIC_VERSION" = "xv2"])
> +AM_CONDITIONAL([GICV3], [test "x$GIC_VERSION" = "xv3"])
> +
>
> # Ensure that we have all the needed programs
> AC_PROG_CC
> @@ -174,7 +183,7 @@ echo " Device tree compiler:
> ${DTC}"
> echo " Linux kernel command line: ${CMDLINE}"
> echo " Embedded initrd: ${FILESYSTEM:-NONE}"
> echo " Use PSCI? ${USE_PSCI}"
> -echo " Use GICv3? ${USE_GICV3}"
> +echo " GIC version: ${GIC_VERSION}"
> echo " Boot-wrapper execution state: AArch${BOOTWRAPPER_ES}"
> echo " Kernel execution state: AArch${KERNEL_ES}"
> echo " Xen image ${XEN_IMAGE:-NONE}"
^ permalink raw reply [flat|nested] 7+ messages in thread
* Re: [BOOTWRAPPER PATCH v2 2/2] Add support for GICv5
2026-03-24 12:59 ` [BOOTWRAPPER PATCH v2 2/2] Add support for GICv5 Vladimir Murzin
@ 2026-05-28 15:10 ` Sascha Bischoff
2026-05-29 9:48 ` Vladimir Murzin
0 siblings, 1 reply; 7+ messages in thread
From: Sascha Bischoff @ 2026-05-28 15:10 UTC (permalink / raw)
To: linux-arm-kernel@lists•infradead.org, Vladimir Murzin
Cc: maz@kernel•org, Joey Gouly, Mark Rutland, nd
Hi Vladimir,
This looks good overall. There are a few nits around comments and one
incorrect comment, but the code itself looks good to me and matches the
spec as far as I can tell.
I've gone and tested this, and it works as advertised to boot Linux
(and run KVM) on a GICv5-enabled FVP. Hence:
Tested-by: Sascha Bischoff <sascha.bischoff@arm•com>
On Tue, 2026-03-24 at 12:59 +0000, Vladimir Murzin wrote:
> Performs the minimal initialization required for GICv5 support. GICv5
> support can be requested with --with-gic=v5.
>
> Signed-off-by: Vladimir Murzin <vladimir.murzin@arm•com>
> ---
> Makefile.am | 7 ++
> arch/aarch64/include/asm/cpu.h | 11 +++
> common/gic-v5.c | 134
> +++++++++++++++++++++++++++++++++
> configure.ac | 7 +-
> scripts/FDT.pm | 16 ++++
> scripts/findbase-by-regname.pl | 44 +++++++++++
> 6 files changed, 216 insertions(+), 3 deletions(-)
> create mode 100644 common/gic-v5.c
> create mode 100755 scripts/findbase-by-regname.pl
>
> diff --git a/Makefile.am b/Makefile.am
> index 2710494..aacd639 100644
> --- a/Makefile.am
> +++ b/Makefile.am
> @@ -82,6 +82,13 @@ PSCI_NODE :=
> CPU_NODES :=
> endif
>
> +if GICV5
> +GIC_IRS_BASE := $(shell perl -I $(SCRIPT_DIR)
> $(SCRIPT_DIR)/findbase-by-regname.pl $(KERNEL_DTB) "el3-config"
> 'arm,gic-v5-irs')
> +GIC_IWB_BASE := $(shell perl -I $(SCRIPT_DIR)
> $(SCRIPT_DIR)/findbase.pl $(KERNEL_DTB) 0 'arm,gic-v5-iwb')
> +DEFINES += -DGIC_IRS_BASE=$(GIC_IRS_BASE)
> +DEFINES += -DGIC_IWB_BASE=$(GIC_IWB_BASE)
> +endif
> +
> if GICV3
> GIC_DIST_BASE := $(shell perl -I $(SCRIPT_DIR)
> $(SCRIPT_DIR)/findbase.pl $(KERNEL_DTB) 0 'arm,gic-v3')
> GIC_RDIST_BASE := $(shell perl -I $(SCRIPT_DIR)
> $(SCRIPT_DIR)/findbase.pl $(KERNEL_DTB) 1 'arm,gic-v3')
> diff --git a/arch/aarch64/include/asm/cpu.h
> b/arch/aarch64/include/asm/cpu.h
> index ac50474..af4191c 100644
> --- a/arch/aarch64/include/asm/cpu.h
> +++ b/arch/aarch64/include/asm/cpu.h
> @@ -128,6 +128,7 @@
> #define ID_AA64PFR1_EL1_THE BITS(51, 48)
>
> #define ID_AA64PFR2_EL1 s3_0_c0_c4_2
> +#define ID_AA64PFR2_EL1_GCIE BITS(15, 12)
> #define ID_AA64PFR2_EL1_FPMR BITS(35, 32)
>
> #define ID_AA64SMFR0_EL1 s3_0_c0_c4_5
> @@ -169,6 +170,11 @@
> #define ICC_CTLR_EL3 S3_6_C12_C12_4
> #define ICC_PMR_EL1 S3_0_C4_C6_0
>
> +#define ICC_PPI_DOMAINR0_EL3 S3_6_C12_C8_4
> +#define ICC_PPI_DOMAINR1_EL3 S3_6_C12_C8_5
> +#define ICC_PPI_DOMAINR2_EL3 S3_6_C12_C8_6
> +#define ICC_PPI_DOMAINR3_EL3 S3_6_C12_C8_7
> +
> #define VSTCR_EL2 s3_4_c2_c6_2
> #define VSCTLR_EL2 s3_4_c2_c0_0
>
> @@ -245,6 +251,11 @@ static inline int has_gicv3_sysreg(void)
> return !!mrs_field(ID_AA64PFR0_EL1, GIC);
> }
>
> +static inline int has_gicv5_sysreg(void)
> +{
> + return !!mrs_field(ID_AA64PFR2_EL1, GCIE);
> +}
> +
> #endif /* !__ASSEMBLY__ */
>
> #endif
> diff --git a/common/gic-v5.c b/common/gic-v5.c
> new file mode 100644
> index 0000000..cef2ece
> --- /dev/null
> +++ b/common/gic-v5.c
> @@ -0,0 +1,134 @@
> +/*
> + * gic-v5.c
> + *
> + * Copyright (C) 2025 ARM Limited. All rights reserved.
> + *
> + * Use of this source code is governed by a BSD-style license that
> can be
> + * found in the LICENSE.txt file.
> + */
> +
> +#include <stdint.h>
> +
> +#include <cpu.h>
> +#include <gic.h>
> +#include <asm/io.h>
> +
> +#define IWB_IDR0 0x0
> +#define IWB_IDR0_IW_RANGE_SHIFT 0x0
> +#define IWB_IDR0_IW_RANGE_MASK 0x7ff
> +
> +#define IWB_CR0 0x80
> +#define IWB_CR0_IWBEN (1 << 0)
> +#define IWB_CR0_IDLE (1 << 1)
> +
> +#define IWB_WENABLE_STATUSR 0xc0
> +#define IWB_WENABLE_STATUSR_IDLE (1 << 0)
> +
> +#define IWB_WDOMAIN_STATUSR 0xc4
> +#define IWB_WDOMAIN_STATUSR_IDLE (1 << 0)
> +
> +#define IWB_WENABLER 0x2000
> +#define IWB_WDOMAINR 0x8000
> +
> +#define IRS_IDR6 0x0018
> +#define IRS_IDR6_SPI_IRS_RANGE_MASK 0x1ffffff
> +
> +#define IRS_IDR7 0x001c
> +#define IRS_IDR7_SPI_BASE_MASK 0xffffff
> +
> +#define IRS_SPI_SELR 0x108
> +#define IRS_SPI_DOMAINR 0x10c
> +
> +#define IRS_SPI_STATUSR 0x0118
> +#define IRS_SPI_STATUSR_IDLE (1 << 0)
> +
> +
nit: extra newline
> +static void gic_iwb_init(void) {
> + void *iwb_ptr = (void *)GIC_IWB_BASE;
> + unsigned int num;
> + unsigned int i;
> +
> + /* Get number of implemented wires */
This comment is wrong. This isn't getting the number of wires. It is
getting the number of wire control registers, which is
number_of_wires/32.
> + num = ((raw_readl(iwb_ptr + IWB_IDR0) >>
> IWB_IDR0_IW_RANGE_SHIFT) & IWB_IDR0_IW_RANGE_MASK) + 1;
> +
> + /* Disable all wires */
> + for (i = 0; i < num; i++)
> + raw_writel(0, iwb_ptr + IWB_WENABLER + i * 4);
> +
> +
Extra newline
> + while (!(raw_readl(iwb_ptr + IWB_WENABLE_STATUSR) &
> IWB_WENABLE_STATUSR_IDLE));
> +
> + /* Asign all wires to Non-Secure domain */
nit: Assign
> + for (i = 0; i < num * 2; i++)
> + raw_writel(0x55555555, iwb_ptr + IWB_WDOMAINR + i *
> 4);
> +
> + while (!(raw_readl(iwb_ptr + IWB_WDOMAIN_STATUSR) &
> IWB_WDOMAIN_STATUSR_IDLE));
> +
> + /* Enable IWB */
> + raw_writel(IWB_CR0_IWBEN, iwb_ptr + IWB_CR0);
> +
> + while (!(raw_readl(iwb_ptr + IWB_CR0) & IWB_CR0_IDLE));
> +}
> +
> +static void gic_irs_init(void) {
> + void *irs_ptr = (void *)GIC_IRS_BASE;
> + unsigned int range;
> + unsigned int base;
> + unsigned int i;
> +
> + /* Get the range of implemented SPI's ids */
nit: SPI IDs (or just SPIs)
> + base = raw_readl(irs_ptr + IRS_IDR7) &
> IRS_IDR7_SPI_BASE_MASK;
> + range = raw_readl(irs_ptr + IRS_IDR6) &
> IRS_IDR6_SPI_IRS_RANGE_MASK;
> +
> + for (i = base; i < base + range; i++) {
> + /* Select SPI */
> + raw_writel(i, irs_ptr + IRS_SPI_SELR);
> + while (!(raw_readl(irs_ptr + IRS_SPI_STATUSR) &
> IRS_SPI_STATUSR_IDLE));
> +
> + /* Asign SPI to Non-Secure domain */
> + raw_writel(1, irs_ptr + IRS_SPI_DOMAINR);
> + while (!(raw_readl(irs_ptr + IRS_SPI_STATUSR) &
> IRS_SPI_STATUSR_IDLE));
> + }
> +}
> +
> +static void gic_ppi_init(void) {
> + uint64_t val = 0;
> +
> + val |= 1UL << (2 * 31); // Trace Buffer Unit
> + val |= 1UL << (2 * 30); // EL1 Physical Timer
> + val |= 1UL << (2 * 28); // Non-secure EL2 Virtual Timer
> + val |= 1UL << (2 * 27); // EL1 Virtual Timer
> + val |= 1UL << (2 * 26); // Non-secure EL2 Physical Timer
> + val |= 1UL << (2 * 25); // GIC maintenance interrupt
> + val |= 1UL << (2 * 24); // Generic CTI interrupt trigger
> event
> + val |= 1UL << (2 * 23); // PMU overflow interrupt request
> + val |= 1UL << (2 * 22); // Debug communication channel
> + val |= 1UL << (2 * 21); // Profiling Buffer management
> interrupt request
> + val |= 1UL << (2 * 15); // Hardware accelerator for cleaning
> Dirty state interrupt
> + val |= 1UL << (2 * 3); // Reserved for software usage
> +
> + /* Asign PPI to Non-Secure domain */
nit: Assign PPIs
> + msr(ICC_PPI_DOMAINR0_EL3, val);
> + isb();
> +}
> +
> +void gic_secure_init(void)
> +{
> + /*
> + * If GICv5 is not available, skip initialisation. The OS
> will probably
> + * fail with a warning, but this should be easier to debug
> than a
> + * failure within the boot wrapper.
> + */
> + if (!has_gicv5_sysreg())
> + return;
> +
> + if (this_cpu_logical_id() == 0) {
> + gic_iwb_init();
> + gic_irs_init();
> + }
> +
> + gic_ppi_init();
> +
> + return;
> +}
> +
> diff --git a/configure.ac b/configure.ac
> index 6f486c4..f4faff7 100644
> --- a/configure.ac
> +++ b/configure.ac
> @@ -141,18 +141,19 @@ AC_SUBST([XEN_CMDLINE], [$X_CMDLINE])
>
>
> AC_ARG_WITH([gic],
> - AS_HELP_STRING([--with-gic={v2|v3}], [select GIC version]),
> + AS_HELP_STRING([--with-gic={v2|v3|v5}], [select GIC version]),
> [GIC_VERSION=$withval],
> [GIC_VERSION=v2])
>
> AS_CASE([$GIC_VERSION],
> - [v2|v3], [],
> - [AC_MSG_ERROR([Invalid GIC version: $GIC_VERSION (use v2 or
> v3)])])
> + [v2|v3|v5], [],
> + [AC_MSG_ERROR([Invalid GIC version: $GIC_VERSION (use v2, v3, or
> v5)])])
>
> AC_SUBST([GIC_VERSION], [$GIC_VERSION])
>
> AM_CONDITIONAL([GICV2], [test "x$GIC_VERSION" = "xv2"])
> AM_CONDITIONAL([GICV3], [test "x$GIC_VERSION" = "xv3"])
> +AM_CONDITIONAL([GICV5], [test "x$GIC_VERSION" = "xv5"])
>
>
> # Ensure that we have all the needed programs
> diff --git a/scripts/FDT.pm b/scripts/FDT.pm
> index 9adf70b..3f49ba6 100755
> --- a/scripts/FDT.pm
> +++ b/scripts/FDT.pm
> @@ -322,6 +322,22 @@ sub get_num_reg_cells
> return ($ac, $sc);
> }
>
> +sub get_regname_idx
> +{
> + my $self = shift;
> + my $regname = shift;
> +
> + my $prop = $self->get_property("reg-names");
> +
> + return undef if (not defined($prop));
> +
> + my @names = $prop->read_strings();
> +
> + my ($idx) = grep { $names[$_] eq $regname } 0 .. $#names;
> +
> + return $idx;
> +}
> +
> sub translate_address
> {
> my $self = shift;
> diff --git a/scripts/findbase-by-regname.pl b/scripts/findbase-by-
> regname.pl
> new file mode 100755
> index 0000000..49cd0ce
> --- /dev/null
> +++ b/scripts/findbase-by-regname.pl
> @@ -0,0 +1,44 @@
> +#!/usr/bin/perl -w
> +# Find device register base addresses.
> +#
> +# Usage: ./$0 <DTB> <regname> <compatible ...>
> +#
> +# Copyright (C) 2026 ARM Limited. All rights reserved.
> +#
> +# Use of this source code is governed by a BSD-style license that
> can be
> +# found in the LICENSE.txt file.
> +
> +use warnings;
> +use strict;
> +
> +use FDT;
> +
> +my $filename = shift;
> +die("No filename provided") unless defined($filename);
> +
> +my $regname = shift;
> +die("no reg regname provided") unless defined($regname);
> +
> +my @compats = shift;
> +
> +open (my $fh, "<:raw", $filename) or die("Unable to open file
> '$filename'");
> +
> +my $fdt = FDT->parse($fh) or die("Unable to parse DTB");
> +
> +my $root = $fdt->get_root();
> +
> +my @devs = ();
> +for my $compat (@compats) {
> + push @devs, $root->find_compatible($compat);
> +}
> +
> +# We only care about finding the first matching device
> +my $dev = shift @devs;
> +die("No matching devices found") if (not defined($dev));
> +
> +my $idx = $dev->get_regname_idx($regname);
> +die("Cannot find reg name $regname") if (not defined($idx));
> +my ($addr, $size) = $dev->get_translated_reg($idx);
> +die("Cannot find reg entry $idx") if (not defined($addr) or not
> defined($size));
> +
> +printf("0x%016x\n", $addr);
Thanks,
Sascha
^ permalink raw reply [flat|nested] 7+ messages in thread
* Re: [BOOTWRAPPER PATCH v2 1/2] Introduce --with-gic option
2026-05-28 15:06 ` Sascha Bischoff
@ 2026-05-29 9:47 ` Vladimir Murzin
0 siblings, 0 replies; 7+ messages in thread
From: Vladimir Murzin @ 2026-05-29 9:47 UTC (permalink / raw)
To: Sascha Bischoff, linux-arm-kernel@lists•infradead.org
Cc: maz@kernel•org, Joey Gouly, Mark Rutland, nd
On 5/28/26 16:06, Sascha Bischoff wrote:
> Hi Vladimir,
>
> Sorry for taking so long to get to this!
>
> On Tue, 2026-03-24 at 12:59 +0000, Vladimir Murzin wrote:
>> We are about adding support for another GIC version, so introduce a
> nit: We are about to add support
>
>> new --with-gic option to select the desired GIC version at configure
>> time. The default remains v2, preserving existing behavior.
>> Howevere,
> nit: However
>
> Aside from these nits, this looks good to me, so:
> Reviewed-by: Sascha Bischoff <sascha.bischoff@arm•com>
>
> Thanks,
> Sascha
Thanks Sascha, all fixed locally.
Cheers
Vladimir
^ permalink raw reply [flat|nested] 7+ messages in thread
* Re: [BOOTWRAPPER PATCH v2 2/2] Add support for GICv5
2026-05-28 15:10 ` Sascha Bischoff
@ 2026-05-29 9:48 ` Vladimir Murzin
0 siblings, 0 replies; 7+ messages in thread
From: Vladimir Murzin @ 2026-05-29 9:48 UTC (permalink / raw)
To: Sascha Bischoff, linux-arm-kernel@lists•infradead.org
Cc: maz@kernel•org, Joey Gouly, Mark Rutland, nd
Hi Sascha,
On 5/28/26 16:10, Sascha Bischoff wrote:
> Hi Vladimir,
>
> This looks good overall. There are a few nits around comments and one
> incorrect comment, but the code itself looks good to me and matches the
> spec as far as I can tell.
>
> I've gone and tested this, and it works as advertised to boot Linux
> (and run KVM) on a GICv5-enabled FVP. Hence:
>
> Tested-by: Sascha Bischoff <sascha.bischoff@arm•com>
>
Happy to hear it works not only in my setup :)
> On Tue, 2026-03-24 at 12:59 +0000, Vladimir Murzin wrote:
>> Performs the minimal initialization required for GICv5 support. GICv5
>> support can be requested with --with-gic=v5.
>>
>> Signed-off-by: Vladimir Murzin <vladimir.murzin@arm•com>
>> ---
>> Makefile.am | 7 ++
>> arch/aarch64/include/asm/cpu.h | 11 +++
>> common/gic-v5.c | 134
>> +++++++++++++++++++++++++++++++++
>> configure.ac | 7 +-
>> scripts/FDT.pm | 16 ++++
>> scripts/findbase-by-regname.pl | 44 +++++++++++
>> 6 files changed, 216 insertions(+), 3 deletions(-)
>> create mode 100644 common/gic-v5.c
>> create mode 100755 scripts/findbase-by-regname.pl
>>
>> diff --git a/Makefile.am b/Makefile.am
>> index 2710494..aacd639 100644
>> --- a/Makefile.am
>> +++ b/Makefile.am
>> @@ -82,6 +82,13 @@ PSCI_NODE :=
>> CPU_NODES :=
>> endif
>>
>> +if GICV5
>> +GIC_IRS_BASE := $(shell perl -I $(SCRIPT_DIR)
>> $(SCRIPT_DIR)/findbase-by-regname.pl $(KERNEL_DTB) "el3-config"
>> 'arm,gic-v5-irs')
>> +GIC_IWB_BASE := $(shell perl -I $(SCRIPT_DIR)
>> $(SCRIPT_DIR)/findbase.pl $(KERNEL_DTB) 0 'arm,gic-v5-iwb')
>> +DEFINES += -DGIC_IRS_BASE=$(GIC_IRS_BASE)
>> +DEFINES += -DGIC_IWB_BASE=$(GIC_IWB_BASE)
>> +endif
>> +
>> if GICV3
>> GIC_DIST_BASE := $(shell perl -I $(SCRIPT_DIR)
>> $(SCRIPT_DIR)/findbase.pl $(KERNEL_DTB) 0 'arm,gic-v3')
>> GIC_RDIST_BASE := $(shell perl -I $(SCRIPT_DIR)
>> $(SCRIPT_DIR)/findbase.pl $(KERNEL_DTB) 1 'arm,gic-v3')
>> diff --git a/arch/aarch64/include/asm/cpu.h
>> b/arch/aarch64/include/asm/cpu.h
>> index ac50474..af4191c 100644
>> --- a/arch/aarch64/include/asm/cpu.h
>> +++ b/arch/aarch64/include/asm/cpu.h
>> @@ -128,6 +128,7 @@
>> #define ID_AA64PFR1_EL1_THE BITS(51, 48)
>>
>> #define ID_AA64PFR2_EL1 s3_0_c0_c4_2
>> +#define ID_AA64PFR2_EL1_GCIE BITS(15, 12)
>> #define ID_AA64PFR2_EL1_FPMR BITS(35, 32)
>>
>> #define ID_AA64SMFR0_EL1 s3_0_c0_c4_5
>> @@ -169,6 +170,11 @@
>> #define ICC_CTLR_EL3 S3_6_C12_C12_4
>> #define ICC_PMR_EL1 S3_0_C4_C6_0
>>
>> +#define ICC_PPI_DOMAINR0_EL3 S3_6_C12_C8_4
>> +#define ICC_PPI_DOMAINR1_EL3 S3_6_C12_C8_5
>> +#define ICC_PPI_DOMAINR2_EL3 S3_6_C12_C8_6
>> +#define ICC_PPI_DOMAINR3_EL3 S3_6_C12_C8_7
>> +
>> #define VSTCR_EL2 s3_4_c2_c6_2
>> #define VSCTLR_EL2 s3_4_c2_c0_0
>>
>> @@ -245,6 +251,11 @@ static inline int has_gicv3_sysreg(void)
>> return !!mrs_field(ID_AA64PFR0_EL1, GIC);
>> }
>>
>> +static inline int has_gicv5_sysreg(void)
>> +{
>> + return !!mrs_field(ID_AA64PFR2_EL1, GCIE);
>> +}
>> +
>> #endif /* !__ASSEMBLY__ */
>>
>> #endif
>> diff --git a/common/gic-v5.c b/common/gic-v5.c
>> new file mode 100644
>> index 0000000..cef2ece
>> --- /dev/null
>> +++ b/common/gic-v5.c
>> @@ -0,0 +1,134 @@
>> +/*
>> + * gic-v5.c
>> + *
>> + * Copyright (C) 2025 ARM Limited. All rights reserved.
>> + *
>> + * Use of this source code is governed by a BSD-style license that
>> can be
>> + * found in the LICENSE.txt file.
>> + */
>> +
>> +#include <stdint.h>
>> +
>> +#include <cpu.h>
>> +#include <gic.h>
>> +#include <asm/io.h>
>> +
>> +#define IWB_IDR0 0x0
>> +#define IWB_IDR0_IW_RANGE_SHIFT 0x0
>> +#define IWB_IDR0_IW_RANGE_MASK 0x7ff
>> +
>> +#define IWB_CR0 0x80
>> +#define IWB_CR0_IWBEN (1 << 0)
>> +#define IWB_CR0_IDLE (1 << 1)
>> +
>> +#define IWB_WENABLE_STATUSR 0xc0
>> +#define IWB_WENABLE_STATUSR_IDLE (1 << 0)
>> +
>> +#define IWB_WDOMAIN_STATUSR 0xc4
>> +#define IWB_WDOMAIN_STATUSR_IDLE (1 << 0)
>> +
>> +#define IWB_WENABLER 0x2000
>> +#define IWB_WDOMAINR 0x8000
>> +
>> +#define IRS_IDR6 0x0018
>> +#define IRS_IDR6_SPI_IRS_RANGE_MASK 0x1ffffff
>> +
>> +#define IRS_IDR7 0x001c
>> +#define IRS_IDR7_SPI_BASE_MASK 0xffffff
>> +
>> +#define IRS_SPI_SELR 0x108
>> +#define IRS_SPI_DOMAINR 0x10c
>> +
>> +#define IRS_SPI_STATUSR 0x0118
>> +#define IRS_SPI_STATUSR_IDLE (1 << 0)
>> +
>> +
> nit: extra newline
>
>> +static void gic_iwb_init(void) {
>> + void *iwb_ptr = (void *)GIC_IWB_BASE;
>> + unsigned int num;
>> + unsigned int i;
>> +
>> + /* Get number of implemented wires */
> This comment is wrong. This isn't getting the number of wires. It is
> getting the number of wire control registers, which is
> number_of_wires/32.
>
>> + num = ((raw_readl(iwb_ptr + IWB_IDR0) >>
>> IWB_IDR0_IW_RANGE_SHIFT) & IWB_IDR0_IW_RANGE_MASK) + 1;
>> +
>> + /* Disable all wires */
>> + for (i = 0; i < num; i++)
>> + raw_writel(0, iwb_ptr + IWB_WENABLER + i * 4);
>> +
>> +
> Extra newline
>
>> + while (!(raw_readl(iwb_ptr + IWB_WENABLE_STATUSR) &
>> IWB_WENABLE_STATUSR_IDLE));
>> +
>> + /* Asign all wires to Non-Secure domain */
> nit: Assign
>
>> + for (i = 0; i < num * 2; i++)
>> + raw_writel(0x55555555, iwb_ptr + IWB_WDOMAINR + i *
>> 4);
>> +
>> + while (!(raw_readl(iwb_ptr + IWB_WDOMAIN_STATUSR) &
>> IWB_WDOMAIN_STATUSR_IDLE));
>> +
>> + /* Enable IWB */
>> + raw_writel(IWB_CR0_IWBEN, iwb_ptr + IWB_CR0);
>> +
>> + while (!(raw_readl(iwb_ptr + IWB_CR0) & IWB_CR0_IDLE));
>> +}
>> +
>> +static void gic_irs_init(void) {
>> + void *irs_ptr = (void *)GIC_IRS_BASE;
>> + unsigned int range;
>> + unsigned int base;
>> + unsigned int i;
>> +
>> + /* Get the range of implemented SPI's ids */
> nit: SPI IDs (or just SPIs)
>
>> + base = raw_readl(irs_ptr + IRS_IDR7) &
>> IRS_IDR7_SPI_BASE_MASK;
>> + range = raw_readl(irs_ptr + IRS_IDR6) &
>> IRS_IDR6_SPI_IRS_RANGE_MASK;
>> +
>> + for (i = base; i < base + range; i++) {
>> + /* Select SPI */
>> + raw_writel(i, irs_ptr + IRS_SPI_SELR);
>> + while (!(raw_readl(irs_ptr + IRS_SPI_STATUSR) &
>> IRS_SPI_STATUSR_IDLE));
>> +
>> + /* Asign SPI to Non-Secure domain */
>> + raw_writel(1, irs_ptr + IRS_SPI_DOMAINR);
>> + while (!(raw_readl(irs_ptr + IRS_SPI_STATUSR) &
>> IRS_SPI_STATUSR_IDLE));
>> + }
>> +}
>> +
>> +static void gic_ppi_init(void) {
>> + uint64_t val = 0;
>> +
>> + val |= 1UL << (2 * 31); // Trace Buffer Unit
>> + val |= 1UL << (2 * 30); // EL1 Physical Timer
>> + val |= 1UL << (2 * 28); // Non-secure EL2 Virtual Timer
>> + val |= 1UL << (2 * 27); // EL1 Virtual Timer
>> + val |= 1UL << (2 * 26); // Non-secure EL2 Physical Timer
>> + val |= 1UL << (2 * 25); // GIC maintenance interrupt
>> + val |= 1UL << (2 * 24); // Generic CTI interrupt trigger
>> event
>> + val |= 1UL << (2 * 23); // PMU overflow interrupt request
>> + val |= 1UL << (2 * 22); // Debug communication channel
>> + val |= 1UL << (2 * 21); // Profiling Buffer management
>> interrupt request
>> + val |= 1UL << (2 * 15); // Hardware accelerator for cleaning
>> Dirty state interrupt
>> + val |= 1UL << (2 * 3); // Reserved for software usage
>> +
>> + /* Asign PPI to Non-Secure domain */
> nit: Assign PPIs
>
>> + msr(ICC_PPI_DOMAINR0_EL3, val);
>> + isb();
>> +}
>> +
>> +void gic_secure_init(void)
>> +{
>> + /*
>> + * If GICv5 is not available, skip initialisation. The OS
>> will probably
>> + * fail with a warning, but this should be easier to debug
>> than a
>> + * failure within the boot wrapper.
>> + */
>> + if (!has_gicv5_sysreg())
>> + return;
>> +
>> + if (this_cpu_logical_id() == 0) {
>> + gic_iwb_init();
>> + gic_irs_init();
>> + }
>> +
>> + gic_ppi_init();
>> +
>> + return;
>> +}
>> +
>> diff --git a/configure.ac b/configure.ac
>> index 6f486c4..f4faff7 100644
>> --- a/configure.ac
>> +++ b/configure.ac
>> @@ -141,18 +141,19 @@ AC_SUBST([XEN_CMDLINE], [$X_CMDLINE])
>>
>>
>> AC_ARG_WITH([gic],
>> - AS_HELP_STRING([--with-gic={v2|v3}], [select GIC version]),
>> + AS_HELP_STRING([--with-gic={v2|v3|v5}], [select GIC version]),
>> [GIC_VERSION=$withval],
>> [GIC_VERSION=v2])
>>
>> AS_CASE([$GIC_VERSION],
>> - [v2|v3], [],
>> - [AC_MSG_ERROR([Invalid GIC version: $GIC_VERSION (use v2 or
>> v3)])])
>> + [v2|v3|v5], [],
>> + [AC_MSG_ERROR([Invalid GIC version: $GIC_VERSION (use v2, v3, or
>> v5)])])
>>
>> AC_SUBST([GIC_VERSION], [$GIC_VERSION])
>>
>> AM_CONDITIONAL([GICV2], [test "x$GIC_VERSION" = "xv2"])
>> AM_CONDITIONAL([GICV3], [test "x$GIC_VERSION" = "xv3"])
>> +AM_CONDITIONAL([GICV5], [test "x$GIC_VERSION" = "xv5"])
>>
>>
>> # Ensure that we have all the needed programs
>> diff --git a/scripts/FDT.pm b/scripts/FDT.pm
>> index 9adf70b..3f49ba6 100755
>> --- a/scripts/FDT.pm
>> +++ b/scripts/FDT.pm
>> @@ -322,6 +322,22 @@ sub get_num_reg_cells
>> return ($ac, $sc);
>> }
>>
>> +sub get_regname_idx
>> +{
>> + my $self = shift;
>> + my $regname = shift;
>> +
>> + my $prop = $self->get_property("reg-names");
>> +
>> + return undef if (not defined($prop));
>> +
>> + my @names = $prop->read_strings();
>> +
>> + my ($idx) = grep { $names[$_] eq $regname } 0 .. $#names;
>> +
>> + return $idx;
>> +}
>> +
>> sub translate_address
>> {
>> my $self = shift;
>> diff --git a/scripts/findbase-by-regname.pl b/scripts/findbase-by-
>> regname.pl
>> new file mode 100755
>> index 0000000..49cd0ce
>> --- /dev/null
>> +++ b/scripts/findbase-by-regname.pl
>> @@ -0,0 +1,44 @@
>> +#!/usr/bin/perl -w
>> +# Find device register base addresses.
>> +#
>> +# Usage: ./$0 <DTB> <regname> <compatible ...>
>> +#
>> +# Copyright (C) 2026 ARM Limited. All rights reserved.
>> +#
>> +# Use of this source code is governed by a BSD-style license that
>> can be
>> +# found in the LICENSE.txt file.
>> +
>> +use warnings;
>> +use strict;
>> +
>> +use FDT;
>> +
>> +my $filename = shift;
>> +die("No filename provided") unless defined($filename);
>> +
>> +my $regname = shift;
>> +die("no reg regname provided") unless defined($regname);
>> +
>> +my @compats = shift;
>> +
>> +open (my $fh, "<:raw", $filename) or die("Unable to open file
>> '$filename'");
>> +
>> +my $fdt = FDT->parse($fh) or die("Unable to parse DTB");
>> +
>> +my $root = $fdt->get_root();
>> +
>> +my @devs = ();
>> +for my $compat (@compats) {
>> + push @devs, $root->find_compatible($compat);
>> +}
>> +
>> +# We only care about finding the first matching device
>> +my $dev = shift @devs;
>> +die("No matching devices found") if (not defined($dev));
>> +
>> +my $idx = $dev->get_regname_idx($regname);
>> +die("Cannot find reg name $regname") if (not defined($idx));
>> +my ($addr, $size) = $dev->get_translated_reg($idx);
>> +die("Cannot find reg entry $idx") if (not defined($addr) or not
>> defined($size));
>> +
>> +printf("0x%016x\n", $addr);
> Thanks,
> Sascha
>
Thanks Sascha, all fixed locally.
Cheers
Vladimir
^ permalink raw reply [flat|nested] 7+ messages in thread
end of thread, other threads:[~2026-05-29 9:49 UTC | newest]
Thread overview: 7+ messages (download: mbox.gz follow: Atom feed
-- links below jump to the message on this page --
2026-03-24 12:59 [BOOTWRAPPER PATCH v2 0/2] Support GICv5 Vladimir Murzin
2026-03-24 12:59 ` [BOOTWRAPPER PATCH v2 1/2] Introduce --with-gic option Vladimir Murzin
2026-05-28 15:06 ` Sascha Bischoff
2026-05-29 9:47 ` Vladimir Murzin
2026-03-24 12:59 ` [BOOTWRAPPER PATCH v2 2/2] Add support for GICv5 Vladimir Murzin
2026-05-28 15:10 ` Sascha Bischoff
2026-05-29 9:48 ` Vladimir Murzin
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox