Skip to content

Commit

Permalink
runtime: check amd64 microarchitecture level at startup
Browse files Browse the repository at this point in the history
Make Go runtime throw if it's been compiled to assume instruction
set extensions that aren't available on the CPU.
Updates #485064
  • Loading branch information
vpachkov committed Sep 24, 2021
1 parent 7d67f8d commit b6a6c17
Showing 1 changed file with 72 additions and 2 deletions.
74 changes: 72 additions & 2 deletions src/runtime/asm_amd64.s
Original file line number Diff line number Diff line change
Expand Up @@ -78,6 +78,30 @@ GLOBL _rt0_amd64_lib_argc<>(SB),NOPTR, $8
DATA _rt0_amd64_lib_argv<>(SB)/8, $0
GLOBL _rt0_amd64_lib_argv<>(SB),NOPTR, $8

#ifdef GOAMD64_v2
DATA bad_proc_msg<>+0x00(SB)/78, $"This program can only be run on processors with v2 microarchitecture support.\n"
#endif

#ifdef GOAMD64_v3
DATA bad_proc_msg<>+0x00(SB)/78, $"This program can only be run on processors with v3 microarchitecture support.\n"
#endif

GLOBL bad_proc_msg<>(SB), RODATA, $78

// Define a list of AMD64 microarchitecture level features
// https://en.wikipedia.org/wiki/X86-64#Microarchitecture_levels

// SSE3 SSSE3 CMPXCHNG16 SSE4.1 SSE4.2 POPCNT
#define V2_FEATURES_CX (1 << 0 | 1 << 9 | 1 << 13 | 1 << 19 | 1 << 20 | 1 << 23)
// LAHF/SAHF
#define V2_EXT_FEATURES_CX (1 << 0)
// FMA MOVBE OSXSAVE AVX F16C
#define V3_FEATURES_CX (V2_FEATURES_CX | 1 << 12 | 1 << 22 | 1 << 27 | 1 << 28 | 1 << 29)
// ABM (FOR LZNCT)
#define V3_EXT_FEATURES_CX (V2_EXT_FEATURES_CX | 1 << 5)
// BMI1 AVX2 BMI2
#define V3_EXT_FEATURES_BX (1 << 3 | 1 << 5 | 1 << 8)

TEXT runtime·rt0_go(SB),NOSPLIT|TOPFRAME,$0
// copy arguments forward on an even stack
MOVQ DI, AX // argc
Expand All @@ -101,22 +125,68 @@ TEXT runtime·rt0_go(SB),NOSPLIT|TOPFRAME,$0
CPUID
MOVL AX, SI
CMPL AX, $0
JE nocpuinfo
#ifdef GOAMD64_v1
JE nocpuinfo
#else
JNE has_cpuinfo

bad_proc: // show that the program requires a certain microarchitecture level.
MOVQ $2, 0(SP)
MOVQ $bad_proc_msg<>(SB), AX
MOVQ AX, 8(SP)
MOVQ $78, 16(SP)
CALL runtime·write(SB)
MOVQ $1, 0(SP)
CALL runtime·exit(SB)
CALL runtime·abort(SB)
#endif

has_cpuinfo:
CMPL BX, $0x756E6547 // "Genu"
JNE notintel
CMPL DX, $0x49656E69 // "ineI"
JNE notintel
CMPL CX, $0x6C65746E // "ntel"
JNE notintel
MOVB $1, runtime·isIntel(SB)
notintel:

notintel:
// Load EAX=1 cpuid flags
MOVL $1, AX
CPUID
MOVL AX, runtime·processorVersionInfo(SB)

#ifdef GOAMD64_v2
ANDL $V2_FEATURES_CX, CX
CMPL CX, $V2_FEATURES_CX
JNZ bad_proc
MOVL $0x80000001, AX
CPUID
TESTL $V2_EXT_FEATURES_CX, CX
JZ bad_proc
#endif

#ifdef GOAMD64_v3
ANDL $V3_FEATURES_CX, CX
CMPL CX, $V3_FEATURES_CX
JNZ bad_proc
MOVL $7, AX
MOVL $0, CX
CPUID
ANDL $V3_EXT_FEATURES_BX, BX
CMPL BX, $V3_EXT_FEATURES_BX
JNZ bad_proc
MOVL $0x80000000, AX
CPUID
CMPL AX, $0x80000001
JL bad_proc
MOVL $0x80000001, AX
CPUID
ANDL $V3_EXT_FEATURES_CX, CX
CMPL CX, $V3_EXT_FEATURES_CX
JNZ bad_proc
#endif

nocpuinfo:
// if there is an _cgo_init, call it.
MOVQ _cgo_init(SB), AX
Expand Down

0 comments on commit b6a6c17

Please sign in to comment.