[PATCH 16/24] arm64: Refactor KERNEL_GCR_EL1 out of <sysreg.h>

From: Pierre-Clément Tosi

Date: Sat Nov 07 2026 - 10:53:42 EST


Rework the constant to make the resulting sysreg value (and computation)
obvious at the usage site and clearly indicate that the GCR_EL1.Exclude
is specifically set by a KASAN policy.

As a result, <sysreg.h> is now KASAN-agnostic and writers of GCR_EL1
explicitly depend on KASAN headers, as they should.

Signed-off-by: Pierre-Clément Tosi <ptosi@xxxxxxxxxx>
---
arch/arm64/include/asm/mte-kasan.h | 16 ++++++++++++++++
arch/arm64/include/asm/sysreg.h | 16 ----------------
arch/arm64/kernel/entry.S | 3 ++-
arch/arm64/kernel/mte.c | 4 +++-
4 files changed, 21 insertions(+), 18 deletions(-)

diff --git a/arch/arm64/include/asm/mte-kasan.h b/arch/arm64/include/asm/mte-kasan.h
index 9d00e9460b0f..6f63c788470a 100644
--- a/arch/arm64/include/asm/mte-kasan.h
+++ b/arch/arm64/include/asm/mte-kasan.h
@@ -5,10 +5,26 @@
#ifndef __ASM_MTE_KASAN_H
#define __ASM_MTE_KASAN_H

+#include <linux/bits.h>
+#include <linux/const.h>
+#include <linux/kasan-tags.h>
+
#include <asm/compiler.h>
#include <asm/cputype.h>
#include <asm/mte-def.h>

+/*
+ * KASAN always uses a whole byte for its tags. With CONFIG_KASAN_HW_TAGS it
+ * only uses tags in the range 0xF0-0xFF, which we map to MTE tags 0x0-0xF.
+ */
+#ifdef CONFIG_KASAN_HW_TAGS
+#define __MTE_TAG_MIN (KASAN_TAG_MIN & 0xf)
+#define __MTE_TAG_MAX (KASAN_TAG_MAX & 0xf)
+#define KASAN_GCR_INCL GENMASK(__MTE_TAG_MAX, __MTE_TAG_MIN)
+#else
+#define KASAN_GCR_INCL UL(0)
+#endif
+
#ifndef __ASSEMBLER__

#include <linux/types.h>
diff --git a/arch/arm64/include/asm/sysreg.h b/arch/arm64/include/asm/sysreg.h
index 51c6a54d7146..7d82c769ae69 100644
--- a/arch/arm64/include/asm/sysreg.h
+++ b/arch/arm64/include/asm/sysreg.h
@@ -11,7 +11,6 @@

#include <linux/bits.h>
#include <linux/stringify.h>
-#include <linux/kasan-tags.h>
#include <linux/kconfig.h>

#include <asm/gpr-num.h>
@@ -921,21 +920,6 @@
#define SYS_GCR_EL1_RRND (BIT(16))
#define SYS_GCR_EL1_EXCL_MASK 0xffffUL

-#ifdef CONFIG_KASAN_HW_TAGS
-/*
- * KASAN always uses a whole byte for its tags. With CONFIG_KASAN_HW_TAGS it
- * only uses tags in the range 0xF0-0xFF, which we map to MTE tags 0x0-0xF.
- */
-#define __MTE_TAG_MIN (KASAN_TAG_MIN & 0xf)
-#define __MTE_TAG_MAX (KASAN_TAG_MAX & 0xf)
-#define __MTE_TAG_INCL GENMASK(__MTE_TAG_MAX, __MTE_TAG_MIN)
-#define KERNEL_GCR_EL1_EXCL (SYS_GCR_EL1_EXCL_MASK & ~__MTE_TAG_INCL)
-#else
-#define KERNEL_GCR_EL1_EXCL SYS_GCR_EL1_EXCL_MASK
-#endif
-
-#define KERNEL_GCR_EL1 (SYS_GCR_EL1_RRND | KERNEL_GCR_EL1_EXCL)
-
/* RGSR_EL1 Definitions */
#define SYS_RGSR_EL1_TAG_MASK 0xfUL
#define SYS_RGSR_EL1_SEED_SHIFT 8
diff --git a/arch/arm64/kernel/entry.S b/arch/arm64/kernel/entry.S
index 8d17f61d1b5b..d1d9a7a049a7 100644
--- a/arch/arm64/kernel/entry.S
+++ b/arch/arm64/kernel/entry.S
@@ -21,6 +21,7 @@
#include <asm/esr.h>
#include <asm/irq.h>
#include <asm/memory.h>
+#include <asm/mte-kasan.h>
#include <asm/mmu.h>
#include <asm/processor.h>
#include <asm/ptrace.h>
@@ -176,7 +177,7 @@ alternative_else_nop_endif
alternative_cb ARM64_ALWAYS_SYSTEM, kasan_hw_tags_enable
b 1f
alternative_cb_end
- mov \tmp, KERNEL_GCR_EL1
+ mov \tmp, #(SYS_GCR_EL1_RRND | (SYS_GCR_EL1_EXCL_MASK & ~KASAN_GCR_INCL))
msr_s SYS_GCR_EL1, \tmp
1:
#endif
diff --git a/arch/arm64/kernel/mte.c b/arch/arm64/kernel/mte.c
index 0d998289edcb..725f48faec3e 100644
--- a/arch/arm64/kernel/mte.c
+++ b/arch/arm64/kernel/mte.c
@@ -23,6 +23,7 @@
#include <asm/barrier.h>
#include <asm/cpufeature.h>
#include <asm/mte.h>
+#include <asm/mte-kasan.h>
#include <asm/ptrace.h>
#include <asm/sysreg.h>

@@ -320,7 +321,8 @@ void mte_cpu_setup(void)
MAIR_ATTRIDX(MAIR_ATTR_NORMAL_TAGGED,
MT_NORMAL_TAGGED));

- write_sysreg_s(KERNEL_GCR_EL1, SYS_GCR_EL1);
+ write_sysreg_s(SYS_GCR_EL1_RRND | (SYS_GCR_EL1_EXCL_MASK & ~KASAN_GCR_INCL),
+ SYS_GCR_EL1);

/*
* If GCR_EL1.RRND=1 is implemented the same way as RRND=0, then

--
2.56.0.455.g6c5a503b38-goog