Linux kernel mirror (for testing) git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git
kernel os linux

arm64: Report address tag when FEAT_MTE_TAGGED_FAR is supported

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>

authored by

Yeoreum Yun and committed by
Catalin Marinas
7c7f5503 66984536

+18 -7
+3
Documentation/arch/arm64/elf_hwcaps.rst
··· 435 435 HWCAP2_POE 436 436 Functionality implied by ID_AA64MMFR3_EL1.S1POE == 0b0001. 437 437 438 + HWCAP3_MTE_FAR 439 + Functionality implied by ID_AA64PFR2_EL1.MTEFAR == 0b0001. 440 + 438 441 4. Unused AT_HWCAP bits 439 442 ----------------------- 440 443
+6 -5
Documentation/arch/arm64/tagged-pointers.rst
··· 60 60 on the tag information for user virtual addresses being maintained 61 61 in these fields unless the flag was set. 62 62 63 - Due to architecture limitations, bits 63:60 of the fault address 64 - are not preserved in response to synchronous tag check faults 65 - (SEGV_MTESERR) even if SA_EXPOSE_TAGBITS was set. Applications should 66 - treat the values of these bits as undefined in order to accommodate 67 - future architecture revisions which may preserve the bits. 63 + If FEAT_MTE_TAGGED_FAR (Armv8.9) is supported, bits 63:60 of the fault address 64 + are preserved in response to synchronous tag check faults (SEGV_MTESERR) 65 + otherwise not preserved even if SA_EXPOSE_TAGBITS was set. 66 + Applications should interpret the values of these bits based on 67 + the support for the HWCAP3_MTE_FAR. If the support is not present, 68 + the values of these bits should be considered as undefined otherwise valid. 68 69 69 70 For signals raised in response to watchpoint debug exceptions, the 70 71 tag information will be preserved regardless of the SA_EXPOSE_TAGBITS
+1
arch/arm64/include/asm/hwcap.h
··· 176 176 #define KERNEL_HWCAP_POE __khwcap2_feature(POE) 177 177 178 178 #define __khwcap3_feature(x) (const_ilog2(HWCAP3_ ## x) + 128) 179 + #define KERNEL_HWCAP_MTE_FAR __khwcap3_feature(MTE_FAR) 179 180 180 181 /* 181 182 * This yields a mask that user programs can use to figure out what
+1
arch/arm64/include/uapi/asm/hwcap.h
··· 143 143 /* 144 144 * HWCAP3 flags - for AT_HWCAP3 145 145 */ 146 + #define HWCAP3_MTE_FAR (1UL << 0) 146 147 147 148 #endif /* _UAPI__ASM_HWCAP_H */
+1
arch/arm64/kernel/cpufeature.c
··· 3219 3219 #ifdef CONFIG_ARM64_MTE 3220 3220 HWCAP_CAP(ID_AA64PFR1_EL1, MTE, MTE2, CAP_HWCAP, KERNEL_HWCAP_MTE), 3221 3221 HWCAP_CAP(ID_AA64PFR1_EL1, MTE, MTE3, CAP_HWCAP, KERNEL_HWCAP_MTE3), 3222 + HWCAP_CAP(ID_AA64PFR2_EL1, MTEFAR, IMP, CAP_HWCAP, KERNEL_HWCAP_MTE_FAR), 3222 3223 #endif /* CONFIG_ARM64_MTE */ 3223 3224 HWCAP_CAP(ID_AA64MMFR0_EL1, ECV, IMP, CAP_HWCAP, KERNEL_HWCAP_ECV), 3224 3225 HWCAP_CAP(ID_AA64MMFR1_EL1, AFP, IMP, CAP_HWCAP, KERNEL_HWCAP_AFP),
+1
arch/arm64/kernel/cpuinfo.c
··· 160 160 [KERNEL_HWCAP_SME_SFEXPA] = "smesfexpa", 161 161 [KERNEL_HWCAP_SME_STMOP] = "smestmop", 162 162 [KERNEL_HWCAP_SME_SMOP4] = "smesmop4", 163 + [KERNEL_HWCAP_MTE_FAR] = "mtefar", 163 164 }; 164 165 165 166 #ifdef CONFIG_COMPAT
+5 -2
arch/arm64/mm/fault.c
··· 837 837 /* 838 838 * The architecture specifies that bits 63:60 of FAR_EL1 are UNKNOWN 839 839 * for tag check faults. Set them to corresponding bits in the untagged 840 - * address. 840 + * address if ARM64_MTE_FAR isn't supported. 841 + * Otherwise, bits 63:60 of FAR_EL1 are not UNKNOWN. 841 842 */ 842 - far = (__untagged_addr(far) & ~MTE_TAG_MASK) | (far & MTE_TAG_MASK); 843 + if (!cpus_have_cap(ARM64_MTE_FAR)) 844 + far = (__untagged_addr(far) & ~MTE_TAG_MASK) | (far & MTE_TAG_MASK); 845 + 843 846 do_bad_area(far, esr, regs); 844 847 return 0; 845 848 }