[boot-wrapper-aarch64 PATCH] Enable GCS if it is present in the HW
Mark Rutland
mark.rutland at arm.com
Mon Jul 7 05:32:12 PDT 2025
Hi Tamas,
Usually we'd have a commit log here, mentioning and documents referenced
(e.g. ARM ARM, booting.rst), and any interdependencies (e.g. other
features that might need to be enabled first).
On Mon, Jul 07, 2025 at 11:54:30AM +0200, Tamas Kaman wrote:
> Signed-off-by: Tamas Kaman <tamas.kaman at arm.com>
> ---
> arch/aarch64/include/asm/cpu.h | 5 +++++
> arch/aarch64/init.c | 7 +++++++
> 2 files changed, 12 insertions(+)
>
> diff --git a/arch/aarch64/include/asm/cpu.h b/arch/aarch64/include/asm/cpu.h
> index ac50474..9d6f0fc 100644
> --- a/arch/aarch64/include/asm/cpu.h
> +++ b/arch/aarch64/include/asm/cpu.h
> @@ -70,6 +70,7 @@
> #define SCR_EL3_ECVEN BIT(28)
> #define SCR_EL3_TME BIT(34)
> #define SCR_EL3_HXEn BIT(38)
> +#define SCR_EL3_GCSEn BIT(39)
> #define SCR_EL3_EnTP2 BIT(41)
> #define SCR_EL3_RCWMASKEn BIT(42)
> #define SCR_EL3_TCR2EN BIT(43)
> @@ -125,6 +126,7 @@
> #define ID_AA64PFR1_EL1_MTE BITS(11, 8)
> #define ID_AA64PFR1_EL1_SME BITS(27, 24)
> #define ID_AA64PFR1_EL1_CSV2_frac BITS(35, 32)
> +#define ID_AA64PFR1_EL1_GCS BITS(47, 44)
The two new definitions above look right to me per ARM DDI 0487 L.a
sections D24.2.163 and D24.2.88.
> #define ID_AA64PFR1_EL1_THE BITS(51, 48)
>
> #define ID_AA64PFR2_EL1 s3_0_c0_c4_2
> @@ -133,6 +135,9 @@
> #define ID_AA64SMFR0_EL1 s3_0_c0_c4_5
> #define ID_AA64SMFR0_EL1_FA64 BIT(63)
>
> +#define HCRX_EL2 s3_4_c1_c2_2
> +#define HCRX_EL2_GCSEn BIT(22)
This looks a bit suspicious, given it wasn't mentioned earlier, and
given we don't poke this for anythign else so far.
More on that below.
> +
> /*
> * Initial register values required for the boot-wrapper to run out-of-reset.
> */
> diff --git a/arch/aarch64/init.c b/arch/aarch64/init.c
> index cb24f4e..f815e6a 100644
> --- a/arch/aarch64/init.c
> +++ b/arch/aarch64/init.c
> @@ -118,6 +118,13 @@ static void cpu_init_el3(void)
> if (mrs_field(ID_AA64PFR1_EL1, MTE) >= 2)
> scr |= SCR_EL3_ATA;
>
> + if (mrs_field(ID_AA64PFR1_EL1, GCS)) {
> + scr |= SCR_EL3_GCSEn;
> + unsigned long hcrx_el2 = mrs(HCRX_EL2);
> + hcrx_el2 |= HCRX_EL2_GCSEn;
> + msr(HCRX_EL2, hcrx_el2);
> + }
As a general policy, the boot wrapper avoids RMW sequences, and
initializes all bits in registers to specific values, so this doesn't
look right.
We genreally follow a pattern of accumulating control bits with a final
write, e.g.
unsigned long ctrl_x = DEFAULT_VALUE_X;
if (featute_exists(a)) {
ctrl_x |= CTRL_X_ENABLE_A;
...
}
...
if (feature_exists(b)) {
ctrl_x |= CTRL_X_ENABLE_B;
...
}
...
msr(ctrl_x_el3, ctrl_x);
... but for HCRX_EL2, we haven't done that for any other features (e.g.
FPMR, MOPS). Either that's a latent bug, or we don't need to initialize
HCRX_EL2 here.
Can you describe why you're initializing HCRx_EL2.GCSEn? e.g. are you
trying to boot a kernel at EL1?
Thanks,
Mark.
> +
> if (!kernel_is_32bit())
> scr |= SCR_EL3_RW;
>
> --
> 2.34.1
>
More information about the linux-arm-kernel
mailing list