[1/2] malloc: change --enable-memory-tagging configure flag

Message ID 20260320113657.167707-2-yury.khrustalev@arm.com (mailing list archive)
State Dropped
Headers
Series memtag: Fix and clean-up code |

Checks

Context Check Description
redhat-pt-bot/TryBot-apply_patch success Patch applied to master at the time it was sent
linaro-tcwg-bot/tcwg_glibc_build--master-aarch64 success Build passed
linaro-tcwg-bot/tcwg_glibc_build--master-arm success Build passed
linaro-tcwg-bot/tcwg_glibc_check--master-aarch64 success Test passed
linaro-tcwg-bot/tcwg_glibc_check--master-arm success Test passed

Commit Message

Yury Khrustalev March 20, 2026, 11:36 a.m. UTC
  The --enable-memory-tagging configure flag was added as a generic
option although memory tagging is only implemented for the aarch64
target. This flag was added as blanket on/off switch and at the
time it did not allow to select each of different types of memory
tagging.

This commit extends the behaviour of the --enable-memory-tagging
configure flag adding a value to it. The accepted values are:

 - '--enable-memory-tagging=none'
    (the default): no optional memtag features are enabled

 - '--enable-memory-tagging=no'
   '--disable-memory-tagging'
    same as 'none' (for backward compatibility)

 - '--enable-memory-tagging=all'
    all optional memtag features that are supported by the
    target architecture are enabled

 - '--enable-memory-tagging=yes'
   '--enable-memory-tagging':
    same as 'all' (for backward compatibility)

 - '--enable-memory-tagging=feature1,feature2,...'
    target-dependent selection of optional memtag features
    that should be enabled.

Each supported memtag feature should add a defined target macro
that should be used in the code to guard code that implements
corresponding optional feature. Also, a corresponding makefile
variable is set to 'yes' or 'no' to help with conditional enabling
of tests.

On aarch64 two feature flags are supported: 'heap' and 'stack'.
There is experimental implementation for 'heap' but no code for
'stack' yet.

The meaning of this flags also changes: it is supposed to control
only optional features related to memory tagging: in theory it is
possible that some of the memory tagging features can be always
enabled on some target.

Install documentation and the Glibc manual updated accordingly.
---
 INSTALL                                       | 30 +++++++++-------
 config.h.in                                   |  5 +--
 config.make.in                                |  2 --
 configure                                     | 31 +++++++++--------
 configure.ac                                  | 28 ++++++++-------
 malloc/arena.c                                |  4 +--
 malloc/malloc.c                               |  4 +--
 manual/install.texi                           | 34 ++++++++++++-------
 sysdeps/aarch64/__mtag_tag_region.S           |  4 +--
 sysdeps/aarch64/__mtag_tag_zero_region.S      |  4 +--
 sysdeps/aarch64/configure                     | 30 ++++++++++++++++
 sysdeps/aarch64/configure.ac                  | 26 ++++++++++++++
 sysdeps/aarch64/libc-mtag.h                   |  4 +--
 .../unix/sysv/linux/aarch64/cpu-features.c    |  4 +--
 14 files changed, 143 insertions(+), 67 deletions(-)
  

Comments

Adhemerval Zanella Netto March 25, 2026, 5:07 p.m. UTC | #1
On 20/03/26 08:36, Yury Khrustalev wrote:
> The --enable-memory-tagging configure flag was added as a generic
> option although memory tagging is only implemented for the aarch64
> target. This flag was added as blanket on/off switch and at the
> time it did not allow to select each of different types of memory
> tagging.
> 
> This commit extends the behaviour of the --enable-memory-tagging
> configure flag adding a value to it. The accepted values are:
> 
>  - '--enable-memory-tagging=none'
>     (the default): no optional memtag features are enabled
> 
>  - '--enable-memory-tagging=no'
>    '--disable-memory-tagging'
>     same as 'none' (for backward compatibility)
> 
>  - '--enable-memory-tagging=all'
>     all optional memtag features that are supported by the
>     target architecture are enabled
> 
>  - '--enable-memory-tagging=yes'
>    '--enable-memory-tagging':
>     same as 'all' (for backward compatibility)
> 
>  - '--enable-memory-tagging=feature1,feature2,...'
>     target-dependent selection of optional memtag features
>     that should be enabled.
> 
> Each supported memtag feature should add a defined target macro
> that should be used in the code to guard code that implements
> corresponding optional feature. Also, a corresponding makefile
> variable is set to 'yes' or 'no' to help with conditional enabling
> of tests.
> 
> On aarch64 two feature flags are supported: 'heap' and 'stack'.
> There is experimental implementation for 'heap' but no code for
> 'stack' yet.
> 
> The meaning of this flags also changes: it is supposed to control
> only optional features related to memory tagging: in theory it is
> possible that some of the memory tagging features can be always
> enabled on some target.
> 
> Install documentation and the Glibc manual updated accordingly.

As I mentioned earlier [1], I do not think extending --enable-memory-tagging 
to support multiple combinations is a good way forward.

Besides adding extra build permutations, which most likely will not be 
tested and distro will either not enable or enable the most comprehensive 
set; I also do not think we should add partial support for MTE if/when 
DT_AARCH64_MEMTAG_* is supported.

To allow compatibility support, if/when DT_AARCH64_MEMTAG_* is added (even 
if just DT_AARCH64_MEMTAG_STACK) I would expect glibc to also handle all 
defined DT_AARCH64_MEMTAG_*, even if to advertise user that process can not 
be started because of missing support.

So the question is whether to make sense to enable DT_AARCH64_MEMTAG_* 
support disjoit of MTE malloc tagging support (as current 
--enable-memory-tagging does). 

And since a possible DT_AARCH64_MEMTAG_HEAP support would imply in
--enable-memory-tagging, what I would expect either add another configure 
option (maybe --enable-aarch64-mte or something alike) that implies in 
--enable-memory-tagging; or just gate DT_AARCH64_MEMTAG_* through 
--enable-memory-tagging.

[1] https://sourceware.org/pipermail/libc-alpha/2026-March/176023.html

> ---
>  INSTALL                                       | 30 +++++++++-------
>  config.h.in                                   |  5 +--
>  config.make.in                                |  2 --
>  configure                                     | 31 +++++++++--------
>  configure.ac                                  | 28 ++++++++-------
>  malloc/arena.c                                |  4 +--
>  malloc/malloc.c                               |  4 +--
>  manual/install.texi                           | 34 ++++++++++++-------
>  sysdeps/aarch64/__mtag_tag_region.S           |  4 +--
>  sysdeps/aarch64/__mtag_tag_zero_region.S      |  4 +--
>  sysdeps/aarch64/configure                     | 30 ++++++++++++++++
>  sysdeps/aarch64/configure.ac                  | 26 ++++++++++++++
>  sysdeps/aarch64/libc-mtag.h                   |  4 +--
>  .../unix/sysv/linux/aarch64/cpu-features.c    |  4 +--
>  14 files changed, 143 insertions(+), 67 deletions(-)
> 
> diff --git a/INSTALL b/INSTALL
> index 4174c9661f..0d367315ad 100644
> --- a/INSTALL
> +++ b/INSTALL
> @@ -154,19 +154,23 @@ passed to 'configure'.  For example:
>  
>       NOTE: '--enable-cet' is only supported on x86_64 and x32.
>  
> -'--enable-memory-tagging'
> -     Enable memory tagging support if the architecture supports it.
> -     When the GNU C Library is built with this option then the resulting
> -     library will be able to control the use of tagged memory when
> -     hardware support is present by use of the tunable
> -     'glibc.mem.tagging'.  This includes the generation of tagged memory
> -     when using the 'malloc' APIs.
> -
> -     At present only AArch64 platforms with MTE provide this
> -     functionality, although the library will still operate (without
> -     memory tagging) on older versions of the architecture.
> -
> -     The default is to disable support for memory tagging.
> +'--enable-memory-tagging=none'
> +'--enable-memory-tagging=all'
> +'--enable-memory-tagging=feature1,feature2,...'
> +     Enable support for the selected optional memory tagging features if the
> +     architecture supports it.
> +
> +     'none': (the default) means that no optional memory tagging
> +     features should be enabled.
> +     'all': means that all optional memory tagging features that are
> +     supported by the architecture should be enabled.
> +
> +     The full list of supported values depends on the architecture.
> +
> +     At present only AArch64 platforms with MTE provide this functionality.
> +     The following values are supported on AArch64 platforms with MTE:
> +
> +     'heap': enables experimental support for memory tagging in malloc.
>  
>  '--disable-profile'
>       Don't build libraries with profiling information.  You may want to
> diff --git a/config.h.in b/config.h.in
> index b53731c393..2f51a40de1 100644
> --- a/config.h.in
> +++ b/config.h.in
> @@ -182,8 +182,9 @@
>  /* Define if inlined system calls are available.  */
>  #undef HAVE_INLINED_SYSCALLS
>  
> -/* Define if memory tagging support should be enabled.  */
> -#undef USE_MTAG
> +/* Define if AArch64 memory tagging features should be enabled.  */
> +#undef USE_AARCH64_MTAG_HEAP
> +#undef USE_AARCH64_MTAG_STACK
>  
>  /* Package description.  */
>  #undef PKGVERSION
> diff --git a/config.make.in b/config.make.in
> index 856363d0cd..12ccb55e53 100644
> --- a/config.make.in
> +++ b/config.make.in
> @@ -78,8 +78,6 @@ multi-arch = @multi_arch@
>  
>  mach-interface-list = @mach_interface_list@
>  
> -memory-tagging = @memory_tagging@
> -
>  # Configuration options.
>  build-shared = @shared@
>  build-profile = @profile@
> diff --git a/configure b/configure
> index c84d283bd5..70bb48b181 100755
> --- a/configure
> +++ b/configure
> @@ -703,7 +703,6 @@ INSTALL_PROGRAM
>  base_machine
>  build_pt_chown
>  build_nscd
> -memory_tagging
>  enable_werror
>  force_install
>  bindnow
> @@ -1490,8 +1489,9 @@ Optional Features:
>    --disable-werror        do not build with -Werror
>    --enable-multi-arch     enable single DSO with optimizations for multiple
>                            architectures
> -  --enable-memory-tagging enable memory tagging if supported by the
> -                          architecture [default=no]
> +  --enable-memory-tagging=[none|all|feature1,feature2,...]
> +                          enable memory tagging if supported by the
> +                          architecture [default=none]
>    --enable-systemtap      enable systemtap static probe points [default=no]
>    --disable-build-nscd    disable building and installing the nscd daemon
>    --disable-nscd          library functions will not contact the nscd daemon
> @@ -4690,25 +4690,28 @@ esac
>  fi
>  
>  
> +# Supported values for this option are target-specific.  This option should
> +# accept either 'none', 'all', or a comma-delimited list of optional memory
> +# tagging features that should be enabled (target-specific) where 'all' means
> +# that all supported optional features should be enabled.
>  # Check whether --enable-memory-tagging was given.
>  if test ${enable_memory_tagging+y}
>  then :
>    enableval=$enable_memory_tagging; memory_tagging=$enableval
>  else case e in #(
> -  e) memory_tagging=no ;;
> +  e) memory_tagging=none ;;
>  esac
>  fi
>  
> -if test "$memory_tagging" = yes; then
> -  # Only enable this on architectures that support it.
> -  case $host_cpu in
> -    aarch64)
> -      printf "%s\n" "#define USE_MTAG 1" >>confdefs.h
> -
> -      ;;
> -  esac
> -fi
> -
> +# convert 'yes' to 'all' and 'no' to 'none' for backward compat
> +case $memory_tagging in
> +  yes) memory_tagging=all ;;
> +  no) memory_tagging=none ;;
> +esac
> +case $memory_tagging in
> +  all) memory_tagging_default=yes; ;;
> +  *) memory_tagging_default=no; ;;
> +esac
>  
>  # Check whether --enable-systemtap was given.
>  if test ${enable_systemtap+y}
> diff --git a/configure.ac b/configure.ac
> index 280ec8e5b3..0ac1f2d4d0 100644
> --- a/configure.ac
> +++ b/configure.ac
> @@ -328,20 +328,24 @@ AC_ARG_ENABLE([multi-arch],
>  	      [multi_arch=$enableval],
>  	      [multi_arch=default])
>  
> +# Supported values for this option are target-specific.  This option should
> +# accept either 'none', 'all', or a comma-delimited list of optional memory
> +# tagging features that should be enabled (target-specific) where 'all' means
> +# that all supported optional features should be enabled.
>  AC_ARG_ENABLE([memory-tagging],
> -	      AS_HELP_STRING([--enable-memory-tagging],
> -			     [enable memory tagging if supported by the architecture @<:@default=no@:>@]),
> +	      AS_HELP_STRING([--enable-memory-tagging=@<:@none|all|feature1,feature2,...@:>@],
> +			     [enable memory tagging if supported by the architecture @<:@default=none@:>@]),
>  	      [memory_tagging=$enableval],
> -	      [memory_tagging=no])
> -if test "$memory_tagging" = yes; then
> -  # Only enable this on architectures that support it.
> -  case $host_cpu in
> -    aarch64)
> -      AC_DEFINE(USE_MTAG)
> -      ;;
> -  esac
> -fi
> -AC_SUBST(memory_tagging)
> +	      [memory_tagging=none])
> +# convert 'yes' to 'all' and 'no' to 'none' for backward compat
> +case $memory_tagging in
> +  yes) memory_tagging=all ;;
> +  no) memory_tagging=none ;;
> +esac
> +case $memory_tagging in
> +  all) memory_tagging_default=yes; ;;
> +  *) memory_tagging_default=no; ;;
> +esac
>  
>  AC_ARG_ENABLE([systemtap],
>                [AS_HELP_STRING([--enable-systemtap],
> diff --git a/malloc/arena.c b/malloc/arena.c
> index 03a812f54d..2f894d21e9 100644
> --- a/malloc/arena.c
> +++ b/malloc/arena.c
> @@ -252,7 +252,7 @@ __ptmalloc_init (void)
>    tcache_key_initialize ();
>  #endif
>  
> -#ifdef USE_MTAG
> +#ifdef USE_AARCH64_MTAG_HEAP
>    if ((TUNABLE_GET_FULL (glibc, mem, tagging, int32_t, NULL) & 1) != 0)
>      {
>        /* If the tunable says that we should be using tagged memory
> @@ -264,7 +264,7 @@ __ptmalloc_init (void)
>        mtag_enabled = true;
>        mtag_mmap_flags = __MTAG_MMAP_FLAGS;
>      }
> -#endif
> +#endif /* USE_AARCH64_MTAG_HEAP */
>  
>  #if defined SHARED && IS_IN (libc)
>    /* In case this libc copy is in a non-default namespace, never use
> diff --git a/malloc/malloc.c b/malloc/malloc.c
> index 6455a1b0e0..7de6599d30 100644
> --- a/malloc/malloc.c
> +++ b/malloc/malloc.c
> @@ -405,13 +405,13 @@ verify (PTRDIFF_MAX <= SIZE_MAX / 2);
>     tagging is not enabled, it simply returns the original pointer.
>  */
>  
> -#ifdef USE_MTAG
> +#ifdef USE_AARCH64_MTAG_HEAP
>  static bool mtag_enabled = false;
>  static int mtag_mmap_flags = 0;
>  #else
>  # define mtag_enabled false
>  # define mtag_mmap_flags 0
> -#endif
> +#endif /* USE_AARCH64_MTAG_HEAP */
>  
>  static __always_inline void *
>  tag_region (void *ptr, size_t size)
> diff --git a/manual/install.texi b/manual/install.texi
> index 073cda0530..8d14565d34 100644
> --- a/manual/install.texi
> +++ b/manual/install.texi
> @@ -185,18 +185,28 @@ non CET enabled shared library in CET enabled application.
>  
>  NOTE: @option{--enable-cet} is only supported on x86_64 and x32.
>  
> -@item --enable-memory-tagging
> -Enable memory tagging support if the architecture supports it.  When
> -@theglibc{} is built with this option then the resulting library will
> -be able to control the use of tagged memory when hardware support is
> -present by use of the tunable @samp{glibc.mem.tagging}.  This includes
> -the generation of tagged memory when using the @code{malloc} APIs.
> -
> -At present only AArch64 platforms with MTE provide this functionality,
> -although the library will still operate (without memory tagging) on
> -older versions of the architecture.
> -
> -The default is to disable support for memory tagging.
> +@item --enable-memory-tagging=none
> +@itemx --enable-memory-tagging=all
> +@itemx --enable-memory-tagging=@var{feature1},@var{feature2},...
> +Enable support for the selected optional memory tagging features if the
> +architecture supports it.
> +
> +@itemize @bullet
> +@item @option{none}: (the default) means that no optional memory tagging
> +      features should be enabled.
> +@item @option{all}: means that all optional memory tagging features that are
> +      supported by the architecture should be enabled.
> +@end itemize
> +
> +The full list of supported values depends on the architecture.
> +
> +At present only AArch64 platforms with MTE provide this functionality.
> +The following values are supported on AArch64 platforms with MTE:
> +
> +@itemize @bullet
> +@item @option{heap}: enables experimental support for memory tagging in
> +      malloc.
> +@end itemize
>  
>  @item --disable-profile
>  Don't build libraries with profiling information.  You may want to use
> diff --git a/sysdeps/aarch64/__mtag_tag_region.S b/sysdeps/aarch64/__mtag_tag_region.S
> index bad3193bfe..b75e732269 100644
> --- a/sysdeps/aarch64/__mtag_tag_region.S
> +++ b/sysdeps/aarch64/__mtag_tag_region.S
> @@ -18,7 +18,7 @@
>  
>  #include <sysdep.h>
>  
> -#ifdef USE_MTAG
> +#ifdef USE_AARCH64_MTAG_HEAP
>  
>  /* Assumptions:
>   *
> @@ -107,4 +107,4 @@ L(no_zva_loop):
>  	ret
>  
>  END (__libc_mtag_tag_region)
> -#endif /* USE_MTAG */
> +#endif /* USE_AARCH64_MTAG_HEAP */
> diff --git a/sysdeps/aarch64/__mtag_tag_zero_region.S b/sysdeps/aarch64/__mtag_tag_zero_region.S
> index 3bc6e7301f..fcb647e131 100644
> --- a/sysdeps/aarch64/__mtag_tag_zero_region.S
> +++ b/sysdeps/aarch64/__mtag_tag_zero_region.S
> @@ -18,7 +18,7 @@
>  
>  #include <sysdep.h>
>  
> -#ifdef USE_MTAG
> +#ifdef USE_AARCH64_MTAG_HEAP
>  
>  /* Assumptions:
>   *
> @@ -107,4 +107,4 @@ L(no_zva_loop):
>  	ret
>  
>  END (__libc_mtag_tag_zero_region)
> -#endif /* USE_MTAG */
> +#endif /* USE_AARCH64_MTAG_HEAP */
> diff --git a/sysdeps/aarch64/configure b/sysdeps/aarch64/configure
> index 44b833ea1d..309d04f5fb 100755
> --- a/sysdeps/aarch64/configure
> +++ b/sysdeps/aarch64/configure
> @@ -484,3 +484,33 @@ else
>  have-test-gcs = no"
>  fi
>  
> +# Memory tagging
> +memory_tagging_heap=$memory_tagging_default
> +memory_tagging_stack=$memory_tagging_default
> +case $memory_tagging in
> +  all|none) ;;
> +  *) OLD_IFS=$IFS
> +    IFS=,
> +    for feature in $memory_tagging; do
> +      case $feature in
> +        heap) memory_tagging_heap=yes; ;;
> +        stack) memory_tagging_stack=yes; ;;
> +        *) as_fn_error $? "Not a valid argument for --enable-memory-tagging: \"$feature\"" "$LINENO" 5 ;;
> +      esac
> +    done
> +    IFS=$OLD_IFS
> +    ;;
> +esac
> +config_vars="$config_vars
> +memory-tagging-heap = $memory_tagging_heap"
> +if test $memory_tagging_heap = yes; then
> +  printf "%s\n" "#define USE_AARCH64_MTAG_HEAP 1" >>confdefs.h
> +
> +fi
> +config_vars="$config_vars
> +memory-tagging-stack = $memory_tagging_stack"
> +if test $memory_tagging_stack = yes; then
> +  printf "%s\n" "#define USE_AARCH64_MTAG_STACK 1" >>confdefs.h
> +
> +fi
> +
> diff --git a/sysdeps/aarch64/configure.ac b/sysdeps/aarch64/configure.ac
> index b9981861f6..66cd4bf51e 100644
> --- a/sysdeps/aarch64/configure.ac
> +++ b/sysdeps/aarch64/configure.ac
> @@ -105,3 +105,29 @@ then
>  else
>    LIBC_CONFIG_VAR([have-test-gcs], [no])
>  fi
> +
> +# Memory tagging
> +memory_tagging_heap=$memory_tagging_default
> +memory_tagging_stack=$memory_tagging_default
> +case $memory_tagging in
> +  all|none) ;;
> +  *) OLD_IFS=$IFS
> +    IFS=,
> +    for feature in $memory_tagging; do
> +      case $feature in
> +        heap) memory_tagging_heap=yes; ;;
> +        stack) memory_tagging_stack=yes; ;;
> +        *) AC_MSG_ERROR([Not a valid argument for --enable-memory-tagging: "$feature"]) ;;
> +      esac
> +    done
> +    IFS=$OLD_IFS
> +    ;;
> +esac
> +LIBC_CONFIG_VAR([memory-tagging-heap], [$memory_tagging_heap])
> +if test $memory_tagging_heap = yes; then
> +  AC_DEFINE(USE_AARCH64_MTAG_HEAP)
> +fi
> +LIBC_CONFIG_VAR([memory-tagging-stack], [$memory_tagging_stack])
> +if test $memory_tagging_stack = yes; then
> +  AC_DEFINE(USE_AARCH64_MTAG_STACK)
> +fi
> diff --git a/sysdeps/aarch64/libc-mtag.h b/sysdeps/aarch64/libc-mtag.h
> index 1d7368b806..f821a2087e 100644
> --- a/sysdeps/aarch64/libc-mtag.h
> +++ b/sysdeps/aarch64/libc-mtag.h
> @@ -19,7 +19,7 @@
>  #ifndef _AARCH64_LIBC_MTAG_H
>  #define _AARCH64_LIBC_MTAG_H 1
>  
> -#ifndef USE_MTAG
> +#ifndef USE_AARCH64_MTAG_HEAP
>  /* Generic bindings for systems that do not support memory tagging.  */
>  #include_next "libc-mtag.h"
>  #else
> @@ -64,6 +64,6 @@ __libc_mtag_new_tag (void *p)
>    return x0;
>  }
>  
> -#endif /* USE_MTAG */
> +#endif /* USE_AARCH64_MTAG_HEAP */
>  
>  #endif /* _AARCH64_LIBC_MTAG_H */
> diff --git a/sysdeps/unix/sysv/linux/aarch64/cpu-features.c b/sysdeps/unix/sysv/linux/aarch64/cpu-features.c
> index 1e4f8a86b1..62dcea3f94 100644
> --- a/sysdeps/unix/sysv/linux/aarch64/cpu-features.c
> +++ b/sysdeps/unix/sysv/linux/aarch64/cpu-features.c
> @@ -105,7 +105,7 @@ init_cpu_features (struct cpu_features *cpu_features)
>       the user has requested it.  */
>    cpu_features->mte_state = 0;
>  
> -#ifdef USE_MTAG
> +#ifdef USE_AARCH64_MTAG_HEAP
>    int mte_state = TUNABLE_GET (glibc, mem, tagging, unsigned, 0);
>    cpu_features->mte_state = (GLRO (dl_hwcap2) & HWCAP2_MTE) ? mte_state : 0;
>    /* If we lack the MTE feature, disable the tunable, since it will
> @@ -126,7 +126,7 @@ init_cpu_features (struct cpu_features *cpu_features)
>      __prctl (PR_SET_TAGGED_ADDR_CTRL,
>  	     (PR_TAGGED_ADDR_ENABLE | PR_MTE_TCF_ASYNC | MTE_ALLOWED_TAGS),
>  	     0, 0, 0);
> -#endif
> +#endif /* USE_AARCH64_MTAG_HEAP */
>  
>    /* Check if SVE is supported.  */
>    cpu_features->sve = GLRO (dl_hwcap) & HWCAP_SVE;
  

Patch

diff --git a/INSTALL b/INSTALL
index 4174c9661f..0d367315ad 100644
--- a/INSTALL
+++ b/INSTALL
@@ -154,19 +154,23 @@  passed to 'configure'.  For example:
 
      NOTE: '--enable-cet' is only supported on x86_64 and x32.
 
-'--enable-memory-tagging'
-     Enable memory tagging support if the architecture supports it.
-     When the GNU C Library is built with this option then the resulting
-     library will be able to control the use of tagged memory when
-     hardware support is present by use of the tunable
-     'glibc.mem.tagging'.  This includes the generation of tagged memory
-     when using the 'malloc' APIs.
-
-     At present only AArch64 platforms with MTE provide this
-     functionality, although the library will still operate (without
-     memory tagging) on older versions of the architecture.
-
-     The default is to disable support for memory tagging.
+'--enable-memory-tagging=none'
+'--enable-memory-tagging=all'
+'--enable-memory-tagging=feature1,feature2,...'
+     Enable support for the selected optional memory tagging features if the
+     architecture supports it.
+
+     'none': (the default) means that no optional memory tagging
+     features should be enabled.
+     'all': means that all optional memory tagging features that are
+     supported by the architecture should be enabled.
+
+     The full list of supported values depends on the architecture.
+
+     At present only AArch64 platforms with MTE provide this functionality.
+     The following values are supported on AArch64 platforms with MTE:
+
+     'heap': enables experimental support for memory tagging in malloc.
 
 '--disable-profile'
      Don't build libraries with profiling information.  You may want to
diff --git a/config.h.in b/config.h.in
index b53731c393..2f51a40de1 100644
--- a/config.h.in
+++ b/config.h.in
@@ -182,8 +182,9 @@ 
 /* Define if inlined system calls are available.  */
 #undef HAVE_INLINED_SYSCALLS
 
-/* Define if memory tagging support should be enabled.  */
-#undef USE_MTAG
+/* Define if AArch64 memory tagging features should be enabled.  */
+#undef USE_AARCH64_MTAG_HEAP
+#undef USE_AARCH64_MTAG_STACK
 
 /* Package description.  */
 #undef PKGVERSION
diff --git a/config.make.in b/config.make.in
index 856363d0cd..12ccb55e53 100644
--- a/config.make.in
+++ b/config.make.in
@@ -78,8 +78,6 @@  multi-arch = @multi_arch@
 
 mach-interface-list = @mach_interface_list@
 
-memory-tagging = @memory_tagging@
-
 # Configuration options.
 build-shared = @shared@
 build-profile = @profile@
diff --git a/configure b/configure
index c84d283bd5..70bb48b181 100755
--- a/configure
+++ b/configure
@@ -703,7 +703,6 @@  INSTALL_PROGRAM
 base_machine
 build_pt_chown
 build_nscd
-memory_tagging
 enable_werror
 force_install
 bindnow
@@ -1490,8 +1489,9 @@  Optional Features:
   --disable-werror        do not build with -Werror
   --enable-multi-arch     enable single DSO with optimizations for multiple
                           architectures
-  --enable-memory-tagging enable memory tagging if supported by the
-                          architecture [default=no]
+  --enable-memory-tagging=[none|all|feature1,feature2,...]
+                          enable memory tagging if supported by the
+                          architecture [default=none]
   --enable-systemtap      enable systemtap static probe points [default=no]
   --disable-build-nscd    disable building and installing the nscd daemon
   --disable-nscd          library functions will not contact the nscd daemon
@@ -4690,25 +4690,28 @@  esac
 fi
 
 
+# Supported values for this option are target-specific.  This option should
+# accept either 'none', 'all', or a comma-delimited list of optional memory
+# tagging features that should be enabled (target-specific) where 'all' means
+# that all supported optional features should be enabled.
 # Check whether --enable-memory-tagging was given.
 if test ${enable_memory_tagging+y}
 then :
   enableval=$enable_memory_tagging; memory_tagging=$enableval
 else case e in #(
-  e) memory_tagging=no ;;
+  e) memory_tagging=none ;;
 esac
 fi
 
-if test "$memory_tagging" = yes; then
-  # Only enable this on architectures that support it.
-  case $host_cpu in
-    aarch64)
-      printf "%s\n" "#define USE_MTAG 1" >>confdefs.h
-
-      ;;
-  esac
-fi
-
+# convert 'yes' to 'all' and 'no' to 'none' for backward compat
+case $memory_tagging in
+  yes) memory_tagging=all ;;
+  no) memory_tagging=none ;;
+esac
+case $memory_tagging in
+  all) memory_tagging_default=yes; ;;
+  *) memory_tagging_default=no; ;;
+esac
 
 # Check whether --enable-systemtap was given.
 if test ${enable_systemtap+y}
diff --git a/configure.ac b/configure.ac
index 280ec8e5b3..0ac1f2d4d0 100644
--- a/configure.ac
+++ b/configure.ac
@@ -328,20 +328,24 @@  AC_ARG_ENABLE([multi-arch],
 	      [multi_arch=$enableval],
 	      [multi_arch=default])
 
+# Supported values for this option are target-specific.  This option should
+# accept either 'none', 'all', or a comma-delimited list of optional memory
+# tagging features that should be enabled (target-specific) where 'all' means
+# that all supported optional features should be enabled.
 AC_ARG_ENABLE([memory-tagging],
-	      AS_HELP_STRING([--enable-memory-tagging],
-			     [enable memory tagging if supported by the architecture @<:@default=no@:>@]),
+	      AS_HELP_STRING([--enable-memory-tagging=@<:@none|all|feature1,feature2,...@:>@],
+			     [enable memory tagging if supported by the architecture @<:@default=none@:>@]),
 	      [memory_tagging=$enableval],
-	      [memory_tagging=no])
-if test "$memory_tagging" = yes; then
-  # Only enable this on architectures that support it.
-  case $host_cpu in
-    aarch64)
-      AC_DEFINE(USE_MTAG)
-      ;;
-  esac
-fi
-AC_SUBST(memory_tagging)
+	      [memory_tagging=none])
+# convert 'yes' to 'all' and 'no' to 'none' for backward compat
+case $memory_tagging in
+  yes) memory_tagging=all ;;
+  no) memory_tagging=none ;;
+esac
+case $memory_tagging in
+  all) memory_tagging_default=yes; ;;
+  *) memory_tagging_default=no; ;;
+esac
 
 AC_ARG_ENABLE([systemtap],
               [AS_HELP_STRING([--enable-systemtap],
diff --git a/malloc/arena.c b/malloc/arena.c
index 03a812f54d..2f894d21e9 100644
--- a/malloc/arena.c
+++ b/malloc/arena.c
@@ -252,7 +252,7 @@  __ptmalloc_init (void)
   tcache_key_initialize ();
 #endif
 
-#ifdef USE_MTAG
+#ifdef USE_AARCH64_MTAG_HEAP
   if ((TUNABLE_GET_FULL (glibc, mem, tagging, int32_t, NULL) & 1) != 0)
     {
       /* If the tunable says that we should be using tagged memory
@@ -264,7 +264,7 @@  __ptmalloc_init (void)
       mtag_enabled = true;
       mtag_mmap_flags = __MTAG_MMAP_FLAGS;
     }
-#endif
+#endif /* USE_AARCH64_MTAG_HEAP */
 
 #if defined SHARED && IS_IN (libc)
   /* In case this libc copy is in a non-default namespace, never use
diff --git a/malloc/malloc.c b/malloc/malloc.c
index 6455a1b0e0..7de6599d30 100644
--- a/malloc/malloc.c
+++ b/malloc/malloc.c
@@ -405,13 +405,13 @@  verify (PTRDIFF_MAX <= SIZE_MAX / 2);
    tagging is not enabled, it simply returns the original pointer.
 */
 
-#ifdef USE_MTAG
+#ifdef USE_AARCH64_MTAG_HEAP
 static bool mtag_enabled = false;
 static int mtag_mmap_flags = 0;
 #else
 # define mtag_enabled false
 # define mtag_mmap_flags 0
-#endif
+#endif /* USE_AARCH64_MTAG_HEAP */
 
 static __always_inline void *
 tag_region (void *ptr, size_t size)
diff --git a/manual/install.texi b/manual/install.texi
index 073cda0530..8d14565d34 100644
--- a/manual/install.texi
+++ b/manual/install.texi
@@ -185,18 +185,28 @@  non CET enabled shared library in CET enabled application.
 
 NOTE: @option{--enable-cet} is only supported on x86_64 and x32.
 
-@item --enable-memory-tagging
-Enable memory tagging support if the architecture supports it.  When
-@theglibc{} is built with this option then the resulting library will
-be able to control the use of tagged memory when hardware support is
-present by use of the tunable @samp{glibc.mem.tagging}.  This includes
-the generation of tagged memory when using the @code{malloc} APIs.
-
-At present only AArch64 platforms with MTE provide this functionality,
-although the library will still operate (without memory tagging) on
-older versions of the architecture.
-
-The default is to disable support for memory tagging.
+@item --enable-memory-tagging=none
+@itemx --enable-memory-tagging=all
+@itemx --enable-memory-tagging=@var{feature1},@var{feature2},...
+Enable support for the selected optional memory tagging features if the
+architecture supports it.
+
+@itemize @bullet
+@item @option{none}: (the default) means that no optional memory tagging
+      features should be enabled.
+@item @option{all}: means that all optional memory tagging features that are
+      supported by the architecture should be enabled.
+@end itemize
+
+The full list of supported values depends on the architecture.
+
+At present only AArch64 platforms with MTE provide this functionality.
+The following values are supported on AArch64 platforms with MTE:
+
+@itemize @bullet
+@item @option{heap}: enables experimental support for memory tagging in
+      malloc.
+@end itemize
 
 @item --disable-profile
 Don't build libraries with profiling information.  You may want to use
diff --git a/sysdeps/aarch64/__mtag_tag_region.S b/sysdeps/aarch64/__mtag_tag_region.S
index bad3193bfe..b75e732269 100644
--- a/sysdeps/aarch64/__mtag_tag_region.S
+++ b/sysdeps/aarch64/__mtag_tag_region.S
@@ -18,7 +18,7 @@ 
 
 #include <sysdep.h>
 
-#ifdef USE_MTAG
+#ifdef USE_AARCH64_MTAG_HEAP
 
 /* Assumptions:
  *
@@ -107,4 +107,4 @@  L(no_zva_loop):
 	ret
 
 END (__libc_mtag_tag_region)
-#endif /* USE_MTAG */
+#endif /* USE_AARCH64_MTAG_HEAP */
diff --git a/sysdeps/aarch64/__mtag_tag_zero_region.S b/sysdeps/aarch64/__mtag_tag_zero_region.S
index 3bc6e7301f..fcb647e131 100644
--- a/sysdeps/aarch64/__mtag_tag_zero_region.S
+++ b/sysdeps/aarch64/__mtag_tag_zero_region.S
@@ -18,7 +18,7 @@ 
 
 #include <sysdep.h>
 
-#ifdef USE_MTAG
+#ifdef USE_AARCH64_MTAG_HEAP
 
 /* Assumptions:
  *
@@ -107,4 +107,4 @@  L(no_zva_loop):
 	ret
 
 END (__libc_mtag_tag_zero_region)
-#endif /* USE_MTAG */
+#endif /* USE_AARCH64_MTAG_HEAP */
diff --git a/sysdeps/aarch64/configure b/sysdeps/aarch64/configure
index 44b833ea1d..309d04f5fb 100755
--- a/sysdeps/aarch64/configure
+++ b/sysdeps/aarch64/configure
@@ -484,3 +484,33 @@  else
 have-test-gcs = no"
 fi
 
+# Memory tagging
+memory_tagging_heap=$memory_tagging_default
+memory_tagging_stack=$memory_tagging_default
+case $memory_tagging in
+  all|none) ;;
+  *) OLD_IFS=$IFS
+    IFS=,
+    for feature in $memory_tagging; do
+      case $feature in
+        heap) memory_tagging_heap=yes; ;;
+        stack) memory_tagging_stack=yes; ;;
+        *) as_fn_error $? "Not a valid argument for --enable-memory-tagging: \"$feature\"" "$LINENO" 5 ;;
+      esac
+    done
+    IFS=$OLD_IFS
+    ;;
+esac
+config_vars="$config_vars
+memory-tagging-heap = $memory_tagging_heap"
+if test $memory_tagging_heap = yes; then
+  printf "%s\n" "#define USE_AARCH64_MTAG_HEAP 1" >>confdefs.h
+
+fi
+config_vars="$config_vars
+memory-tagging-stack = $memory_tagging_stack"
+if test $memory_tagging_stack = yes; then
+  printf "%s\n" "#define USE_AARCH64_MTAG_STACK 1" >>confdefs.h
+
+fi
+
diff --git a/sysdeps/aarch64/configure.ac b/sysdeps/aarch64/configure.ac
index b9981861f6..66cd4bf51e 100644
--- a/sysdeps/aarch64/configure.ac
+++ b/sysdeps/aarch64/configure.ac
@@ -105,3 +105,29 @@  then
 else
   LIBC_CONFIG_VAR([have-test-gcs], [no])
 fi
+
+# Memory tagging
+memory_tagging_heap=$memory_tagging_default
+memory_tagging_stack=$memory_tagging_default
+case $memory_tagging in
+  all|none) ;;
+  *) OLD_IFS=$IFS
+    IFS=,
+    for feature in $memory_tagging; do
+      case $feature in
+        heap) memory_tagging_heap=yes; ;;
+        stack) memory_tagging_stack=yes; ;;
+        *) AC_MSG_ERROR([Not a valid argument for --enable-memory-tagging: "$feature"]) ;;
+      esac
+    done
+    IFS=$OLD_IFS
+    ;;
+esac
+LIBC_CONFIG_VAR([memory-tagging-heap], [$memory_tagging_heap])
+if test $memory_tagging_heap = yes; then
+  AC_DEFINE(USE_AARCH64_MTAG_HEAP)
+fi
+LIBC_CONFIG_VAR([memory-tagging-stack], [$memory_tagging_stack])
+if test $memory_tagging_stack = yes; then
+  AC_DEFINE(USE_AARCH64_MTAG_STACK)
+fi
diff --git a/sysdeps/aarch64/libc-mtag.h b/sysdeps/aarch64/libc-mtag.h
index 1d7368b806..f821a2087e 100644
--- a/sysdeps/aarch64/libc-mtag.h
+++ b/sysdeps/aarch64/libc-mtag.h
@@ -19,7 +19,7 @@ 
 #ifndef _AARCH64_LIBC_MTAG_H
 #define _AARCH64_LIBC_MTAG_H 1
 
-#ifndef USE_MTAG
+#ifndef USE_AARCH64_MTAG_HEAP
 /* Generic bindings for systems that do not support memory tagging.  */
 #include_next "libc-mtag.h"
 #else
@@ -64,6 +64,6 @@  __libc_mtag_new_tag (void *p)
   return x0;
 }
 
-#endif /* USE_MTAG */
+#endif /* USE_AARCH64_MTAG_HEAP */
 
 #endif /* _AARCH64_LIBC_MTAG_H */
diff --git a/sysdeps/unix/sysv/linux/aarch64/cpu-features.c b/sysdeps/unix/sysv/linux/aarch64/cpu-features.c
index 1e4f8a86b1..62dcea3f94 100644
--- a/sysdeps/unix/sysv/linux/aarch64/cpu-features.c
+++ b/sysdeps/unix/sysv/linux/aarch64/cpu-features.c
@@ -105,7 +105,7 @@  init_cpu_features (struct cpu_features *cpu_features)
      the user has requested it.  */
   cpu_features->mte_state = 0;
 
-#ifdef USE_MTAG
+#ifdef USE_AARCH64_MTAG_HEAP
   int mte_state = TUNABLE_GET (glibc, mem, tagging, unsigned, 0);
   cpu_features->mte_state = (GLRO (dl_hwcap2) & HWCAP2_MTE) ? mte_state : 0;
   /* If we lack the MTE feature, disable the tunable, since it will
@@ -126,7 +126,7 @@  init_cpu_features (struct cpu_features *cpu_features)
     __prctl (PR_SET_TAGGED_ADDR_CTRL,
 	     (PR_TAGGED_ADDR_ENABLE | PR_MTE_TCF_ASYNC | MTE_ALLOWED_TAGS),
 	     0, 0, 0);
-#endif
+#endif /* USE_AARCH64_MTAG_HEAP */
 
   /* Check if SVE is supported.  */
   cpu_features->sve = GLRO (dl_hwcap) & HWCAP_SVE;