Skip to content

Commit 8c8baad

Browse files
vpachkovrandall77
authored andcommitted
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 #48506 Change-Id: Ic4d6696e1cd6b28d389a86fe64e8175ea3ca135a GitHub-Last-Rev: ba33837 GitHub-Pull-Request: #48514 Reviewed-on: https://go-review.googlesource.com/c/go/+/351191 Run-TryBot: Martin Möhrmann <[email protected]> TryBot-Result: Go Bot <[email protected]> Reviewed-by: Martin Möhrmann <[email protected]> Reviewed-by: Keith Randall <[email protected]> Trust: Martin Möhrmann <[email protected]>
1 parent 58fb05a commit 8c8baad

File tree

1 file changed

+135
-2
lines changed

1 file changed

+135
-2
lines changed

src/runtime/asm_amd64.s

+135-2
Original file line numberDiff line numberDiff line change
@@ -78,6 +78,87 @@ 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_cpu_msg<>+0x00(SB)/84, $"This program can only be run on AMD64 processors with v2 microarchitecture support.\n"
83+
#endif
84+
85+
#ifdef GOAMD64_v3
86+
DATA bad_cpu_msg<>+0x00(SB)/84, $"This program can only be run on AMD64 processors with v3 microarchitecture support.\n"
87+
#endif
88+
89+
#ifdef GOAMD64_v4
90+
DATA bad_cpu_msg<>+0x00(SB)/84, $"This program can only be run on AMD64 processors with v4 microarchitecture support.\n"
91+
#endif
92+
93+
GLOBL bad_cpu_msg<>(SB), RODATA, $84
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+
111+
#define V4_FEATURES_CX V3_FEATURES_CX
112+
113+
#define V4_EXT_FEATURES_CX V3_EXT_FEATURES_CX
114+
// AVX512F AVX512DQ AVX512CD AVX512BW AVX512VL
115+
#define V4_EXT_FEATURES_BX (V3_EXT_FEATURES_BX | 1 << 16 | 1 << 17 | 1 << 28 | 1 << 30 | 1 << 31)
116+
// OPMASK ZMM
117+
#define V4_OS_SUPPORT_AX (V3_OS_SUPPORT_AX | 1 << 5 | (1 << 6 | 1 << 7))
118+
119+
#ifdef GOAMD64_v2
120+
#define NEED_MAX_CPUID 0x80000001
121+
#define NEED_FEATURES_CX V2_FEATURES_CX
122+
#define NEED_EXT_FEATURES_CX V2_EXT_FEATURES_CX
123+
#endif
124+
125+
#ifdef GOAMD64_v3
126+
#define NEED_MAX_CPUID 0x80000001
127+
#define NEED_FEATURES_CX V3_FEATURES_CX
128+
#define NEED_EXT_FEATURES_CX V3_EXT_FEATURES_CX
129+
#define NEED_EXT_FEATURES_BX V3_EXT_FEATURES_BX
130+
#define NEED_OS_SUPPORT_AX V3_OS_SUPPORT_AX
131+
#endif
132+
133+
#ifdef GOAMD64_v4
134+
#define NEED_MAX_CPUID 0x80000001
135+
#define NEED_FEATURES_CX V4_FEATURES_CX
136+
#define NEED_EXT_FEATURES_CX V4_EXT_FEATURES_CX
137+
#define NEED_EXT_FEATURES_BX V4_EXT_FEATURES_BX
138+
139+
// Downgrading v4 OS checks on Darwin for now, see CL 285572.
140+
#ifdef GOOS_darwin
141+
#define NEED_OS_SUPPORT_AX V3_OS_SUPPORT_AX
142+
#else
143+
#define NEED_OS_SUPPORT_AX V4_OS_SUPPORT_AX
144+
#endif
145+
146+
#endif
147+
148+
#ifdef GOAMD64_v1
149+
#define SKIP_GOAMD64_CHECK
150+
#endif
151+
152+
#ifndef GOAMD64_v1
153+
#ifndef GOAMD64_v2
154+
#ifndef GOAMD64_v3
155+
#ifndef GOAMD64_v4
156+
#define SKIP_GOAMD64_CHECK
157+
#endif
158+
#endif
159+
#endif
160+
#endif
161+
81162
TEXT runtime·rt0_go(SB),NOSPLIT|TOPFRAME,$0
82163
// copy arguments forward on an even stack
83164
MOVQ DI, AX // argc
@@ -99,24 +180,76 @@ TEXT runtime·rt0_go(SB),NOSPLIT|TOPFRAME,$0
99180
// find out information about the processor we're on
100181
MOVL $0, AX
101182
CPUID
102-
MOVL AX, SI
103183
CMPL AX, $0
184+
#ifdef SKIP_GOAMD64_CHECK
104185
JE nocpuinfo
186+
#else
187+
JNE has_cpuinfo
105188

189+
bad_cpu: // show that the program requires a certain microarchitecture level.
190+
MOVQ $2, 0(SP)
191+
MOVQ $bad_cpu_msg<>(SB), AX
192+
MOVQ AX, 8(SP)
193+
MOVQ $84, 16(SP)
194+
CALL runtime·write(SB)
195+
MOVQ $1, 0(SP)
196+
CALL runtime·exit(SB)
197+
CALL runtime·abort(SB)
198+
#endif
199+
200+
has_cpuinfo:
106201
CMPL BX, $0x756E6547 // "Genu"
107202
JNE notintel
108203
CMPL DX, $0x49656E69 // "ineI"
109204
JNE notintel
110205
CMPL CX, $0x6C65746E // "ntel"
111206
JNE notintel
112207
MOVB $1, runtime·isIntel(SB)
113-
notintel:
114208

209+
notintel:
115210
// Load EAX=1 cpuid flags
116211
MOVL $1, AX
117212
CPUID
118213
MOVL AX, runtime·processorVersionInfo(SB)
119214

215+
#ifdef NEED_FEATURES_CX
216+
ANDL $NEED_FEATURES_CX, CX
217+
CMPL CX, $NEED_FEATURES_CX
218+
JNE bad_cpu
219+
#endif
220+
221+
#ifdef NEED_MAX_CPUID
222+
MOVL $0x80000000, AX
223+
CPUID
224+
CMPL AX, $NEED_MAX_CPUID
225+
JL bad_cpu
226+
#endif
227+
228+
#ifdef NEED_EXT_FEATURES_BX
229+
MOVL $7, AX
230+
MOVL $0, CX
231+
CPUID
232+
ANDL $NEED_EXT_FEATURES_BX, BX
233+
CMPL BX, $NEED_EXT_FEATURES_BX
234+
JNE bad_cpu
235+
#endif
236+
237+
#ifdef NEED_EXT_FEATURES_CX
238+
MOVL $0x80000001, AX
239+
CPUID
240+
ANDL $NEED_EXT_FEATURES_CX, CX
241+
CMPL CX, $NEED_EXT_FEATURES_CX
242+
JNE bad_cpu
243+
#endif
244+
245+
#ifdef NEED_OS_SUPPORT_AX
246+
XORL CX, CX
247+
XGETBV
248+
ANDL $NEED_OS_SUPPORT_AX, AX
249+
CMPL AX, $NEED_OS_SUPPORT_AX
250+
JNE bad_cpu
251+
#endif
252+
120253
nocpuinfo:
121254
// if there is an _cgo_init, call it.
122255
MOVQ _cgo_init(SB), AX

0 commit comments

Comments
 (0)