mirror of
https://github.com/postgres/postgres.git
synced 2026-06-10 09:10:33 -04:00
Refactor handling of x86 CPUID instructions
Introduce two helpers for CPUID, pg_cpuid and pg_cpuid_subleaf that wrap the platform specific __get_cpuid/__cpuid and __get_cpuid_count/__cpuidex functions. Additionally, use macros to specify registers names (e.g. EAX) for clarity, instead of numeric integers into the result array. Author: Lukas Fittl <lukas@fittl.com> Suggested-By: John Naylor <john.naylor@postgresql.org> Discussion: https://postgr.es/m/CANWCAZZ+Crjt5za9YmFsURRMDW7M4T2mutDezd_3s1gTLnrzGQ@mail.gmail.com
This commit is contained in:
parent
7c64d56fd9
commit
be6a7494d2
1 changed files with 51 additions and 25 deletions
|
|
@ -53,6 +53,46 @@ mask_available(uint32 value, uint32 mask)
|
|||
return (value & mask) == mask;
|
||||
}
|
||||
|
||||
/* Named indexes for CPUID register array */
|
||||
#define EAX 0
|
||||
#define EBX 1
|
||||
#define ECX 2
|
||||
#define EDX 3
|
||||
|
||||
/*
|
||||
* Request CPUID information for the specified leaf.
|
||||
*/
|
||||
static inline void
|
||||
pg_cpuid(int leaf, unsigned int *reg)
|
||||
{
|
||||
#if defined(HAVE__GET_CPUID)
|
||||
__get_cpuid(leaf, ®[EAX], ®[EBX], ®[ECX], ®[EDX]);
|
||||
#elif defined(HAVE__CPUID)
|
||||
__cpuid((int *) reg, leaf);
|
||||
#else
|
||||
#error cpuid instruction not available
|
||||
#endif
|
||||
}
|
||||
|
||||
/*
|
||||
* Request CPUID information for the specified leaf and subleaf.
|
||||
*
|
||||
* Returns true if the CPUID leaf/subleaf is supported, false otherwise.
|
||||
*/
|
||||
static inline bool
|
||||
pg_cpuid_subleaf(int leaf, int subleaf, unsigned int *reg)
|
||||
{
|
||||
#if defined(HAVE__GET_CPUID_COUNT)
|
||||
return __get_cpuid_count(leaf, subleaf, ®[EAX], ®[EBX], ®[ECX], ®[EDX]) == 1;
|
||||
#elif defined(HAVE__CPUIDEX)
|
||||
__cpuidex((int *) reg, leaf, subleaf);
|
||||
return true;
|
||||
#else
|
||||
memset(reg, 0, 4 * sizeof(unsigned int));
|
||||
return false;
|
||||
#endif
|
||||
}
|
||||
|
||||
/*
|
||||
* Parse the CPU ID info for runtime checks.
|
||||
*/
|
||||
|
|
@ -62,33 +102,19 @@ pg_attribute_target("xsave")
|
|||
void
|
||||
set_x86_features(void)
|
||||
{
|
||||
unsigned int exx[4] = {0, 0, 0, 0};
|
||||
unsigned int reg[4] = {0};
|
||||
|
||||
#if defined(HAVE__GET_CPUID)
|
||||
__get_cpuid(1, &exx[0], &exx[1], &exx[2], &exx[3]);
|
||||
#elif defined(HAVE__CPUID)
|
||||
__cpuid(exx, 1);
|
||||
#else
|
||||
#error cpuid instruction not available
|
||||
#endif
|
||||
pg_cpuid(0x01, reg);
|
||||
|
||||
X86Features[PG_SSE4_2] = exx[2] >> 20 & 1;
|
||||
X86Features[PG_POPCNT] = exx[2] >> 23 & 1;
|
||||
X86Features[PG_SSE4_2] = reg[ECX] >> 20 & 1;
|
||||
X86Features[PG_POPCNT] = reg[ECX] >> 23 & 1;
|
||||
|
||||
/* All these features depend on OSXSAVE */
|
||||
if (exx[2] & (1 << 27))
|
||||
/* leaf 7 features that depend on OSXSAVE */
|
||||
if (reg[ECX] & (1 << 27))
|
||||
{
|
||||
uint32 xcr0_val = 0;
|
||||
|
||||
/* second cpuid call on leaf 7 to check extended AVX-512 support */
|
||||
|
||||
memset(exx, 0, 4 * sizeof(exx[0]));
|
||||
|
||||
#if defined(HAVE__GET_CPUID_COUNT)
|
||||
__get_cpuid_count(7, 0, &exx[0], &exx[1], &exx[2], &exx[3]);
|
||||
#elif defined(HAVE__CPUIDEX)
|
||||
__cpuidex(exx, 7, 0);
|
||||
#endif
|
||||
pg_cpuid_subleaf(0x07, 0, reg);
|
||||
|
||||
#ifdef HAVE_XSAVE_INTRINSICS
|
||||
/* get value of Extended Control Register */
|
||||
|
|
@ -99,11 +125,11 @@ set_x86_features(void)
|
|||
if (mask_available(xcr0_val, XMM | YMM |
|
||||
OPMASK | ZMM0_15 | ZMM16_31))
|
||||
{
|
||||
X86Features[PG_AVX512_BW] = exx[1] >> 30 & 1;
|
||||
X86Features[PG_AVX512_VL] = exx[1] >> 31 & 1;
|
||||
X86Features[PG_AVX512_BW] = reg[EBX] >> 30 & 1;
|
||||
X86Features[PG_AVX512_VL] = reg[EBX] >> 31 & 1;
|
||||
|
||||
X86Features[PG_AVX512_VPCLMULQDQ] = exx[2] >> 10 & 1;
|
||||
X86Features[PG_AVX512_VPOPCNTDQ] = exx[2] >> 14 & 1;
|
||||
X86Features[PG_AVX512_VPCLMULQDQ] = reg[ECX] >> 10 & 1;
|
||||
X86Features[PG_AVX512_VPOPCNTDQ] = reg[ECX] >> 14 & 1;
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
|||
Loading…
Reference in a new issue