postgres.git / summary / log / commit / refs
commit be6a7494d2e387d1f5b7a5dcc6c2afcb403188d6
Author: John Naylor <john.naylor@postgresql.org>
Date: Wed Mar 25 05:32:36 2026 +0000
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
src/port/pg_cpu_x86.c | 76 ++++++++++++++++++++++++++++++++++-----------------
1 file changed, 51 insertions(+), 25 deletions(-)
diff --git a/src/port/pg_cpu_x86.c b/src/port/pg_cpu_x86.c
index 7575838245c..e2ab92b09ac 100644
--- a/src/port/pg_cpu_x86.c
+++ b/src/port/pg_cpu_x86.c
@@ -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;
}
}
[parent: 7c64d56fd976]