All of lore.kernel.org
 help / color / mirror / Atom feed
* [PATCH v4 0/2] arm64: Clamp ID overrides and gate the GMID_EL1 read
@ 2026-08-25 16:42 Fuad Tabba
  2026-08-25 16:42 ` [PATCH v4 1/2] arm64: Apply overrides to CPU local capabilities Fuad Tabba
  2026-08-25 16:42 ` [PATCH v4 2/2] arm64: Don't read GMID_EL1 when MTE is disabled Fuad Tabba
  0 siblings, 2 replies; 10+ messages in thread
From: Fuad Tabba @ 2026-08-25 16:42 UTC (permalink / raw)
  To: Catalin Marinas, Will Deacon, linux-arm-kernel
  Cc: Marc Zyngier, Oliver Upton, Mark Rutland, Suzuki K Poulose,
	Mark Brown, kvmarm, linux-kernel, Fuad Tabba

Hi folks,

Changes since v3 [1]:
  - Gate on __read_sysreg_by_encoding() and drop the helper's argument,
    so the command-line override is not open-coded in the header.
    (Catalin)
  - Pick up Suzuki's override clamp as patch 1, rather than adding a
    raw-presence check to the gate. (Will)

Patch 2 fixes a GMID_EL1 read that traps to EL2 when the kernel has
disabled MTE, panicking the host under pKVM on a CPU that is offlined
and brought back online. It gates the read on
__read_sysreg_by_encoding().

That needs patch 1, Suzuki's override clamp [2]. Without it
__read_sysreg_by_encoding() applies the command-line override raw, so
id_aa64pfr1.mte=2 on a CPU without FEAT_MTE2 makes the gate true and the
kernel reads a GMID_EL1 that is not there. On the boot CPU that read
comes before init_cpu_ftr_reg() strips the unsafe override, so the gate
cannot rely on it.

Tested on QEMU under pKVM. With -machine virt,mte=on, offlining and
onlining CPU1 with arm64.nomte panics an unpatched v7.2 in
__cpuinfo_store_cpu() and does not with the series. Without tag memory,
where QEMU implements no GMID_EL1, id_aa64pfr1.mte=2 covers the
force-up case.

Based on Linux 7.2 (8d3ae59288f1e).

Cheers,
/fuad

[1] https://lore.kernel.org/all/20260824184155.2644646-1-fuad.tabba@linux.dev/
[2] https://lore.kernel.org/all/afc5bd00-28ca-413b-b047-ee53589c285d@arm.com/

Fuad Tabba (1):
  arm64: Don't read GMID_EL1 when MTE is disabled

Suzuki K Poulose (1):
  arm64: Apply overrides to CPU local capabilities

 arch/arm64/include/asm/cpufeature.h |  9 ++++++
 arch/arm64/kernel/cpufeature.c      | 48 +++++++++++++++++++++--------
 arch/arm64/kernel/cpuinfo.c         |  2 +-
 3 files changed, 46 insertions(+), 13 deletions(-)

-- 
2.39.5


^ permalink raw reply	[flat|nested] 10+ messages in thread

* [PATCH v4 1/2] arm64: Apply overrides to CPU local capabilities
  2026-08-25 16:42 [PATCH v4 0/2] arm64: Clamp ID overrides and gate the GMID_EL1 read Fuad Tabba
@ 2026-08-25 16:42 ` Fuad Tabba
  2026-08-26 13:47   ` Catalin Marinas
  2026-08-25 16:42 ` [PATCH v4 2/2] arm64: Don't read GMID_EL1 when MTE is disabled Fuad Tabba
  1 sibling, 1 reply; 10+ messages in thread
From: Fuad Tabba @ 2026-08-25 16:42 UTC (permalink / raw)
  To: Catalin Marinas, Will Deacon, linux-arm-kernel
  Cc: Marc Zyngier, Oliver Upton, Mark Rutland, Suzuki K Poulose,
	Mark Brown, kvmarm, linux-kernel, Fuad Tabba

From: Suzuki K Poulose <suzuki.poulose@arm.com>

If an override has been applied, make sure we apply that for the
secondary CPUs too, to limit the features.

Signed-off-by: Suzuki K Poulose <suzuki.poulose@arm.com>
Link: https://lore.kernel.org/all/afc5bd00-28ca-413b-b047-ee53589c285d@arm.com/
Cc: stable@vger.kernel.org
[Fuad: whitespace and comment fixes]
Signed-off-by: Fuad Tabba <fuad.tabba@linux.dev>
---
 arch/arm64/kernel/cpufeature.c | 42 +++++++++++++++++++++++++++-------
 1 file changed, 34 insertions(+), 8 deletions(-)

diff --git a/arch/arm64/kernel/cpufeature.c b/arch/arm64/kernel/cpufeature.c
index 9a22df0c5120f..88b15b5ef2f7f 100644
--- a/arch/arm64/kernel/cpufeature.c
+++ b/arch/arm64/kernel/cpufeature.c
@@ -1232,10 +1232,43 @@ void __init init_cpu_features(struct cpuinfo_arm64 *info)
 		init_cpu_ftr_reg(SYS_GMID_EL1, info->reg_gmid);
 }
 
+/*
+ * Sanitise the register fields to clamp the values to the overrides that
+ * have been applied.
+ */
+static u64 override_cpu_ftr_reg(struct arm64_ftr_reg *reg, u64 val)
+{
+	const struct arm64_ftr_bits *ftrp;
+
+	if (!reg || !reg->override->mask)
+		return val;
+
+	for (ftrp = reg->ftr_bits; ftrp->width; ftrp++) {
+		u64 ftr_mask = arm64_ftr_mask(ftrp);
+		s64 ftr_val, ftr_ovr, ftr_safe;
+
+		/* Skip the fields not overridden */
+		if ((ftr_mask & reg->override->mask) != ftr_mask)
+			continue;
+
+		ftr_val = arm64_ftr_value(ftrp, val);
+		ftr_ovr = arm64_ftr_value(ftrp, reg->override->val);
+		ftr_safe = arm64_ftr_safe_value(ftrp, ftr_ovr, ftr_val);
+
+		if (ftr_safe != ftr_val)
+			val = arm64_ftr_set_value(ftrp, val, ftr_safe);
+	}
+
+	return val;
+}
+
 static void update_cpu_ftr_reg(struct arm64_ftr_reg *reg, u64 new)
 {
 	const struct arm64_ftr_bits *ftrp;
 
+	/* Apply the overrides */
+	new = override_cpu_ftr_reg(reg, new);
+
 	for (ftrp = reg->ftr_bits; ftrp->width; ftrp++) {
 		s64 ftr_cur = arm64_ftr_value(ftrp, reg->sys_val);
 		s64 ftr_new = arm64_ftr_value(ftrp, new);
@@ -1539,7 +1572,6 @@ EXPORT_SYMBOL_GPL(read_sanitised_ftr_reg);
  */
 u64 __read_sysreg_by_encoding(u32 sys_id)
 {
-	struct arm64_ftr_reg *regp;
 	u64 val;
 
 	switch (sys_id) {
@@ -1592,13 +1624,7 @@ u64 __read_sysreg_by_encoding(u32 sys_id)
 		return 0;
 	}
 
-	regp  = get_arm64_ftr_reg(sys_id);
-	if (regp) {
-		val &= ~regp->override->mask;
-		val |= (regp->override->val & regp->override->mask);
-	}
-
-	return val;
+	return override_cpu_ftr_reg(get_arm64_ftr_reg(sys_id), val);
 }
 
 #include <linux/irqchip/arm-gic-v3.h>
-- 
2.39.5


^ permalink raw reply related	[flat|nested] 10+ messages in thread

* [PATCH v4 2/2] arm64: Don't read GMID_EL1 when MTE is disabled
  2026-08-25 16:42 [PATCH v4 0/2] arm64: Clamp ID overrides and gate the GMID_EL1 read Fuad Tabba
  2026-08-25 16:42 ` [PATCH v4 1/2] arm64: Apply overrides to CPU local capabilities Fuad Tabba
@ 2026-08-25 16:42 ` Fuad Tabba
  2026-08-26 13:48   ` Catalin Marinas
  2026-08-27 12:56   ` Will Deacon
  1 sibling, 2 replies; 10+ messages in thread
From: Fuad Tabba @ 2026-08-25 16:42 UTC (permalink / raw)
  To: Catalin Marinas, Will Deacon, linux-arm-kernel
  Cc: Marc Zyngier, Oliver Upton, Mark Rutland, Suzuki K Poulose,
	Mark Brown, kvmarm, linux-kernel, Fuad Tabba

__cpuinfo_store_cpu() gates the GMID_EL1 read on the raw
ID_AA64PFR1_EL1, so it reads the register even when the kernel has
disabled MTE (CONFIG_ARM64_MTE=n or arm64.nomte). KVM sets HCR_EL2.TID5
in that case, and pKVM injects an UNDEF the host cannot handle:

  Internal error: Oops - Undefined instruction: 0000000002000000 [#1]  SMP
  pc : __cpuinfo_store_cpu+0xf4/0x264
  Kernel panic - not syncing: Attempted to kill the idle task!

Only pKVM reaches it, and only after a CPU is offlined and brought back
online: its CPU_ON relay sets the host HCR before the CPU enters EL1,
while plain nVHE sets it at CPUHP_AP_KVM_ONLINE.

Gate the read on __read_sysreg_by_encoding(), which applies the cmdline
override, and on CONFIG_ARM64_MTE, which no register reflects.

Fixes: f35abcbb8a084 ("KVM: arm64: Trap MTE access and discovery when MTE is disabled")
Cc: stable@vger.kernel.org # needs "arm64: Apply overrides to CPU local capabilities"
Signed-off-by: Fuad Tabba <fuad.tabba@linux.dev>
---
 arch/arm64/include/asm/cpufeature.h | 9 +++++++++
 arch/arm64/kernel/cpufeature.c      | 6 ++----
 arch/arm64/kernel/cpuinfo.c         | 2 +-
 3 files changed, 12 insertions(+), 5 deletions(-)

diff --git a/arch/arm64/include/asm/cpufeature.h b/arch/arm64/include/asm/cpufeature.h
index a57870fa96db5..0b374e938f708 100644
--- a/arch/arm64/include/asm/cpufeature.h
+++ b/arch/arm64/include/asm/cpufeature.h
@@ -1085,6 +1085,15 @@ static inline bool cpu_has_lpa2(void)
 #endif
 }
 
+/* No ID register reflects CONFIG_ARM64_MTE. */
+static inline bool gmid_el1_accessible(void)
+{
+	if (!IS_ENABLED(CONFIG_ARM64_MTE))
+		return false;
+
+	return id_aa64pfr1_mte(__read_sysreg_by_encoding(SYS_ID_AA64PFR1_EL1));
+}
+
 #endif /* __ASSEMBLER__ */
 
 #endif
diff --git a/arch/arm64/kernel/cpufeature.c b/arch/arm64/kernel/cpufeature.c
index 88b15b5ef2f7f..23f174b3c4e26 100644
--- a/arch/arm64/kernel/cpufeature.c
+++ b/arch/arm64/kernel/cpufeature.c
@@ -1228,7 +1228,7 @@ void __init init_cpu_features(struct cpuinfo_arm64 *info)
 		init_cpu_ftr_reg(SYS_MPAMIDR_EL1, info->reg_mpamidr);
 	}
 
-	if (id_aa64pfr1_mte(info->reg_id_aa64pfr1))
+	if (gmid_el1_accessible())
 		init_cpu_ftr_reg(SYS_GMID_EL1, info->reg_gmid);
 }
 
@@ -1523,11 +1523,9 @@ void update_cpu_features(int cpu,
 	 * they read/write depends on the GMID_EL1.BS field. Check that the
 	 * value is the same on all CPUs.
 	 */
-	if (IS_ENABLED(CONFIG_ARM64_MTE) &&
-	    id_aa64pfr1_mte(info->reg_id_aa64pfr1)) {
+	if (gmid_el1_accessible())
 		taint |= check_update_ftr_reg(SYS_GMID_EL1, cpu,
 					      info->reg_gmid, boot->reg_gmid);
-	}
 
 	/*
 	 * If we don't have AArch32 at all then skip the checks entirely
diff --git a/arch/arm64/kernel/cpuinfo.c b/arch/arm64/kernel/cpuinfo.c
index d50e2a9b066b3..389fca84f106b 100644
--- a/arch/arm64/kernel/cpuinfo.c
+++ b/arch/arm64/kernel/cpuinfo.c
@@ -502,7 +502,7 @@ static void __cpuinfo_store_cpu(struct cpuinfo_arm64 *info)
 	info->reg_id_aa64smfr0 = read_cpuid(ID_AA64SMFR0_EL1);
 	info->reg_id_aa64fpfr0 = read_cpuid(ID_AA64FPFR0_EL1);
 
-	if (id_aa64pfr1_mte(info->reg_id_aa64pfr1))
+	if (gmid_el1_accessible())
 		info->reg_gmid = read_cpuid(GMID_EL1);
 
 	if (id_aa64pfr0_32bit_el0(info->reg_id_aa64pfr0))
-- 
2.39.5


^ permalink raw reply related	[flat|nested] 10+ messages in thread

* Re: [PATCH v4 1/2] arm64: Apply overrides to CPU local capabilities
  2026-08-25 16:42 ` [PATCH v4 1/2] arm64: Apply overrides to CPU local capabilities Fuad Tabba
@ 2026-08-26 13:47   ` Catalin Marinas
  2026-08-27  8:58     ` Fuad Tabba
  0 siblings, 1 reply; 10+ messages in thread
From: Catalin Marinas @ 2026-08-26 13:47 UTC (permalink / raw)
  To: Fuad Tabba
  Cc: Will Deacon, linux-arm-kernel, Marc Zyngier, Oliver Upton,
	Mark Rutland, Suzuki K Poulose, Mark Brown, kvmarm, linux-kernel,
	Fuad Tabba

On Tue, Aug 25, 2026 at 05:42:18PM +0100, Fuad Tabba wrote:
> From: Suzuki K Poulose <suzuki.poulose@arm.com>
> 
> If an override has been applied, make sure we apply that for the
> secondary CPUs too, to limit the features.
> 
> Signed-off-by: Suzuki K Poulose <suzuki.poulose@arm.com>
> Link: https://lore.kernel.org/all/afc5bd00-28ca-413b-b047-ee53589c285d@arm.com/
> Cc: stable@vger.kernel.org
> [Fuad: whitespace and comment fixes]
> Signed-off-by: Fuad Tabba <fuad.tabba@linux.dev>

For completeness, we should add:

Fixes: b3341ae0efa2  ("arm64: cpufeature: Use IDreg override in __read_sysreg_by_encoding()")

> diff --git a/arch/arm64/kernel/cpufeature.c b/arch/arm64/kernel/cpufeature.c
> index 9a22df0c5120f..88b15b5ef2f7f 100644
> --- a/arch/arm64/kernel/cpufeature.c
> +++ b/arch/arm64/kernel/cpufeature.c
> @@ -1232,10 +1232,43 @@ void __init init_cpu_features(struct cpuinfo_arm64 *info)
>  		init_cpu_ftr_reg(SYS_GMID_EL1, info->reg_gmid);
>  }
>  
> +/*
> + * Sanitise the register fields to clamp the values to the overrides that
> + * have been applied.
> + */
> +static u64 override_cpu_ftr_reg(struct arm64_ftr_reg *reg, u64 val)
> +{
> +	const struct arm64_ftr_bits *ftrp;
> +
> +	if (!reg || !reg->override->mask)
> +		return val;
> +
> +	for (ftrp = reg->ftr_bits; ftrp->width; ftrp++) {
> +		u64 ftr_mask = arm64_ftr_mask(ftrp);
> +		s64 ftr_val, ftr_ovr, ftr_safe;
> +
> +		/* Skip the fields not overridden */
> +		if ((ftr_mask & reg->override->mask) != ftr_mask)
> +			continue;
> +
> +		ftr_val = arm64_ftr_value(ftrp, val);
> +		ftr_ovr = arm64_ftr_value(ftrp, reg->override->val);
> +		ftr_safe = arm64_ftr_safe_value(ftrp, ftr_ovr, ftr_val);
> +
> +		if (ftr_safe != ftr_val)
> +			val = arm64_ftr_set_value(ftrp, val, ftr_safe);
> +	}
> +
> +	return val;
> +}
> +
>  static void update_cpu_ftr_reg(struct arm64_ftr_reg *reg, u64 new)
>  {
>  	const struct arm64_ftr_bits *ftrp;
>  
> +	/* Apply the overrides */
> +	new = override_cpu_ftr_reg(reg, new);

Not sure we need this. The init value has already been clamped, made
safe, so it won't change the result.

Otherwise:

Reviewed-by: Catalin Marinas <catalin.marinas@arm.com>


^ permalink raw reply	[flat|nested] 10+ messages in thread

* Re: [PATCH v4 2/2] arm64: Don't read GMID_EL1 when MTE is disabled
  2026-08-25 16:42 ` [PATCH v4 2/2] arm64: Don't read GMID_EL1 when MTE is disabled Fuad Tabba
@ 2026-08-26 13:48   ` Catalin Marinas
  2026-08-27 12:56   ` Will Deacon
  1 sibling, 0 replies; 10+ messages in thread
From: Catalin Marinas @ 2026-08-26 13:48 UTC (permalink / raw)
  To: Fuad Tabba
  Cc: Will Deacon, linux-arm-kernel, Marc Zyngier, Oliver Upton,
	Mark Rutland, Suzuki K Poulose, Mark Brown, kvmarm, linux-kernel,
	Fuad Tabba

On Tue, Aug 25, 2026 at 05:42:19PM +0100, Fuad Tabba wrote:
> __cpuinfo_store_cpu() gates the GMID_EL1 read on the raw
> ID_AA64PFR1_EL1, so it reads the register even when the kernel has
> disabled MTE (CONFIG_ARM64_MTE=n or arm64.nomte). KVM sets HCR_EL2.TID5
> in that case, and pKVM injects an UNDEF the host cannot handle:
> 
>   Internal error: Oops - Undefined instruction: 0000000002000000 [#1]  SMP
>   pc : __cpuinfo_store_cpu+0xf4/0x264
>   Kernel panic - not syncing: Attempted to kill the idle task!
> 
> Only pKVM reaches it, and only after a CPU is offlined and brought back
> online: its CPU_ON relay sets the host HCR before the CPU enters EL1,
> while plain nVHE sets it at CPUHP_AP_KVM_ONLINE.
> 
> Gate the read on __read_sysreg_by_encoding(), which applies the cmdline
> override, and on CONFIG_ARM64_MTE, which no register reflects.
> 
> Fixes: f35abcbb8a084 ("KVM: arm64: Trap MTE access and discovery when MTE is disabled")
> Cc: stable@vger.kernel.org # needs "arm64: Apply overrides to CPU local capabilities"
> Signed-off-by: Fuad Tabba <fuad.tabba@linux.dev>

Reviewed-by: Catalin Marinas <catalin.marinas@arm.com>


^ permalink raw reply	[flat|nested] 10+ messages in thread

* Re: [PATCH v4 1/2] arm64: Apply overrides to CPU local capabilities
  2026-08-26 13:47   ` Catalin Marinas
@ 2026-08-27  8:58     ` Fuad Tabba
  0 siblings, 0 replies; 10+ messages in thread
From: Fuad Tabba @ 2026-08-27  8:58 UTC (permalink / raw)
  To: Catalin Marinas
  Cc: Will Deacon, linux-arm-kernel, Marc Zyngier, Oliver Upton,
	Mark Rutland, Suzuki K Poulose, Mark Brown, kvmarm, linux-kernel

Hi Catalin,

On Wed, 26 Aug 2026 at 14:47, Catalin Marinas <catalin.marinas@arm.com> wrote:
...
> For completeness, we should add:
>
> Fixes: b3341ae0efa2  ("arm64: cpufeature: Use IDreg override in __read_sysreg_by_encoding()")

Ack

...
> > +     /* Apply the overrides */
> > +     new = override_cpu_ftr_reg(reg, new);
>
> Not sure we need this. The init value has already been clamped, made
> safe, so it won't change the result.

I'll fix both on the respin. I'll wait to see if Will or anyone else
has further comments before doing that.

> Otherwise:
>
> Reviewed-by: Catalin Marinas <catalin.marinas@arm.com>

Thanks for the reviews!
/fuad


^ permalink raw reply	[flat|nested] 10+ messages in thread

* Re: [PATCH v4 2/2] arm64: Don't read GMID_EL1 when MTE is disabled
  2026-08-25 16:42 ` [PATCH v4 2/2] arm64: Don't read GMID_EL1 when MTE is disabled Fuad Tabba
  2026-08-26 13:48   ` Catalin Marinas
@ 2026-08-27 12:56   ` Will Deacon
  2026-08-27 13:19     ` Will Deacon
  2026-08-28 10:50     ` Catalin Marinas
  1 sibling, 2 replies; 10+ messages in thread
From: Will Deacon @ 2026-08-27 12:56 UTC (permalink / raw)
  To: Fuad Tabba
  Cc: Catalin Marinas, linux-arm-kernel, Marc Zyngier, Oliver Upton,
	Mark Rutland, Suzuki K Poulose, Mark Brown, kvmarm, linux-kernel,
	Fuad Tabba

On Tue, Aug 25, 2026 at 05:42:19PM +0100, Fuad Tabba wrote:
> __cpuinfo_store_cpu() gates the GMID_EL1 read on the raw
> ID_AA64PFR1_EL1, so it reads the register even when the kernel has
> disabled MTE (CONFIG_ARM64_MTE=n or arm64.nomte). KVM sets HCR_EL2.TID5
> in that case, and pKVM injects an UNDEF the host cannot handle:
> 
>   Internal error: Oops - Undefined instruction: 0000000002000000 [#1]  SMP
>   pc : __cpuinfo_store_cpu+0xf4/0x264
>   Kernel panic - not syncing: Attempted to kill the idle task!
> 
> Only pKVM reaches it, and only after a CPU is offlined and brought back
> online: its CPU_ON relay sets the host HCR before the CPU enters EL1,
> while plain nVHE sets it at CPUHP_AP_KVM_ONLINE.
> 
> Gate the read on __read_sysreg_by_encoding(), which applies the cmdline
> override, and on CONFIG_ARM64_MTE, which no register reflects.
> 
> Fixes: f35abcbb8a084 ("KVM: arm64: Trap MTE access and discovery when MTE is disabled")
> Cc: stable@vger.kernel.org # needs "arm64: Apply overrides to CPU local capabilities"
> Signed-off-by: Fuad Tabba <fuad.tabba@linux.dev>
> ---
>  arch/arm64/include/asm/cpufeature.h | 9 +++++++++
>  arch/arm64/kernel/cpufeature.c      | 6 ++----
>  arch/arm64/kernel/cpuinfo.c         | 2 +-
>  3 files changed, 12 insertions(+), 5 deletions(-)
> 
> diff --git a/arch/arm64/include/asm/cpufeature.h b/arch/arm64/include/asm/cpufeature.h
> index a57870fa96db5..0b374e938f708 100644
> --- a/arch/arm64/include/asm/cpufeature.h
> +++ b/arch/arm64/include/asm/cpufeature.h
> @@ -1085,6 +1085,15 @@ static inline bool cpu_has_lpa2(void)
>  #endif
>  }
>  
> +/* No ID register reflects CONFIG_ARM64_MTE. */
> +static inline bool gmid_el1_accessible(void)
> +{
> +	if (!IS_ENABLED(CONFIG_ARM64_MTE))
> +		return false;
> +
> +	return id_aa64pfr1_mte(__read_sysreg_by_encoding(SYS_ID_AA64PFR1_EL1));

I'm planning to internalise __read_sysreg_by_encoding() into cpufeature.c
so I'd prefer to avoid adding another user of it, if possible. In this case,
__cpuinfo_store_cpu() has already read the thing, so all it needs is the
override logic (but see below).

> +}
> +
>  #endif /* __ASSEMBLER__ */
>  
>  #endif
> diff --git a/arch/arm64/kernel/cpufeature.c b/arch/arm64/kernel/cpufeature.c
> index 88b15b5ef2f7f..23f174b3c4e26 100644
> --- a/arch/arm64/kernel/cpufeature.c
> +++ b/arch/arm64/kernel/cpufeature.c
> @@ -1228,7 +1228,7 @@ void __init init_cpu_features(struct cpuinfo_arm64 *info)
>  		init_cpu_ftr_reg(SYS_MPAMIDR_EL1, info->reg_mpamidr);
>  	}
>  
> -	if (id_aa64pfr1_mte(info->reg_id_aa64pfr1))
> +	if (gmid_el1_accessible())
>  		init_cpu_ftr_reg(SYS_GMID_EL1, info->reg_gmid);
>  }
>  
> @@ -1523,11 +1523,9 @@ void update_cpu_features(int cpu,
>  	 * they read/write depends on the GMID_EL1.BS field. Check that the
>  	 * value is the same on all CPUs.
>  	 */
> -	if (IS_ENABLED(CONFIG_ARM64_MTE) &&
> -	    id_aa64pfr1_mte(info->reg_id_aa64pfr1)) {
> +	if (gmid_el1_accessible())
>  		taint |= check_update_ftr_reg(SYS_GMID_EL1, cpu,
>  					      info->reg_gmid, boot->reg_gmid);
> -	}
>  
>  	/*
>  	 * If we don't have AArch32 at all then skip the checks entirely
> diff --git a/arch/arm64/kernel/cpuinfo.c b/arch/arm64/kernel/cpuinfo.c
> index d50e2a9b066b3..389fca84f106b 100644
> --- a/arch/arm64/kernel/cpuinfo.c
> +++ b/arch/arm64/kernel/cpuinfo.c
> @@ -502,7 +502,7 @@ static void __cpuinfo_store_cpu(struct cpuinfo_arm64 *info)
>  	info->reg_id_aa64smfr0 = read_cpuid(ID_AA64SMFR0_EL1);
>  	info->reg_id_aa64fpfr0 = read_cpuid(ID_AA64FPFR0_EL1);
>  
> -	if (id_aa64pfr1_mte(info->reg_id_aa64pfr1))
> +	if (gmid_el1_accessible())
>  		info->reg_gmid = read_cpuid(GMID_EL1);

I'm not sure this is safe. For the boot CPU, __cpuinfo_store_cpu() is
called before init_cpu_features(), so the arm64_ftr_regs[] array hasn't
been sorted and we can't call get_arm64_ftr_reg() reliably. In fact, it
doesn't even look like the overrides will have been processed.

So we're in a bit of a chicken-and-egg problem here. Perhaps we need an
early (__init) function that can apply the override manually to the
value read from hardware using arm64_ftr_safe_value(). You'll probably
need something like my old hack [1] to avoid the bsearch though :/

Will

[1] https://lore.kernel.org/all/20230110161651.GB9436@willie-the-truck/


^ permalink raw reply	[flat|nested] 10+ messages in thread

* Re: [PATCH v4 2/2] arm64: Don't read GMID_EL1 when MTE is disabled
  2026-08-27 12:56   ` Will Deacon
@ 2026-08-27 13:19     ` Will Deacon
  2026-08-28 10:50     ` Catalin Marinas
  1 sibling, 0 replies; 10+ messages in thread
From: Will Deacon @ 2026-08-27 13:19 UTC (permalink / raw)
  To: Fuad Tabba
  Cc: Catalin Marinas, linux-arm-kernel, Marc Zyngier, Oliver Upton,
	Mark Rutland, Suzuki K Poulose, Mark Brown, kvmarm, linux-kernel,
	Fuad Tabba

On Thu, Aug 27, 2026 at 01:56:35PM +0100, Will Deacon wrote:
> On Tue, Aug 25, 2026 at 05:42:19PM +0100, Fuad Tabba wrote:
> > diff --git a/arch/arm64/kernel/cpuinfo.c b/arch/arm64/kernel/cpuinfo.c
> > index d50e2a9b066b3..389fca84f106b 100644
> > --- a/arch/arm64/kernel/cpuinfo.c
> > +++ b/arch/arm64/kernel/cpuinfo.c
> > @@ -502,7 +502,7 @@ static void __cpuinfo_store_cpu(struct cpuinfo_arm64 *info)
> >  	info->reg_id_aa64smfr0 = read_cpuid(ID_AA64SMFR0_EL1);
> >  	info->reg_id_aa64fpfr0 = read_cpuid(ID_AA64FPFR0_EL1);
> >  
> > -	if (id_aa64pfr1_mte(info->reg_id_aa64pfr1))
> > +	if (gmid_el1_accessible())
> >  		info->reg_gmid = read_cpuid(GMID_EL1);
> 
> I'm not sure this is safe. For the boot CPU, __cpuinfo_store_cpu() is
> called before init_cpu_features(), so the arm64_ftr_regs[] array hasn't
> been sorted and we can't call get_arm64_ftr_reg() reliably. In fact, it
> doesn't even look like the overrides will have been processed.
> 
> So we're in a bit of a chicken-and-egg problem here. Perhaps we need an
> early (__init) function that can apply the override manually to the
> value read from hardware using arm64_ftr_safe_value(). You'll probably
> need something like my old hack [1] to avoid the bsearch though :/

Thinking about this for a few more minutes, perhaps the best option for
a quick fix would be to:

 - Internalise gmid_el1_accessible() in cpufeature.c and take cpuinfo *
   as a parameter

 - It could then refer directly to the ftr reg, along the lines of:

	val = arm64_ftr_safe_value(&ftr_id_aa64pfr1,
				   <value from id_aa64pfr1_override>,
				   <value from cpuinfo>);

 - Then check val before accessing the gmid.

Then we can fix all this properly in the future by moving the override
stuff earlier.

Will


^ permalink raw reply	[flat|nested] 10+ messages in thread

* Re: [PATCH v4 2/2] arm64: Don't read GMID_EL1 when MTE is disabled
  2026-08-27 12:56   ` Will Deacon
  2026-08-27 13:19     ` Will Deacon
@ 2026-08-28 10:50     ` Catalin Marinas
  2026-08-28 13:53       ` Will Deacon
  1 sibling, 1 reply; 10+ messages in thread
From: Catalin Marinas @ 2026-08-28 10:50 UTC (permalink / raw)
  To: Will Deacon
  Cc: Fuad Tabba, linux-arm-kernel, Marc Zyngier, Oliver Upton,
	Mark Rutland, Suzuki K Poulose, Mark Brown, kvmarm, linux-kernel,
	Fuad Tabba

On Thu, Aug 27, 2026 at 01:56:35PM +0100, Will Deacon wrote:
> On Tue, Aug 25, 2026 at 05:42:19PM +0100, Fuad Tabba wrote:
> > +/* No ID register reflects CONFIG_ARM64_MTE. */
> > +static inline bool gmid_el1_accessible(void)
> > +{
> > +	if (!IS_ENABLED(CONFIG_ARM64_MTE))
> > +		return false;
> > +
> > +	return id_aa64pfr1_mte(__read_sysreg_by_encoding(SYS_ID_AA64PFR1_EL1));
> 
> I'm planning to internalise __read_sysreg_by_encoding() into cpufeature.c
> so I'd prefer to avoid adding another user of it, if possible. In this case,
> __cpuinfo_store_cpu() has already read the thing, so all it needs is the
> override logic (but see below).

That's a valid point.

> > @@ -502,7 +502,7 @@ static void __cpuinfo_store_cpu(struct cpuinfo_arm64 *info)
> >  	info->reg_id_aa64smfr0 = read_cpuid(ID_AA64SMFR0_EL1);
> >  	info->reg_id_aa64fpfr0 = read_cpuid(ID_AA64FPFR0_EL1);
> >  
> > -	if (id_aa64pfr1_mte(info->reg_id_aa64pfr1))
> > +	if (gmid_el1_accessible())
> >  		info->reg_gmid = read_cpuid(GMID_EL1);
> 
> I'm not sure this is safe. For the boot CPU, __cpuinfo_store_cpu() is
> called before init_cpu_features(), so the arm64_ftr_regs[] array hasn't
> been sorted and we can't call get_arm64_ftr_reg() reliably.

We no longer sort this array at boot-time, we just check that it's
pre-sorted.

> In fact, it
> doesn't even look like the overrides will have been processed.

init_feature_override() runs from early_map_kernel() but yes,
init_cpu_ftr_reg() hasn't been called yet to vet the override. Suzuki's
patch was adding extra checks in __read_sysreg_by_encoding() but if we
drop that patch (and function eventually), better not to rely on it.

So I don't think we have a correctness issue here but I don't mind v5
either. I'll go and check.

-- 
Catalin


^ permalink raw reply	[flat|nested] 10+ messages in thread

* Re: [PATCH v4 2/2] arm64: Don't read GMID_EL1 when MTE is disabled
  2026-08-28 10:50     ` Catalin Marinas
@ 2026-08-28 13:53       ` Will Deacon
  0 siblings, 0 replies; 10+ messages in thread
From: Will Deacon @ 2026-08-28 13:53 UTC (permalink / raw)
  To: Catalin Marinas
  Cc: Fuad Tabba, linux-arm-kernel, Marc Zyngier, Oliver Upton,
	Mark Rutland, Suzuki K Poulose, Mark Brown, kvmarm, linux-kernel,
	Fuad Tabba

On Fri, Aug 28, 2026 at 11:50:12AM +0100, Catalin Marinas wrote:
> On Thu, Aug 27, 2026 at 01:56:35PM +0100, Will Deacon wrote:
> > On Tue, Aug 25, 2026 at 05:42:19PM +0100, Fuad Tabba wrote:
> > > +/* No ID register reflects CONFIG_ARM64_MTE. */
> > > +static inline bool gmid_el1_accessible(void)
> > > +{
> > > +	if (!IS_ENABLED(CONFIG_ARM64_MTE))
> > > +		return false;
> > > +
> > > +	return id_aa64pfr1_mte(__read_sysreg_by_encoding(SYS_ID_AA64PFR1_EL1));
> > 
> > I'm planning to internalise __read_sysreg_by_encoding() into cpufeature.c
> > so I'd prefer to avoid adding another user of it, if possible. In this case,
> > __cpuinfo_store_cpu() has already read the thing, so all it needs is the
> > override logic (but see below).
> 
> That's a valid point.
> 
> > > @@ -502,7 +502,7 @@ static void __cpuinfo_store_cpu(struct cpuinfo_arm64 *info)
> > >  	info->reg_id_aa64smfr0 = read_cpuid(ID_AA64SMFR0_EL1);
> > >  	info->reg_id_aa64fpfr0 = read_cpuid(ID_AA64FPFR0_EL1);
> > >  
> > > -	if (id_aa64pfr1_mte(info->reg_id_aa64pfr1))
> > > +	if (gmid_el1_accessible())
> > >  		info->reg_gmid = read_cpuid(GMID_EL1);
> > 
> > I'm not sure this is safe. For the boot CPU, __cpuinfo_store_cpu() is
> > called before init_cpu_features(), so the arm64_ftr_regs[] array hasn't
> > been sorted and we can't call get_arm64_ftr_reg() reliably.
> 
> We no longer sort this array at boot-time, we just check that it's
> pre-sorted.

Fair enough, but I still don't think we should access it until we've
checked that.

> > In fact, it
> > doesn't even look like the overrides will have been processed.
> 
> init_feature_override() runs from early_map_kernel() but yes,
> init_cpu_ftr_reg() hasn't been called yet to vet the override. Suzuki's
> patch was adding extra checks in __read_sysreg_by_encoding() but if we
> drop that patch (and function eventually), better not to rely on it.

Right, and we have to be really careful here with things like the new
"nohaft" override because otherwise we could accidentally end up
thinking we have hardware dirty on CPUs that don't have it. In other
words, it's not just about people passing bonkers settings on the cmdline.

> So I don't think we have a correctness issue here but I don't mind v5
> either. I'll go and check.

Thanks.

Will


^ permalink raw reply	[flat|nested] 10+ messages in thread

end of thread, other threads:[~2026-08-28 13:53 UTC | newest]

Thread overview: 10+ messages (download: mbox.gz follow: Atom feed
-- links below jump to the message on this page --
2026-08-25 16:42 [PATCH v4 0/2] arm64: Clamp ID overrides and gate the GMID_EL1 read Fuad Tabba
2026-08-25 16:42 ` [PATCH v4 1/2] arm64: Apply overrides to CPU local capabilities Fuad Tabba
2026-08-26 13:47   ` Catalin Marinas
2026-08-27  8:58     ` Fuad Tabba
2026-08-25 16:42 ` [PATCH v4 2/2] arm64: Don't read GMID_EL1 when MTE is disabled Fuad Tabba
2026-08-26 13:48   ` Catalin Marinas
2026-08-27 12:56   ` Will Deacon
2026-08-27 13:19     ` Will Deacon
2026-08-28 10:50     ` Catalin Marinas
2026-08-28 13:53       ` Will Deacon

This is an external index of several public inboxes,
see mirroring instructions on how to clone and mirror
all data and code used by this external index.