Home | History | Annotate | Line # | Download | only in arch
      1 /* Target description related code for GNU/Linux x86 (i386 and x86-64).
      2 
      3    Copyright (C) 2024 Free Software Foundation, Inc.
      4 
      5    This file is part of GDB.
      6 
      7    This program is free software; you can redistribute it and/or modify
      8    it under the terms of the GNU General Public License as published by
      9    the Free Software Foundation; either version 3 of the License, or
     10    (at your option) any later version.
     11 
     12    This program is distributed in the hope that it will be useful,
     13    but WITHOUT ANY WARRANTY; without even the implied warranty of
     14    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
     15    GNU General Public License for more details.
     16 
     17    You should have received a copy of the GNU General Public License
     18    along with this program.  If not, see <http://www.gnu.org/licenses/>.  */
     19 
     20 #include "arch/x86-linux-tdesc-features.h"
     21 
     22 /* A structure used to describe a single xstate feature bit that might, or
     23    might not, be checked for when creating a target description for one of
     24    i386, amd64, or x32.
     25 
     26    The different CPU/ABI types check for different xstate features when
     27    creating a target description.
     28 
     29    We want to cache target descriptions, and this is currently done in
     30    three separate caches, one each for i386, amd64, and x32.  Additionally,
     31    the caching we're discussing here is Linux only, and for Linux, the only
     32    thing that has an impact on target description creation is the xcr0
     33    value.
     34 
     35    In order to ensure the cache functions correctly we need to filter out
     36    only those xcr0 feature bits that are relevant, we can then cache target
     37    descriptions based on the relevant feature bits.  Two xcr0 values might
     38    be different, but have the same relevant feature bits.  In this case we
     39    would expect the two xcr0 values to map to the same cache entry.  */
     40 
     41 struct x86_xstate_feature {
     42   /* The xstate feature mask.  This is a mask against an xcr0 value.  */
     43   uint64_t feature;
     44 
     45   /* Is this feature checked when creating an i386 target description.  */
     46   bool is_i386;
     47 
     48   /* Is this feature checked when creating an amd64 target description.  */
     49   bool is_amd64;
     50 
     51   /* Is this feature checked when creating an x32 target description.  */
     52   bool is_x32;
     53 };
     54 
     55 /* A constant table that describes all of the xstate features that are
     56    checked when building a target description for i386, amd64, or x32.
     57 
     58    If in the future, due to simplifications or refactoring, this table ever
     59    ends up with 'true' for every xcr0 feature on every target type, then this
     60    is an indication that this table should probably be removed, and that the
     61    rest of the code in this file can be simplified.  */
     62 
     63 static constexpr x86_xstate_feature x86_linux_all_xstate_features[] = {
     64   /* Feature,           i386,	amd64,	x32.  */
     65   { X86_XSTATE_PKRU,	true,	true, 	true },
     66   { X86_XSTATE_AVX512,	true,	true, 	true },
     67   { X86_XSTATE_AVX,	true,	true, 	true },
     68   { X86_XSTATE_SSE,	true,	false, 	false },
     69   { X86_XSTATE_X87,	true,	false, 	false }
     70 };
     71 
     72 /* Return a compile time constant which is a mask of all the xstate features
     73    that are checked for when building an i386 target description.  */
     74 
     75 static constexpr uint64_t
     76 x86_linux_i386_xcr0_feature_mask_1 ()
     77 {
     78   uint64_t mask = 0;
     79 
     80   for (const auto &entry : x86_linux_all_xstate_features)
     81     if (entry.is_i386)
     82       mask |= entry.feature;
     83 
     84   return mask;
     85 }
     86 
     87 /* Return a compile time constant which is a mask of all the xstate features
     88    that are checked for when building an amd64 target description.  */
     89 
     90 static constexpr uint64_t
     91 x86_linux_amd64_xcr0_feature_mask_1 ()
     92 {
     93   uint64_t mask = 0;
     94 
     95   for (const auto &entry : x86_linux_all_xstate_features)
     96     if (entry.is_amd64)
     97       mask |= entry.feature;
     98 
     99   return mask;
    100 }
    101 
    102 /* Return a compile time constant which is a mask of all the xstate features
    103    that are checked for when building an x32 target description.  */
    104 
    105 static constexpr uint64_t
    106 x86_linux_x32_xcr0_feature_mask_1 ()
    107 {
    108   uint64_t mask = 0;
    109 
    110   for (const auto &entry : x86_linux_all_xstate_features)
    111     if (entry.is_x32)
    112       mask |= entry.feature;
    113 
    114   return mask;
    115 }
    116 
    117 /* See arch/x86-linux-tdesc-features.h.  */
    118 
    119 uint64_t
    120 x86_linux_i386_xcr0_feature_mask ()
    121 {
    122   return x86_linux_i386_xcr0_feature_mask_1 ();
    123 }
    124 
    125 /* See arch/x86-linux-tdesc-features.h.  */
    126 
    127 uint64_t
    128 x86_linux_amd64_xcr0_feature_mask ()
    129 {
    130   return x86_linux_amd64_xcr0_feature_mask_1 ();
    131 }
    132 
    133 /* See arch/x86-linux-tdesc-features.h.  */
    134 
    135 uint64_t
    136 x86_linux_x32_xcr0_feature_mask ()
    137 {
    138   return x86_linux_x32_xcr0_feature_mask_1 ();
    139 }
    140 
    141 #ifdef GDBSERVER
    142 
    143 /* See arch/x86-linux-tdesc-features.h.  */
    144 
    145 int
    146 x86_linux_xcr0_to_tdesc_idx (uint64_t xcr0)
    147 {
    148   /* The following table shows which features are checked for when creating
    149      the target descriptions (see nat/x86-linux-tdesc.c), the feature order
    150      represents the bit order within the generated index number.
    151 
    152      i386  | x87 sse avx avx512 pkru
    153      amd64 |         avx avx512 pkru
    154      i32   |         avx avx512 pkru
    155 
    156      The features are ordered so that for each mode (i386, amd64, i32) the
    157      generated index will form a continuous range.  */
    158 
    159   int idx = 0;
    160 
    161   for (int i = 0; i < ARRAY_SIZE (x86_linux_all_xstate_features); ++i)
    162     {
    163       if ((xcr0 & x86_linux_all_xstate_features[i].feature)
    164 	  == x86_linux_all_xstate_features[i].feature)
    165 	idx |= (1 << i);
    166     }
    167 
    168   return idx;
    169 }
    170 
    171 #endif /* GDBSERVER */
    172 
    173 #ifdef IN_PROCESS_AGENT
    174 
    175 /* Return a compile time constant which is a count of the number of xstate
    176    features that are checked for when building an i386 target description.  */
    177 
    178 static constexpr int
    179 x86_linux_i386_tdesc_count_1 ()
    180 {
    181   uint64_t count = 0;
    182 
    183   for (const auto &entry : x86_linux_all_xstate_features)
    184     if (entry.is_i386)
    185       ++count;
    186 
    187   gdb_assert (count > 0);
    188 
    189   return (1 << count);
    190 }
    191 
    192 /* Return a compile time constant which is a count of the number of xstate
    193    features that are checked for when building an amd64 target description.  */
    194 
    195 static constexpr int
    196 x86_linux_amd64_tdesc_count_1 ()
    197 {
    198   uint64_t count = 0;
    199 
    200   for (const auto &entry : x86_linux_all_xstate_features)
    201     if (entry.is_amd64)
    202       ++count;
    203 
    204   gdb_assert (count > 0);
    205 
    206   return (1 << count);
    207 }
    208 
    209 /* Return a compile time constant which is a count of the number of xstate
    210    features that are checked for when building an x32 target description.  */
    211 
    212 static constexpr int
    213 x86_linux_x32_tdesc_count_1 ()
    214 {
    215   uint64_t count = 0;
    216 
    217   for (const auto &entry : x86_linux_all_xstate_features)
    218     if (entry.is_x32)
    219       ++count;
    220 
    221   gdb_assert (count > 0);
    222 
    223   return (1 << count);
    224 }
    225 
    226 /* See arch/x86-linux-tdesc-features.h.  */
    227 
    228 int
    229 x86_linux_amd64_tdesc_count ()
    230 {
    231   return x86_linux_amd64_tdesc_count_1 ();
    232 }
    233 
    234 /* See arch/x86-linux-tdesc-features.h.  */
    235 
    236 int
    237 x86_linux_x32_tdesc_count ()
    238 {
    239   return x86_linux_x32_tdesc_count_1 ();
    240 }
    241 
    242 /* See arch/x86-linux-tdesc-features.h.  */
    243 
    244 int
    245 x86_linux_i386_tdesc_count ()
    246 {
    247   return x86_linux_i386_tdesc_count_1 ();
    248 }
    249 
    250 /* See arch/x86-linux-tdesc-features.h.  */
    251 
    252 uint64_t
    253 x86_linux_tdesc_idx_to_xcr0 (int idx)
    254 {
    255   uint64_t xcr0 = 0;
    256 
    257   for (int i = 0; i < ARRAY_SIZE (x86_linux_all_xstate_features); ++i)
    258     {
    259       if ((idx & (1 << i)) != 0)
    260 	xcr0 |= x86_linux_all_xstate_features[i].feature;
    261     }
    262 
    263   return xcr0;
    264 }
    265 
    266 #endif /* IN_PROCESS_AGENT */
    267