gdb, gdbserver: Use xstate_bv for target description creation on x86.

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

The Intel Software Developer's Manual 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.

Reviewed-By: Thiago Jung Bauermann <thiago.bauermann@linaro.org>
Approved-By: Luis Machado <luis.machado@arm.com>
This commit is contained in:
Christina Schimpe
2024-12-03 08:32:10 -08:00
parent 92cc4fb226
commit 6ef3896cfe
22 changed files with 196 additions and 155 deletions

View File

@@ -3568,23 +3568,23 @@ amd64_x32_none_init_abi (gdbarch_info info, gdbarch *arch)
amd64_target_description (X86_XSTATE_SSE_MASK, true)); 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 * const struct target_desc *
amd64_target_description (uint64_t xcr0, bool segments) amd64_target_description (uint64_t xstate_bv, bool segments)
{ {
static target_desc *amd64_tdescs \ static target_desc *amd64_tdescs \
[2/*AVX*/][2/*AVX512*/][2/*PKRU*/][2/*segments*/] = {}; [2/*AVX*/][2/*AVX512*/][2/*PKRU*/][2/*segments*/] = {};
target_desc **tdesc; target_desc **tdesc;
tdesc = &amd64_tdescs[(xcr0 & X86_XSTATE_AVX) ? 1 : 0] tdesc = &amd64_tdescs[(xstate_bv & X86_XSTATE_AVX) ? 1 : 0]
[(xcr0 & X86_XSTATE_AVX512) ? 1 : 0] [(xstate_bv & X86_XSTATE_AVX512) ? 1 : 0]
[(xcr0 & X86_XSTATE_PKRU) ? 1 : 0] [(xstate_bv & X86_XSTATE_PKRU) ? 1 : 0]
[segments ? 1 : 0]; [segments ? 1 : 0];
if (*tdesc == NULL) if (*tdesc == NULL)
*tdesc = amd64_create_target_description (xcr0, false, false, *tdesc = amd64_create_target_description (xstate_bv, false,
segments); false, segments);
return *tdesc; return *tdesc;
} }

View File

@@ -108,8 +108,12 @@ extern void amd64_init_abi (struct gdbarch_info info,
extern void amd64_x32_init_abi (struct gdbarch_info info, extern void amd64_x32_init_abi (struct gdbarch_info info,
struct gdbarch *gdbarch, struct gdbarch *gdbarch,
const target_desc *default_tdesc); 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 and SEGMENTS. */
extern const struct target_desc *amd64_target_description
(uint64_t xstate_bv, bool segments);
/* Fill register REGNUM in REGCACHE with the appropriate /* Fill register REGNUM in REGCACHE with the appropriate
floating-point or SSE register value from *FXSAVE. If REGNUM is floating-point or SSE register value from *FXSAVE. If REGNUM is

View File

@@ -26,34 +26,35 @@
/* See arch/amd64-linux-tdesc.h. */ /* See arch/amd64-linux-tdesc.h. */
const struct target_desc * const struct target_desc *
amd64_linux_read_description (uint64_t xcr0, bool is_x32) amd64_linux_read_description (uint64_t xstate_bv, bool is_x32)
{ {
/* The type used for the amd64 and x32 target description caches. */ /* The type used for the amd64 and x32 target description caches. */
using tdesc_cache_type = std::unordered_map<uint64_t, const target_desc_up>; using tdesc_cache_type = std::unordered_map<uint64_t, const target_desc_up>;
/* Caches for the previously seen amd64 and x32 target descriptions, /* Caches for the previously seen amd64 and x32 target descriptions,
indexed by the xcr0 value that created the target description. These indexed by the xstate_bv value that created the target
need to be static within this function to ensure they are initialised description. These need to be static within this function to ensure
before first use. */ they are initialised before first use. */
static tdesc_cache_type amd64_tdesc_cache, x32_tdesc_cache; static tdesc_cache_type amd64_tdesc_cache, x32_tdesc_cache;
tdesc_cache_type &tdesc_cache = is_x32 ? x32_tdesc_cache : amd64_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 /* Only some bits are checked when creating a tdesc, but the
contains other feature bits that are not relevant for tdesc creation. xstate_bv value contains other feature bits that are not
When indexing into the TDESC_CACHE we need to use a consistent xcr0 relevant for tdesc creation.
value otherwise we might fail to find an existing tdesc which has the When indexing into the TDESC_CACHE we need to use a consistent
same set of relevant bits set. */ xstate_bv value otherwise we might fail to find an existing
xcr0 &= is_x32 tdesc which has the same set of relevant bits set. */
? x86_linux_x32_xcr0_feature_mask () xstate_bv &= is_x32
: x86_linux_amd64_xcr0_feature_mask (); ? 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);
if (it != tdesc_cache.end ()) if (it != tdesc_cache.end ())
return it->second.get (); return it->second.get ();
/* Create the previously unseen target description. */ /* Create the previously unseen target description. */
target_desc_up tdesc (amd64_create_target_description (xcr0, is_x32, target_desc_up tdesc (amd64_create_target_description (xstate_bv, is_x32,
true, true)); true, true));
x86_linux_post_init_tdesc (tdesc.get (), true); x86_linux_post_init_tdesc (tdesc.get (), true);
@@ -61,6 +62,6 @@ amd64_linux_read_description (uint64_t xcr0, bool is_x32)
target_desc_up. This is safe as the cache (and the pointers contained target_desc_up. This is safe as the cache (and the pointers contained
within it) are not deleted until GDB exits. */ within it) are not deleted until GDB exits. */
target_desc *ptr = tdesc.get (); target_desc *ptr = tdesc.get ();
tdesc_cache.emplace (xcr0, std::move (tdesc)); tdesc_cache.emplace (xstate_bv, std::move (tdesc));
return ptr; return ptr;
} }

View File

@@ -22,9 +22,10 @@
struct target_desc; struct target_desc;
/* Return the AMD64 target descriptions corresponding to XCR0 and IS_X32. */ /* Return the AMD64 target descriptions corresponding to XSTATE_BV and
IS_X32. */
extern const target_desc *amd64_linux_read_description (uint64_t xcr0, extern const target_desc *amd64_linux_read_description
bool is_x32); (uint64_t xstate_bv, bool is_x32);
#endif /* GDB_ARCH_AMD64_LINUX_TDESC_H */ #endif /* GDB_ARCH_AMD64_LINUX_TDESC_H */

View File

@@ -30,14 +30,11 @@
#include "../features/i386/x32-core.c" #include "../features/i386/x32-core.c"
/* Create amd64 target descriptions according to XCR0. If IS_X32 is /* See arch/amd64.h. */
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 * target_desc *
amd64_create_target_description (uint64_t xcr0, bool is_x32, bool is_linux, amd64_create_target_description (uint64_t xstate_bv, bool is_x32,
bool segments) bool is_linux, bool segments)
{ {
target_desc_up tdesc = allocate_target_description (); 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) if (segments)
regnum = create_feature_i386_64bit_segments (tdesc.get (), regnum); regnum = create_feature_i386_64bit_segments (tdesc.get (), regnum);
if (xcr0 & X86_XSTATE_AVX) if (xstate_bv & X86_XSTATE_AVX)
regnum = create_feature_i386_64bit_avx (tdesc.get (), regnum); regnum = create_feature_i386_64bit_avx (tdesc.get (), regnum);
if (xcr0 & X86_XSTATE_AVX512) if (xstate_bv & X86_XSTATE_AVX512)
regnum = create_feature_i386_64bit_avx512 (tdesc.get (), regnum); regnum = create_feature_i386_64bit_avx512 (tdesc.get (), regnum);
if (xcr0 & X86_XSTATE_PKRU) if (xstate_bv & X86_XSTATE_PKRU)
regnum = create_feature_i386_pkeys (tdesc.get (), regnum); regnum = create_feature_i386_pkeys (tdesc.get (), regnum);
return tdesc.release (); return tdesc.release ();

View File

@@ -21,7 +21,13 @@
#include "gdbsupport/tdesc.h" #include "gdbsupport/tdesc.h"
#include <stdint.h> #include <stdint.h>
target_desc *amd64_create_target_description (uint64_t xcr0, bool is_x32, /* Create amd64 target descriptions according to XSTATE_BV. If
bool is_linux, bool segments); 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,
bool is_x32, bool is_linux,
bool segments);
#endif /* GDB_ARCH_AMD64_H */ #endif /* GDB_ARCH_AMD64_H */

View File

@@ -25,32 +25,35 @@
/* See arch/i386-linux-tdesc.h. */ /* See arch/i386-linux-tdesc.h. */
const target_desc * const target_desc *
i386_linux_read_description (uint64_t xcr0) i386_linux_read_description (uint64_t xstate_bv)
{ {
/* Cache of previously seen i386 target descriptions, indexed by the xcr0 /* Cache of previously seen i386 target descriptions, indexed by the
value that created the target description. This needs to be static xstate_bv value that created the target description. This
within this function to ensure it is initialised before first use. */ 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; 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 /* Only some bits are checked when creating a tdesc, but the
contains other feature bits that are not relevant for tdesc creation. XSTATE_BV value contains other feature bits that are not relevant
When indexing into the I386_TDESC_CACHE we need to use a consistent for tdesc creation. When indexing into the I386_TDESC_CACHE
xcr0 value otherwise we might fail to find an existing tdesc which has we need to use a consistent XSTATE_BV value otherwise we might fail
the same set of relevant bits set. */ to find an existing tdesc which has the same set of relevant bits
xcr0 &= x86_linux_i386_xcr0_feature_mask (); set. */
xstate_bv &= x86_linux_i386_xstate_bv_feature_mask ();
const auto it = i386_tdesc_cache.find (xcr0); const auto it = i386_tdesc_cache.find (xstate_bv);
if (it != i386_tdesc_cache.end ()) if (it != i386_tdesc_cache.end ())
return it->second.get (); return it->second.get ();
/* Create the previously unseen target description. */ /* 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, true, false));
x86_linux_post_init_tdesc (tdesc.get (), false); x86_linux_post_init_tdesc (tdesc.get (), false);
/* Add to the cache, and return a pointer borrowed from the /* Add to the cache, and return a pointer borrowed from the
target_desc_up. This is safe as the cache (and the pointers contained target_desc_up. This is safe as the cache (and the pointers contained
within it) are not deleted until GDB exits. */ within it) are not deleted until GDB exits. */
target_desc *ptr = tdesc.get (); target_desc *ptr = tdesc.get ();
i386_tdesc_cache.emplace (xcr0, std::move (tdesc)); i386_tdesc_cache.emplace (xstate_bv, std::move (tdesc));
return ptr; return ptr;
} }

View File

@@ -22,8 +22,9 @@
struct target_desc; struct target_desc;
/* Return the i386 target description corresponding to XCR0. */ /* Return the i386 target description corresponding to XSTATE_BV. */
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);
#endif /* GDB_ARCH_I386_LINUX_TDESC_H */ #endif /* GDB_ARCH_I386_LINUX_TDESC_H */

View File

@@ -29,10 +29,11 @@
#include "../features/i386/32bit-segments.c" #include "../features/i386/32bit-segments.c"
#include "../features/i386/pkeys.c" #include "../features/i386/pkeys.c"
/* Create i386 target descriptions according to XCR0. */ /* See arch/i386.h. */
target_desc * target_desc *
i386_create_target_description (uint64_t xcr0, bool is_linux, bool segments) i386_create_target_description (uint64_t xstate_bv, bool is_linux,
bool segments)
{ {
target_desc_up tdesc = allocate_target_description (); 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; long regnum = 0;
if (xcr0 & X86_XSTATE_X87) if (xstate_bv & X86_XSTATE_X87)
regnum = create_feature_i386_32bit_core (tdesc.get (), regnum); regnum = create_feature_i386_32bit_core (tdesc.get (), regnum);
if (xcr0 & X86_XSTATE_SSE) if (xstate_bv & X86_XSTATE_SSE)
regnum = create_feature_i386_32bit_sse (tdesc.get (), regnum); regnum = create_feature_i386_32bit_sse (tdesc.get (), regnum);
if (is_linux) if (is_linux)
@@ -56,13 +57,13 @@ i386_create_target_description (uint64_t xcr0, bool is_linux, bool segments)
if (segments) if (segments)
regnum = create_feature_i386_32bit_segments (tdesc.get (), regnum); regnum = create_feature_i386_32bit_segments (tdesc.get (), regnum);
if (xcr0 & X86_XSTATE_AVX) if (xstate_bv & X86_XSTATE_AVX)
regnum = create_feature_i386_32bit_avx (tdesc.get (), regnum); regnum = create_feature_i386_32bit_avx (tdesc.get (), regnum);
if (xcr0 & X86_XSTATE_AVX512) if (xstate_bv & X86_XSTATE_AVX512)
regnum = create_feature_i386_32bit_avx512 (tdesc.get (), regnum); regnum = create_feature_i386_32bit_avx512 (tdesc.get (), regnum);
if (xcr0 & X86_XSTATE_PKRU) if (xstate_bv & X86_XSTATE_PKRU)
regnum = create_feature_i386_pkeys (tdesc.get (), regnum); regnum = create_feature_i386_pkeys (tdesc.get (), regnum);
return tdesc.release (); return tdesc.release ();

View File

@@ -21,7 +21,12 @@
#include "gdbsupport/tdesc.h" #include "gdbsupport/tdesc.h"
#include <stdint.h> #include <stdint.h>
target_desc *i386_create_target_description (uint64_t xcr0, bool is_linux, /* Create i386 target descriptions according to XSTATE_BV. 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,
bool is_linux,
bool segments); bool segments);
#endif /* GDB_ARCH_I386_H */ #endif /* GDB_ARCH_I386_H */

View File

@@ -28,18 +28,21 @@
We want to cache target descriptions, and this is currently done in We want to cache target descriptions, and this is currently done in
three separate caches, one each for i386, amd64, and x32. Additionally, 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 the caching we're discussing here is Linux only. Currently for Linux,
thing that has an impact on target description creation is the xcr0 the only thing that has an impact on target description creation are
value. the supported features in xsave which are modelled by a xstate_bv
value, which has the same format than the state component bitmap.
In order to ensure the cache functions correctly we need to filter out In order to ensure the cache functions correctly we need to filter only
only those xcr0 feature bits that are relevant, we can then cache target those xstate_bv feature bits that are relevant, we can then cache
descriptions based on the relevant feature bits. Two xcr0 values might target descriptions based on the relevant feature bits. Two xstate_bv
be different, but have the same relevant feature bits. In this case we values might be different, but have the same relevant feature bits. In
would expect the two xcr0 values to map to the same cache entry. */ this case we would expect the two xstate_bv values to map to the same
cache entry. */
struct x86_xstate_feature { 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; uint64_t feature;
/* Is this feature checked when creating an i386 target description. */ /* 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. checked when building a target description for i386, amd64, or x32.
If in the future, due to simplifications or refactoring, this table ever 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 ends up with 'true' for every xsave feature on every target type, then
is an indication that this table should probably be removed, and that the this is an indication that this table should probably be removed, and
rest of the code in this file can be simplified. */ that the rest of the code in this file can be simplified. */
static constexpr x86_xstate_feature x86_linux_all_xstate_features[] = { static constexpr x86_xstate_feature x86_linux_all_xstate_features[] = {
/* Feature, i386, amd64, x32. */ /* 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. */ that are checked for when building an i386 target description. */
static constexpr uint64_t static constexpr uint64_t
x86_linux_i386_xcr0_feature_mask_1 () x86_linux_i386_xstate_bv_feature_mask_1 ()
{ {
uint64_t mask = 0; 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. */ that are checked for when building an amd64 target description. */
static constexpr uint64_t static constexpr uint64_t
x86_linux_amd64_xcr0_feature_mask_1 () x86_linux_amd64_xstate_bv_feature_mask_1 ()
{ {
uint64_t mask = 0; 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. */ that are checked for when building an x32 target description. */
static constexpr uint64_t static constexpr uint64_t
x86_linux_x32_xcr0_feature_mask_1 () x86_linux_x32_xstate_bv_feature_mask_1 ()
{ {
uint64_t mask = 0; uint64_t mask = 0;
@@ -117,25 +120,25 @@ x86_linux_x32_xcr0_feature_mask_1 ()
/* See arch/x86-linux-tdesc-features.h. */ /* See arch/x86-linux-tdesc-features.h. */
uint64_t 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. */ /* See arch/x86-linux-tdesc-features.h. */
uint64_t 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. */ /* See arch/x86-linux-tdesc-features.h. */
uint64_t 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 #ifdef GDBSERVER
@@ -143,7 +146,7 @@ x86_linux_x32_xcr0_feature_mask ()
/* See arch/x86-linux-tdesc-features.h. */ /* See arch/x86-linux-tdesc-features.h. */
int int
x86_linux_xcr0_to_tdesc_idx (uint64_t xcr0) x86_linux_xstate_bv_to_tdesc_idx (uint64_t xstate_bv)
{ {
/* The following table shows which features are checked for when creating /* The following table shows which features are checked for when creating
the target descriptions (see nat/x86-linux-tdesc.c), the feature order 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) 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 & x86_linux_all_xstate_features[i].feature)
== x86_linux_all_xstate_features[i].feature) == x86_linux_all_xstate_features[i].feature)
idx |= (1 << i); idx |= (1 << i);
} }
@@ -250,17 +253,17 @@ x86_linux_i386_tdesc_count ()
/* See arch/x86-linux-tdesc-features.h. */ /* See arch/x86-linux-tdesc-features.h. */
uint64_t uint64_t
x86_linux_tdesc_idx_to_xcr0 (int idx) x86_linux_tdesc_idx_to_xstate_bv (int idx)
{ {
uint64_t xcr0 = 0; uint64_t xstate_bv = 0;
for (int i = 0; i < ARRAY_SIZE (x86_linux_all_xstate_features); ++i) for (int i = 0; i < ARRAY_SIZE (x86_linux_all_xstate_features); ++i)
{ {
if ((idx & (1 << i)) != 0) if ((idx & (1 << i)) != 0)
xcr0 |= x86_linux_all_xstate_features[i].feature; xstate_bv |= x86_linux_all_xstate_features[i].feature;
} }
return xcr0; return xstate_bv;
} }
#endif /* IN_PROCESS_AGENT */ #endif /* IN_PROCESS_AGENT */

View File

@@ -27,17 +27,20 @@
the set of features which are checked for when creating the target the set of features which are checked for when creating the target
description for each of amd64, x32, and i386. */ description for each of amd64, x32, and i386. */
extern uint64_t x86_linux_amd64_xcr0_feature_mask (); extern uint64_t x86_linux_amd64_xstate_bv_feature_mask ();
extern uint64_t x86_linux_x32_xcr0_feature_mask (); extern uint64_t x86_linux_x32_xstate_bv_feature_mask ();
extern uint64_t x86_linux_i386_xcr0_feature_mask (); extern uint64_t x86_linux_i386_xstate_bv_feature_mask ();
#ifdef GDBSERVER #ifdef GDBSERVER
/* Convert an xcr0 value into an integer. The integer will be passed from /* Convert an XSTATE_BV value into an integer. XSTATE_BV has the same
gdbserver to the in-process-agent where it will then be passed through format than the state component bitmap and does include user and
x86_linux_tdesc_idx_to_xcr0 to get back the original xcr0 value. */ 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_xstate_bv to get back the original value. */
extern int x86_linux_xcr0_to_tdesc_idx (uint64_t xcr0);
extern int x86_linux_xstate_bv_to_tdesc_idx (uint64_t xstate_bv);
#endif /* GDBSERVER */ #endif /* GDBSERVER */
@@ -51,11 +54,13 @@ extern int x86_linux_amd64_tdesc_count ();
extern int x86_linux_x32_tdesc_count (); extern int x86_linux_x32_tdesc_count ();
extern int x86_linux_i386_tdesc_count (); extern int x86_linux_i386_tdesc_count ();
/* Convert an index number (as returned from x86_linux_xcr0_to_tdesc_idx) /* Convert an index number (as returned from
into an xcr0 value which can then be used to create a target x86_linux_xstate_bv_to_tdesc_idx) into an xstate_bv value which can
description. */ then be used to create a target description.
The return mask has the 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 (int idx);
#endif /* IN_PROCESS_AGENT */ #endif /* IN_PROCESS_AGENT */

View File

@@ -9097,23 +9097,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 * const struct target_desc *
i386_target_description (uint64_t xcr0, bool segments) i386_target_description (uint64_t xstate_bv, bool segments)
{ {
static target_desc *i386_tdescs \ static target_desc *i386_tdescs \
[2/*SSE*/][2/*AVX*/][2/*AVX512*/][2/*PKRU*/][2/*segments*/] = {}; [2/*SSE*/][2/*AVX*/][2/*AVX512*/][2/*PKRU*/][2/*segments*/] = {};
target_desc **tdesc; target_desc **tdesc;
tdesc = &i386_tdescs[(xcr0 & X86_XSTATE_SSE) ? 1 : 0] tdesc = &i386_tdescs[(xstate_bv & X86_XSTATE_SSE) ? 1 : 0]
[(xcr0 & X86_XSTATE_AVX) ? 1 : 0] [(xstate_bv & X86_XSTATE_AVX) ? 1 : 0]
[(xcr0 & X86_XSTATE_AVX512) ? 1 : 0] [(xstate_bv & X86_XSTATE_AVX512) ? 1 : 0]
[(xcr0 & X86_XSTATE_PKRU) ? 1 : 0] [(xstate_bv & X86_XSTATE_PKRU) ? 1 : 0]
[segments ? 1 : 0]; [segments ? 1 : 0];
if (*tdesc == NULL) if (*tdesc == NULL)
*tdesc = i386_create_target_description (xcr0, false, segments); *tdesc = i386_create_target_description (xstate_bv, false, segments);
return *tdesc; return *tdesc;
} }

View File

@@ -454,8 +454,11 @@ extern int i386_svr4_reg_to_regnum (struct gdbarch *gdbarch, int reg);
extern int i386_process_record (struct gdbarch *gdbarch, extern int i386_process_record (struct gdbarch *gdbarch,
struct regcache *regcache, CORE_ADDR addr); 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 and SEGMENTS. */
extern const struct target_desc *i386_target_description
(uint64_t xstate_bv, bool segments);
/* Functions and variables exported from i386-bsd-tdep.c. */ /* Functions and variables exported from i386-bsd-tdep.c. */

View File

@@ -43,7 +43,7 @@
/* See nat/x86-linux-tdesc.h. */ /* See nat/x86-linux-tdesc.h. */
const target_desc * 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) x86_xsave_layout *xsave_layout_storage)
{ {
#ifdef __x86_64__ #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 these bits being set we generate a completely empty tdesc for
i386 which will be rejected by GDB. */ i386 which will be rejected by GDB. */
have_ptrace_getregset = TRIBOOL_FALSE; have_ptrace_getregset = TRIBOOL_FALSE;
*xcr0_storage = X86_XSTATE_SSE_MASK; *xstate_bv_storage = X86_XSTATE_SSE_MASK;
} }
else else
{ {
have_ptrace_getregset = TRIBOOL_TRUE; have_ptrace_getregset = TRIBOOL_TRUE;
/* Get XCR0 from XSAVE extended state. */ /* 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))]; / sizeof (uint64_t))];
*xsave_layout_storage *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. */ /* Use cached XSTATE_BV_STORAGE value. */
uint64_t xcr0_features_bits = *xcr0_storage & X86_XSTATE_ALL_MASK; uint64_t xstate_bv_features_bits = *xstate_bv_storage & X86_XSTATE_ALL_MASK;
#ifdef __x86_64__ #ifdef __x86_64__
if (is_64bit) 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 else
#endif #endif
return i386_linux_read_description (xcr0_features_bits); return i386_linux_read_description (xstate_bv_features_bits);
} }
#endif /* !IN_PROCESS_AGENT */ #endif /* !IN_PROCESS_AGENT */

View File

@@ -27,9 +27,9 @@ struct x86_xsave_layout;
/* Return the target description for Linux thread TID. /* 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 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 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 function is called if the have_ptrace_getregset global is set to
TRIBOOL_UNKNOWN. TRIBOOL_UNKNOWN.
@@ -45,6 +45,7 @@ struct x86_xsave_layout;
returned. */ returned. */
extern const target_desc *x86_linux_tdesc_for_tid 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 */ #endif /* GDB_NAT_X86_LINUX_TDESC_H */

View File

@@ -97,15 +97,20 @@ const struct target_desc *
x86_linux_nat_target::read_description () x86_linux_nat_target::read_description ()
{ {
/* The x86_linux_tdesc_for_tid call only reads xcr0 the first time it is /* 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. */ called. The mask is stored in XSTATE_BV_STORAGE and reused on
static uint64_t xcr0_storage; subsequent calls. Note that GDB currently supports features for user
state components only. However, once supervisor state components are
supported in GDB, the value XSTATE_BV_STORAGE will not be configured
based on xcr0 only. */
static uint64_t xstate_bv_storage;
if (inferior_ptid == null_ptid) if (inferior_ptid == null_ptid)
return this->beneath ()->read_description (); return this->beneath ()->read_description ();
int tid = inferior_ptid.pid (); 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);
} }

View File

@@ -21,7 +21,7 @@
#include "nat/x86-xstate.h" #include "nat/x86-xstate.h"
/* Default to SSE. */ /* 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_avx512_k_registers = 8;
static const int num_pkeys_registers = 1; 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 /* The supported bits in `xstat_bv' are 8 bytes. Clear part in
vector registers if its bit in xstat_bv is zero. */ 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 /* Clear part in x87 and vector registers if its bit in xstat_bv is
zero. */ zero. */
@@ -315,7 +315,7 @@ i387_cache_to_xsave (struct regcache *regcache, void *buf)
} }
/* Check if any x87 registers are changed. */ /* 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"); 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. */ /* 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"); 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. */ /* 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"); 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. */ /* 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"); 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. */ /* 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"); 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. */ /* 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 zmm16h_regnum = find_regno (regcache->tdesc, "zmm16h");
int ymm16h_regnum = find_regno (regcache->tdesc, "ymm16h"); 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. */ /* 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"); 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); collect_register_by_name (regcache, "mxcsr", raw);
if (memcmp (raw, &fp->mxcsr, 4) != 0) 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); collect_register_by_name (regcache, "fioff", raw);
if (memcmp (raw, &fp->fioff, 4) != 0) 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 /* The supported bits in `xstat_bv' are 8 bytes. Clear part in
vector registers if its bit in xstat_bv is zero. */ 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. */ /* 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"); 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"); 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"); 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"); 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"); 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 zmm16h_regnum = find_regno (regcache->tdesc, "zmm16h");
int ymm16h_regnum = find_regno (regcache->tdesc, "ymm16h"); 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"); 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 *> std::pair<uint64_t *, x86_xsave_layout *>
i387_get_xsave_storage () i387_get_xsave_storage ()
{ {
return { &x86_xcr0, &xsave_layout }; return { &x86_xstate_bv, &xsave_layout };
} }

View File

@@ -82,7 +82,7 @@ get_raw_reg (const unsigned char *raw_regs, int regnum)
const struct target_desc * const struct target_desc *
get_ipa_tdesc (int idx) get_ipa_tdesc (int idx)
{ {
uint64_t xcr0 = x86_linux_tdesc_idx_to_xcr0 (idx); uint64_t xstate_bv = x86_linux_tdesc_idx_to_xstate_bv (idx);
#if defined __ILP32__ #if defined __ILP32__
bool is_x32 = true; bool is_x32 = true;
@@ -90,7 +90,7 @@ get_ipa_tdesc (int idx)
bool is_x32 = false; bool is_x32 = false;
#endif #endif
return amd64_linux_read_description (xcr0, is_x32); return amd64_linux_read_description (xstate_bv, is_x32);
} }
/* Allocate buffer for the jump pads. The branch instruction has a /* Allocate buffer for the jump pads. The branch instruction has a
@@ -159,9 +159,11 @@ initialize_low_tracepoint (void)
{ {
#if defined __ILP32__ #if defined __ILP32__
for (int i = 0; i < x86_linux_x32_tdesc_count (); i++) 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 (i), true);
#else #else
for (int i = 0; i < x86_linux_amd64_tdesc_count (); i++) 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 (i), false);
#endif #endif
} }

View File

@@ -174,9 +174,9 @@ initialize_fast_tracepoint_trampoline_buffer (void)
const struct target_desc * const struct target_desc *
get_ipa_tdesc (int idx) get_ipa_tdesc (int idx)
{ {
uint64_t xcr0 = x86_linux_tdesc_idx_to_xcr0 (idx); uint64_t xstate_bv = x86_linux_tdesc_idx_to_xstate_bv (idx);
return i386_linux_read_description (xcr0); return i386_linux_read_description (xstate_bv);
} }
/* Allocate buffer for the jump pads. On i386, we can reach an arbitrary /* Allocate buffer for the jump pads. On i386, we can reach an arbitrary
@@ -199,5 +199,5 @@ initialize_low_tracepoint (void)
{ {
initialize_fast_tracepoint_trampoline_buffer (); initialize_fast_tracepoint_trampoline_buffer ();
for (int i = 0; i < x86_linux_i386_tdesc_count (); i++) 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 (i));
} }

View File

@@ -873,7 +873,7 @@ x86_linux_read_description ()
bool have_ptrace_getregset_was_unknown bool have_ptrace_getregset_was_unknown
= have_ptrace_getregset == TRIBOOL_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 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 time that the function is called. Subsequent calls will not modify
the stored values. */ the stored values. */
@@ -2892,17 +2892,16 @@ x86_target::get_ipa_tdesc_idx ()
|| tdesc == tdesc_amd64_linux_no_xml.get () || tdesc == tdesc_amd64_linux_no_xml.get ()
#endif /* __x86_64__ */ #endif /* __x86_64__ */
); );
return x86_linux_xcr0_to_tdesc_idx (X86_XSTATE_SSE_MASK); return x86_linux_xstate_bv_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 description is read. Grab their cache location, and use the cached
value to calculate a tdesc index. */ value to calculate a tdesc index. */
std::pair<uint64_t *, x86_xsave_layout *> storage std::pair<uint64_t *, x86_xsave_layout *> storage
= i387_get_xsave_storage (); = i387_get_xsave_storage ();
uint64_t xcr0 = *storage.first;
return x86_linux_xcr0_to_tdesc_idx (xcr0); return x86_linux_xstate_bv_to_tdesc_idx (*storage.first);
} }
/* The linux target ops object. */ /* The linux target ops object. */

View File

@@ -83,8 +83,10 @@ constexpr bool operator!= (const x86_xsave_layout &lhs,
#define X86_XSTATE_AVX_AVX512_PKU_MASK (X86_XSTATE_AVX_MASK\ #define X86_XSTATE_AVX_AVX512_PKU_MASK (X86_XSTATE_AVX_MASK\
| X86_XSTATE_AVX512 | X86_XSTATE_PKRU) | 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_SSE_SIZE 576
#define X86_XSTATE_AVX_SIZE 832 #define X86_XSTATE_AVX_SIZE 832