Skip to content

Commit 5c9be39

Browse files
committed
runtime: check amd64 microarchitecture level at startup
Make Go runtime throw if it's been compiled to assume instruction set extensions that aren't available on the CPU. Updates #485064
1 parent 7d67f8d commit 5c9be39

File tree

1 file changed

+111
-2
lines changed

1 file changed

+111
-2
lines changed

src/runtime/asm_amd64.s

+111-2
Original file line numberDiff line numberDiff line change
@@ -78,6 +78,62 @@ GLOBL _rt0_amd64_lib_argc<>(SB),NOPTR, $8
7878
DATA _rt0_amd64_lib_argv<>(SB)/8, $0
7979
GLOBL _rt0_amd64_lib_argv<>(SB),NOPTR, $8
8080

81+
#ifdef GOAMD64_v2
82+
DATA bad_proc_msg<>+0x00(SB)/78, $"This program can only be run on processors with v2 microarchitecture support.\n"
83+
#endif
84+
85+
#ifdef GOAMD64_v3
86+
DATA bad_proc_msg<>+0x00(SB)/78, $"This program can only be run on processors with v3 microarchitecture support.\n"
87+
#endif
88+
89+
#ifdef GOAMD64_v4
90+
DATA bad_proc_msg<>+0x00(SB)/78, $"This program can only be run on processors with v4 microarchitecture support.\n"
91+
#endif
92+
93+
GLOBL bad_proc_msg<>(SB), RODATA, $78
94+
95+
// Define a list of AMD64 microarchitecture level features
96+
// https://en.wikipedia.org/wiki/X86-64#Microarchitecture_levels
97+
98+
// SSE3 SSSE3 CMPXCHNG16 SSE4.1 SSE4.2 POPCNT
99+
#define V2_FEATURES_CX (1 << 0 | 1 << 9 | 1 << 13 | 1 << 19 | 1 << 20 | 1 << 23)
100+
// LAHF/SAHF
101+
#define V2_EXT_FEATURES_CX (1 << 0)
102+
// FMA MOVBE OSXSAVE AVX F16C
103+
#define V3_FEATURES_CX (V2_FEATURES_CX | 1 << 12 | 1 << 22 | 1 << 27 | 1 << 28 | 1 << 29)
104+
// ABM (FOR LZNCT)
105+
#define V3_EXT_FEATURES_CX (V2_EXT_FEATURES_CX | 1 << 5)
106+
// BMI1 AVX2 BMI2
107+
#define V3_EXT_FEATURES_BX (1 << 3 | 1 << 5 | 1 << 8)
108+
// XMM YMM
109+
#define V3_OS_SUPPORT_AX (1 << 1 | 1 << 2)
110+
// AVX512F AVX512DQ AVX512CD AVX512BW AVX512VL
111+
#define V4_EXT_FEATURES_BX (V3_EXT_FEATURES_BX | 1 << 16 | 1 << 17 | 1 << 28 | 1 << 30 | 1 << 31)
112+
// OPMASK ZMM
113+
#define V4_OS_SUPPORT_AX (V3_OS_SUPPORT_AX | 1 << 5 | (1 << 6 | 1 << 7))
114+
115+
#ifdef GOAMD64_v2
116+
#define NEED_MAX_CPUID 0x80000001
117+
#define NEED_FEATURES_CX V2_FEATURES_CX
118+
#define NEED_EXT_FEATURES_CX V2_EXT_FEATURES_CX
119+
#endif
120+
121+
#ifdef GOAMD64_v3
122+
#define NEED_MAX_CPUID 0x80000001
123+
#define NEED_FEATURES_CX V3_FEATURES_CX
124+
#define NEED_EXT_FEATURES_CX V3_EXT_FEATURES_CX
125+
#define NEED_EXT_FEATURES_BX V3_EXT_FEATURES_BX
126+
#define NEED_OS_SUPPORT_AX V3_OS_SUPPORT_AX
127+
#endif
128+
129+
#ifdef GOAMD64_v4
130+
#define NEED_MAX_CPUID 0x80000001
131+
#define NEED_FEATURES_CX V3_FEATURES_CX
132+
#define NEED_EXT_FEATURES_CX V3_EXT_FEATURES_CX
133+
#define NEED_EXT_FEATURES_BX V4_EXT_FEATURES_BX
134+
#define NEED_OS_SUPPORT_AX V4_OS_SUPPORT_AX
135+
#endif
136+
81137
TEXT runtime·rt0_go(SB),NOSPLIT|TOPFRAME,$0
82138
// copy arguments forward on an even stack
83139
MOVQ DI, AX // argc
@@ -101,22 +157,75 @@ TEXT runtime·rt0_go(SB),NOSPLIT|TOPFRAME,$0
101157
CPUID
102158
MOVL AX, SI
103159
CMPL AX, $0
104-
JE nocpuinfo
160+
#ifdef GOAMD64_v1
161+
JE nocpuinfo
162+
#else
163+
JNE has_cpuinfo
105164

165+
bad_proc: // show that the program requires a certain microarchitecture level.
166+
MOVQ $2, 0(SP)
167+
MOVQ $bad_proc_msg<>(SB), AX
168+
MOVQ AX, 8(SP)
169+
MOVQ $78, 16(SP)
170+
CALL runtime·write(SB)
171+
MOVQ $1, 0(SP)
172+
CALL runtime·exit(SB)
173+
CALL runtime·abort(SB)
174+
#endif
175+
176+
has_cpuinfo:
106177
CMPL BX, $0x756E6547 // "Genu"
107178
JNE notintel
108179
CMPL DX, $0x49656E69 // "ineI"
109180
JNE notintel
110181
CMPL CX, $0x6C65746E // "ntel"
111182
JNE notintel
112183
MOVB $1, runtime·isIntel(SB)
113-
notintel:
114184

185+
notintel:
115186
// Load EAX=1 cpuid flags
116187
MOVL $1, AX
117188
CPUID
118189
MOVL AX, runtime·processorVersionInfo(SB)
119190

191+
#ifdef NEED_FEATURES_CX
192+
ANDL $NEED_FEATURES_CX, CX
193+
CMPL CX, $NEED_FEATURES_CX
194+
JNZ bad_proc
195+
#endif
196+
197+
#ifdef NEED_MAX_CPUID
198+
MOVL $0x80000000, AX
199+
CPUID
200+
CMPL AX, $NEED_MAX_CPUID
201+
JL bad_proc
202+
#endif
203+
204+
#ifdef NEED_EXT_FEATURES_BX
205+
MOVL $7, AX
206+
MOVL $0, CX
207+
CPUID
208+
ANDL $NEED_EXT_FEATURES_BX, BX
209+
CMPL BX, $NEED_EXT_FEATURES_BX
210+
JNZ bad_proc
211+
#endif
212+
213+
#ifdef NEED_EXT_FEATURES_CX
214+
MOVL $0x80000001, AX
215+
CPUID
216+
ANDL $NEED_EXT_FEATURES_CX, CX
217+
CMPL CX, $NEED_EXT_FEATURES_CX
218+
JNZ bad_proc
219+
#endif
220+
221+
#ifdef NEED_OS_SUPPORT_AX
222+
MOVL $0, CX
223+
XGETBV
224+
ANDL $NEED_OS_SUPPORT_AX, AX
225+
CMPL AX, $NEED_OS_SUPPORT_AX
226+
JNZ bad_proc
227+
#endif
228+
120229
nocpuinfo:
121230
// if there is an _cgo_init, call it.
122231
MOVQ _cgo_init(SB), AX

0 commit comments

Comments
 (0)