]> git.ipfire.org Git - thirdparty/kernel/stable.git/commitdiff
arm64: Report address tag when FEAT_MTE_TAGGED_FAR is supported
authorYeoreum Yun <yeoreum.yun@arm.com>
Wed, 18 Jun 2025 08:45:05 +0000 (09:45 +0100)
committerCatalin Marinas <catalin.marinas@arm.com>
Wed, 2 Jul 2025 16:44:17 +0000 (17:44 +0100)
If FEAT_MTE_TAGGED_FAR (Armv8.9) is supported, bits 63:60 of the fault address
are preserved in response to synchronous tag check faults (SEGV_MTESERR).

This patch modifies below to support this feature:
  - Use the original FAR_EL1 value when an MTE tag check fault occurs,
    if ARM64_MTE_FAR is supported so that not only logical tag
    (bits 59:56) but also address tag (bits 63:60] being reported too.

  - Add HWCAP for mtefar to let user know bits 63:60 includes
    address tag information when when FEAT_MTE_TAGGED_FAR is supported.

Applications that require this information should install
a signal handler with the SA_EXPOSE_TAGBITS flag.
While this introduces a minor ABI change,
most applications do not set this flag and therefore will not be affected.

Signed-off-by: Yeoreum Yun <yeoreum.yun@arm.com>
Link: https://lore.kernel.org/r/20250618084513.1761345-3-yeoreum.yun@arm.com
Signed-off-by: Catalin Marinas <catalin.marinas@arm.com>
Documentation/arch/arm64/elf_hwcaps.rst
Documentation/arch/arm64/tagged-pointers.rst
arch/arm64/include/asm/hwcap.h
arch/arm64/include/uapi/asm/hwcap.h
arch/arm64/kernel/cpufeature.c
arch/arm64/kernel/cpuinfo.c
arch/arm64/mm/fault.c

index 69d7afe5685306a5965d279dfb0b971988424ddd..358f5af035ffdd05ee27f4466422be68fdf6a680 100644 (file)
@@ -435,6 +435,9 @@ HWCAP2_SME_SF8DP4
 HWCAP2_POE
     Functionality implied by ID_AA64MMFR3_EL1.S1POE == 0b0001.
 
+HWCAP3_MTE_FAR
+    Functionality implied by ID_AA64PFR2_EL1.MTEFAR == 0b0001.
+
 4. Unused AT_HWCAP bits
 -----------------------
 
index 81b6c2a770dd6dc7a71c9af2e557c9f8b6281bb8..f87a925ca9a551eda4781ea2967d9e2187622b81 100644 (file)
@@ -60,11 +60,12 @@ that signal handlers in applications making use of tags cannot rely
 on the tag information for user virtual addresses being maintained
 in these fields unless the flag was set.
 
-Due to architecture limitations, bits 63:60 of the fault address
-are not preserved in response to synchronous tag check faults
-(SEGV_MTESERR) even if SA_EXPOSE_TAGBITS was set. Applications should
-treat the values of these bits as undefined in order to accommodate
-future architecture revisions which may preserve the bits.
+If FEAT_MTE_TAGGED_FAR (Armv8.9) is supported, bits 63:60 of the fault address
+are preserved in response to synchronous tag check faults (SEGV_MTESERR)
+otherwise not preserved even if SA_EXPOSE_TAGBITS was set.
+Applications should interpret the values of these bits based on
+the support for the HWCAP3_MTE_FAR. If the support is not present,
+the values of these bits should be considered as undefined otherwise valid.
 
 For signals raised in response to watchpoint debug exceptions, the
 tag information will be preserved regardless of the SA_EXPOSE_TAGBITS
index 1c3f9617d54fe5a0090e87153b8633ea4dc7ffa0..28dd1ac29ecc84d188b56c41d46690c2c6f05a28 100644 (file)
 #define KERNEL_HWCAP_POE               __khwcap2_feature(POE)
 
 #define __khwcap3_feature(x)           (const_ilog2(HWCAP3_ ## x) + 128)
+#define KERNEL_HWCAP_MTE_FAR           __khwcap3_feature(MTE_FAR)
 
 /*
  * This yields a mask that user programs can use to figure out what
index 705a7afa8e587dc007523779c71dfc247c0b006a..7d22527a7975d29b29345bfff2c71d14a484e342 100644 (file)
 /*
  * HWCAP3 flags - for AT_HWCAP3
  */
+#define HWCAP3_MTE_FAR         (1UL << 0)
 
 #endif /* _UAPI__ASM_HWCAP_H */
index af6a6924a3e81d505eb05d3c21ee49c6d3f2522d..8a5284c733b724751dbe2d5168d22ff2b828374f 100644 (file)
@@ -3219,6 +3219,7 @@ static const struct arm64_cpu_capabilities arm64_elf_hwcaps[] = {
 #ifdef CONFIG_ARM64_MTE
        HWCAP_CAP(ID_AA64PFR1_EL1, MTE, MTE2, CAP_HWCAP, KERNEL_HWCAP_MTE),
        HWCAP_CAP(ID_AA64PFR1_EL1, MTE, MTE3, CAP_HWCAP, KERNEL_HWCAP_MTE3),
+       HWCAP_CAP(ID_AA64PFR2_EL1, MTEFAR, IMP, CAP_HWCAP, KERNEL_HWCAP_MTE_FAR),
 #endif /* CONFIG_ARM64_MTE */
        HWCAP_CAP(ID_AA64MMFR0_EL1, ECV, IMP, CAP_HWCAP, KERNEL_HWCAP_ECV),
        HWCAP_CAP(ID_AA64MMFR1_EL1, AFP, IMP, CAP_HWCAP, KERNEL_HWCAP_AFP),
index c1f2b6b04b411ad3b310a0fc905e4dc594463082..e552cb305641498c8e05d4bf93d84a55a938cb32 100644 (file)
@@ -160,6 +160,7 @@ static const char *const hwcap_str[] = {
        [KERNEL_HWCAP_SME_SFEXPA]       = "smesfexpa",
        [KERNEL_HWCAP_SME_STMOP]        = "smestmop",
        [KERNEL_HWCAP_SME_SMOP4]        = "smesmop4",
+       [KERNEL_HWCAP_MTE_FAR]          = "mtefar",
 };
 
 #ifdef CONFIG_COMPAT
index ec0a337891ddfc705238fe07444c085f0d48aa5c..832d8540e13b542ebe30c2eb65fc0635468170e3 100644 (file)
@@ -837,9 +837,12 @@ static int do_tag_check_fault(unsigned long far, unsigned long esr,
        /*
         * The architecture specifies that bits 63:60 of FAR_EL1 are UNKNOWN
         * for tag check faults. Set them to corresponding bits in the untagged
-        * address.
+        * address if ARM64_MTE_FAR isn't supported.
+        * Otherwise, bits 63:60 of FAR_EL1 are not UNKNOWN.
         */
-       far = (__untagged_addr(far) & ~MTE_TAG_MASK) | (far & MTE_TAG_MASK);
+       if (!cpus_have_cap(ARM64_MTE_FAR))
+               far = (__untagged_addr(far) & ~MTE_TAG_MASK) | (far & MTE_TAG_MASK);
+
        do_bad_area(far, esr, regs);
        return 0;
 }