1
0
mirror of https://sourceware.org/git/glibc.git synced 2025-07-30 22:43:12 +03:00

x86: Support usable check for all CPU features

Support usable check for all CPU features with the following changes:

1. Change struct cpu_features to

struct cpuid_features
{
  struct cpuid_registers cpuid;
  struct cpuid_registers usable;
};

struct cpu_features
{
  struct cpu_features_basic basic;
  struct cpuid_features features[COMMON_CPUID_INDEX_MAX];
  unsigned int preferred[PREFERRED_FEATURE_INDEX_MAX];
...
};

so that there is a usable bit for each cpuid bit.
2. After the cpuid bits have been initialized, copy the known bits to the
usable bits.  EAX/EBX from INDEX_1 and EAX from INDEX_7 aren't used for
CPU feature detection.
3. Clear the usable bits which require OS support.
4. If the feature is supported by OS, copy its cpuid bit to its usable
bit.
5. Replace HAS_CPU_FEATURE and CPU_FEATURES_CPU_P with CPU_FEATURE_USABLE
and CPU_FEATURE_USABLE_P to check if a feature is usable.
6. Add DEPR_FPU_CS_DS for INDEX_7_EBX_13.
7. Unset MPX feature since it has been deprecated.

The results are

1. If the feature is known and doesn't requre OS support, its usable bit
is copied from the cpuid bit.
2. Otherwise, its usable bit is copied from the cpuid bit only if the
feature is known to supported by OS.
3. CPU_FEATURE_USABLE/CPU_FEATURE_USABLE_P are used to check if the
feature can be used.
4. HAS_CPU_FEATURE/CPU_FEATURE_CPU_P are used to check if CPU supports
the feature.
This commit is contained in:
H.J. Lu
2020-06-29 16:36:08 -07:00
parent 10b01bd452
commit 107e6a3c22
63 changed files with 849 additions and 727 deletions

View File

@ -43,66 +43,45 @@ extern __typeof (memcmp) DEFAULT_MEMCMP;
_Static_assert (sizeof (#name) - 1 == len, #name " != " #len); \
if (!DEFAULT_MEMCMP (f, #name, len)) \
{ \
cpu_features->cpuid[index_cpu_##name].reg_##name \
&= ~bit_cpu_##name; \
CPU_FEATURE_UNSET (cpu_features, name) \
break; \
}
/* Disable an ARCH feature NAME. We don't enable an ARCH feature which
isn't available. */
# define CHECK_GLIBC_IFUNC_ARCH_OFF(f, cpu_features, name, len) \
/* Disable a preferred feature NAME. We don't enable a preferred feature
which isn't available. */
# define CHECK_GLIBC_IFUNC_PREFERRED_OFF(f, cpu_features, name, len) \
_Static_assert (sizeof (#name) - 1 == len, #name " != " #len); \
if (!DEFAULT_MEMCMP (f, #name, len)) \
{ \
cpu_features->feature_##name[index_arch_##name] \
cpu_features->preferred[index_arch_##name] \
&= ~bit_arch_##name; \
break; \
}
/* Enable/disable an ARCH feature NAME. */
# define CHECK_GLIBC_IFUNC_ARCH_BOTH(f, cpu_features, name, disable, \
len) \
/* Enable/disable a preferred feature NAME. */
# define CHECK_GLIBC_IFUNC_PREFERRED_BOTH(f, cpu_features, name, \
disable, len) \
_Static_assert (sizeof (#name) - 1 == len, #name " != " #len); \
if (!DEFAULT_MEMCMP (f, #name, len)) \
{ \
if (disable) \
cpu_features->feature_##name[index_arch_##name] \
&= ~bit_arch_##name; \
cpu_features->preferred[index_arch_##name] &= ~bit_arch_##name; \
else \
cpu_features->feature_##name[index_arch_##name] \
|= bit_arch_##name; \
cpu_features->preferred[index_arch_##name] |= bit_arch_##name; \
break; \
}
/* Enable/disable an ARCH feature NAME. Enable an ARCH feature only
if the ARCH feature NEED is also enabled. */
# define CHECK_GLIBC_IFUNC_ARCH_NEED_ARCH_BOTH(f, cpu_features, name, \
/* Enable/disable a preferred feature NAME. Enable a preferred feature
only if the feature NEED is usable. */
# define CHECK_GLIBC_IFUNC_PREFERRED_NEED_BOTH(f, cpu_features, name, \
need, disable, len) \
_Static_assert (sizeof (#name) - 1 == len, #name " != " #len); \
if (!DEFAULT_MEMCMP (f, #name, len)) \
{ \
if (disable) \
cpu_features->feature_##name[index_arch_##name] \
&= ~bit_arch_##name; \
else if (CPU_FEATURES_ARCH_P (cpu_features, need)) \
cpu_features->feature_##name[index_arch_##name] \
|= bit_arch_##name; \
break; \
}
/* Enable/disable an ARCH feature NAME. Enable an ARCH feature only
if the CPU feature NEED is also enabled. */
# define CHECK_GLIBC_IFUNC_ARCH_NEED_CPU_BOTH(f, cpu_features, name, \
need, disable, len) \
_Static_assert (sizeof (#name) - 1 == len, #name " != " #len); \
if (!DEFAULT_MEMCMP (f, #name, len)) \
{ \
if (disable) \
cpu_features->feature_##name[index_arch_##name] \
&= ~bit_arch_##name; \
else if (CPU_FEATURES_CPU_P (cpu_features, need)) \
cpu_features->feature_##name[index_arch_##name] \
|= bit_arch_##name; \
cpu_features->preferred[index_arch_##name] &= ~bit_arch_##name; \
else if (CPU_FEATURE_USABLE_P (cpu_features, need)) \
cpu_features->preferred[index_arch_##name] |= bit_arch_##name; \
break; \
}
@ -178,8 +157,8 @@ TUNABLE_CALLBACK (set_hwcaps) (tunable_val_t *valp)
CHECK_GLIBC_IFUNC_CPU_OFF (n, cpu_features, ERMS, 4);
CHECK_GLIBC_IFUNC_CPU_OFF (n, cpu_features, FMA4, 4);
CHECK_GLIBC_IFUNC_CPU_OFF (n, cpu_features, SSE2, 4);
CHECK_GLIBC_IFUNC_ARCH_OFF (n, cpu_features, I586, 4);
CHECK_GLIBC_IFUNC_ARCH_OFF (n, cpu_features, I686, 4);
CHECK_GLIBC_IFUNC_PREFERRED_OFF (n, cpu_features, I586, 4);
CHECK_GLIBC_IFUNC_PREFERRED_OFF (n, cpu_features, I686, 4);
}
break;
case 5:
@ -197,6 +176,13 @@ TUNABLE_CALLBACK (set_hwcaps) (tunable_val_t *valp)
CHECK_GLIBC_IFUNC_CPU_OFF (n, cpu_features, POPCNT, 6);
CHECK_GLIBC_IFUNC_CPU_OFF (n, cpu_features, SSE4_1, 6);
CHECK_GLIBC_IFUNC_CPU_OFF (n, cpu_features, SSE4_2, 6);
if (!DEFAULT_MEMCMP (n, "XSAVEC", 6))
{
/* Update xsave_state_size to XSAVE state size. */
cpu_features->xsave_state_size
= cpu_features->xsave_state_full_size;
CPU_FEATURE_UNSET (cpu_features, XSAVEC);
}
}
break;
case 7:
@ -216,115 +202,85 @@ TUNABLE_CALLBACK (set_hwcaps) (tunable_val_t *valp)
CHECK_GLIBC_IFUNC_CPU_OFF (n, cpu_features, AVX512PF, 8);
CHECK_GLIBC_IFUNC_CPU_OFF (n, cpu_features, AVX512VL, 8);
}
CHECK_GLIBC_IFUNC_ARCH_BOTH (n, cpu_features, Slow_BSF,
disable, 8);
break;
case 10:
if (disable)
{
CHECK_GLIBC_IFUNC_ARCH_OFF (n, cpu_features, AVX_Usable,
10);
CHECK_GLIBC_IFUNC_ARCH_OFF (n, cpu_features, FMA_Usable,
10);
}
CHECK_GLIBC_IFUNC_PREFERRED_BOTH (n, cpu_features, Slow_BSF,
disable, 8);
break;
case 11:
if (disable)
{
CHECK_GLIBC_IFUNC_ARCH_OFF (n, cpu_features, AVX2_Usable,
11);
CHECK_GLIBC_IFUNC_ARCH_OFF (n, cpu_features, FMA4_Usable,
11);
}
CHECK_GLIBC_IFUNC_ARCH_BOTH (n, cpu_features, Prefer_ERMS,
disable, 11);
CHECK_GLIBC_IFUNC_ARCH_NEED_CPU_BOTH (n, cpu_features,
Slow_SSE4_2, SSE4_2,
CHECK_GLIBC_IFUNC_PREFERRED_BOTH (n, cpu_features,
Prefer_ERMS,
disable, 11);
CHECK_GLIBC_IFUNC_ARCH_BOTH (n, cpu_features, Prefer_FSRM,
disable, 11);
break;
case 13:
if (disable)
{
/* Update xsave_state_size to XSAVE state size. */
cpu_features->xsave_state_size
= cpu_features->xsave_state_full_size;
CHECK_GLIBC_IFUNC_ARCH_OFF (n, cpu_features,
XSAVEC_Usable, 13);
}
break;
case 14:
if (disable)
{
CHECK_GLIBC_IFUNC_ARCH_OFF (n, cpu_features,
AVX512F_Usable, 14);
CHECK_GLIBC_IFUNC_PREFERRED_BOTH (n, cpu_features,
Prefer_FSRM,
disable, 11);
CHECK_GLIBC_IFUNC_PREFERRED_NEED_BOTH (n, cpu_features,
Slow_SSE4_2,
SSE4_2,
disable, 11);
}
break;
case 15:
if (disable)
{
CHECK_GLIBC_IFUNC_ARCH_OFF (n, cpu_features,
AVX512DQ_Usable, 15);
CHECK_GLIBC_IFUNC_PREFERRED_BOTH (n, cpu_features,
Fast_Rep_String,
disable, 15);
}
CHECK_GLIBC_IFUNC_ARCH_BOTH (n, cpu_features, Fast_Rep_String,
disable, 15);
break;
case 16:
{
CHECK_GLIBC_IFUNC_ARCH_NEED_ARCH_BOTH
(n, cpu_features, Prefer_No_AVX512, AVX512F_Usable,
CHECK_GLIBC_IFUNC_PREFERRED_NEED_BOTH
(n, cpu_features, Prefer_No_AVX512, AVX512F,
disable, 16);
}
break;
case 18:
{
CHECK_GLIBC_IFUNC_ARCH_BOTH (n, cpu_features,
Fast_Copy_Backward, disable,
18);
CHECK_GLIBC_IFUNC_PREFERRED_BOTH (n, cpu_features,
Fast_Copy_Backward,
disable, 18);
}
break;
case 19:
{
CHECK_GLIBC_IFUNC_ARCH_BOTH (n, cpu_features,
Fast_Unaligned_Load, disable,
19);
CHECK_GLIBC_IFUNC_ARCH_BOTH (n, cpu_features,
Fast_Unaligned_Copy, disable,
19);
CHECK_GLIBC_IFUNC_PREFERRED_BOTH (n, cpu_features,
Fast_Unaligned_Load,
disable, 19);
CHECK_GLIBC_IFUNC_PREFERRED_BOTH (n, cpu_features,
Fast_Unaligned_Copy,
disable, 19);
}
break;
case 20:
{
CHECK_GLIBC_IFUNC_ARCH_NEED_ARCH_BOTH
(n, cpu_features, Prefer_No_VZEROUPPER, AVX_Usable,
disable, 20);
CHECK_GLIBC_IFUNC_PREFERRED_NEED_BOTH
(n, cpu_features, Prefer_No_VZEROUPPER, AVX, disable,
20);
}
break;
case 21:
{
CHECK_GLIBC_IFUNC_ARCH_BOTH (n, cpu_features,
Prefer_MAP_32BIT_EXEC, disable,
21);
CHECK_GLIBC_IFUNC_PREFERRED_BOTH (n, cpu_features,
Prefer_MAP_32BIT_EXEC,
disable, 21);
}
break;
case 23:
{
CHECK_GLIBC_IFUNC_ARCH_NEED_ARCH_BOTH
(n, cpu_features, AVX_Fast_Unaligned_Load, AVX_Usable,
CHECK_GLIBC_IFUNC_PREFERRED_NEED_BOTH
(n, cpu_features, AVX_Fast_Unaligned_Load, AVX,
disable, 23);
}
break;
case 24:
{
CHECK_GLIBC_IFUNC_ARCH_NEED_ARCH_BOTH
(n, cpu_features, MathVec_Prefer_No_AVX512,
AVX512F_Usable, disable, 24);
CHECK_GLIBC_IFUNC_PREFERRED_NEED_BOTH
(n, cpu_features, MathVec_Prefer_No_AVX512, AVX512F,
disable, 24);
}
break;
case 26:
{
CHECK_GLIBC_IFUNC_ARCH_NEED_CPU_BOTH
CHECK_GLIBC_IFUNC_PREFERRED_NEED_BOTH
(n, cpu_features, Prefer_PMINUB_for_stringop, SSE2,
disable, 26);
}