Skip to content

Commit b6a6c17

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 b6a6c17

File tree

1 file changed

+72
-2
lines changed

1 file changed

+72
-2
lines changed

src/runtime/asm_amd64.s

+72-2
Original file line numberDiff line numberDiff line change
@@ -78,6 +78,30 @@ 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+
GLOBL bad_proc_msg<>(SB), RODATA, $78
90+
91+
// Define a list of AMD64 microarchitecture level features
92+
// https://en.wikipedia.org/wiki/X86-64#Microarchitecture_levels
93+
94+
// SSE3 SSSE3 CMPXCHNG16 SSE4.1 SSE4.2 POPCNT
95+
#define V2_FEATURES_CX (1 << 0 | 1 << 9 | 1 << 13 | 1 << 19 | 1 << 20 | 1 << 23)
96+
// LAHF/SAHF
97+
#define V2_EXT_FEATURES_CX (1 << 0)
98+
// FMA MOVBE OSXSAVE AVX F16C
99+
#define V3_FEATURES_CX (V2_FEATURES_CX | 1 << 12 | 1 << 22 | 1 << 27 | 1 << 28 | 1 << 29)
100+
// ABM (FOR LZNCT)
101+
#define V3_EXT_FEATURES_CX (V2_EXT_FEATURES_CX | 1 << 5)
102+
// BMI1 AVX2 BMI2
103+
#define V3_EXT_FEATURES_BX (1 << 3 | 1 << 5 | 1 << 8)
104+
81105
TEXT runtime·rt0_go(SB),NOSPLIT|TOPFRAME,$0
82106
// copy arguments forward on an even stack
83107
MOVQ DI, AX // argc
@@ -101,22 +125,68 @@ TEXT runtime·rt0_go(SB),NOSPLIT|TOPFRAME,$0
101125
CPUID
102126
MOVL AX, SI
103127
CMPL AX, $0
104-
JE nocpuinfo
128+
#ifdef GOAMD64_v1
129+
JE nocpuinfo
130+
#else
131+
JNE has_cpuinfo
132+
133+
bad_proc: // show that the program requires a certain microarchitecture level.
134+
MOVQ $2, 0(SP)
135+
MOVQ $bad_proc_msg<>(SB), AX
136+
MOVQ AX, 8(SP)
137+
MOVQ $78, 16(SP)
138+
CALL runtime·write(SB)
139+
MOVQ $1, 0(SP)
140+
CALL runtime·exit(SB)
141+
CALL runtime·abort(SB)
142+
#endif
105143

144+
has_cpuinfo:
106145
CMPL BX, $0x756E6547 // "Genu"
107146
JNE notintel
108147
CMPL DX, $0x49656E69 // "ineI"
109148
JNE notintel
110149
CMPL CX, $0x6C65746E // "ntel"
111150
JNE notintel
112151
MOVB $1, runtime·isIntel(SB)
113-
notintel:
114152

153+
notintel:
115154
// Load EAX=1 cpuid flags
116155
MOVL $1, AX
117156
CPUID
118157
MOVL AX, runtime·processorVersionInfo(SB)
119158

159+
#ifdef GOAMD64_v2
160+
ANDL $V2_FEATURES_CX, CX
161+
CMPL CX, $V2_FEATURES_CX
162+
JNZ bad_proc
163+
MOVL $0x80000001, AX
164+
CPUID
165+
TESTL $V2_EXT_FEATURES_CX, CX
166+
JZ bad_proc
167+
#endif
168+
169+
#ifdef GOAMD64_v3
170+
ANDL $V3_FEATURES_CX, CX
171+
CMPL CX, $V3_FEATURES_CX
172+
JNZ bad_proc
173+
MOVL $7, AX
174+
MOVL $0, CX
175+
CPUID
176+
ANDL $V3_EXT_FEATURES_BX, BX
177+
CMPL BX, $V3_EXT_FEATURES_BX
178+
JNZ bad_proc
179+
MOVL $0x80000000, AX
180+
CPUID
181+
CMPL AX, $0x80000001
182+
JL bad_proc
183+
MOVL $0x80000001, AX
184+
CPUID
185+
ANDL $V3_EXT_FEATURES_CX, CX
186+
CMPL CX, $V3_EXT_FEATURES_CX
187+
JNZ bad_proc
188+
#endif
189+
120190
nocpuinfo:
121191
// if there is an _cgo_init, call it.
122192
MOVQ _cgo_init(SB), AX

0 commit comments

Comments
 (0)