[05/12] gdb, gdbserver: Use xstate_bv for target description creation on x86.

Message ID 20241220200501.324191-6-christina.schimpe@intel.com
State New
Headers
Series Add CET shadow stack support |

Commit Message

Schimpe, Christina Dec. 20, 2024, 8:04 p.m. UTC
  The XSAVE features set is organized in state components, which are a set
of or parts of registers.  So-called XSAVE-supported features are
organized using state-component bitmaps, each bit corresonding to a
single state component.

The SDM uses the term xstate_bv for a state-component bitmap, which is
defined as XCR0 | IA32_XSS.  The control register XCR0 only contains a
state-component bitmap that specifies user state components, while IA32_XSS
contains a state-component bitmap that specifies supervisor state components.

Until now, XCR0 is used as input for target description creation in GDB.
However, a following patch will add userspace support for the CET shadow
stack feature by Intel.  The CET state is configured in IA32_XSS and consists
of 2 state components:
- State component 11 used for the 2 MSRs controlling user-mode
  functionality for CET (CET_U state)
- State component 12 used for the 3 MSRs containing shadow-stack pointers
  for privilege levels 0-2 (CET_S state).

Reading the CET shadow stack pointer register on linux requires a separate
ptrace call using NT_X86_SHSTK.  To pass the CET shadow stack enablement
state we would like to pass the xstate_bv value instead of xcr0 for target
description creation.  To prepare for that, we rename the xcr0 mask
values for target description creation to xstate_bv.  However, this
patch doesn't add any functional changes in GDB.

Future states specified in IA32_XSS such as CET will create a combined
xstate_bv_mask including xcr0 register value and its corresponding bit in
the state component bitmap.  This combined mask will then be used to create
the target descriptions.
---
 gdb/amd64-tdep.c                    | 14 ++++----
 gdb/amd64-tdep.h                    |  8 +++--
 gdb/arch/amd64-linux-tdesc.c        | 33 ++++++++---------
 gdb/arch/amd64-linux-tdesc.h        |  7 ++--
 gdb/arch/amd64.c                    | 15 ++++----
 gdb/arch/amd64.h                    | 10 ++++--
 gdb/arch/i386-linux-tdesc.c         | 29 ++++++++-------
 gdb/arch/i386-linux-tdesc.h         |  5 +--
 gdb/arch/i386.c                     | 15 ++++----
 gdb/arch/i386.h                     |  8 ++++-
 gdb/arch/x86-linux-tdesc-features.c | 55 +++++++++++++++--------------
 gdb/arch/x86-linux-tdesc-features.h | 25 +++++++------
 gdb/i386-tdep.c                     | 14 ++++----
 gdb/i386-tdep.h                     |  7 ++--
 gdb/nat/x86-linux-tdesc.c           | 18 +++++-----
 gdb/nat/x86-linux-tdesc.h           |  7 ++--
 gdb/x86-linux-nat.c                 | 11 ++++--
 gdbserver/i387-fp.cc                | 40 ++++++++++-----------
 gdbserver/linux-amd64-ipa.cc        | 10 +++---
 gdbserver/linux-i386-ipa.cc         |  6 ++--
 gdbserver/linux-x86-low.cc          |  9 +++--
 gdbsupport/x86-xstate.h             |  4 ++-
 22 files changed, 196 insertions(+), 154 deletions(-)
  

Comments

Guinevere Larsen Jan. 30, 2025, 2:51 p.m. UTC | #1
On 12/20/24 5:04 PM, Schimpe, Christina wrote:
> The XSAVE features set is organized in state components, which are a set
> of or parts of registers.  So-called XSAVE-supported features are

I think the phrasing "are a set of or parts of registers" is a bit 
confusing.

I would find it more readable if it said something like "are a set of 
registers, or parts of registers".

> organized using state-component bitmaps, each bit corresonding to a
typo, corresponding.
> single state component.
>
> The SDM uses the term xstate_bv for a state-component bitmap, which is
> defined as XCR0 | IA32_XSS.  The control register XCR0 only contains a
> state-component bitmap that specifies user state components, while IA32_XSS
> contains a state-component bitmap that specifies supervisor state components.
>
> Until now, XCR0 is used as input for target description creation in GDB.
> However, a following patch will add userspace support for the CET shadow
> stack feature by Intel.  The CET state is configured in IA32_XSS and consists
> of 2 state components:
> - State component 11 used for the 2 MSRs controlling user-mode
>    functionality for CET (CET_U state)
> - State component 12 used for the 3 MSRs containing shadow-stack pointers
>    for privilege levels 0-2 (CET_S state).
>
> Reading the CET shadow stack pointer register on linux requires a separate
> ptrace call using NT_X86_SHSTK.  To pass the CET shadow stack enablement
> state we would like to pass the xstate_bv value instead of xcr0 for target
> description creation.  To prepare for that, we rename the xcr0 mask
> values for target description creation to xstate_bv.  However, this
> patch doesn't add any functional changes in GDB.
>
> Future states specified in IA32_XSS such as CET will create a combined
> xstate_bv_mask including xcr0 register value and its corresponding bit in
> the state component bitmap.  This combined mask will then be used to create
> the target descriptions.
All this stuff is absolute magic to me, so I can't really give a review 
on the code....
  
Thiago Jung Bauermann Feb. 6, 2025, 3:09 a.m. UTC | #2
"Schimpe, Christina" <christina.schimpe@intel.com> writes:

> The XSAVE features set is organized in state components, which are a set
> of or parts of registers.  So-called XSAVE-supported features are
> organized using state-component bitmaps, each bit corresonding to a

Typo: "corresponding"

> single state component.
>
> The SDM uses the term xstate_bv for a state-component bitmap, which is
> defined as XCR0 | IA32_XSS.  The control register XCR0 only contains a
> state-component bitmap that specifies user state components, while IA32_XSS
> contains a state-component bitmap that specifies supervisor state components.
>
> Until now, XCR0 is used as input for target description creation in GDB.
> However, a following patch will add userspace support for the CET shadow
> stack feature by Intel.  The CET state is configured in IA32_XSS and consists
> of 2 state components:
> - State component 11 used for the 2 MSRs controlling user-mode
>   functionality for CET (CET_U state)
> - State component 12 used for the 3 MSRs containing shadow-stack pointers
>   for privilege levels 0-2 (CET_S state).
>
> Reading the CET shadow stack pointer register on linux requires a separate
> ptrace call using NT_X86_SHSTK.  To pass the CET shadow stack enablement
> state we would like to pass the xstate_bv value instead of xcr0 for target
> description creation.  To prepare for that, we rename the xcr0 mask
> values for target description creation to xstate_bv.  However, this
> patch doesn't add any functional changes in GDB.
>
> Future states specified in IA32_XSS such as CET will create a combined
> xstate_bv_mask including xcr0 register value and its corresponding bit in
> the state component bitmap.  This combined mask will then be used to create
> the target descriptions.
> ---
>  gdb/amd64-tdep.c                    | 14 ++++----
>  gdb/amd64-tdep.h                    |  8 +++--
>  gdb/arch/amd64-linux-tdesc.c        | 33 ++++++++---------
>  gdb/arch/amd64-linux-tdesc.h        |  7 ++--
>  gdb/arch/amd64.c                    | 15 ++++----
>  gdb/arch/amd64.h                    | 10 ++++--
>  gdb/arch/i386-linux-tdesc.c         | 29 ++++++++-------
>  gdb/arch/i386-linux-tdesc.h         |  5 +--
>  gdb/arch/i386.c                     | 15 ++++----
>  gdb/arch/i386.h                     |  8 ++++-
>  gdb/arch/x86-linux-tdesc-features.c | 55 +++++++++++++++--------------
>  gdb/arch/x86-linux-tdesc-features.h | 25 +++++++------
>  gdb/i386-tdep.c                     | 14 ++++----
>  gdb/i386-tdep.h                     |  7 ++--
>  gdb/nat/x86-linux-tdesc.c           | 18 +++++-----
>  gdb/nat/x86-linux-tdesc.h           |  7 ++--
>  gdb/x86-linux-nat.c                 | 11 ++++--
>  gdbserver/i387-fp.cc                | 40 ++++++++++-----------
>  gdbserver/linux-amd64-ipa.cc        | 10 +++---
>  gdbserver/linux-i386-ipa.cc         |  6 ++--
>  gdbserver/linux-x86-low.cc          |  9 +++--
>  gdbsupport/x86-xstate.h             |  4 ++-
>  22 files changed, 196 insertions(+), 154 deletions(-)

Just some minor suggestions in comments.

Reviewed-by: Thiago Jung Bauermann <thiago.bauermann@linaro.org>

> diff --git a/gdb/arch/x86-linux-tdesc-features.c b/gdb/arch/x86-linux-tdesc-features.c
> index f6eb112f312..3f041ece6eb 100644
> --- a/gdb/arch/x86-linux-tdesc-features.c
> +++ b/gdb/arch/x86-linux-tdesc-features.c
> @@ -28,18 +28,21 @@
>
>     We want to cache target descriptions, and this is currently done in
>     three separate caches, one each for i386, amd64, and x32.  Additionally,
> -   the caching we're discussing here is Linux only, and for Linux, the only
> -   thing that has an impact on target description creation is the xcr0
> -   value.
> +   the caching we're discussing here is Linux only.  Currently for linux,

Nit: "Linux"

> +   the only thing that has an impact on target description creation are
> +   the supported features in xsave which are modelled by a xstate_bv_mask
> +   value, which has the same format than the state component bitmap.
>
>     In order to ensure the cache functions correctly we need to filter out

I think this should read "filter" rather than "filter out". I understand
the latter to mean that xstate_bv_mask feature bits that are relevant
should be ignored, which isn't what the code does.

> @@ -51,11 +54,13 @@ extern int x86_linux_amd64_tdesc_count ();
>  extern int x86_linux_x32_tdesc_count ();
>  extern int x86_linux_i386_tdesc_count ();
>
> -/* Convert an index number (as returned from x86_linux_xcr0_to_tdesc_idx)
> -   into an xcr0 value which can then be used to create a target
> -   description.  */
> +/* Convert an index number (as returned from
> +   x86_linux_xstate_bv_mask_to_tdesc_idx) into an xstate_bv_mask
> +   value which can then be used to create a target description.
> +   The return mask same format than the state component bitmap and does

Missing words: "The return mask has the same format ..."

> +   include user and supervisor state components.*/
>
> -extern uint64_t x86_linux_tdesc_idx_to_xcr0 (int idx);
> +extern uint64_t x86_linux_tdesc_idx_to_xstate_bv_mask (int idx);
>
>  #endif /* IN_PROCESS_AGENT */

--
Thiago
  
Schimpe, Christina Feb. 6, 2025, 12:33 p.m. UTC | #3
Hi Thiago,

Please see my comments below.

> -----Original Message-----
> From: Thiago Jung Bauermann <thiago.bauermann@linaro.org>
> Sent: Thursday, February 6, 2025 4:10 AM
> To: Schimpe, Christina <christina.schimpe@intel.com>
> Cc: gdb-patches@sourceware.org
> Subject: Re: [PATCH 05/12] gdb, gdbserver: Use xstate_bv for target description
> creation on x86.
> 
> 
> "Schimpe, Christina" <christina.schimpe@intel.com> writes:
> 
> > The XSAVE features set is organized in state components, which are a
> > set of or parts of registers.  So-called XSAVE-supported features are
> > organized using state-component bitmaps, each bit corresonding to a
> 
> Typo: "corresponding"

Will fix.

> > single state component.
> >
> > The SDM uses the term xstate_bv for a state-component bitmap, which is
> > defined as XCR0 | IA32_XSS.  The control register XCR0 only contains a
> > state-component bitmap that specifies user state components, while
> > IA32_XSS contains a state-component bitmap that specifies supervisor state
> components.
> >
> > Until now, XCR0 is used as input for target description creation in GDB.
> > However, a following patch will add userspace support for the CET
> > shadow stack feature by Intel.  The CET state is configured in
> > IA32_XSS and consists of 2 state components:
> > - State component 11 used for the 2 MSRs controlling user-mode
> >   functionality for CET (CET_U state)
> > - State component 12 used for the 3 MSRs containing shadow-stack pointers
> >   for privilege levels 0-2 (CET_S state).
> >
> > Reading the CET shadow stack pointer register on linux requires a
> > separate ptrace call using NT_X86_SHSTK.  To pass the CET shadow stack
> > enablement state we would like to pass the xstate_bv value instead of
> > xcr0 for target description creation.  To prepare for that, we rename
> > the xcr0 mask values for target description creation to xstate_bv.
> > However, this patch doesn't add any functional changes in GDB.
> >
> > Future states specified in IA32_XSS such as CET will create a combined
> > xstate_bv_mask including xcr0 register value and its corresponding bit
> > in the state component bitmap.  This combined mask will then be used
> > to create the target descriptions.
> > ---
> >  gdb/amd64-tdep.c                    | 14 ++++----
> >  gdb/amd64-tdep.h                    |  8 +++--
> >  gdb/arch/amd64-linux-tdesc.c        | 33 ++++++++---------
> >  gdb/arch/amd64-linux-tdesc.h        |  7 ++--
> >  gdb/arch/amd64.c                    | 15 ++++----
> >  gdb/arch/amd64.h                    | 10 ++++--
> >  gdb/arch/i386-linux-tdesc.c         | 29 ++++++++-------
> >  gdb/arch/i386-linux-tdesc.h         |  5 +--
> >  gdb/arch/i386.c                     | 15 ++++----
> >  gdb/arch/i386.h                     |  8 ++++-
> >  gdb/arch/x86-linux-tdesc-features.c | 55
> > +++++++++++++++--------------  gdb/arch/x86-linux-tdesc-features.h | 25
> +++++++------
> >  gdb/i386-tdep.c                     | 14 ++++----
> >  gdb/i386-tdep.h                     |  7 ++--
> >  gdb/nat/x86-linux-tdesc.c           | 18 +++++-----
> >  gdb/nat/x86-linux-tdesc.h           |  7 ++--
> >  gdb/x86-linux-nat.c                 | 11 ++++--
> >  gdbserver/i387-fp.cc                | 40 ++++++++++-----------
> >  gdbserver/linux-amd64-ipa.cc        | 10 +++---
> >  gdbserver/linux-i386-ipa.cc         |  6 ++--
> >  gdbserver/linux-x86-low.cc          |  9 +++--
> >  gdbsupport/x86-xstate.h             |  4 ++-
> >  22 files changed, 196 insertions(+), 154 deletions(-)
> 
> Just some minor suggestions in comments.
> 
> Reviewed-by: Thiago Jung Bauermann <thiago.bauermann@linaro.org>
> 
> > diff --git a/gdb/arch/x86-linux-tdesc-features.c
> > b/gdb/arch/x86-linux-tdesc-features.c
> > index f6eb112f312..3f041ece6eb 100644
> > --- a/gdb/arch/x86-linux-tdesc-features.c
> > +++ b/gdb/arch/x86-linux-tdesc-features.c
> > @@ -28,18 +28,21 @@
> >
> >     We want to cache target descriptions, and this is currently done in
> >     three separate caches, one each for i386, amd64, and x32.  Additionally,
> > -   the caching we're discussing here is Linux only, and for Linux, the only
> > -   thing that has an impact on target description creation is the xcr0
> > -   value.
> > +   the caching we're discussing here is Linux only.  Currently for
> > + linux,
> 
> Nit: "Linux"

Will fix.

> > +   the only thing that has an impact on target description creation are
> > +   the supported features in xsave which are modelled by a xstate_bv_mask
> > +   value, which has the same format than the state component bitmap.
> >
> >     In order to ensure the cache functions correctly we need to filter
> > out
> 
> I think this should read "filter" rather than "filter out". I understand the latter to
> mean that xstate_bv_mask feature bits that are relevant should be ignored, which
> isn't what the code does.

I think you are right.
I could even make it a separate generic patch since "to filter out" was used 
before already. But I think it's also ok, to just fix it with that patch.

> > @@ -51,11 +54,13 @@ extern int x86_linux_amd64_tdesc_count ();  extern
> > int x86_linux_x32_tdesc_count ();  extern int
> > x86_linux_i386_tdesc_count ();
> >
> > -/* Convert an index number (as returned from x86_linux_xcr0_to_tdesc_idx)
> > -   into an xcr0 value which can then be used to create a target
> > -   description.  */
> > +/* Convert an index number (as returned from
> > +   x86_linux_xstate_bv_mask_to_tdesc_idx) into an xstate_bv_mask
> > +   value which can then be used to create a target description.
> > +   The return mask same format than the state component bitmap and
> > +does
> 
> Missing words: "The return mask has the same format ..."

Will fix this and all your comments above for the next version. 
Also I'll add your Reviewed-by tag.

Thanks!
Christina
Intel Deutschland GmbH
Registered Address: Am Campeon 10, 85579 Neubiberg, Germany
Tel: +49 89 99 8853-0, www.intel.de
Managing Directors: Sean Fennelly, Jeffrey Schneiderman, Tiffany Doon Silva
Chairperson of the Supervisory Board: Nicole Lau
Registered Office: Munich
Commercial Register: Amtsgericht Muenchen HRB 186928
  

Patch

diff --git a/gdb/amd64-tdep.c b/gdb/amd64-tdep.c
index e03180b08af..37a2e3b03d4 100644
--- a/gdb/amd64-tdep.c
+++ b/gdb/amd64-tdep.c
@@ -3353,23 +3353,23 @@  amd64_x32_none_init_abi (gdbarch_info info, gdbarch *arch)
 		      amd64_target_description (X86_XSTATE_SSE_MASK, true));
 }
 
-/* Return the target description for a specified XSAVE feature mask.  */
+/* See amd64-tdep.h.  */
 
 const struct target_desc *
-amd64_target_description (uint64_t xcr0, bool segments)
+amd64_target_description (uint64_t xstate_bv_mask, bool segments)
 {
   static target_desc *amd64_tdescs \
     [2/*AVX*/][2/*AVX512*/][2/*PKRU*/][2/*segments*/] = {};
   target_desc **tdesc;
 
-  tdesc = &amd64_tdescs[(xcr0 & X86_XSTATE_AVX) ? 1 : 0]
-    [(xcr0 & X86_XSTATE_AVX512) ? 1 : 0]
-    [(xcr0 & X86_XSTATE_PKRU) ? 1 : 0]
+  tdesc = &amd64_tdescs[(xstate_bv_mask & X86_XSTATE_AVX) ? 1 : 0]
+    [(xstate_bv_mask & X86_XSTATE_AVX512) ? 1 : 0]
+    [(xstate_bv_mask & X86_XSTATE_PKRU) ? 1 : 0]
     [segments ? 1 : 0];
 
   if (*tdesc == NULL)
-    *tdesc = amd64_create_target_description (xcr0, false, false,
-					      segments);
+    *tdesc = amd64_create_target_description (xstate_bv_mask, false,
+					      false, segments);
 
   return *tdesc;
 }
diff --git a/gdb/amd64-tdep.h b/gdb/amd64-tdep.h
index 7439b6e2e20..e93e3931df3 100644
--- a/gdb/amd64-tdep.h
+++ b/gdb/amd64-tdep.h
@@ -108,8 +108,12 @@  extern void amd64_init_abi (struct gdbarch_info info,
 extern void amd64_x32_init_abi (struct gdbarch_info info,
 				struct gdbarch *gdbarch,
 				const target_desc *default_tdesc);
-extern const struct target_desc *amd64_target_description (uint64_t xcr0,
-							   bool segments);
+
+/* Return the target description for the specified xsave features as
+   defined in XSTATE_BV_MASK and SEGMENTS.  */
+
+extern const struct target_desc *amd64_target_description
+  (uint64_t xstate_bv_mask, bool segments);
 
 /* Fill register REGNUM in REGCACHE with the appropriate
    floating-point or SSE register value from *FXSAVE.  If REGNUM is
diff --git a/gdb/arch/amd64-linux-tdesc.c b/gdb/arch/amd64-linux-tdesc.c
index e9c4a99806d..17dfcfeaee8 100644
--- a/gdb/arch/amd64-linux-tdesc.c
+++ b/gdb/arch/amd64-linux-tdesc.c
@@ -26,41 +26,42 @@ 
 /* See arch/amd64-linux-tdesc.h.  */
 
 const struct target_desc *
-amd64_linux_read_description (uint64_t xcr0, bool is_x32)
+amd64_linux_read_description (uint64_t xstate_bv_mask, bool is_x32)
 {
   /* The type used for the amd64 and x32 target description caches.  */
   using tdesc_cache_type = std::unordered_map<uint64_t, const target_desc_up>;
 
   /* Caches for the previously seen amd64 and x32 target descriptions,
-     indexed by the xcr0 value that created the target description.  These
-     need to be static within this function to ensure they are initialised
-     before first use.  */
+     indexed by the xstate_bv_mask value that created the target
+     description.  These need to be static within this function to ensure
+     they are initialised before first use.  */
   static tdesc_cache_type amd64_tdesc_cache, x32_tdesc_cache;
 
   tdesc_cache_type &tdesc_cache = is_x32 ? x32_tdesc_cache : amd64_tdesc_cache;
 
-  /* Only some bits are checked when creating a tdesc, but the XCR0 value
-     contains other feature bits that are not relevant for tdesc creation.
-     When indexing into the TDESC_CACHE we need to use a consistent xcr0
-     value otherwise we might fail to find an existing tdesc which has the
-     same set of relevant bits set.  */
-  xcr0 &= is_x32
-    ? x86_linux_x32_xcr0_feature_mask ()
-    : x86_linux_amd64_xcr0_feature_mask ();
+  /* Only some bits are checked when creating a tdesc, but the
+     xstate_bv_mask value contains other feature bits that are not
+     relevant for tdesc creation.
+     When indexing into the TDESC_CACHE we need to use a consistent
+     xstate_bv_mask value otherwise we might fail to find an existing
+     tdesc which has the same set of relevant bits set.  */
+  xstate_bv_mask &= is_x32
+    ? x86_linux_x32_xstate_bv_feature_mask ()
+    : x86_linux_amd64_xstate_bv_feature_mask ();
 
-  const auto it = tdesc_cache.find (xcr0);
+  const auto it = tdesc_cache.find (xstate_bv_mask);
   if (it != tdesc_cache.end ())
     return it->second.get ();
 
   /* Create the previously unseen target description.  */
-  target_desc_up tdesc (amd64_create_target_description (xcr0, is_x32,
-							 true, true));
+  target_desc_up tdesc (amd64_create_target_description (xstate_bv_mask,
+							 is_x32, true, true));
   x86_linux_post_init_tdesc (tdesc.get (), true);
 
   /* Add to the cache, and return a pointer borrowed from the
      target_desc_up.  This is safe as the cache (and the pointers contained
      within it) are not deleted until GDB exits.  */
   target_desc *ptr = tdesc.get ();
-  tdesc_cache.emplace (xcr0, std::move (tdesc));
+  tdesc_cache.emplace (xstate_bv_mask, std::move (tdesc));
   return ptr;
 }
diff --git a/gdb/arch/amd64-linux-tdesc.h b/gdb/arch/amd64-linux-tdesc.h
index f6a424862bb..27a99efbe10 100644
--- a/gdb/arch/amd64-linux-tdesc.h
+++ b/gdb/arch/amd64-linux-tdesc.h
@@ -22,9 +22,10 @@ 
 
 struct target_desc;
 
-/* Return the AMD64 target descriptions corresponding to XCR0 and IS_X32.  */
+/* Return the AMD64 target descriptions corresponding to XSTATE_BV_MASK
+   and IS_X32.  */
 
-extern const target_desc *amd64_linux_read_description (uint64_t xcr0,
-							bool is_x32);
+extern const target_desc *amd64_linux_read_description
+  (uint64_t xstate_bv_mask, bool is_x32);
 
 #endif /* GDB_ARCH_AMD64_LINUX_TDESC_H */
diff --git a/gdb/arch/amd64.c b/gdb/arch/amd64.c
index 5fc9947d489..72bd96aff76 100644
--- a/gdb/arch/amd64.c
+++ b/gdb/arch/amd64.c
@@ -30,14 +30,11 @@ 
 
 #include "../features/i386/x32-core.c"
 
-/* Create amd64 target descriptions according to XCR0.  If IS_X32 is
-   true, create the x32 ones.  If IS_LINUX is true, create target
-   descriptions for Linux.  If SEGMENTS is true, then include
-   the "org.gnu.gdb.i386.segments" feature registers.  */
+/* See amd64.h.  */
 
 target_desc *
-amd64_create_target_description (uint64_t xcr0, bool is_x32, bool is_linux,
-				 bool segments)
+amd64_create_target_description (uint64_t xstate_bv_mask, bool is_x32,
+				 bool is_linux, bool segments)
 {
   target_desc_up tdesc = allocate_target_description ();
 
@@ -62,13 +59,13 @@  amd64_create_target_description (uint64_t xcr0, bool is_x32, bool is_linux,
   if (segments)
     regnum = create_feature_i386_64bit_segments (tdesc.get (), regnum);
 
-  if (xcr0 & X86_XSTATE_AVX)
+  if (xstate_bv_mask & X86_XSTATE_AVX)
     regnum = create_feature_i386_64bit_avx (tdesc.get (), regnum);
 
-  if (xcr0 & X86_XSTATE_AVX512)
+  if (xstate_bv_mask & X86_XSTATE_AVX512)
     regnum = create_feature_i386_64bit_avx512 (tdesc.get (), regnum);
 
-  if (xcr0 & X86_XSTATE_PKRU)
+  if (xstate_bv_mask & X86_XSTATE_PKRU)
     regnum = create_feature_i386_pkeys (tdesc.get (), regnum);
 
   return tdesc.release ();
diff --git a/gdb/arch/amd64.h b/gdb/arch/amd64.h
index 1c7a2bb26e9..3ce1a5557b2 100644
--- a/gdb/arch/amd64.h
+++ b/gdb/arch/amd64.h
@@ -21,7 +21,13 @@ 
 #include "gdbsupport/tdesc.h"
 #include <stdint.h>
 
-target_desc *amd64_create_target_description (uint64_t xcr0, bool is_x32,
-					      bool is_linux, bool segments);
+/* Create amd64 target descriptions according to XSTATE_BV_MASK.  If
+   IS_X32 is true, create the x32 ones.  If IS_LINUX is true, create
+   target descriptions for Linux.  If SEGMENTS is true, then include
+   the "org.gnu.gdb.i386.segments" feature registers.  */
+
+target_desc *amd64_create_target_description (uint64_t xstate_bv_mask,
+					      bool is_x32, bool is_linux,
+					      bool segments);
 
 #endif /* GDB_ARCH_AMD64_H */
diff --git a/gdb/arch/i386-linux-tdesc.c b/gdb/arch/i386-linux-tdesc.c
index 9f12e59d214..bae8741b210 100644
--- a/gdb/arch/i386-linux-tdesc.c
+++ b/gdb/arch/i386-linux-tdesc.c
@@ -25,32 +25,35 @@ 
 /* See arch/i386-linux-tdesc.h.  */
 
 const target_desc *
-i386_linux_read_description (uint64_t xcr0)
+i386_linux_read_description (uint64_t xstate_bv_mask)
 {
-  /* Cache of previously seen i386 target descriptions, indexed by the xcr0
-     value that created the target description.  This needs to be static
-     within this function to ensure it is initialised before first use.  */
+  /* Cache of previously seen i386 target descriptions, indexed by the
+     xstate_bv_mask value that created the target description.  This
+     needs to be static within this function to ensure it is initialised
+     before first use.  */
   static std::unordered_map<uint64_t, const target_desc_up> i386_tdesc_cache;
 
-  /* Only some bits are checked when creating a tdesc, but the XCR0 value
-     contains other feature bits that are not relevant for tdesc creation.
-     When indexing into the I386_TDESC_CACHE we need to use a consistent
-     xcr0 value otherwise we might fail to find an existing tdesc which has
-     the same set of relevant bits set.  */
-  xcr0 &= x86_linux_i386_xcr0_feature_mask ();
+  /* Only some bits are checked when creating a tdesc, but the
+     XSTATE_BV_MASK value contains other feature bits that are not
+     relevant for tdesc creation.  When indexing into the I386_TDESC_CACHE
+     we need to use a consistent XSTATE_BV_MASK value otherwise we might
+     fail to find an existing tdesc which has the same set of relevant
+     bits set.  */
+  xstate_bv_mask &= x86_linux_i386_xstate_bv_feature_mask ();
 
-  const auto it = i386_tdesc_cache.find (xcr0);
+  const auto it = i386_tdesc_cache.find (xstate_bv_mask);
   if (it != i386_tdesc_cache.end ())
     return it->second.get ();
 
   /* Create the previously unseen target description.  */
-  target_desc_up tdesc (i386_create_target_description (xcr0, true, false));
+  target_desc_up tdesc
+    (i386_create_target_description (xstate_bv_mask, true, false));
   x86_linux_post_init_tdesc (tdesc.get (), false);
 
   /* Add to the cache, and return a pointer borrowed from the
      target_desc_up.  This is safe as the cache (and the pointers contained
      within it) are not deleted until GDB exits.  */
   target_desc *ptr = tdesc.get ();
-  i386_tdesc_cache.emplace (xcr0, std::move (tdesc));
+  i386_tdesc_cache.emplace (xstate_bv_mask, std::move (tdesc));
   return ptr;
 }
diff --git a/gdb/arch/i386-linux-tdesc.h b/gdb/arch/i386-linux-tdesc.h
index 4ecd674aa96..6970202ce4d 100644
--- a/gdb/arch/i386-linux-tdesc.h
+++ b/gdb/arch/i386-linux-tdesc.h
@@ -22,8 +22,9 @@ 
 
 struct target_desc;
 
-/* Return the i386 target description corresponding to XCR0.  */
+/* Return the i386 target description corresponding to XSTATE_BV_MASK.  */
 
-extern const struct target_desc *i386_linux_read_description (uint64_t xcr0);
+extern const struct target_desc *i386_linux_read_description
+  (uint64_t xstate_bv_mask);
 
 #endif /* GDB_ARCH_I386_LINUX_TDESC_H */
diff --git a/gdb/arch/i386.c b/gdb/arch/i386.c
index 2072eae88ad..4a39028a472 100644
--- a/gdb/arch/i386.c
+++ b/gdb/arch/i386.c
@@ -29,10 +29,11 @@ 
 #include "../features/i386/32bit-segments.c"
 #include "../features/i386/pkeys.c"
 
-/* Create i386 target descriptions according to XCR0.  */
+/* See i386.h.  */
 
 target_desc *
-i386_create_target_description (uint64_t xcr0, bool is_linux, bool segments)
+i386_create_target_description (uint64_t xstate_bv_mask, bool is_linux,
+				bool segments)
 {
   target_desc_up tdesc = allocate_target_description ();
 
@@ -44,10 +45,10 @@  i386_create_target_description (uint64_t xcr0, bool is_linux, bool segments)
 
   long regnum = 0;
 
-  if (xcr0 & X86_XSTATE_X87)
+  if (xstate_bv_mask & X86_XSTATE_X87)
     regnum = create_feature_i386_32bit_core (tdesc.get (), regnum);
 
-  if (xcr0 & X86_XSTATE_SSE)
+  if (xstate_bv_mask & X86_XSTATE_SSE)
     regnum = create_feature_i386_32bit_sse (tdesc.get (), regnum);
 
   if (is_linux)
@@ -56,13 +57,13 @@  i386_create_target_description (uint64_t xcr0, bool is_linux, bool segments)
   if (segments)
     regnum = create_feature_i386_32bit_segments (tdesc.get (), regnum);
 
-  if (xcr0 & X86_XSTATE_AVX)
+  if (xstate_bv_mask & X86_XSTATE_AVX)
     regnum = create_feature_i386_32bit_avx (tdesc.get (), regnum);
 
-  if (xcr0 & X86_XSTATE_AVX512)
+  if (xstate_bv_mask & X86_XSTATE_AVX512)
     regnum = create_feature_i386_32bit_avx512 (tdesc.get (), regnum);
 
-  if (xcr0 & X86_XSTATE_PKRU)
+  if (xstate_bv_mask & X86_XSTATE_PKRU)
     regnum = create_feature_i386_pkeys (tdesc.get (), regnum);
 
   return tdesc.release ();
diff --git a/gdb/arch/i386.h b/gdb/arch/i386.h
index 1b5cc6e1095..89f8aa49b9d 100644
--- a/gdb/arch/i386.h
+++ b/gdb/arch/i386.h
@@ -21,7 +21,13 @@ 
 #include "gdbsupport/tdesc.h"
 #include <stdint.h>
 
-target_desc *i386_create_target_description (uint64_t xcr0, bool is_linux,
+/* Create i386 target descriptions according to XSTATE_BV_MASK.  If
+   IS_LINUX is true, create target descriptions for Linux.  If SEGMENTS
+   is true, then include the "org.gnu.gdb.i386.segments" feature
+   registers.  */
+
+target_desc *i386_create_target_description (uint64_t xstate_bv_mask,
+					     bool is_linux,
 					     bool segments);
 
 #endif /* GDB_ARCH_I386_H */
diff --git a/gdb/arch/x86-linux-tdesc-features.c b/gdb/arch/x86-linux-tdesc-features.c
index f6eb112f312..3f041ece6eb 100644
--- a/gdb/arch/x86-linux-tdesc-features.c
+++ b/gdb/arch/x86-linux-tdesc-features.c
@@ -28,18 +28,21 @@ 
 
    We want to cache target descriptions, and this is currently done in
    three separate caches, one each for i386, amd64, and x32.  Additionally,
-   the caching we're discussing here is Linux only, and for Linux, the only
-   thing that has an impact on target description creation is the xcr0
-   value.
+   the caching we're discussing here is Linux only.  Currently for linux,
+   the only thing that has an impact on target description creation are
+   the supported features in xsave which are modelled by a xstate_bv_mask
+   value, which has the same format than the state component bitmap.
 
    In order to ensure the cache functions correctly we need to filter out
-   only those xcr0 feature bits that are relevant, we can then cache target
-   descriptions based on the relevant feature bits.  Two xcr0 values might
-   be different, but have the same relevant feature bits.  In this case we
-   would expect the two xcr0 values to map to the same cache entry.  */
+   only those xstate_bv_mask feature bits that are relevant, we can then
+   cache target descriptions based on the relevant feature bits.  Two
+   xstate_bv_mask values might be different, but have the same relevant
+   feature bits.  In this case we would expect the two xstate_bv_mask
+   values to map to the same cache entry.  */
 
 struct x86_xstate_feature {
-  /* The xstate feature mask.  This is a mask against an xcr0 value.  */
+  /* The xstate feature mask.  This is a mask against the state component
+     bitmap.  */
   uint64_t feature;
 
   /* Is this feature checked when creating an i386 target description.  */
@@ -56,9 +59,9 @@  struct x86_xstate_feature {
    checked when building a target description for i386, amd64, or x32.
 
    If in the future, due to simplifications or refactoring, this table ever
-   ends up with 'true' for every xcr0 feature on every target type, then this
-   is an indication that this table should probably be removed, and that the
-   rest of the code in this file can be simplified.  */
+   ends up with 'true' for every xsave feature on every target type, then
+   this is an indication that this table should probably be removed, and
+   that the rest of the code in this file can be simplified.  */
 
 static constexpr x86_xstate_feature x86_linux_all_xstate_features[] = {
   /* Feature,           i386,	amd64,	x32.  */
@@ -73,7 +76,7 @@  static constexpr x86_xstate_feature x86_linux_all_xstate_features[] = {
    that are checked for when building an i386 target description.  */
 
 static constexpr uint64_t
-x86_linux_i386_xcr0_feature_mask_1 ()
+x86_linux_i386_xstate_bv_feature_mask_1 ()
 {
   uint64_t mask = 0;
 
@@ -88,7 +91,7 @@  x86_linux_i386_xcr0_feature_mask_1 ()
    that are checked for when building an amd64 target description.  */
 
 static constexpr uint64_t
-x86_linux_amd64_xcr0_feature_mask_1 ()
+x86_linux_amd64_xstate_bv_feature_mask_1 ()
 {
   uint64_t mask = 0;
 
@@ -103,7 +106,7 @@  x86_linux_amd64_xcr0_feature_mask_1 ()
    that are checked for when building an x32 target description.  */
 
 static constexpr uint64_t
-x86_linux_x32_xcr0_feature_mask_1 ()
+x86_linux_x32_xstate_bv_feature_mask_1 ()
 {
   uint64_t mask = 0;
 
@@ -117,25 +120,25 @@  x86_linux_x32_xcr0_feature_mask_1 ()
 /* See arch/x86-linux-tdesc-features.h.  */
 
 uint64_t
-x86_linux_i386_xcr0_feature_mask ()
+x86_linux_i386_xstate_bv_feature_mask ()
 {
-  return x86_linux_i386_xcr0_feature_mask_1 ();
+  return x86_linux_i386_xstate_bv_feature_mask_1 ();
 }
 
 /* See arch/x86-linux-tdesc-features.h.  */
 
 uint64_t
-x86_linux_amd64_xcr0_feature_mask ()
+x86_linux_amd64_xstate_bv_feature_mask ()
 {
-  return x86_linux_amd64_xcr0_feature_mask_1 ();
+  return x86_linux_amd64_xstate_bv_feature_mask_1 ();
 }
 
 /* See arch/x86-linux-tdesc-features.h.  */
 
 uint64_t
-x86_linux_x32_xcr0_feature_mask ()
+x86_linux_x32_xstate_bv_feature_mask ()
 {
-  return x86_linux_x32_xcr0_feature_mask_1 ();
+  return x86_linux_x32_xstate_bv_feature_mask_1 ();
 }
 
 #ifdef GDBSERVER
@@ -143,7 +146,7 @@  x86_linux_x32_xcr0_feature_mask ()
 /* See arch/x86-linux-tdesc-features.h.  */
 
 int
-x86_linux_xcr0_to_tdesc_idx (uint64_t xcr0)
+x86_linux_xstate_bv_mask_to_tdesc_idx (uint64_t xstate_bv_mask)
 {
   /* The following table shows which features are checked for when creating
      the target descriptions (see nat/x86-linux-tdesc.c), the feature order
@@ -160,7 +163,7 @@  x86_linux_xcr0_to_tdesc_idx (uint64_t xcr0)
 
   for (int i = 0; i < ARRAY_SIZE (x86_linux_all_xstate_features); ++i)
     {
-      if ((xcr0 & x86_linux_all_xstate_features[i].feature)
+      if ((xstate_bv_mask & x86_linux_all_xstate_features[i].feature)
 	  == x86_linux_all_xstate_features[i].feature)
 	idx |= (1 << i);
     }
@@ -250,17 +253,17 @@  x86_linux_i386_tdesc_count ()
 /* See arch/x86-linux-tdesc-features.h.  */
 
 uint64_t
-x86_linux_tdesc_idx_to_xcr0 (int idx)
+x86_linux_tdesc_idx_to_xstate_bv_mask (int idx)
 {
-  uint64_t xcr0 = 0;
+  uint64_t xstate_bv_mask = 0;
 
   for (int i = 0; i < ARRAY_SIZE (x86_linux_all_xstate_features); ++i)
     {
       if ((idx & (1 << i)) != 0)
-	xcr0 |= x86_linux_all_xstate_features[i].feature;
+	xstate_bv_mask |= x86_linux_all_xstate_features[i].feature;
     }
 
-  return xcr0;
+  return xstate_bv_mask;
 }
 
 #endif /* IN_PROCESS_AGENT */
diff --git a/gdb/arch/x86-linux-tdesc-features.h b/gdb/arch/x86-linux-tdesc-features.h
index cf8351dea8e..a9dfdbc3068 100644
--- a/gdb/arch/x86-linux-tdesc-features.h
+++ b/gdb/arch/x86-linux-tdesc-features.h
@@ -27,17 +27,20 @@ 
    the set of features which are checked for when creating the target
    description for each of amd64, x32, and i386.  */
 
-extern uint64_t x86_linux_amd64_xcr0_feature_mask ();
-extern uint64_t x86_linux_x32_xcr0_feature_mask ();
-extern uint64_t x86_linux_i386_xcr0_feature_mask ();
+extern uint64_t x86_linux_amd64_xstate_bv_feature_mask ();
+extern uint64_t x86_linux_x32_xstate_bv_feature_mask ();
+extern uint64_t x86_linux_i386_xstate_bv_feature_mask ();
 
 #ifdef GDBSERVER
 
-/* Convert an xcr0 value into an integer.  The integer will be passed from
+/* Convert an XSTATE_BV_MASK value into an integer.  XSTATE_BV_MASK has
+   the same format than the state component bitmap and does include user
+   and supervisor state components.  The integer will be passed from
    gdbserver to the in-process-agent where it will then be passed through
-   x86_linux_tdesc_idx_to_xcr0 to get back the original xcr0 value.  */
+   x86_linux_tdesc_idx_to_xstate_bv_mask to get back the original mask.  */
 
-extern int x86_linux_xcr0_to_tdesc_idx (uint64_t xcr0);
+
+extern int x86_linux_xstate_bv_mask_to_tdesc_idx (uint64_t xstate_bv_mask);
 
 #endif /* GDBSERVER */
 
@@ -51,11 +54,13 @@  extern int x86_linux_amd64_tdesc_count ();
 extern int x86_linux_x32_tdesc_count ();
 extern int x86_linux_i386_tdesc_count ();
 
-/* Convert an index number (as returned from x86_linux_xcr0_to_tdesc_idx)
-   into an xcr0 value which can then be used to create a target
-   description.  */
+/* Convert an index number (as returned from
+   x86_linux_xstate_bv_mask_to_tdesc_idx) into an xstate_bv_mask
+   value which can then be used to create a target description.
+   The return mask same format than the state component bitmap and does
+   include user and supervisor state components.*/
 
-extern uint64_t x86_linux_tdesc_idx_to_xcr0 (int idx);
+extern uint64_t x86_linux_tdesc_idx_to_xstate_bv_mask (int idx);
 
 #endif /* IN_PROCESS_AGENT */
 
diff --git a/gdb/i386-tdep.c b/gdb/i386-tdep.c
index a552a2bee8f..54aa1294917 100644
--- a/gdb/i386-tdep.c
+++ b/gdb/i386-tdep.c
@@ -8899,23 +8899,23 @@  i386_gdbarch_init (struct gdbarch_info info, struct gdbarch_list *arches)
 
 
 
-/* Return the target description for a specified XSAVE feature mask.  */
+/* See i386-tdep.h.  */
 
 const struct target_desc *
-i386_target_description (uint64_t xcr0, bool segments)
+i386_target_description (uint64_t xstate_bv_mask, bool segments)
 {
   static target_desc *i386_tdescs \
     [2/*SSE*/][2/*AVX*/][2/*AVX512*/][2/*PKRU*/][2/*segments*/] = {};
   target_desc **tdesc;
 
-  tdesc = &i386_tdescs[(xcr0 & X86_XSTATE_SSE) ? 1 : 0]
-    [(xcr0 & X86_XSTATE_AVX) ? 1 : 0]
-    [(xcr0 & X86_XSTATE_AVX512) ? 1 : 0]
-    [(xcr0 & X86_XSTATE_PKRU) ? 1 : 0]
+  tdesc = &i386_tdescs[(xstate_bv_mask & X86_XSTATE_SSE) ? 1 : 0]
+    [(xstate_bv_mask & X86_XSTATE_AVX) ? 1 : 0]
+    [(xstate_bv_mask & X86_XSTATE_AVX512) ? 1 : 0]
+    [(xstate_bv_mask & X86_XSTATE_PKRU) ? 1 : 0]
     [segments ? 1 : 0];
 
   if (*tdesc == NULL)
-    *tdesc = i386_create_target_description (xcr0, false, segments);
+    *tdesc = i386_create_target_description (xstate_bv_mask, false, segments);
 
   return *tdesc;
 }
diff --git a/gdb/i386-tdep.h b/gdb/i386-tdep.h
index 680eb027a04..3f990e71abf 100644
--- a/gdb/i386-tdep.h
+++ b/gdb/i386-tdep.h
@@ -450,8 +450,11 @@  extern int i386_svr4_reg_to_regnum (struct gdbarch *gdbarch, int reg);
 
 extern int i386_process_record (struct gdbarch *gdbarch,
 				struct regcache *regcache, CORE_ADDR addr);
-extern const struct target_desc *i386_target_description (uint64_t xcr0,
-							  bool segments);
+
+/* Return the target description for the specified xsave features as
+   defined in XSTATE_BV_MASK and SEGMENTS.  */
+extern const struct target_desc *i386_target_description
+  (uint64_t xstate_bv_mask, bool segments);
 
 /* Functions and variables exported from i386-bsd-tdep.c.  */
 
diff --git a/gdb/nat/x86-linux-tdesc.c b/gdb/nat/x86-linux-tdesc.c
index 1824f57c70f..c5eac277bfd 100644
--- a/gdb/nat/x86-linux-tdesc.c
+++ b/gdb/nat/x86-linux-tdesc.c
@@ -43,7 +43,7 @@ 
 /* See nat/x86-linux-tdesc.h.  */
 
 const target_desc *
-x86_linux_tdesc_for_tid (int tid, uint64_t *xcr0_storage,
+x86_linux_tdesc_for_tid (int tid, uint64_t *xstate_bv_storage,
 			 x86_xsave_layout *xsave_layout_storage)
 {
 #ifdef __x86_64__
@@ -96,30 +96,32 @@  x86_linux_tdesc_for_tid (int tid, uint64_t *xcr0_storage,
 	     these bits being set we generate a completely empty tdesc for
 	     i386 which will be rejected by GDB.  */
 	  have_ptrace_getregset = TRIBOOL_FALSE;
-	  *xcr0_storage = X86_XSTATE_SSE_MASK;
+	  *xstate_bv_storage = X86_XSTATE_SSE_MASK;
 	}
       else
 	{
 	  have_ptrace_getregset = TRIBOOL_TRUE;
 
 	  /* Get XCR0 from XSAVE extended state.  */
-	  *xcr0_storage = xstateregs[(I386_LINUX_XSAVE_XCR0_OFFSET
+	  uint64_t xcr0 = xstateregs[(I386_LINUX_XSAVE_XCR0_OFFSET
 				      / sizeof (uint64_t))];
 
 	  *xsave_layout_storage
-	    = x86_fetch_xsave_layout (*xcr0_storage, x86_xsave_length ());
+	    = x86_fetch_xsave_layout (xcr0, x86_xsave_length ());
+
+	  *xstate_bv_storage = xcr0;
 	}
     }
 
-  /* Use cached xcr0 value.  */
-  uint64_t xcr0_features_bits = *xcr0_storage & X86_XSTATE_ALL_MASK;
+  /* Use cached XSTATE_BV_STORAGE value.  */
+  uint64_t xstate_bv_features_bits = *xstate_bv_storage & X86_XSTATE_ALL_MASK;
 
 #ifdef __x86_64__
   if (is_64bit)
-    return amd64_linux_read_description (xcr0_features_bits, is_x32);
+    return amd64_linux_read_description (xstate_bv_features_bits, is_x32);
   else
 #endif
-    return i386_linux_read_description (xcr0_features_bits);
+    return i386_linux_read_description (xstate_bv_features_bits);
 }
 
 #endif /* !IN_PROCESS_AGENT */
diff --git a/gdb/nat/x86-linux-tdesc.h b/gdb/nat/x86-linux-tdesc.h
index 2a2d8697cbe..548f2f10b65 100644
--- a/gdb/nat/x86-linux-tdesc.h
+++ b/gdb/nat/x86-linux-tdesc.h
@@ -27,9 +27,9 @@  struct x86_xsave_layout;
 
 /* Return the target description for Linux thread TID.
 
-   The storage pointed to by XCR0_STORAGE and XSAVE_LAYOUT_STORAGE must
+   The storage pointed to by XSTATE_BV_STORAGE and XSAVE_LAYOUT_STORAGE must
    exist until the program (GDB or gdbserver) terminates, this storage is
-   used to cache the xcr0 and xsave layout values.  The values pointed to
+   used to cache the xstate_bv and xsave layout values.  The values pointed to
    by these arguments are only updated at most once, the first time this
    function is called if the have_ptrace_getregset global is set to
    TRIBOOL_UNKNOWN.
@@ -45,6 +45,7 @@  struct x86_xsave_layout;
    returned.  */
 
 extern const target_desc *x86_linux_tdesc_for_tid
-  (int tid, uint64_t *xcr0_storage, x86_xsave_layout *xsave_layout_storage);
+  (int tid, uint64_t *xstate_bv_storage,
+   x86_xsave_layout *xsave_layout_storage);
 
 #endif /* GDB_NAT_X86_LINUX_TDESC_H */
diff --git a/gdb/x86-linux-nat.c b/gdb/x86-linux-nat.c
index 2afa04f6288..d1fece717a7 100644
--- a/gdb/x86-linux-nat.c
+++ b/gdb/x86-linux-nat.c
@@ -97,15 +97,20 @@  const struct target_desc *
 x86_linux_nat_target::read_description ()
 {
   /* The x86_linux_tdesc_for_tid call only reads xcr0 the first time it is
-     called, the xcr0 value is stored here and reused on subsequent calls.  */
-  static uint64_t xcr0_storage;
+     called.  The mask is stored in XSTATE_BV_STORAGE and reused on
+     subsequent calls.  Note that GDB currently supports features for user
+     state components only.  However, once supervisor state components are
+     supported in GDB XSTATE_BV_STORAGE will not be configured based on
+     xcr0 only.  */
+  static uint64_t xstate_bv_storage;
 
   if (inferior_ptid == null_ptid)
     return this->beneath ()->read_description ();
 
   int tid = inferior_ptid.pid ();
 
-  return x86_linux_tdesc_for_tid (tid, &xcr0_storage, &this->m_xsave_layout);
+  return x86_linux_tdesc_for_tid (tid, &xstate_bv_storage,
+				  &this->m_xsave_layout);
 }
 
 
diff --git a/gdbserver/i387-fp.cc b/gdbserver/i387-fp.cc
index 0bf57a3aa5d..3e9e823827e 100644
--- a/gdbserver/i387-fp.cc
+++ b/gdbserver/i387-fp.cc
@@ -21,7 +21,7 @@ 
 #include "nat/x86-xstate.h"
 
 /* Default to SSE.  */
-static uint64_t x86_xcr0 = X86_XSTATE_SSE_MASK;
+static uint64_t x86_xstate_bv = X86_XSTATE_SSE_MASK;
 
 static const int num_avx512_k_registers = 8;
 static const int num_pkeys_registers = 1;
@@ -265,7 +265,7 @@  i387_cache_to_xsave (struct regcache *regcache, void *buf)
 
   /* The supported bits in `xstat_bv' are 8 bytes.  Clear part in
      vector registers if its bit in xstat_bv is zero.  */
-  clear_bv = (~fp->xstate_bv) & x86_xcr0;
+  clear_bv = (~fp->xstate_bv) & x86_xstate_bv;
 
   /* Clear part in x87 and vector registers if its bit in xstat_bv is
      zero.  */
@@ -315,7 +315,7 @@  i387_cache_to_xsave (struct regcache *regcache, void *buf)
     }
 
   /* Check if any x87 registers are changed.  */
-  if ((x86_xcr0 & X86_XSTATE_X87))
+  if ((x86_xstate_bv & X86_XSTATE_X87))
     {
       int st0_regnum = find_regno (regcache->tdesc, "st0");
 
@@ -332,7 +332,7 @@  i387_cache_to_xsave (struct regcache *regcache, void *buf)
     }
 
   /* Check if any SSE registers are changed.  */
-  if ((x86_xcr0 & X86_XSTATE_SSE))
+  if ((x86_xstate_bv & X86_XSTATE_SSE))
     {
       int xmm0_regnum = find_regno (regcache->tdesc, "xmm0");
 
@@ -349,7 +349,7 @@  i387_cache_to_xsave (struct regcache *regcache, void *buf)
     }
 
   /* Check if any AVX registers are changed.  */
-  if ((x86_xcr0 & X86_XSTATE_AVX))
+  if ((x86_xstate_bv & X86_XSTATE_AVX))
     {
       int ymm0h_regnum = find_regno (regcache->tdesc, "ymm0h");
 
@@ -366,7 +366,7 @@  i387_cache_to_xsave (struct regcache *regcache, void *buf)
     }
 
   /* Check if any K registers are changed.  */
-  if ((x86_xcr0 & X86_XSTATE_K))
+  if ((x86_xstate_bv & X86_XSTATE_K))
     {
       int k0_regnum = find_regno (regcache->tdesc, "k0");
 
@@ -383,7 +383,7 @@  i387_cache_to_xsave (struct regcache *regcache, void *buf)
     }
 
   /* Check if any of ZMM0H-ZMM15H registers are changed.  */
-  if ((x86_xcr0 & X86_XSTATE_ZMM_H))
+  if ((x86_xstate_bv & X86_XSTATE_ZMM_H))
     {
       int zmm0h_regnum = find_regno (regcache->tdesc, "zmm0h");
 
@@ -400,7 +400,7 @@  i387_cache_to_xsave (struct regcache *regcache, void *buf)
     }
 
   /* Check if any of ZMM16-ZMM31 registers are changed.  */
-  if ((x86_xcr0 & X86_XSTATE_ZMM) && num_zmm_high_registers != 0)
+  if ((x86_xstate_bv & X86_XSTATE_ZMM) && num_zmm_high_registers != 0)
     {
       int zmm16h_regnum = find_regno (regcache->tdesc, "zmm16h");
       int ymm16h_regnum = find_regno (regcache->tdesc, "ymm16h");
@@ -437,7 +437,7 @@  i387_cache_to_xsave (struct regcache *regcache, void *buf)
     }
 
   /* Check if any PKEYS registers are changed.  */
-  if ((x86_xcr0 & X86_XSTATE_PKRU))
+  if ((x86_xstate_bv & X86_XSTATE_PKRU))
     {
       int pkru_regnum = find_regno (regcache->tdesc, "pkru");
 
@@ -453,7 +453,7 @@  i387_cache_to_xsave (struct regcache *regcache, void *buf)
 	}
     }
 
-  if ((x86_xcr0 & X86_XSTATE_SSE) || (x86_xcr0 & X86_XSTATE_AVX))
+  if ((x86_xstate_bv & X86_XSTATE_SSE) || (x86_xstate_bv & X86_XSTATE_AVX))
     {
       collect_register_by_name (regcache, "mxcsr", raw);
       if (memcmp (raw, &fp->mxcsr, 4) != 0)
@@ -465,7 +465,7 @@  i387_cache_to_xsave (struct regcache *regcache, void *buf)
 	}
     }
 
-  if (x86_xcr0 & X86_XSTATE_X87)
+  if (x86_xstate_bv & X86_XSTATE_X87)
     {
       collect_register_by_name (regcache, "fioff", raw);
       if (memcmp (raw, &fp->fioff, 4) != 0)
@@ -658,10 +658,10 @@  i387_xsave_to_cache (struct regcache *regcache, const void *buf)
 
   /* The supported bits in `xstat_bv' are 8 bytes.  Clear part in
      vector registers if its bit in xstat_bv is zero.  */
-  clear_bv = (~fp->xstate_bv) & x86_xcr0;
+  clear_bv = (~fp->xstate_bv) & x86_xstate_bv;
 
   /* Check if any x87 registers are changed.  */
-  if ((x86_xcr0 & X86_XSTATE_X87) != 0)
+  if ((x86_xstate_bv & X86_XSTATE_X87) != 0)
     {
       int st0_regnum = find_regno (regcache->tdesc, "st0");
 
@@ -678,7 +678,7 @@  i387_xsave_to_cache (struct regcache *regcache, const void *buf)
 	}
     }
 
-  if ((x86_xcr0 & X86_XSTATE_SSE) != 0)
+  if ((x86_xstate_bv & X86_XSTATE_SSE) != 0)
     {
       int xmm0_regnum = find_regno (regcache->tdesc, "xmm0");
 
@@ -695,7 +695,7 @@  i387_xsave_to_cache (struct regcache *regcache, const void *buf)
 	}
     }
 
-  if ((x86_xcr0 & X86_XSTATE_AVX) != 0)
+  if ((x86_xstate_bv & X86_XSTATE_AVX) != 0)
     {
       int ymm0h_regnum = find_regno (regcache->tdesc, "ymm0h");
 
@@ -712,7 +712,7 @@  i387_xsave_to_cache (struct regcache *regcache, const void *buf)
 	}
     }
 
-  if ((x86_xcr0 & X86_XSTATE_K) != 0)
+  if ((x86_xstate_bv & X86_XSTATE_K) != 0)
     {
       int k0_regnum = find_regno (regcache->tdesc, "k0");
 
@@ -729,7 +729,7 @@  i387_xsave_to_cache (struct regcache *regcache, const void *buf)
 	}
     }
 
-  if ((x86_xcr0 & X86_XSTATE_ZMM_H) != 0)
+  if ((x86_xstate_bv & X86_XSTATE_ZMM_H) != 0)
     {
       int zmm0h_regnum = find_regno (regcache->tdesc, "zmm0h");
 
@@ -746,7 +746,7 @@  i387_xsave_to_cache (struct regcache *regcache, const void *buf)
 	}
     }
 
-  if ((x86_xcr0 & X86_XSTATE_ZMM) != 0 && num_zmm_high_registers != 0)
+  if ((x86_xstate_bv & X86_XSTATE_ZMM) != 0 && num_zmm_high_registers != 0)
     {
       int zmm16h_regnum = find_regno (regcache->tdesc, "zmm16h");
       int ymm16h_regnum = find_regno (regcache->tdesc, "ymm16h");
@@ -773,7 +773,7 @@  i387_xsave_to_cache (struct regcache *regcache, const void *buf)
 	}
     }
 
-  if ((x86_xcr0 & X86_XSTATE_PKRU) != 0)
+  if ((x86_xstate_bv & X86_XSTATE_PKRU) != 0)
     {
       int pkru_regnum = find_regno (regcache->tdesc, "pkru");
 
@@ -858,5 +858,5 @@  i387_xsave_to_cache (struct regcache *regcache, const void *buf)
 std::pair<uint64_t *, x86_xsave_layout *>
 i387_get_xsave_storage ()
 {
-  return { &x86_xcr0, &xsave_layout };
+  return { &x86_xstate_bv, &xsave_layout };
 }
diff --git a/gdbserver/linux-amd64-ipa.cc b/gdbserver/linux-amd64-ipa.cc
index c53758a7dbe..9450a2114e4 100644
--- a/gdbserver/linux-amd64-ipa.cc
+++ b/gdbserver/linux-amd64-ipa.cc
@@ -170,7 +170,7 @@  supply_static_tracepoint_registers (struct regcache *regcache,
 const struct target_desc *
 get_ipa_tdesc (int idx)
 {
-  uint64_t xcr0 = x86_linux_tdesc_idx_to_xcr0 (idx);
+  uint64_t xstate_bv_mask = x86_linux_tdesc_idx_to_xstate_bv_mask (idx);
 
 #if defined __ILP32__
   bool is_x32 = true;
@@ -178,7 +178,7 @@  get_ipa_tdesc (int idx)
   bool is_x32 = false;
 #endif
 
-  return amd64_linux_read_description (xcr0, is_x32);
+  return amd64_linux_read_description (xstate_bv_mask, is_x32);
 }
 
 /* Allocate buffer for the jump pads.  The branch instruction has a
@@ -247,9 +247,11 @@  initialize_low_tracepoint (void)
 {
 #if defined __ILP32__
   for (int i = 0; i < x86_linux_x32_tdesc_count (); i++)
-    amd64_linux_read_description (x86_linux_tdesc_idx_to_xcr0 (i), true);
+    amd64_linux_read_description
+      (x86_linux_tdesc_idx_to_xstate_bv_mask (i), true);
 #else
   for (int i = 0; i < x86_linux_amd64_tdesc_count (); i++)
-    amd64_linux_read_description (x86_linux_tdesc_idx_to_xcr0 (i), false);
+    amd64_linux_read_description
+      (x86_linux_tdesc_idx_to_xstate_bv_mask (i), false);
 #endif
 }
diff --git a/gdbserver/linux-i386-ipa.cc b/gdbserver/linux-i386-ipa.cc
index 2b363271ab6..ec06f16a2bf 100644
--- a/gdbserver/linux-i386-ipa.cc
+++ b/gdbserver/linux-i386-ipa.cc
@@ -251,9 +251,9 @@  initialize_fast_tracepoint_trampoline_buffer (void)
 const struct target_desc *
 get_ipa_tdesc (int idx)
 {
-  uint64_t xcr0 = x86_linux_tdesc_idx_to_xcr0 (idx);
+  uint64_t xstate_bv_mask = x86_linux_tdesc_idx_to_xstate_bv_mask  (idx);
 
-  return i386_linux_read_description (xcr0);
+  return i386_linux_read_description (xstate_bv_mask);
 }
 
 /* Allocate buffer for the jump pads.  On i386, we can reach an arbitrary
@@ -276,5 +276,5 @@  initialize_low_tracepoint (void)
 {
   initialize_fast_tracepoint_trampoline_buffer ();
   for (int i = 0; i < x86_linux_i386_tdesc_count (); i++)
-    i386_linux_read_description (x86_linux_tdesc_idx_to_xcr0 (i));
+    i386_linux_read_description (x86_linux_tdesc_idx_to_xstate_bv_mask (i));
 }
diff --git a/gdbserver/linux-x86-low.cc b/gdbserver/linux-x86-low.cc
index b023b34a0a4..4575ea2fdc0 100644
--- a/gdbserver/linux-x86-low.cc
+++ b/gdbserver/linux-x86-low.cc
@@ -873,7 +873,7 @@  x86_linux_read_description ()
   bool have_ptrace_getregset_was_unknown
     = have_ptrace_getregset == TRIBOOL_UNKNOWN;
 
-  /* Get pointers to where we should store the xcr0 and xsave_layout
+  /* Get pointers to where we should store the xstate_bv and xsave_layout
      values.  These will be filled in by x86_linux_tdesc_for_tid the first
      time that the function is called.  Subsequent calls will not modify
      the stored values.  */
@@ -2892,17 +2892,16 @@  x86_target::get_ipa_tdesc_idx ()
 		  || tdesc == tdesc_amd64_linux_no_xml.get ()
 #endif /* __x86_64__ */
 		  );
-      return x86_linux_xcr0_to_tdesc_idx (X86_XSTATE_SSE_MASK);
+      return x86_linux_xstate_bv_mask_to_tdesc_idx (X86_XSTATE_SSE_MASK);
     }
 
-  /* The xcr0 value and xsave layout value are cached when the target
+  /* The xstate_bv value and xsave layout value are cached when the target
      description is read.  Grab their cache location, and use the cached
      value to calculate a tdesc index.  */
   std::pair<uint64_t *, x86_xsave_layout *> storage
     = i387_get_xsave_storage ();
-  uint64_t xcr0 = *storage.first;
 
-  return x86_linux_xcr0_to_tdesc_idx (xcr0);
+  return x86_linux_xstate_bv_mask_to_tdesc_idx (*storage.first);
 }
 
 /* The linux target ops object.  */
diff --git a/gdbsupport/x86-xstate.h b/gdbsupport/x86-xstate.h
index 45300b2c18d..76932c765a7 100644
--- a/gdbsupport/x86-xstate.h
+++ b/gdbsupport/x86-xstate.h
@@ -83,8 +83,10 @@  constexpr bool operator!= (const x86_xsave_layout &lhs,
 #define X86_XSTATE_AVX_AVX512_PKU_MASK 	(X86_XSTATE_AVX_MASK\
 					| X86_XSTATE_AVX512 | X86_XSTATE_PKRU)
 
-#define X86_XSTATE_ALL_MASK		(X86_XSTATE_AVX_AVX512_PKU_MASK)
+/* Supported mask of state-component bitmap xstate_bv.  The SDM defines
+   xstate_bv as XCR0 | IA32_XSS.  */
 
+#define X86_XSTATE_ALL_MASK		(X86_XSTATE_AVX_AVX512_PKU_MASK)
 
 #define X86_XSTATE_SSE_SIZE	576
 #define X86_XSTATE_AVX_SIZE	832