[v5,1/1] <sys/tagged-address.h>: An API for tagged address

Message ID 20210805131358.300475-2-hjl.tools@gmail.com
State Superseded
Headers
Series RFC: Add <sys/tagged-address.h> |

Checks

Context Check Description
dj/TryBot-apply_patch success Patch applied to master at the time it was sent
dj/TryBot-32bit success Build for i686

Commit Message

H.J. Lu Aug. 5, 2021, 1:13 p.m. UTC
  By default, the number of the address bits used in address translation
is the number of address bits.  But it can be changed by ARM Top-byte
Ignore (TBI) or Intel Linear Address Masking (LAM).

<sys/tagged-address.h> provides an API for tagged address manipulation
with restrictions:

1. All bits between 0 and N - 1, where N is the number of tagged address
bits, are used in address translation.
2. All pointers participating in a pointer arithmetic operation should have
the same tag if they point to the same memory object so that pointer
equality operation can be performed on tagged pointers.

/* Get the current address bits used in address translation.  */
extern unsigned int get_tagged_address_bits (void);

/* Get the current mask for address bits used in address translation.  */
extern uintptr_t get_tagged_address_mask (void);

/* Set the mask for address bits used in address translation.  Return 0
   on success.  Return -1 on error.  */
extern int set_tagged_address_mask (uintptr_t __mask);

/* Return the tagged address of __ADDR with the tag value __TAG.  */
extern void *tag_address (void *__addr, unsigned int __tag);

/* Return the untagged address of __ADDR.  */
extern void *untag_address (void *__addr);

/* TRUE if constant address BITS is a valid tagged address bits.  */
 #define TAGGED_ADDRESS_VALID_BITS(BITS)

/* A mask for constant address BITS used in address translation.  */
 #define TAGGED_ADDRESS_MASK(BITS)

1. set_tagged_address_mask should be called as early as possible.
2. set_tagged_address_mask shouldn't be allowed after main is called.
3. After set_tagged_address_mask is called, don't allow it to be called
again to change the tagged address mask.  Otherwise, the previously
tagged addresses may not work anymore.
---
 NEWS                                          |  2 +-
 bits/tagged-address-mask.h                    | 47 +++++++++++
 bits/tagged-address-valid-bits.h              | 28 +++++++
 csu/libc-start.c                              |  3 +
 elf/dl-support.c                              |  5 ++
 include/sys/tagged-address.h                  |  9 +++
 manual/Makefile                               |  3 +-
 manual/ctype.texi                             |  2 +-
 manual/memory.texi                            |  2 +-
 manual/tagged-address.texi                    | 80 +++++++++++++++++++
 misc/Makefile                                 | 35 ++++++--
 misc/Versions                                 |  7 ++
 misc/set-tagged-address-mask.c                | 41 ++++++++++
 misc/sys/tagged-address.h                     | 45 +++++++++++
 misc/tagged-address.c                         | 55 +++++++++++++
 misc/tst-tagged-address-1-static.c            |  1 +
 misc/tst-tagged-address-1.c                   | 53 ++++++++++++
 misc/tst-tagged-address-2-static.c            |  1 +
 misc/tst-tagged-address-2.c                   | 44 ++++++++++
 misc/tst-tagged-address-3-static.c            |  1 +
 misc/tst-tagged-address-3.c                   | 48 +++++++++++
 misc/tst-tagged-address-4-static.c            |  1 +
 misc/tst-tagged-address-4.c                   | 35 ++++++++
 misc/tst-tagged-address-5.c                   | 25 ++++++
 misc/tst-tagged-address-6.c                   | 34 ++++++++
 misc/tst-tagged-address-7.c                   | 40 ++++++++++
 misc/tst-tagged-address-mod-5.c               | 45 +++++++++++
 misc/tst-tagged-address-mod-6.c               | 34 ++++++++
 misc/tst-tagged-address-mod-7.c               | 34 ++++++++
 sysdeps/generic/inline-tagged-address.h       | 43 ++++++++++
 sysdeps/generic/ldsodefs.h                    |  4 +
 sysdeps/unix/sysv/linux/i386/libc.abilist     |  5 ++
 .../unix/sysv/linux/x86_64/64/libc.abilist    |  5 ++
 .../unix/sysv/linux/x86_64/x32/libc.abilist   |  5 ++
 34 files changed, 813 insertions(+), 9 deletions(-)
 create mode 100644 bits/tagged-address-mask.h
 create mode 100644 bits/tagged-address-valid-bits.h
 create mode 100644 include/sys/tagged-address.h
 create mode 100644 manual/tagged-address.texi
 create mode 100644 misc/set-tagged-address-mask.c
 create mode 100644 misc/sys/tagged-address.h
 create mode 100644 misc/tagged-address.c
 create mode 100644 misc/tst-tagged-address-1-static.c
 create mode 100644 misc/tst-tagged-address-1.c
 create mode 100644 misc/tst-tagged-address-2-static.c
 create mode 100644 misc/tst-tagged-address-2.c
 create mode 100644 misc/tst-tagged-address-3-static.c
 create mode 100644 misc/tst-tagged-address-3.c
 create mode 100644 misc/tst-tagged-address-4-static.c
 create mode 100644 misc/tst-tagged-address-4.c
 create mode 100644 misc/tst-tagged-address-5.c
 create mode 100644 misc/tst-tagged-address-6.c
 create mode 100644 misc/tst-tagged-address-7.c
 create mode 100644 misc/tst-tagged-address-mod-5.c
 create mode 100644 misc/tst-tagged-address-mod-6.c
 create mode 100644 misc/tst-tagged-address-mod-7.c
 create mode 100644 sysdeps/generic/inline-tagged-address.h
  

Comments

Joseph Myers Aug. 5, 2021, 5:26 p.m. UTC | #1
On Thu, 5 Aug 2021, H.J. Lu via Libc-alpha wrote:

> +#ifdef __GNUC__
> +# if defined __USE_ISOC11 || defined __USE_ISOCXX11
> +#  ifdef __USE_ISOCXX11
> +#   define TAGGED_ADDRESS_ASSERT static_assert
> +#  else
> +#   define TAGGED_ADDRESS_ASSERT _Static_assert
> +#  endif

These __USE_* conditionals say what library features to enable.  
__USE_ISOC11 doesn't imply that C11 language features are available; you 
can use -D_ISOC11_SOURCE with a GCC version too old to support 
_Static_assert.

However, you should be able to rely on _Static_assert when building as C 
(regardless of feature test macros or compiler versions) because of the 
definition in sys/cdefs.h.
  
H.J. Lu Aug. 5, 2021, 5:41 p.m. UTC | #2
On Thu, Aug 5, 2021 at 10:26 AM Joseph Myers <joseph@codesourcery.com> wrote:
>
> On Thu, 5 Aug 2021, H.J. Lu via Libc-alpha wrote:
>
> > +#ifdef __GNUC__
> > +# if defined __USE_ISOC11 || defined __USE_ISOCXX11
> > +#  ifdef __USE_ISOCXX11
> > +#   define TAGGED_ADDRESS_ASSERT static_assert
> > +#  else
> > +#   define TAGGED_ADDRESS_ASSERT _Static_assert
> > +#  endif
>
> These __USE_* conditionals say what library features to enable.
> __USE_ISOC11 doesn't imply that C11 language features are available; you
> can use -D_ISOC11_SOURCE with a GCC version too old to support
> _Static_assert.
>
> However, you should be able to rely on _Static_assert when building as C
> (regardless of feature test macros or compiler versions) because of the
> definition in sys/cdefs.h.

I can use _Static_assert directly for C.  How should I use static_assert
for C++?
  
Joseph Myers Aug. 5, 2021, 5:54 p.m. UTC | #3
On Thu, 5 Aug 2021, H.J. Lu via Libc-alpha wrote:

> I can use _Static_assert directly for C.  How should I use static_assert
> for C++?

Probably based on a test of the value of __cplusplus.
  
H.J. Lu Aug. 5, 2021, 7:33 p.m. UTC | #4
On Thu, Aug 5, 2021 at 10:54 AM Joseph Myers <joseph@codesourcery.com> wrote:
>
> On Thu, 5 Aug 2021, H.J. Lu via Libc-alpha wrote:
>
> > I can use _Static_assert directly for C.  How should I use static_assert
> > for C++?
>
> Probably based on a test of the value of __cplusplus.
>

Like

#ifdef __cplusplus
# if __cplusplus >= 201103L
#  define TAGGED_ADDRESS_ASSERT static_assert
# else
#  define TAGGED_ADDRESS_ASSERT(expr, msg)
# endif
#else
#  define TAGGED_ADDRESS_ASSERT _Static_assert
#endif

Thanks.
  
Florian Weimer Aug. 12, 2021, 8:36 a.m. UTC | #5
* H. J. Lu:

> diff --git a/manual/ctype.texi b/manual/ctype.texi
> index d0618c5c38..28af73ff0e 100644
> --- a/manual/ctype.texi
> +++ b/manual/ctype.texi
> @@ -1,4 +1,4 @@
> -@node Character Handling, String and Array Utilities, Memory, Top
> +@node Character Handling, String and Array Utilities, Tagged Address, Top
>  @c %MENU% Character testing and conversion functions
>  @chapter Character Handling

Allegedly, it should not be necessary to maintain the @node linkage
manually (if we remove it).

> diff --git a/manual/tagged-address.texi b/manual/tagged-address.texi
> new file mode 100644
> index 0000000000..a3929a0eb7
> --- /dev/null
> +++ b/manual/tagged-address.texi
> @@ -0,0 +1,80 @@
> +@node Tagged Address, Character Handling, Memory, Top
> +@c %MENU% Tagged address functions and macros
> +@chapter Tagged Address
> +
> +By default, the number of the address bits used in address translation
> +is the number of address bits.  But it can be changed by ARM Top-byte
> +Ignore (TBI) or Intel Linear Address Masking (LAM).

Current spelling is “Arm”, I think.

> +@Theglibc{} provides several functions and macros in the header file
> +@file{sys/tagged-address.h} to manipulate tagged address bits, which is
> +the number of the address bits used in address translation, with
> +restrictions:

Aren't the tagged address bits *not* used in address translation?

The Arm documentation

  <https://www.kernel.org/doc/html/latest/arm64/tagged-address-abi.html>

implies that the tag bits are those that are ignored for address
translation purposes (e.g., “The syscall behaviour for a valid tagged
pointer is the same as for the corresponding untagged pointer.”).  This
manual change uses the reverse terminology: tagged address bits are
those that are used in address translation (including the untranslated
intra-page offset).

I find it more intuitive to refer to the ignored bits as “tagged address
bits”.

> +@deftypefun int set_tagged_address_mask (uintptr_t @var{mask})
> +@standards{GNU, sys/tagged-address.h}
> +@safety{@prelim{}@mtsafe{}@assafe{}@acsafe{}}
> +Set the mask for address bits used in address translation to @var{mask}.
> +Only bits set in @var{mask} will be used in address translation.  The
> +return value is @code{0} on success and @code{-1} on failure.  This
> +function can be called only once before @code{main}.

Again the restriction around @code{main} is unclear.  If it's “before
allocating memory” or “before starting threads”, than we should say
that.

I still don't see a way how we can split tag address bits used by the
implementation (glibc, sanitizers) and the application.

For example, glibc could use a tag bit to indicate whether an allocation
is in a mmap-based allocation.  This way, we could use an out-of-line
object header (found via a hash table, for example), and utilize the
fact that mmap-based allocations are always page-aligned.  This would no
core malloc algorithm changes and should be an obvious improvement.
With more substantial changes, we could use another bit to encode that
an allocation is in a small objects region and does not have an
immediately preceding object header, either.  Introducing small object
regions is a much larger change, though.

Thanks,
Florian
  
Szabolcs Nagy Aug. 12, 2021, 12:01 p.m. UTC | #6
The 08/12/2021 10:36, Florian Weimer wrote:
> * H. J. Lu:
> > +@deftypefun int set_tagged_address_mask (uintptr_t @var{mask})
> > +@standards{GNU, sys/tagged-address.h}
> > +@safety{@prelim{}@mtsafe{}@assafe{}@acsafe{}}
> > +Set the mask for address bits used in address translation to @var{mask}.
> > +Only bits set in @var{mask} will be used in address translation.  The
> > +return value is @code{0} on success and @code{-1} on failure.  This
> > +function can be called only once before @code{main}.
> 
> Again the restriction around @code{main} is unclear.  If it's “before
> allocating memory” or “before starting threads”, than we should say
> that.

it should be at least before thread creation on aarch64.

> I still don't see a way how we can split tag address bits used by the
> implementation (glibc, sanitizers) and the application.

an application may not be able to use tag bits at all:

+All pointers participating in a pointer arithmetic operation should have
+the same tag if they point to the same memory object so that pointer
+equality operation can be performed on tagged pointers.

if the implementation gives an untagged pointer to user code
which tags it then there are differently tagged pointers to
the same object: 0 tag and user tag. it is generally hard to
ensure that pointers don't escape and don't end up breaking
pointer cmp somewhere.

so one approach is to just disallow user tags, only sanitizer
and similar tools can tag (and i think hwasan can coordinate
with glibc via less formal api/abi that we can change later)

another approach is to allow user tags and user has to deal
with potential problems (requiring compiler barriers around
pointer tagging etc), in that case i think we have to reserve
bits for the implementation if we want to use that for malloc.
  
Szabolcs Nagy Aug. 17, 2021, 12:32 p.m. UTC | #7
The 08/12/2021 13:01, Szabolcs Nagy via Libc-alpha wrote:
> The 08/12/2021 10:36, Florian Weimer wrote:
> > I still don't see a way how we can split tag address bits used by the
> > implementation (glibc, sanitizers) and the application.
...
> so one approach is to just disallow user tags, only sanitizer
> and similar tools can tag (and i think hwasan can coordinate
> with glibc via less formal api/abi that we can change later)

to expand on this: i think we should just focus on the hwasan
use-case. there may be other use-cases for tagged addresses,
but we need more experience before we can design a generic api.
hwasan can just poke at implementation internals and have
target specific logic for now.

allowing application code to use the tag bits can break c
semantics and compiler assumptions too easily.

and we should not require hwasan to use libc apis to work
with tagged addresses, that would slow it down.

so i think we don't need the tagged address representation
related apis. we may need something __hwasan_init can call
to set up os support. on aarch64 that's a prctl now, but a
libc api would allow us to disable hwasan from glibc (e.g.
if there are elf markings for incompatible dsos), i don't
know if that makes sense (does hwasan have a fall back if
there is no os support?).
  
H.J. Lu Aug. 17, 2021, 12:53 p.m. UTC | #8
On Tue, Aug 17, 2021 at 5:33 AM Szabolcs Nagy via Libc-alpha
<libc-alpha@sourceware.org> wrote:
>
> The 08/12/2021 13:01, Szabolcs Nagy via Libc-alpha wrote:
> > The 08/12/2021 10:36, Florian Weimer wrote:
> > > I still don't see a way how we can split tag address bits used by the
> > > implementation (glibc, sanitizers) and the application.
> ...
> > so one approach is to just disallow user tags, only sanitizer
> > and similar tools can tag (and i think hwasan can coordinate
> > with glibc via less formal api/abi that we can change later)
>
> to expand on this: i think we should just focus on the hwasan
> use-case. there may be other use-cases for tagged addresses,
> but we need more experience before we can design a generic api.
> hwasan can just poke at implementation internals and have
> target specific logic for now.

Agreed.  My motivation is hwasan.

> allowing application code to use the tag bits can break c
> semantics and compiler assumptions too easily.
>
> and we should not require hwasan to use libc apis to work
> with tagged addresses, that would slow it down.

There is no reason why a libc API should be slow.   Currently,
LAM enabled libsanitizer/hwasan has

#include <sys/tagged-address.h>

bool lam_failed = set_tagged_address_mask (TAGGED_ADDRESS_MASK (57))

We only need this function to enable LAM in libsanitizer/hwasan
and inform glibc that LAM is enabled.  The rest of functions in
<sys/tagged-address.h> are used to make memmove and memmove
tests LAM compatible.  We can move them to internal header files.

> so i think we don't need the tagged address representation
> related apis. we may need something __hwasan_init can call
> to set up os support. on aarch64 that's a prctl now, but a
> libc api would allow us to disable hwasan from glibc (e.g.
> if there are elf markings for incompatible dsos), i don't

set_tagged_address_mask can be used to enable and disable
LAM/TBI.  memmove needs to know if LAM/TBI is enabled or not
to work correctly.

> know if that makes sense (does hwasan have a fall back if
> there is no os support?).
>

It is a hard error for hwasan if LAM/TBI isn't available.

Thanks.
  
Szabolcs Nagy Aug. 17, 2021, 2:59 p.m. UTC | #9
The 08/17/2021 05:53, H.J. Lu via Libc-alpha wrote:
> On Tue, Aug 17, 2021 at 5:33 AM Szabolcs Nagy via Libc-alpha
> <libc-alpha@sourceware.org> wrote:
> >
> > The 08/12/2021 13:01, Szabolcs Nagy via Libc-alpha wrote:
> > > The 08/12/2021 10:36, Florian Weimer wrote:
> > > > I still don't see a way how we can split tag address bits used by the
> > > > implementation (glibc, sanitizers) and the application.
> > ...
> > > so one approach is to just disallow user tags, only sanitizer
> > > and similar tools can tag (and i think hwasan can coordinate
> > > with glibc via less formal api/abi that we can change later)
> >
> > to expand on this: i think we should just focus on the hwasan
> > use-case. there may be other use-cases for tagged addresses,
> > but we need more experience before we can design a generic api.
> > hwasan can just poke at implementation internals and have
> > target specific logic for now.
> 
> Agreed.  My motivation is hwasan.
> 
> > allowing application code to use the tag bits can break c
> > semantics and compiler assumptions too easily.
> >
> > and we should not require hwasan to use libc apis to work
> > with tagged addresses, that would slow it down.
> 
> There is no reason why a libc API should be slow.   Currently,
> LAM enabled libsanitizer/hwasan has
> 
> #include <sys/tagged-address.h>
> 
> bool lam_failed = set_tagged_address_mask (TAGGED_ADDRESS_MASK (57))
> 
> We only need this function to enable LAM in libsanitizer/hwasan
> and inform glibc that LAM is enabled.  The rest of functions in
> <sys/tagged-address.h> are used to make memmove and memmove
> tests LAM compatible.  We can move them to internal header files.

ok.

libc internal api is a different story, i thought you
expect hwasan to use tag_address, get_tagged_address_mask
etc and that would affect hwasan code gen.

if that's not the case then i don't think these apis should
be exposed.

> > so i think we don't need the tagged address representation
> > related apis. we may need something __hwasan_init can call
> > to set up os support. on aarch64 that's a prctl now, but a
> > libc api would allow us to disable hwasan from glibc (e.g.
> > if there are elf markings for incompatible dsos), i don't
> 
> set_tagged_address_mask can be used to enable and disable
> LAM/TBI.  memmove needs to know if LAM/TBI is enabled or not
> to work correctly.

i'm not convinced memmove needs to know.

if hwasan tags memory more fine grained than what is
passed to memmove as single object then there can be
issues in user code too with pointer diff calculations
within that object.

> > know if that makes sense (does hwasan have a fall back if
> > there is no os support?).
> >
> 
> It is a hard error for hwasan if LAM/TBI isn't available.
> 
> Thanks.

i see.
  
H.J. Lu Aug. 17, 2021, 3:37 p.m. UTC | #10
On Tue, Aug 17, 2021 at 8:00 AM Szabolcs Nagy <szabolcs.nagy@arm.com> wrote:
>
> The 08/17/2021 05:53, H.J. Lu via Libc-alpha wrote:
> > On Tue, Aug 17, 2021 at 5:33 AM Szabolcs Nagy via Libc-alpha
> > <libc-alpha@sourceware.org> wrote:
> > >
> > > The 08/12/2021 13:01, Szabolcs Nagy via Libc-alpha wrote:
> > > > The 08/12/2021 10:36, Florian Weimer wrote:
> > > > > I still don't see a way how we can split tag address bits used by the
> > > > > implementation (glibc, sanitizers) and the application.
> > > ...
> > > > so one approach is to just disallow user tags, only sanitizer
> > > > and similar tools can tag (and i think hwasan can coordinate
> > > > with glibc via less formal api/abi that we can change later)
> > >
> > > to expand on this: i think we should just focus on the hwasan
> > > use-case. there may be other use-cases for tagged addresses,
> > > but we need more experience before we can design a generic api.
> > > hwasan can just poke at implementation internals and have
> > > target specific logic for now.
> >
> > Agreed.  My motivation is hwasan.
> >
> > > allowing application code to use the tag bits can break c
> > > semantics and compiler assumptions too easily.
> > >
> > > and we should not require hwasan to use libc apis to work
> > > with tagged addresses, that would slow it down.
> >
> > There is no reason why a libc API should be slow.   Currently,
> > LAM enabled libsanitizer/hwasan has
> >
> > #include <sys/tagged-address.h>
> >
> > bool lam_failed = set_tagged_address_mask (TAGGED_ADDRESS_MASK (57))
> >
> > We only need this function to enable LAM in libsanitizer/hwasan
> > and inform glibc that LAM is enabled.  The rest of functions in
> > <sys/tagged-address.h> are used to make memmove and memmove
> > tests LAM compatible.  We can move them to internal header files.
>
> ok.
>
> libc internal api is a different story, i thought you
> expect hwasan to use tag_address, get_tagged_address_mask
> etc and that would affect hwasan code gen.

They are not used in the current implementation of LAM-enabled hwasan.

> if that's not the case then i don't think these apis should
> be exposed.
>
> > > so i think we don't need the tagged address representation
> > > related apis. we may need something __hwasan_init can call
> > > to set up os support. on aarch64 that's a prctl now, but a
> > > libc api would allow us to disable hwasan from glibc (e.g.
> > > if there are elf markings for incompatible dsos), i don't
> >
> > set_tagged_address_mask can be used to enable and disable
> > LAM/TBI.  memmove needs to know if LAM/TBI is enabled or not
> > to work correctly.
>
> i'm not convinced memmove needs to know.

memmove may not need to know LAM bits for hwasn.  But memmove
needs to know if LAM is enabled in general.

> if hwasan tags memory more fine grained than what is
> passed to memmove as single object then there can be
> issues in user code too with pointer diff calculations
> within that object.
>
> > > know if that makes sense (does hwasan have a fall back if
> > > there is no os support?).
> > >
> >
> > It is a hard error for hwasan if LAM/TBI isn't available.
> >
> > Thanks.
>
> i see.



--
H.J.
  
H.J. Lu Aug. 20, 2021, 4:14 p.m. UTC | #11
On Thu, Aug 12, 2021 at 5:01 AM Szabolcs Nagy <szabolcs.nagy@arm.com> wrote:
>
> The 08/12/2021 10:36, Florian Weimer wrote:
> > * H. J. Lu:
> > > +@deftypefun int set_tagged_address_mask (uintptr_t @var{mask})
> > > +@standards{GNU, sys/tagged-address.h}
> > > +@safety{@prelim{}@mtsafe{}@assafe{}@acsafe{}}
> > > +Set the mask for address bits used in address translation to @var{mask}.
> > > +Only bits set in @var{mask} will be used in address translation.  The
> > > +return value is @code{0} on success and @code{-1} on failure.  This
> > > +function can be called only once before @code{main}.
> >
> > Again the restriction around @code{main} is unclear.  If it's “before
> > allocating memory” or “before starting threads”, than we should say
> > that.
>
> it should be at least before thread creation on aarch64.

Before main is before thread creation and before main is safer
than before thread creation.

> > I still don't see a way how we can split tag address bits used by the
> > implementation (glibc, sanitizers) and the application.
>
> an application may not be able to use tag bits at all:
>
> +All pointers participating in a pointer arithmetic operation should have
> +the same tag if they point to the same memory object so that pointer
> +equality operation can be performed on tagged pointers.
>
> if the implementation gives an untagged pointer to user code
> which tags it then there are differently tagged pointers to
> the same object: 0 tag and user tag. it is generally hard to
> ensure that pointers don't escape and don't end up breaking
> pointer cmp somewhere.
>
> so one approach is to just disallow user tags, only sanitizer
> and similar tools can tag (and i think hwasan can coordinate
> with glibc via less formal api/abi that we can change later)
>
> another approach is to allow user tags and user has to deal
> with potential problems (requiring compiler barriers around
> pointer tagging etc), in that case i think we have to reserve
> bits for the implementation if we want to use that for malloc.

Tag usage must be exclusive for malloc or HWASAN.   malloc
usage must be checked at run-time for

1. Is tag enabled? And
2. Is tag used for another purpose?

If tag isn't enabled or used for another purpose, malloc should
avoid using tag.   This API can inform glibc that an user code
is requesting tag usage.
  
Florian Weimer Aug. 20, 2021, 4:25 p.m. UTC | #12
* H. J. Lu:

> On Thu, Aug 12, 2021 at 5:01 AM Szabolcs Nagy <szabolcs.nagy@arm.com> wrote:
>>
>> The 08/12/2021 10:36, Florian Weimer wrote:
>> > * H. J. Lu:
>> > > +@deftypefun int set_tagged_address_mask (uintptr_t @var{mask})
>> > > +@standards{GNU, sys/tagged-address.h}
>> > > +@safety{@prelim{}@mtsafe{}@assafe{}@acsafe{}}
>> > > +Set the mask for address bits used in address translation to @var{mask}.
>> > > +Only bits set in @var{mask} will be used in address translation.  The
>> > > +return value is @code{0} on success and @code{-1} on failure.  This
>> > > +function can be called only once before @code{main}.
>> >
>> > Again the restriction around @code{main} is unclear.  If it's “before
>> > allocating memory” or “before starting threads”, than we should say
>> > that.
>>
>> it should be at least before thread creation on aarch64.
>
> Before main is before thread creation and before main is safer
> than before thread creation.

You can create threads from ELF constructors, and those run before main.
(Although this tends to run into deadlocks in our implementation.)

Thanks,
Florian
  
H.J. Lu Aug. 20, 2021, 4:30 p.m. UTC | #13
On Fri, Aug 20, 2021 at 9:25 AM Florian Weimer <fweimer@redhat.com> wrote:
>
> * H. J. Lu:
>
> > On Thu, Aug 12, 2021 at 5:01 AM Szabolcs Nagy <szabolcs.nagy@arm.com> wrote:
> >>
> >> The 08/12/2021 10:36, Florian Weimer wrote:
> >> > * H. J. Lu:
> >> > > +@deftypefun int set_tagged_address_mask (uintptr_t @var{mask})
> >> > > +@standards{GNU, sys/tagged-address.h}
> >> > > +@safety{@prelim{}@mtsafe{}@assafe{}@acsafe{}}
> >> > > +Set the mask for address bits used in address translation to @var{mask}.
> >> > > +Only bits set in @var{mask} will be used in address translation.  The
> >> > > +return value is @code{0} on success and @code{-1} on failure.  This
> >> > > +function can be called only once before @code{main}.
> >> >
> >> > Again the restriction around @code{main} is unclear.  If it's “before
> >> > allocating memory” or “before starting threads”, than we should say
> >> > that.
> >>
> >> it should be at least before thread creation on aarch64.
> >
> > Before main is before thread creation and before main is safer
> > than before thread creation.
>
> You can create threads from ELF constructors, and those run before main.
> (Although this tends to run into deadlocks in our implementation.)

I will change the wording to before man AND thread creation.
  
H.J. Lu Aug. 20, 2021, 11:26 p.m. UTC | #14
On Thu, Aug 12, 2021 at 1:36 AM Florian Weimer <fweimer@redhat.com> wrote:
>
> * H. J. Lu:
>
> > diff --git a/manual/ctype.texi b/manual/ctype.texi
> > index d0618c5c38..28af73ff0e 100644
> > --- a/manual/ctype.texi
> > +++ b/manual/ctype.texi
> > @@ -1,4 +1,4 @@
> > -@node Character Handling, String and Array Utilities, Memory, Top
> > +@node Character Handling, String and Array Utilities, Tagged Address, Top
> >  @c %MENU% Character testing and conversion functions
> >  @chapter Character Handling
>
> Allegedly, it should not be necessary to maintain the @node linkage
> manually (if we remove it).

Since @node isn't removed, I guess I have to keep this change.

> > diff --git a/manual/tagged-address.texi b/manual/tagged-address.texi
> > new file mode 100644
> > index 0000000000..a3929a0eb7
> > --- /dev/null
> > +++ b/manual/tagged-address.texi
> > @@ -0,0 +1,80 @@
> > +@node Tagged Address, Character Handling, Memory, Top
> > +@c %MENU% Tagged address functions and macros
> > +@chapter Tagged Address
> > +
> > +By default, the number of the address bits used in address translation
> > +is the number of address bits.  But it can be changed by ARM Top-byte
> > +Ignore (TBI) or Intel Linear Address Masking (LAM).
>
> Current spelling is “Arm”, I think.

There are

contrib.texi:Philip Blundell for the ports to Linux/ARM
contrib.texi:(@code{arm-@var{ANYTHING}-linuxaout}) and ARM standalone
contrib.texi:Richard Earnshaw for continued support and fixes to the various ARM
contrib.texi:his maintainership of the ARM and MIPS architectures and the math
contrib.texi:encryption support for ARM and various fixes.
creature.texi:architectures (i686, ARM), this is planned to change and
applications

and

contrib.texi:Ulrich Weigand for various fixes to the PowerPC64 and Arm ports.

I will keep ARM.

> > +@Theglibc{} provides several functions and macros in the header file
> > +@file{sys/tagged-address.h} to manipulate tagged address bits, which is
> > +the number of the address bits used in address translation, with
> > +restrictions:
>
> Aren't the tagged address bits *not* used in address translation?
>
> The Arm documentation
>
>   <https://www.kernel.org/doc/html/latest/arm64/tagged-address-abi.html>
>
> implies that the tag bits are those that are ignored for address
> translation purposes (e.g., “The syscall behaviour for a valid tagged
> pointer is the same as for the corresponding untagged pointer.”).  This
> manual change uses the reverse terminology: tagged address bits are
> those that are used in address translation (including the untranslated
> intra-page offset).
>
> I find it more intuitive to refer to the ignored bits as “tagged address
> bits”.

I will rename it to set_translated_address_mask.

> > +@deftypefun int set_tagged_address_mask (uintptr_t @var{mask})
> > +@standards{GNU, sys/tagged-address.h}
> > +@safety{@prelim{}@mtsafe{}@assafe{}@acsafe{}}
> > +Set the mask for address bits used in address translation to @var{mask}.
> > +Only bits set in @var{mask} will be used in address translation.  The
> > +return value is @code{0} on success and @code{-1} on failure.  This
> > +function can be called only once before @code{main}.
>
> Again the restriction around @code{main} is unclear.  If it's “before
> allocating memory” or “before starting threads”, than we should say
> that.

I will change it to

This function can be called only once before @code{main} and thread creation.

> I still don't see a way how we can split tag address bits used by the
> implementation (glibc, sanitizers) and the application.
>
> For example, glibc could use a tag bit to indicate whether an allocation
> is in a mmap-based allocation.  This way, we could use an out-of-line
> object header (found via a hash table, for example), and utilize the
> fact that mmap-based allocations are always page-aligned.  This would no
> core malloc algorithm changes and should be an obvious improvement.
> With more substantial changes, we could use another bit to encode that
> an allocation is in a small objects region and does not have an
> immediately preceding object header, either.  Introducing small object
> regions is a much larger change, though.
>

Tag usage should be exclusive to glibc.  set_translated_address_mask
tells glibc that tag will be used for another purpose.

Thanks.
  
Sunil Pandey Aug. 21, 2021, 4:10 p.m. UTC | #15
On Fri, Aug 20, 2021 at 4:27 PM H.J. Lu <hjl.tools@gmail.com> wrote:

> On Thu, Aug 12, 2021 at 1:36 AM Florian Weimer <fweimer@redhat.com> wrote:
> >
> > * H. J. Lu:
> >
> > > diff --git a/manual/ctype.texi b/manual/ctype.texi
> > > index d0618c5c38..28af73ff0e 100644
> > > --- a/manual/ctype.texi
> > > +++ b/manual/ctype.texi
> > > @@ -1,4 +1,4 @@
> > > -@node Character Handling, String and Array Utilities, Memory, Top
> > > +@node Character Handling, String and Array Utilities, Tagged Address,
> Top
> > >  @c %MENU% Character testing and conversion functions
> > >  @chapter Character Handling
> >
> > Allegedly, it should not be necessary to maintain the @node linkage
> > manually (if we remove it).
>
> Since @node isn't removed, I guess I have to keep this change.
>
> > > diff --git a/manual/tagged-address.texi b/manual/tagged-address.texi
> > > new file mode 100644
> > > index 0000000000..a3929a0eb7
> > > --- /dev/null
> > > +++ b/manual/tagged-address.texi
> > > @@ -0,0 +1,80 @@
> > > +@node Tagged Address, Character Handling, Memory, Top
> > > +@c %MENU% Tagged address functions and macros
> > > +@chapter Tagged Address
> > > +
> > > +By default, the number of the address bits used in address translation
> > > +is the number of address bits.  But it can be changed by ARM Top-byte
> > > +Ignore (TBI) or Intel Linear Address Masking (LAM).
> >
> > Current spelling is “Arm”, I think.
>
> There are
>
> contrib.texi:Philip Blundell for the ports to Linux/ARM
> contrib.texi:(@code{arm-@var{ANYTHING}-linuxaout}) and ARM standalone
> contrib.texi:Richard Earnshaw for continued support and fixes to the
> various ARM
> contrib.texi:his maintainership of the ARM and MIPS architectures and the
> math
> contrib.texi:encryption support for ARM and various fixes.
> creature.texi:architectures (i686, ARM), this is planned to change and
> applications
>
> and
>
> contrib.texi:Ulrich Weigand for various fixes to the PowerPC64 and Arm
> ports.
>
> I will keep ARM.
>
> > > +@Theglibc{} provides several functions and macros in the header file
> > > +@file{sys/tagged-address.h} to manipulate tagged address bits, which
> is
> > > +the number of the address bits used in address translation, with
> > > +restrictions:
> >
> > Aren't the tagged address bits *not* used in address translation?
> >
> > The Arm documentation
> >
> >   <https://www.kernel.org/doc/html/latest/arm64/tagged-address-abi.html>
> >
> > implies that the tag bits are those that are ignored for address
> > translation purposes (e.g., “The syscall behaviour for a valid tagged
> > pointer is the same as for the corresponding untagged pointer.”).  This
> > manual change uses the reverse terminology: tagged address bits are
> > those that are used in address translation (including the untranslated
> > intra-page offset).
> >
> > I find it more intuitive to refer to the ignored bits as “tagged address
> > bits”.
>
> I will rename it to set_translated_address_mask.
>
Existing name set_tagged_address_mask may not be intuitive but it looks
more clear to me than the proposed new name(set_translated_address_mask).
For the proposed new name, it is not clear which particular portion of
address will be masked.
How about set_address_tagbit_mask?

>
> > > +@deftypefun int set_tagged_address_mask (uintptr_t @var{mask})
> > > +@standards{GNU, sys/tagged-address.h}
> > > +@safety{@prelim{}@mtsafe{}@assafe{}@acsafe{}}
> > > +Set the mask for address bits used in address translation to
> @var{mask}.
> > > +Only bits set in @var{mask} will be used in address translation.  The
> > > +return value is @code{0} on success and @code{-1} on failure.  This
> > > +function can be called only once before @code{main}.
> >
> > Again the restriction around @code{main} is unclear.  If it's “before
> > allocating memory” or “before starting threads”, than we should say
> > that.
>
> I will change it to
>
> This function can be called only once before @code{main} and thread
> creation.
>
> > I still don't see a way how we can split tag address bits used by the
> > implementation (glibc, sanitizers) and the application.
> >
> > For example, glibc could use a tag bit to indicate whether an allocation
> > is in a mmap-based allocation.  This way, we could use an out-of-line
> > object header (found via a hash table, for example), and utilize the
> > fact that mmap-based allocations are always page-aligned.  This would no
> > core malloc algorithm changes and should be an obvious improvement.
> > With more substantial changes, we could use another bit to encode that
> > an allocation is in a small objects region and does not have an
> > immediately preceding object header, either.  Introducing small object
> > regions is a much larger change, though.
> >
>
> Tag usage should be exclusive to glibc.  set_translated_address_mask
> tells glibc that tag will be used for another purpose.
>
> Thanks.
>
> --
> H.J.
>
  
H.J. Lu Aug. 21, 2021, 4:37 p.m. UTC | #16
On Sat, Aug 21, 2021 at 9:10 AM Sunil Pandey <skpgkp2@gmail.com> wrote:
>
>
>
> On Fri, Aug 20, 2021 at 4:27 PM H.J. Lu <hjl.tools@gmail.com> wrote:
>>
>> On Thu, Aug 12, 2021 at 1:36 AM Florian Weimer <fweimer@redhat.com> wrote:
>> >
>> > * H. J. Lu:
>> >
>> > > diff --git a/manual/ctype.texi b/manual/ctype.texi
>> > > index d0618c5c38..28af73ff0e 100644
>> > > --- a/manual/ctype.texi
>> > > +++ b/manual/ctype.texi
>> > > @@ -1,4 +1,4 @@
>> > > -@node Character Handling, String and Array Utilities, Memory, Top
>> > > +@node Character Handling, String and Array Utilities, Tagged Address, Top
>> > >  @c %MENU% Character testing and conversion functions
>> > >  @chapter Character Handling
>> >
>> > Allegedly, it should not be necessary to maintain the @node linkage
>> > manually (if we remove it).
>>
>> Since @node isn't removed, I guess I have to keep this change.
>>
>> > > diff --git a/manual/tagged-address.texi b/manual/tagged-address.texi
>> > > new file mode 100644
>> > > index 0000000000..a3929a0eb7
>> > > --- /dev/null
>> > > +++ b/manual/tagged-address.texi
>> > > @@ -0,0 +1,80 @@
>> > > +@node Tagged Address, Character Handling, Memory, Top
>> > > +@c %MENU% Tagged address functions and macros
>> > > +@chapter Tagged Address
>> > > +
>> > > +By default, the number of the address bits used in address translation
>> > > +is the number of address bits.  But it can be changed by ARM Top-byte
>> > > +Ignore (TBI) or Intel Linear Address Masking (LAM).
>> >
>> > Current spelling is “Arm”, I think.
>>
>> There are
>>
>> contrib.texi:Philip Blundell for the ports to Linux/ARM
>> contrib.texi:(@code{arm-@var{ANYTHING}-linuxaout}) and ARM standalone
>> contrib.texi:Richard Earnshaw for continued support and fixes to the various ARM
>> contrib.texi:his maintainership of the ARM and MIPS architectures and the math
>> contrib.texi:encryption support for ARM and various fixes.
>> creature.texi:architectures (i686, ARM), this is planned to change and
>> applications
>>
>> and
>>
>> contrib.texi:Ulrich Weigand for various fixes to the PowerPC64 and Arm ports.
>>
>> I will keep ARM.
>>
>> > > +@Theglibc{} provides several functions and macros in the header file
>> > > +@file{sys/tagged-address.h} to manipulate tagged address bits, which is
>> > > +the number of the address bits used in address translation, with
>> > > +restrictions:
>> >
>> > Aren't the tagged address bits *not* used in address translation?
>> >
>> > The Arm documentation
>> >
>> >   <https://www.kernel.org/doc/html/latest/arm64/tagged-address-abi.html>
>> >
>> > implies that the tag bits are those that are ignored for address
>> > translation purposes (e.g., “The syscall behaviour for a valid tagged
>> > pointer is the same as for the corresponding untagged pointer.”).  This
>> > manual change uses the reverse terminology: tagged address bits are
>> > those that are used in address translation (including the untranslated
>> > intra-page offset).
>> >
>> > I find it more intuitive to refer to the ignored bits as “tagged address
>> > bits”.
>>
>> I will rename it to set_translated_address_mask.
>
> Existing name set_tagged_address_mask may not be intuitive but it looks more clear to me than the proposed new name(set_translated_address_mask). For the proposed new name, it is not clear which particular portion of address will be masked.
> How about set_address_tagbit_mask?

Can you give it an example of how set_address_tagbit_mask should
be used?

>>
>>
>> > > +@deftypefun int set_tagged_address_mask (uintptr_t @var{mask})
>> > > +@standards{GNU, sys/tagged-address.h}
>> > > +@safety{@prelim{}@mtsafe{}@assafe{}@acsafe{}}
>> > > +Set the mask for address bits used in address translation to @var{mask}.
>> > > +Only bits set in @var{mask} will be used in address translation.  The
>> > > +return value is @code{0} on success and @code{-1} on failure.  This
>> > > +function can be called only once before @code{main}.
>> >
>> > Again the restriction around @code{main} is unclear.  If it's “before
>> > allocating memory” or “before starting threads”, than we should say
>> > that.
>>
>> I will change it to
>>
>> This function can be called only once before @code{main} and thread creation.
>>
>> > I still don't see a way how we can split tag address bits used by the
>> > implementation (glibc, sanitizers) and the application.
>> >
>> > For example, glibc could use a tag bit to indicate whether an allocation
>> > is in a mmap-based allocation.  This way, we could use an out-of-line
>> > object header (found via a hash table, for example), and utilize the
>> > fact that mmap-based allocations are always page-aligned.  This would no
>> > core malloc algorithm changes and should be an obvious improvement.
>> > With more substantial changes, we could use another bit to encode that
>> > an allocation is in a small objects region and does not have an
>> > immediately preceding object header, either.  Introducing small object
>> > regions is a much larger change, though.
>> >
>>
>> Tag usage should be exclusive to glibc.  set_translated_address_mask
>> tells glibc that tag will be used for another purpose.
>>
>> Thanks.
>>
>> --
>> H.J.
  
Sunil Pandey Aug. 21, 2021, 9:20 p.m. UTC | #17
On Sat, Aug 21, 2021 at 9:38 AM H.J. Lu <hjl.tools@gmail.com> wrote:

> On Sat, Aug 21, 2021 at 9:10 AM Sunil Pandey <skpgkp2@gmail.com> wrote:
> >
> >
> >
> > On Fri, Aug 20, 2021 at 4:27 PM H.J. Lu <hjl.tools@gmail.com> wrote:
> >>
> >> On Thu, Aug 12, 2021 at 1:36 AM Florian Weimer <fweimer@redhat.com>
> wrote:
> >> >
> >> > * H. J. Lu:
> >> >
> >> > > diff --git a/manual/ctype.texi b/manual/ctype.texi
> >> > > index d0618c5c38..28af73ff0e 100644
> >> > > --- a/manual/ctype.texi
> >> > > +++ b/manual/ctype.texi
> >> > > @@ -1,4 +1,4 @@
> >> > > -@node Character Handling, String and Array Utilities, Memory, Top
> >> > > +@node Character Handling, String and Array Utilities, Tagged
> Address, Top
> >> > >  @c %MENU% Character testing and conversion functions
> >> > >  @chapter Character Handling
> >> >
> >> > Allegedly, it should not be necessary to maintain the @node linkage
> >> > manually (if we remove it).
> >>
> >> Since @node isn't removed, I guess I have to keep this change.
> >>
> >> > > diff --git a/manual/tagged-address.texi b/manual/tagged-address.texi
> >> > > new file mode 100644
> >> > > index 0000000000..a3929a0eb7
> >> > > --- /dev/null
> >> > > +++ b/manual/tagged-address.texi
> >> > > @@ -0,0 +1,80 @@
> >> > > +@node Tagged Address, Character Handling, Memory, Top
> >> > > +@c %MENU% Tagged address functions and macros
> >> > > +@chapter Tagged Address
> >> > > +
> >> > > +By default, the number of the address bits used in address
> translation
> >> > > +is the number of address bits.  But it can be changed by ARM
> Top-byte
> >> > > +Ignore (TBI) or Intel Linear Address Masking (LAM).
> >> >
> >> > Current spelling is “Arm”, I think.
> >>
> >> There are
> >>
> >> contrib.texi:Philip Blundell for the ports to Linux/ARM
> >> contrib.texi:(@code{arm-@var{ANYTHING}-linuxaout}) and ARM standalone
> >> contrib.texi:Richard Earnshaw for continued support and fixes to the
> various ARM
> >> contrib.texi:his maintainership of the ARM and MIPS architectures and
> the math
> >> contrib.texi:encryption support for ARM and various fixes.
> >> creature.texi:architectures (i686, ARM), this is planned to change and
> >> applications
> >>
> >> and
> >>
> >> contrib.texi:Ulrich Weigand for various fixes to the PowerPC64 and Arm
> ports.
> >>
> >> I will keep ARM.
> >>
> >> > > +@Theglibc{} provides several functions and macros in the header
> file
> >> > > +@file{sys/tagged-address.h} to manipulate tagged address bits,
> which is
> >> > > +the number of the address bits used in address translation, with
> >> > > +restrictions:
> >> >
> >> > Aren't the tagged address bits *not* used in address translation?
> >> >
> >> > The Arm documentation
> >> >
> >> >   <
> https://www.kernel.org/doc/html/latest/arm64/tagged-address-abi.html>
> >> >
> >> > implies that the tag bits are those that are ignored for address
> >> > translation purposes (e.g., “The syscall behaviour for a valid tagged
> >> > pointer is the same as for the corresponding untagged pointer.”).
> This
> >> > manual change uses the reverse terminology: tagged address bits are
> >> > those that are used in address translation (including the untranslated
> >> > intra-page offset).
> >> >
> >> > I find it more intuitive to refer to the ignored bits as “tagged
> address
> >> > bits”.
> >>
> >> I will rename it to set_translated_address_mask.
> >
> > Existing name set_tagged_address_mask may not be intuitive but it looks
> more clear to me than the proposed new name(set_translated_address_mask).
> For the proposed new name, it is not clear which particular portion of
> address will be masked.
> > How about set_address_tagbit_mask?
>
> Can you give it an example of how set_address_tagbit_mask should
> be used?
>
I looked at the code again, for the set_tagged_address_mask, it will set
machine to ignore the upper bits depending on parameters, independent of
how upper bits will actually be used by the application. You are correct,
api name shouldn't have tagged in it.

>
> >>
> >>
> >> > > +@deftypefun int set_tagged_address_mask (uintptr_t @var{mask})
> >> > > +@standards{GNU, sys/tagged-address.h}
> >> > > +@safety{@prelim{}@mtsafe{}@assafe{}@acsafe{}}
> >> > > +Set the mask for address bits used in address translation to
> @var{mask}.
> >> > > +Only bits set in @var{mask} will be used in address translation.
> The
> >> > > +return value is @code{0} on success and @code{-1} on failure.  This
> >> > > +function can be called only once before @code{main}.
> >> >
> >> > Again the restriction around @code{main} is unclear.  If it's “before
> >> > allocating memory” or “before starting threads”, than we should say
> >> > that.
> >>
> >> I will change it to
> >>
> >> This function can be called only once before @code{main} and thread
> creation.
> >>
> >> > I still don't see a way how we can split tag address bits used by the
> >> > implementation (glibc, sanitizers) and the application.
> >> >
> >> > For example, glibc could use a tag bit to indicate whether an
> allocation
> >> > is in a mmap-based allocation.  This way, we could use an out-of-line
> >> > object header (found via a hash table, for example), and utilize the
> >> > fact that mmap-based allocations are always page-aligned.  This would
> no
> >> > core malloc algorithm changes and should be an obvious improvement.
> >> > With more substantial changes, we could use another bit to encode that
> >> > an allocation is in a small objects region and does not have an
> >> > immediately preceding object header, either.  Introducing small object
> >> > regions is a much larger change, though.
> >> >
> >>
> >> Tag usage should be exclusive to glibc.  set_translated_address_mask
> >> tells glibc that tag will be used for another purpose.
> >>
> >> Thanks.
> >>
> >> --
> >> H.J.
>
>
>
> --
> H.J.
>
  

Patch

diff --git a/NEWS b/NEWS
index 79c895e382..4f80340f9f 100644
--- a/NEWS
+++ b/NEWS
@@ -9,7 +9,7 @@  Version 2.35
 
 Major new features:
 
-  [Add new features here]
+* Add <sys/tagged-address.h> to provide an API for tagged address.
 
 Deprecated and removed features, and other changes affecting compatibility:
 
diff --git a/bits/tagged-address-mask.h b/bits/tagged-address-mask.h
new file mode 100644
index 0000000000..649e05b1b7
--- /dev/null
+++ b/bits/tagged-address-mask.h
@@ -0,0 +1,47 @@ 
+/* Copyright (C) 2021 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/>.  */
+
+#ifndef _BITS_TAGGED_ADDRESS_MASK_H
+#define _BITS_TAGGED_ADDRESS_MASK_H 1
+
+#ifndef _SYS_TAGGED_ADDRESS_H
+# error "Never include this file directly.  Use <sys/tagged-address.h> instead"
+#endif
+
+#include <bits/tagged-address-valid-bits.h>
+
+#ifdef __GNUC__
+# if defined __USE_ISOC11 || defined __USE_ISOCXX11
+#  ifdef __USE_ISOCXX11
+#   define TAGGED_ADDRESS_ASSERT static_assert
+#  else
+#   define TAGGED_ADDRESS_ASSERT _Static_assert
+#  endif
+# else
+#  define TAGGED_ADDRESS_ASSERT(expr, msg)
+# endif
+/* A mask for constant address BITS used in address translation.  */
+# define TAGGED_ADDRESS_MASK(BITS)				    \
+  (__extension__						    \
+    ({								    \
+       TAGGED_ADDRESS_ASSERT (TAGGED_ADDRESS_VALID_BITS (BITS),	    \
+			      "Tagged address bits must be valid"); \
+       (((uintptr_t) 1) << (BITS)) - 1;				    \
+     }))
+#endif
+
+#endif /* <bits/tagged-address-mask.h> */
diff --git a/bits/tagged-address-valid-bits.h b/bits/tagged-address-valid-bits.h
new file mode 100644
index 0000000000..38b6c12b01
--- /dev/null
+++ b/bits/tagged-address-valid-bits.h
@@ -0,0 +1,28 @@ 
+/* Copyright (C) 2021 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/>.  */
+
+#ifndef _BITS_TAGGED_ADDRESS_VALID_BITS_H
+#define _BITS_TAGGED_ADDRESS_VALID_BITS_H 1
+
+#ifndef _SYS_TAGGED_ADDRESS_H
+# error "Never include this file directly.  Use <sys/tagged-address.h> instead"
+#endif
+
+/* Non-zero if constant address BITS is a valid tagged address bits.  */
+#define TAGGED_ADDRESS_VALID_BITS(BITS) 0
+
+#endif /* <bits/tagged-address-valid-bits.h> */
diff --git a/csu/libc-start.c b/csu/libc-start.c
index 0350b006fd..984659a394 100644
--- a/csu/libc-start.c
+++ b/csu/libc-start.c
@@ -402,6 +402,9 @@  LIBC_START_MAIN (int (*main) (int, char **, char ** MAIN_AUXVEC_DECL),
     GLRO(dl_debug_printf) ("\ntransferring control: %s\n\n", argv[0]);
 #endif
 
+  /* set_tagged_address_mask can only be called before main.  */
+  GL(dl_tagged_address_mask_locked) = 1;
+
 #ifndef SHARED
   _dl_debug_initialize (0, LM_ID_BASE);
 #endif
diff --git a/elf/dl-support.c b/elf/dl-support.c
index 0155718175..e8cbe8fa81 100644
--- a/elf/dl-support.c
+++ b/elf/dl-support.c
@@ -213,6 +213,11 @@  struct link_map *_dl_sysinfo_map;
 
 # include "get-dynamic-info.h"
 #endif
+
+/* If nonzero, the mask for address bits used in address translation
+   is locked.  */
+int _dl_tagged_address_mask_locked;
+
 #include "setup-vdso.h"
 /* Define the vDSO function pointers.  */
 #include <dl-vdso-setup.c>
diff --git a/include/sys/tagged-address.h b/include/sys/tagged-address.h
new file mode 100644
index 0000000000..2e902f72b2
--- /dev/null
+++ b/include/sys/tagged-address.h
@@ -0,0 +1,9 @@ 
+#include <misc/sys/tagged-address.h>
+
+#ifndef _ISOMAC
+# include <inline-tagged-address.h>
+# define get_tagged_address_bits()	__get_tagged_address_bits ()
+# define get_tagged_address_mask()	__get_tagged_address_mask ()
+# define tag_address(addr, tag)		__tag_address ((addr), (tag))
+# define untag_address(addr)		__untag_address ((addr))
+#endif
diff --git a/manual/Makefile b/manual/Makefile
index e83444341e..08df2daa6b 100644
--- a/manual/Makefile
+++ b/manual/Makefile
@@ -34,7 +34,8 @@  info: $(objpfx)libc.info
 endif
 
 chapters = $(addsuffix .texi, \
-		       intro errno memory ctype string charset locale	\
+		       intro errno memory tagged-address ctype string	\
+		       charset locale					\
 		       message search pattern io stdio llio filesys	\
 		       pipe socket terminal syslog math arith time	\
 		       resource setjmp signal startup process ipc job	\
diff --git a/manual/ctype.texi b/manual/ctype.texi
index d0618c5c38..28af73ff0e 100644
--- a/manual/ctype.texi
+++ b/manual/ctype.texi
@@ -1,4 +1,4 @@ 
-@node Character Handling, String and Array Utilities, Memory, Top
+@node Character Handling, String and Array Utilities, Tagged Address, Top
 @c %MENU% Character testing and conversion functions
 @chapter Character Handling
 
diff --git a/manual/memory.texi b/manual/memory.texi
index 0b2b9c8795..2e283e41f9 100644
--- a/manual/memory.texi
+++ b/manual/memory.texi
@@ -1,4 +1,4 @@ 
-@node Memory, Character Handling, Error Reporting, Top
+@node Memory, Tagged Address, Error Reporting, Top
 @chapter Virtual Memory Allocation And Paging
 @c %MENU% Allocating virtual memory and controlling paging
 @cindex memory allocation
diff --git a/manual/tagged-address.texi b/manual/tagged-address.texi
new file mode 100644
index 0000000000..a3929a0eb7
--- /dev/null
+++ b/manual/tagged-address.texi
@@ -0,0 +1,80 @@ 
+@node Tagged Address, Character Handling, Memory, Top
+@c %MENU% Tagged address functions and macros
+@chapter Tagged Address
+
+By default, the number of the address bits used in address translation
+is the number of address bits.  But it can be changed by ARM Top-byte
+Ignore (TBI) or Intel Linear Address Masking (LAM).
+
+@Theglibc{} provides several functions and macros in the header file
+@file{sys/tagged-address.h} to manipulate tagged address bits, which is
+the number of the address bits used in address translation, with
+restrictions:
+
+@itemize @bullet
+@item
+All bits between 0 and N - 1, where N is the number of tagged address
+bits, are used in address translation.
+
+@item
+All pointers participating in a pointer arithmetic operation should have
+the same tag if they point to the same memory object so that pointer
+equality operation can be performed on tagged pointers.
+@end itemize
+
+@pindex sys/tagged-address.h
+
+@deftypefun {unsigned int} get_tagged_address_bits (void)
+@standards{GNU, sys/tagged-address.h}
+@safety{@prelim{}@mtsafe{}@assafe{}@acsafe{}}
+Get the current address bits used in address translation.  The return
+value is @code{0} if tag bits are not the highest bits in addresses.  The
+return value is the number of address bits when tagged address is
+unsupported.
+@end deftypefun
+
+@deftypefun uintptr_t get_tagged_address_mask (void)
+@standards{GNU, sys/tagged-address.h}
+@safety{@prelim{}@mtsafe{}@assafe{}@acsafe{}}
+Get the current mask for address bits used in address translation.  If a
+bit is set in the return value, this bit is used in address translation.
+The return value is @code{-1} when all bits are used in address
+translation.
+@end deftypefun
+
+@deftypefun int set_tagged_address_mask (uintptr_t @var{mask})
+@standards{GNU, sys/tagged-address.h}
+@safety{@prelim{}@mtsafe{}@assafe{}@acsafe{}}
+Set the mask for address bits used in address translation to @var{mask}.
+Only bits set in @var{mask} will be used in address translation.  The
+return value is @code{0} on success and @code{-1} on failure.  This
+function can be called only once before @code{main}.  The possible
+@code{errno} error conditions are @code{ENODEV}, @code{EPERM},
+@code{EINVAL}, and @code{ENOSYS}.
+@end deftypefun
+
+@deftypefun {void *} tag_address (void *@var{addr}, unsigned int @var{tag})
+@standards{GNU, sys/tagged-address.h}
+@safety{@prelim{}@mtsafe{}@assafe{}@acsafe{}}
+Return the address of @var{addr} with the tag value @var{tag} stored
+in the untranslated bits.  Overflow of @var{tag} in the untranslated
+bits are ignored.
+@end deftypefun
+
+@deftypefun {void *} untag_address (void *@var{addr})
+@standards{GNU, sys/tagged-address.h}
+@safety{@prelim{}@mtsafe{}@assafe{}@acsafe{}}
+Return the address of @var{addr} with all zero untranslated bits.
+@end deftypefun
+
+@deftypefn Macro int TAGGED_ADDRESS_VALID_BITS (@var{bits})
+This macro returns a nonzero value (true) if @var{bits} is a valid
+constant number of the lower address bits which can be used in address
+translation.
+@end deftypefn
+
+@deftypefn Macro {const uintptr_t} TAGGED_ADDRESS_MASK (@var{bits})
+This macro returns a nonzero value which can be passed to
+@code{set_tagged_address_mask} to specify the lower address @var{bits}
+for address translation.
+@end deftypefn
diff --git a/misc/Makefile b/misc/Makefile
index 1083ba3bfc..77fa2cd6df 100644
--- a/misc/Makefile
+++ b/misc/Makefile
@@ -38,7 +38,10 @@  headers	:= sys/uio.h bits/uio-ext.h bits/uio_lim.h \
 	   bits/select2.h bits/hwcap.h sys/auxv.h \
 	   sys/sysmacros.h bits/sysmacros.h bits/types/struct_iovec.h \
 	   bits/err-ldbl.h bits/error-ldbl.h \
-	   sys/single_threaded.h
+	   sys/single_threaded.h \
+	   sys/tagged-address.h \
+	   bits/tagged-address-mask.h \
+	   bits/tagged-address-valid-bits.h
 
 routines := brk sbrk sstk ioctl \
 	    readv writev preadv preadv64 pwritev pwritev64 \
@@ -73,7 +76,8 @@  routines := brk sbrk sstk ioctl \
 	    fgetxattr flistxattr fremovexattr fsetxattr getxattr \
 	    listxattr lgetxattr llistxattr lremovexattr lsetxattr \
 	    removexattr setxattr getauxval ifunc-impl-list makedev \
-	    allocate_once fd_to_filename single_threaded unwind-link
+	    allocate_once fd_to_filename single_threaded unwind-link \
+	    tagged-address set-tagged-address-mask
 
 generated += tst-error1.mtrace tst-error1-mem.out \
   tst-allocate_once.mtrace tst-allocate_once-mem.out
@@ -89,7 +93,11 @@  tests := tst-dirname tst-tsearch tst-fdset tst-mntent tst-hsearch \
 	 tst-preadvwritev2 tst-preadvwritev64v2 tst-warn-wide \
 	 tst-ldbl-warn tst-ldbl-error tst-dbl-efgcvt tst-ldbl-efgcvt \
 	 tst-mntent-autofs tst-syscalls tst-mntent-escape tst-select \
-	 tst-ioctl
+	 tst-ioctl \
+	 tst-tagged-address-1 tst-tagged-address-1-static \
+	 tst-tagged-address-2 tst-tagged-address-2-static \
+	 tst-tagged-address-3 tst-tagged-address-3-static \
+	 tst-tagged-address-4 tst-tagged-address-4-static
 
 tests-time64 := \
   tst-select-time64 \
@@ -99,11 +107,22 @@  tests-time64 := \
 
 # Tests which need libdl.
 ifeq (yes,$(build-shared))
-tests += tst-gethostid
+tests += tst-gethostid \
+  tst-tagged-address-5 \
+  tst-tagged-address-6 \
+  tst-tagged-address-7
+modules-names += \
+  tst-tagged-address-mod-5 \
+  tst-tagged-address-mod-6 \
+  tst-tagged-address-mod-7
 endif
 
 tests-internal := tst-atomic tst-atomic-long tst-allocate_once
-tests-static := tst-empty
+tests-static := tst-empty \
+  tst-tagged-address-1-static \
+  tst-tagged-address-2-static \
+  tst-tagged-address-3-static \
+  tst-tagged-address-4-static
 
 # Test for the internal, non-exported __fd_to_filename function.
 tests-internal += tst-fd_to_filename
@@ -172,3 +191,9 @@  $(objpfx)tst-select: $(librt)
 $(objpfx)tst-select-time64: $(librt)
 $(objpfx)tst-pselect: $(librt)
 $(objpfx)tst-pselect-time64: $(librt)
+
+$(objpfx)tst-tagged-address-2: $(shared-thread-library)
+$(objpfx)tst-tagged-address-2-static: $(static-thread-library)
+$(objpfx)tst-tagged-address-7: $(libdl)
+$(objpfx)tst-tagged-address-7.out: $(objpfx)tst-tagged-address-mod-7.so
+$(objpfx)tst-tagged-address-mod-7.so: $(libsupport)
diff --git a/misc/Versions b/misc/Versions
index d5b348e83a..6ab64586eb 100644
--- a/misc/Versions
+++ b/misc/Versions
@@ -164,6 +164,13 @@  libc {
   GLIBC_2.32 {
     __libc_single_threaded;
   }
+  GLIBC_2.35 {
+    get_tagged_address_bits;
+    get_tagged_address_mask;
+    set_tagged_address_mask;
+    tag_address;
+    untag_address;
+  }
   GLIBC_PRIVATE {
     __madvise;
     __mktemp;
diff --git a/misc/set-tagged-address-mask.c b/misc/set-tagged-address-mask.c
new file mode 100644
index 0000000000..2e1e2f2343
--- /dev/null
+++ b/misc/set-tagged-address-mask.c
@@ -0,0 +1,41 @@ 
+/* Copyright (C) 2021 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/tagged-address.h>
+#include <ldsodefs.h>
+
+/* Set the mask for address bits used in address translation.  Return 0
+   on success.  Return -1 on error.  */
+
+int
+set_tagged_address_mask (uintptr_t mask)
+{
+  if (GL(dl_tagged_address_mask_locked) != 0)
+    __set_errno (EPERM);
+  else
+    {
+      /* set_tagged_address_mask can only be called once.  */
+      GL(dl_tagged_address_mask_locked) = 1;
+
+      /* Only NOP is allowed.  */
+      if (mask == __get_tagged_address_mask ())
+	return 0;
+
+      __set_errno (ENOSYS);
+    }
+  return -1;
+}
diff --git a/misc/sys/tagged-address.h b/misc/sys/tagged-address.h
new file mode 100644
index 0000000000..025a333cac
--- /dev/null
+++ b/misc/sys/tagged-address.h
@@ -0,0 +1,45 @@ 
+/* Copyright (C) 2021 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/>.  */
+
+#ifndef _SYS_TAGGED_ADDRESS_H
+#define _SYS_TAGGED_ADDRESS_H 1
+
+#include <features.h>
+#include <stdint.h>
+#include <bits/tagged-address-mask.h>
+
+__BEGIN_DECLS
+
+/* Get the current address bits used in address translation.  */
+extern unsigned int get_tagged_address_bits (void);
+
+/* Get the current mask for address bits used in address translation.  */
+extern uintptr_t get_tagged_address_mask (void);
+
+/* Set the mask for address bits used in address translation.  Return 0
+   on success.  Return -1 on error.  */
+extern int set_tagged_address_mask (uintptr_t __mask);
+
+/* Return the tagged address of __ADDR with the tag value __TAG.  */
+extern void *tag_address (void *__addr, unsigned int __tag);
+
+/* Return the untagged address of __ADDR.  */
+extern void *untag_address (void *__addr);
+
+__END_DECLS
+
+#endif /* <sys/tagged-address.h> */
diff --git a/misc/tagged-address.c b/misc/tagged-address.c
new file mode 100644
index 0000000000..df474f3d0b
--- /dev/null
+++ b/misc/tagged-address.c
@@ -0,0 +1,55 @@ 
+/* Copyright (C) 2021 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/tagged-address.h>
+
+#undef get_tagged_address_bits
+#undef get_tagged_address_mask
+#undef tag_address
+#undef untag_address
+
+/* Get the current address bits used in address translation.  */
+
+unsigned int
+get_tagged_address_bits (void)
+{
+  return __get_tagged_address_bits ();
+}
+
+/* Get the current mask for address bits used in address translation.  */
+
+uintptr_t
+get_tagged_address_mask (void)
+{
+  return __get_tagged_address_mask ();
+}
+
+/* Return the tagged address of ADDR with the tag value TAG.  */
+
+void *
+tag_address (void *addr, unsigned int tag)
+{
+  return __tag_address (addr, tag);
+}
+
+/* Return the untagged address of ADDR.  */
+
+void *
+untag_address (void *addr)
+{
+  return __untag_address (addr);
+}
diff --git a/misc/tst-tagged-address-1-static.c b/misc/tst-tagged-address-1-static.c
new file mode 100644
index 0000000000..3ed71a66c2
--- /dev/null
+++ b/misc/tst-tagged-address-1-static.c
@@ -0,0 +1 @@ 
+#include <tst-tagged-address-1.c>
diff --git a/misc/tst-tagged-address-1.c b/misc/tst-tagged-address-1.c
new file mode 100644
index 0000000000..0bbc214a2f
--- /dev/null
+++ b/misc/tst-tagged-address-1.c
@@ -0,0 +1,53 @@ 
+/* Tests for set_tagged_address_mask.
+   Copyright (C) 2021 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 <errno.h>
+#include <sys/tagged-address.h>
+#include <support/check.h>
+
+static void
+init_0 (void)
+{
+  if (set_tagged_address_mask (get_tagged_address_mask ()) != 0)
+    FAIL_EXIT1 ("set_tagged_address_mask failed: %m");
+}
+
+static void
+init_1 (void)
+{
+  if (set_tagged_address_mask (get_tagged_address_mask ()) == 0)
+    FAIL_EXIT1 ("set_tagged_address_mask should fail");
+
+  if (errno != EPERM)
+    FAIL_EXIT1 ("set_tagged_address_mask: errno (%m) != EPERM");
+}
+
+static void (*init_array []) (void)
+  __attribute__ ((used, section (".init_array"), aligned (sizeof (void *)))) =
+{
+  &init_0,
+  &init_1
+};
+
+static int
+do_test (void)
+{
+  return 0;
+}
+
+#include <support/test-driver.c>
diff --git a/misc/tst-tagged-address-2-static.c b/misc/tst-tagged-address-2-static.c
new file mode 100644
index 0000000000..ac0d95e6c0
--- /dev/null
+++ b/misc/tst-tagged-address-2-static.c
@@ -0,0 +1 @@ 
+#include <tst-tagged-address-2.c>
diff --git a/misc/tst-tagged-address-2.c b/misc/tst-tagged-address-2.c
new file mode 100644
index 0000000000..76caae4053
--- /dev/null
+++ b/misc/tst-tagged-address-2.c
@@ -0,0 +1,44 @@ 
+/* Test for set_tagged_address_mask with pthread.
+   Copyright (C) 2021 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 <errno.h>
+#include <sys/tagged-address.h>
+#include <support/xthread.h>
+#include <support/check.h>
+
+static void *
+tf (void *arg)
+{
+  if (set_tagged_address_mask (get_tagged_address_mask ()) == 0)
+    FAIL_EXIT1 ("set_tagged_address_mask should fail");
+
+  if (errno != EPERM)
+    FAIL_EXIT1 ("set_tagged_address_mask: errno (%m) != EPERM");
+
+  return NULL;
+}
+
+static int
+do_test (void)
+{
+  pthread_t thr = xpthread_create (NULL, tf, NULL);
+  xpthread_join (thr);
+  return 0;
+}
+
+#include <support/test-driver.c>
diff --git a/misc/tst-tagged-address-3-static.c b/misc/tst-tagged-address-3-static.c
new file mode 100644
index 0000000000..1e3591e0d6
--- /dev/null
+++ b/misc/tst-tagged-address-3-static.c
@@ -0,0 +1 @@ 
+#include <tst-tagged-address-3.c>
diff --git a/misc/tst-tagged-address-3.c b/misc/tst-tagged-address-3.c
new file mode 100644
index 0000000000..e241950959
--- /dev/null
+++ b/misc/tst-tagged-address-3.c
@@ -0,0 +1,48 @@ 
+/* Tests for set_tagged_address_mask to turn off tagged address.
+   Copyright (C) 2021 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/tagged-address.h>
+#include <support/check.h>
+
+static void
+init (void)
+{
+  uintptr_t mask = (uintptr_t) -1;
+  if (set_tagged_address_mask (mask) != 0)
+    FAIL_EXIT1 ("set_tagged_address_mask failed: %m");
+}
+
+static void (*init_array []) (void)
+  __attribute__ ((used, section (".init_array"), aligned (sizeof (void *)))) =
+{
+  &init
+};
+
+static int
+do_test (void)
+{
+  uintptr_t mask = (uintptr_t) -1;
+  uintptr_t curent_mask = get_tagged_address_mask ();
+  if (curent_mask != mask)
+    FAIL_EXIT1 ("get_tagged_address_mask failed: %p != %p",
+		(void *) curent_mask, (void *) mask);
+
+  return 0;
+}
+
+#include <support/test-driver.c>
diff --git a/misc/tst-tagged-address-4-static.c b/misc/tst-tagged-address-4-static.c
new file mode 100644
index 0000000000..b0681f6f9b
--- /dev/null
+++ b/misc/tst-tagged-address-4-static.c
@@ -0,0 +1 @@ 
+#include <tst-tagged-address-4.c>
diff --git a/misc/tst-tagged-address-4.c b/misc/tst-tagged-address-4.c
new file mode 100644
index 0000000000..9843f780af
--- /dev/null
+++ b/misc/tst-tagged-address-4.c
@@ -0,0 +1,35 @@ 
+/* Tests for set_tagged_address_mask.
+   Copyright (C) 2021 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 <errno.h>
+#include <sys/tagged-address.h>
+#include <support/check.h>
+
+static int
+do_test (void)
+{
+  if (set_tagged_address_mask (get_tagged_address_mask ()) == 0)
+    FAIL_EXIT1 ("set_tagged_address_mask should fail");
+
+  if (errno != EPERM)
+    FAIL_EXIT1 ("set_tagged_address_mask: errno (%m) != EPERM");
+
+  return 0;
+}
+
+#include <support/test-driver.c>
diff --git a/misc/tst-tagged-address-5.c b/misc/tst-tagged-address-5.c
new file mode 100644
index 0000000000..e00679a2cb
--- /dev/null
+++ b/misc/tst-tagged-address-5.c
@@ -0,0 +1,25 @@ 
+/* Tests for set_tagged_address_mask.
+   Copyright (C) 2021 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/>.  */
+
+static int
+do_test (void)
+{
+  return 0;
+}
+
+#include <support/test-driver.c>
diff --git a/misc/tst-tagged-address-6.c b/misc/tst-tagged-address-6.c
new file mode 100644
index 0000000000..5fdceb1fb4
--- /dev/null
+++ b/misc/tst-tagged-address-6.c
@@ -0,0 +1,34 @@ 
+/* Tests for set_tagged_address_mask to turn off tagged address.
+   Copyright (C) 2021 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/tagged-address.h>
+#include <support/check.h>
+
+static int
+do_test (void)
+{
+  uintptr_t mask = (uintptr_t) -1;
+  uintptr_t curent_mask = get_tagged_address_mask ();
+  if (curent_mask != mask)
+    FAIL_EXIT1 ("get_tagged_address_mask failed: %p != %p",
+		(void *) curent_mask, (void *) mask);
+
+  return 0;
+}
+
+#include <support/test-driver.c>
diff --git a/misc/tst-tagged-address-7.c b/misc/tst-tagged-address-7.c
new file mode 100644
index 0000000000..f0a078188d
--- /dev/null
+++ b/misc/tst-tagged-address-7.c
@@ -0,0 +1,40 @@ 
+/* Tests for set_tagged_address_mask.
+   Copyright (C) 2021 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 <stddef.h>
+#include <dlfcn.h>
+#include <support/check.h>
+
+static int
+do_test (void)
+{
+  const char *modname = "$ORIGIN/tst-tagged-address-mod-7.so";
+  void *h = dlopen (modname, RTLD_LAZY);
+
+  if (h == NULL)
+    {
+      const char *err = dlerror ();
+      FAIL_EXIT1 ("cannot open '%s': %s\n", modname, err);
+    }
+
+  dlclose (h);
+
+  return 0;
+}
+
+#include <support/test-driver.c>
diff --git a/misc/tst-tagged-address-mod-5.c b/misc/tst-tagged-address-mod-5.c
new file mode 100644
index 0000000000..275ecc406d
--- /dev/null
+++ b/misc/tst-tagged-address-mod-5.c
@@ -0,0 +1,45 @@ 
+/* Tests for set_tagged_address_mask.
+   Copyright (C) 2021 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 <errno.h>
+#include <sys/tagged-address.h>
+#include <support/check.h>
+
+static void
+init_0 (void)
+{
+  if (set_tagged_address_mask (get_tagged_address_mask ()) != 0)
+    FAIL_EXIT1 ("set_tagged_address_mask failed: %m");
+}
+
+static void
+init_1 (void)
+{
+  if (set_tagged_address_mask (get_tagged_address_mask ()) == 0)
+    FAIL_EXIT1 ("set_tagged_address_mask should fail");
+
+  if (errno != EPERM)
+    FAIL_EXIT1 ("set_tagged_address_mask: errno (%m) != EPERM");
+}
+
+static void (*init_array []) (void)
+  __attribute__ ((used, section (".init_array"), aligned (sizeof (void *)))) =
+{
+  &init_0,
+  &init_1
+};
diff --git a/misc/tst-tagged-address-mod-6.c b/misc/tst-tagged-address-mod-6.c
new file mode 100644
index 0000000000..75dfe8e8d2
--- /dev/null
+++ b/misc/tst-tagged-address-mod-6.c
@@ -0,0 +1,34 @@ 
+/* Tests for set_tagged_address_mask to turn off tagged address.
+   Copyright (C) 2021 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/tagged-address.h>
+#include <support/check.h>
+
+static void
+init (void)
+{
+  uintptr_t mask = (uintptr_t) -1;
+  if (set_tagged_address_mask (mask) != 0)
+    FAIL_EXIT1 ("set_tagged_address_mask failed: %m");
+}
+
+static void (*init_array []) (void)
+  __attribute__ ((used, section (".init_array"), aligned (sizeof (void *)))) =
+{
+  &init
+};
diff --git a/misc/tst-tagged-address-mod-7.c b/misc/tst-tagged-address-mod-7.c
new file mode 100644
index 0000000000..c902a4e55e
--- /dev/null
+++ b/misc/tst-tagged-address-mod-7.c
@@ -0,0 +1,34 @@ 
+/* Tests for set_tagged_address_mask to turn off tagged address.
+   Copyright (C) 2021 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/tagged-address.h>
+#include <support/check.h>
+
+static void
+init (void)
+{
+  uintptr_t mask = (uintptr_t) -1;
+  if (set_tagged_address_mask (mask) == 0)
+    FAIL_EXIT1 ("set_tagged_address_mask should have failed");
+}
+
+static void (*init_array []) (void)
+  __attribute__ ((used, section (".init_array"), aligned (sizeof (void *)))) =
+{
+  &init
+};
diff --git a/sysdeps/generic/inline-tagged-address.h b/sysdeps/generic/inline-tagged-address.h
new file mode 100644
index 0000000000..a016b16f21
--- /dev/null
+++ b/sysdeps/generic/inline-tagged-address.h
@@ -0,0 +1,43 @@ 
+/* Inline tagged address functions.  Generic version.
+   Copyright (C) 2021 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 <errno.h>
+
+static inline unsigned int
+__get_tagged_address_bits (void)
+{
+  return sizeof (uintptr_t) * 8;
+}
+
+static inline uintptr_t
+__get_tagged_address_mask (void)
+{
+  return (uintptr_t) -1;
+}
+
+static inline void *
+__tag_address (void *addr, unsigned int tag)
+{
+  return addr;
+}
+
+static inline void *
+__untag_address (void *addr)
+{
+  return addr;
+}
diff --git a/sysdeps/generic/ldsodefs.h b/sysdeps/generic/ldsodefs.h
index 9c15259236..ea64fed6e6 100644
--- a/sysdeps/generic/ldsodefs.h
+++ b/sysdeps/generic/ldsodefs.h
@@ -489,6 +489,10 @@  struct rtld_global
 #else
   EXTERN int _dl_thread_gscope_count;
 #endif
+
+  /* If nonzero, the mask for address bits used in address translation
+     is locked.  */
+  EXTERN int _dl_tagged_address_mask_locked;
 #ifdef SHARED
 };
 # define __rtld_global_attribute__
diff --git a/sysdeps/unix/sysv/linux/i386/libc.abilist b/sysdeps/unix/sysv/linux/i386/libc.abilist
index 2e7603d9ed..3c87dab94a 100644
--- a/sysdeps/unix/sysv/linux/i386/libc.abilist
+++ b/sysdeps/unix/sysv/linux/i386/libc.abilist
@@ -2780,6 +2780,11 @@  GLIBC_2.34 tss_create F
 GLIBC_2.34 tss_delete F
 GLIBC_2.34 tss_get F
 GLIBC_2.34 tss_set F
+GLIBC_2.35 get_tagged_address_bits F
+GLIBC_2.35 get_tagged_address_mask F
+GLIBC_2.35 set_tagged_address_mask F
+GLIBC_2.35 tag_address F
+GLIBC_2.35 untag_address F
 GLIBC_2.4 __confstr_chk F
 GLIBC_2.4 __fgets_chk F
 GLIBC_2.4 __fgets_unlocked_chk F
diff --git a/sysdeps/unix/sysv/linux/x86_64/64/libc.abilist b/sysdeps/unix/sysv/linux/x86_64/64/libc.abilist
index 095e914b73..cc4edb86bd 100644
--- a/sysdeps/unix/sysv/linux/x86_64/64/libc.abilist
+++ b/sysdeps/unix/sysv/linux/x86_64/64/libc.abilist
@@ -2521,6 +2521,11 @@  GLIBC_2.34 tss_create F
 GLIBC_2.34 tss_delete F
 GLIBC_2.34 tss_get F
 GLIBC_2.34 tss_set F
+GLIBC_2.35 get_tagged_address_bits F
+GLIBC_2.35 get_tagged_address_mask F
+GLIBC_2.35 set_tagged_address_mask F
+GLIBC_2.35 tag_address F
+GLIBC_2.35 untag_address F
 GLIBC_2.4 __confstr_chk F
 GLIBC_2.4 __fgets_chk F
 GLIBC_2.4 __fgets_unlocked_chk F
diff --git a/sysdeps/unix/sysv/linux/x86_64/x32/libc.abilist b/sysdeps/unix/sysv/linux/x86_64/x32/libc.abilist
index dd910f7fe9..f8c889ba87 100644
--- a/sysdeps/unix/sysv/linux/x86_64/x32/libc.abilist
+++ b/sysdeps/unix/sysv/linux/x86_64/x32/libc.abilist
@@ -2627,3 +2627,8 @@  GLIBC_2.34 tss_create F
 GLIBC_2.34 tss_delete F
 GLIBC_2.34 tss_get F
 GLIBC_2.34 tss_set F
+GLIBC_2.35 get_tagged_address_bits F
+GLIBC_2.35 get_tagged_address_mask F
+GLIBC_2.35 set_tagged_address_mask F
+GLIBC_2.35 tag_address F
+GLIBC_2.35 untag_address F