PostgreSQL Source Code git master
Loading...
Searching...
No Matches
pg_cpu_x86.c
Go to the documentation of this file.
1/*-------------------------------------------------------------------------
2 *
3 * pg_cpu_x86.c
4 * Runtime CPU feature detection for x86
5 *
6 * Portions Copyright (c) 1996-2026, PostgreSQL Global Development Group
7 * Portions Copyright (c) 1994, Regents of the University of California
8 *
9 *
10 * IDENTIFICATION
11 * src/port/pg_cpu_x86.c
12 *
13 *-------------------------------------------------------------------------
14 */
15
16#include "c.h"
17
18#if defined(USE_SSE2) || defined(__i386__)
19
20#if defined(HAVE__GET_CPUID) || defined(HAVE__GET_CPUID_COUNT)
21#include <cpuid.h>
22#endif
23
24#if defined(HAVE__CPUID) || defined(HAVE__CPUIDEX)
25#include <intrin.h>
26#endif
27
28#ifdef HAVE_XSAVE_INTRINSICS
29#include <immintrin.h>
30#endif
31
32#include "port/pg_cpu.h"
33
34/*
35 * XSAVE state component bits that we need
36 *
37 * https://www.intel.com/content/dam/www/public/us/en/documents/manuals/64-ia-32-architectures-software-developer-vol-1-manual.pdf
38 * Chapter "MANAGING STATE USING THE XSAVE FEATURE SET"
39 */
40#define XMM (1<<1)
41#define YMM (1<<2)
42#define OPMASK (1<<5)
43#define ZMM0_15 (1<<6)
44#define ZMM16_31 (1<<7)
45
46
47/* array indexed by enum X86FeatureId */
49
50static bool
52{
53 return (value & mask) == mask;
54}
55
56/* Named indexes for CPUID register array */
57#define EAX 0
58#define EBX 1
59#define ECX 2
60#define EDX 3
61
62/*
63 * Request CPUID information for the specified leaf.
64 */
65static inline void
66pg_cpuid(int leaf, unsigned int *reg)
67{
68#if defined(HAVE__GET_CPUID)
69 __get_cpuid(leaf, &reg[EAX], &reg[EBX], &reg[ECX], &reg[EDX]);
70#elif defined(HAVE__CPUID)
71 __cpuid((int *) reg, leaf);
72#else
73#error cpuid instruction not available
74#endif
75}
76
77/*
78 * Request CPUID information for the specified leaf and subleaf.
79 *
80 * Returns true if the CPUID leaf/subleaf is supported, false otherwise.
81 */
82static inline bool
83pg_cpuid_subleaf(int leaf, int subleaf, unsigned int *reg)
84{
85#if defined(HAVE__GET_CPUID_COUNT)
86 return __get_cpuid_count(leaf, subleaf, &reg[EAX], &reg[EBX], &reg[ECX], &reg[EDX]) == 1;
87#elif defined(HAVE__CPUIDEX)
88 __cpuidex((int *) reg, leaf, subleaf);
89 return true;
90#else
91 memset(reg, 0, 4 * sizeof(unsigned int));
92 return false;
93#endif
94}
95
96/*
97 * Parse the CPU ID info for runtime checks.
98 */
99#ifdef HAVE_XSAVE_INTRINSICS
100pg_attribute_target("xsave")
101#endif
102void
104{
105 unsigned int reg[4] = {0};
106
107 pg_cpuid(0x01, reg);
108
109 X86Features[PG_SSE4_2] = reg[ECX] >> 20 & 1;
110 X86Features[PG_POPCNT] = reg[ECX] >> 23 & 1;
111
112 /* leaf 7 features that depend on OSXSAVE */
113 if (reg[ECX] & (1 << 27))
114 {
115 uint32 xcr0_val = 0;
116
117 pg_cpuid_subleaf(0x07, 0, reg);
118
119#ifdef HAVE_XSAVE_INTRINSICS
120 /* get value of Extended Control Register */
121 xcr0_val = _xgetbv(0);
122#endif
123
124 /* Are ZMM registers enabled? */
127 {
128 X86Features[PG_AVX512_BW] = reg[EBX] >> 30 & 1;
129 X86Features[PG_AVX512_VL] = reg[EBX] >> 31 & 1;
130
131 X86Features[PG_AVX512_VPCLMULQDQ] = reg[ECX] >> 10 & 1;
132 X86Features[PG_AVX512_VPOPCNTDQ] = reg[ECX] >> 14 & 1;
133 }
134 }
135
136 X86Features[INIT_PG_X86] = true;
137}
138
139#endif /* defined(USE_SSE2) || defined(__i386__) */
uint32_t uint32
Definition c.h:618
#define pg_attribute_target(...)
Definition c.h:232
static struct @175 value
static int fb(int x)