[glibc/arm/malloc-mte-v1] aarch64: add glibc.mem.aarch64_mte tunable
Yury Khrustalev via Glibc-cvs <[email protected]> Thu, 7 May 2026 12:45:34 +0000 (GMT)
| Newsgroups | gmane.comp.lib.glibc.cvs |
|---|---|
| Message-ID | <[email protected]> |
https://sourceware.org/git/gitweb.cgi?p=glibc.git;h=fe1173fcf4ef578e472bc54d9141bfcb32f8c943 commit fe1173fcf4ef578e472bc54d9141bfcb32f8c943 Author: Yury Khrustalev <[email protected]> Date: Thu Apr 23 14:31:54 2026 +0100 aarch64: add glibc.mem.aarch64_mte tunable Add new tunable glibc.mem.aarch64_mte of string type with supported values: none, sync, async, and auto. Use it to control prctl syscall used to send the PR_SET_TAGGED_ADDR_CTRL command. To avoid confusion, we also remove the glibc.mem.tagging tunable. The new tunable defaults to 'none' and only works of MTE is supported. Diff: --- manual/tunables.texi | 15 ++++++ sysdeps/aarch64/Makefile | 1 + sysdeps/aarch64/cpu-features.h | 7 +++ sysdeps/aarch64/dl-mte.c | 65 ++++++++++++++++++++++++ sysdeps/aarch64/dl-start.S | 2 + sysdeps/aarch64/dl-tunables.list | 5 ++ sysdeps/unix/sysv/linux/aarch64/cpu-features.c | 20 ++++++++ sysdeps/unix/sysv/linux/aarch64/dl-procruntime.c | 16 ++++++ sysdeps/unix/sysv/linux/aarch64/libc-start.h | 6 +++ 9 files changed, 137 insertions(+) diff --git a/manual/tunables.texi b/manual/tunables.texi index 95b7075ae7..dcba120b2b 100644 --- a/manual/tunables.texi +++ b/manual/tunables.texi @@ -682,6 +682,21 @@ This tunable takes a value of 0 and 1, where 1 enables the feature. The default value is @samp{0}, which disables the decoration. @end deftp +@deftp Tunable glibc.mem.aarch64_mte +On AArch64 systems that support the Memory Tagging Extension (MTE) extension +this tunable allows to select the tag check fault mode (MTE mode). + +Available values are: + +@itemize @bullet +@item @code{none}: (the default), memory tagging is disabled. +@item @code{auto}: enable CPU preferred tag checking mode. +@item @code{sync}: enable synchronous tag check fault mode. +@item @code{async}: enable asynchronous tag check fault mode. +@end itemize + +@end deftp + @node gmon Tunables @section gmon Tunables @cindex gmon tunables diff --git a/sysdeps/aarch64/Makefile b/sysdeps/aarch64/Makefile index 949c87ff1d..8fcd8526ac 100644 --- a/sysdeps/aarch64/Makefile +++ b/sysdeps/aarch64/Makefile @@ -4,6 +4,7 @@ ifeq ($(subdir),elf) sysdep-dl-routines += \ dl-bti \ dl-gcs \ + dl-mte \ # sysdep-dl-routines tests += \ diff --git a/sysdeps/aarch64/cpu-features.h b/sysdeps/aarch64/cpu-features.h index f414060066..238b8fb030 100644 --- a/sysdeps/aarch64/cpu-features.h +++ b/sysdeps/aarch64/cpu-features.h @@ -59,6 +59,13 @@ enum { BTI_CHECK_ENFORCED = 1, }; +enum { + MTE_TUNABLE_NONE = 0, + MTE_TUNABLE_AUTO = 1, + MTE_TUNABLE_SYNC = 2, + MTE_TUNABLE_ASYNC = 3, +}; + struct cpu_features { uint64_t midr_el1; diff --git a/sysdeps/aarch64/dl-mte.c b/sysdeps/aarch64/dl-mte.c new file mode 100644 index 0000000000..af65680bf4 --- /dev/null +++ b/sysdeps/aarch64/dl-mte.c @@ -0,0 +1,65 @@ +/* AArch64 implementation for MTE (memory tagging). + Copyright (C) 2026 Free Software Foundation, Inc. + This file is part of the GNU C Library. + + The GNU C Library is free software; you can redistribute it and/or + modify it under the terms of the GNU Lesser General Public + License as published by the Free Software Foundation; either + version 2.1 of the License, or (at your option) any later version. + + The GNU C Library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Lesser General Public License for more details. + + You should have received a copy of the GNU Lesser General Public + License along with the GNU C Library; if not, see + <https://www.gnu.org/licenses/>. */ + +#include <sys/cdefs.h> +#include <ldsodefs.h> + +/* For the prctl syscall. */ +#define PR_SET_TAGGED_ADDR_CTRL 55 +#define PR_MTE_TAG_SHIFT 3 +#define PR_TAGGED_ADDR_ENABLE (1UL << 0) +#define PR_MTE_TCF_SYNC (1UL << 1) +#define PR_MTE_TCF_ASYNC (1UL << 2) + +/* The maximal set of permitted tags that the MTE random tag generation + instruction may use. We exclude tag 0 because a) we want to reserve + that for the libc heap structures and b) because it makes it easier + to see when pointer have been correctly tagged. */ +#define MTE_ALLOWED_TAGS (0xfffe << PR_MTE_TAG_SHIFT) + +void __mte_init (void); +rtld_hidden_proto (__mte_init) + +void __mte_init (void) +{ + int mode = GL (dl_aarch64_mte); + if (mode == MTE_TUNABLE_NONE) + return; + uint64_t flags = PR_TAGGED_ADDR_ENABLE | MTE_ALLOWED_TAGS; + switch (mode) + { + case MTE_TUNABLE_AUTO: + flags |= PR_MTE_TCF_SYNC | PR_MTE_TCF_ASYNC; + break; + case MTE_TUNABLE_SYNC: + flags |= PR_MTE_TCF_SYNC; + break; + case MTE_TUNABLE_ASYNC: + flags |= PR_MTE_TCF_ASYNC; + break; + default: + _dl_fatal_printf ("unknown MTE mode: %d\n", mode); + __builtin_unreachable (); + } + /* We use inline system call to avoid unnecessary dependency + on the sys/prctl.h header. */ + int r = INLINE_SYSCALL_CALL (prctl, PR_SET_TAGGED_ADDR_CTRL, flags, 0, 0, 0); + if (r == -1) + _dl_fatal_printf ("failed to enable MTE\n"); +} +rtld_hidden_def (__mte_init) diff --git a/sysdeps/aarch64/dl-start.S b/sysdeps/aarch64/dl-start.S index c278485cd3..ab490d2460 100644 --- a/sysdeps/aarch64/dl-start.S +++ b/sysdeps/aarch64/dl-start.S @@ -66,6 +66,8 @@ ENTRY (_start) cbnz w0, L(failed_gcs_lock) L(skip_gcs_enable): + bl HIDDEN_JUMPTARGET(__mte_init) + .globl _dl_start_user .type _dl_start_user, %function _dl_start_user: diff --git a/sysdeps/aarch64/dl-tunables.list b/sysdeps/aarch64/dl-tunables.list index a2ccba0b29..e153387971 100644 --- a/sysdeps/aarch64/dl-tunables.list +++ b/sysdeps/aarch64/dl-tunables.list @@ -34,4 +34,9 @@ glibc { default: 0 } } + mem { + aarch64_mte { + type: STRING + } + } } diff --git a/sysdeps/unix/sysv/linux/aarch64/cpu-features.c b/sysdeps/unix/sysv/linux/aarch64/cpu-features.c index cda1f82948..89a0e94b3d 100644 --- a/sysdeps/unix/sysv/linux/aarch64/cpu-features.c +++ b/sysdeps/unix/sysv/linux/aarch64/cpu-features.c @@ -59,6 +59,19 @@ get_midr_from_mcpu (const struct tunable_str_t *mcpu) return UINT64_MAX; } +static void +TUNABLE_CALLBACK (set_aarch64_mte) (tunable_val_t *val) +{ + if (tunable_strcmp_cte (val, "auto")) + GL (dl_aarch64_mte) = MTE_TUNABLE_AUTO; + else if (tunable_strcmp_cte (val, "sync")) + GL (dl_aarch64_mte) = MTE_TUNABLE_SYNC; + else if (tunable_strcmp_cte (val, "async")) + GL (dl_aarch64_mte) = MTE_TUNABLE_ASYNC; + else + GL (dl_aarch64_mte) = MTE_TUNABLE_NONE; +} + static inline void init_cpu_features (struct cpu_features *cpu_features) { @@ -95,6 +108,13 @@ init_cpu_features (struct cpu_features *cpu_features) if (cpu_features->bti) GLRO (dl_aarch64_bti) = TUNABLE_GET (glibc, cpu, aarch64_bti, uint64_t, 0); + /* Check if MTE is supported. */ + if (GLRO (dl_hwcap2) & HWCAP2_MTE) + TUNABLE_GET (glibc, mem, aarch64_mte, tunable_val_t *, + TUNABLE_CALLBACK (set_aarch64_mte)); + else + GL (dl_aarch64_mte) = MTE_TUNABLE_NONE; + /* Check if SVE is supported. */ cpu_features->sve = GLRO (dl_hwcap) & HWCAP_SVE; diff --git a/sysdeps/unix/sysv/linux/aarch64/dl-procruntime.c b/sysdeps/unix/sysv/linux/aarch64/dl-procruntime.c index 1f3b58d0fc..0ddba83fb1 100644 --- a/sysdeps/unix/sysv/linux/aarch64/dl-procruntime.c +++ b/sysdeps/unix/sysv/linux/aarch64/dl-procruntime.c @@ -35,3 +35,19 @@ PROCINFO_CLASS unsigned long _dl_aarch64_gcs , # endif #endif + +#if !IS_IN (ldconfig) +# if !defined PROCINFO_DECL && defined SHARED + ._dl_aarch64_mte +# else +PROCINFO_CLASS int _dl_aarch64_mte +# endif +# ifndef PROCINFO_DECL += 0 +# endif +# if !defined SHARED || defined PROCINFO_DECL +; +# else +, +# endif +#endif diff --git a/sysdeps/unix/sysv/linux/aarch64/libc-start.h b/sysdeps/unix/sysv/linux/aarch64/libc-start.h index 4ccd13741b..967875c989 100644 --- a/sysdeps/unix/sysv/linux/aarch64/libc-start.h +++ b/sysdeps/unix/sysv/linux/aarch64/libc-start.h @@ -36,6 +36,9 @@ # define GCS_POLICY_OPTIONAL 2 # endif +void __mte_init (void); +rtld_hidden_proto (__mte_init) + /* Must be on a top-level stack frame that does not return. */ static inline void __attribute__((always_inline)) aarch64_libc_setup_tls (void) @@ -72,6 +75,9 @@ aarch64_libc_setup_tls (void) _dl_fatal_printf ("failed to lock GCS: %d\n", -ret); } } + + __mte_init (); + } # define ARCH_SETUP_IREL() apply_irel ()