From 309352d2d5a12b7cfee2b27d543faee6f3a6ece1 Mon Sep 17 00:00:00 2001 From: Vyacheslav Pachkov Date: Fri, 24 Sep 2021 12:02:41 +0300 Subject: [PATCH 1/4] 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 --- src/runtime/asm_amd64.s | 113 +++++++++++++++++++++++++++++++++++++++- 1 file changed, 111 insertions(+), 2 deletions(-) diff --git a/src/runtime/asm_amd64.s b/src/runtime/asm_amd64.s index 3ab6060ec0c608..508419780eb291 100644 --- a/src/runtime/asm_amd64.s +++ b/src/runtime/asm_amd64.s @@ -78,6 +78,62 @@ 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 + +#ifdef GOAMD64_v4 +DATA bad_proc_msg<>+0x00(SB)/78, $"This program can only be run on processors with v4 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) + // XMM YMM +#define V3_OS_SUPPORT_AX (1 << 1 | 1 << 2) + // AVX512F AVX512DQ AVX512CD AVX512BW AVX512VL +#define V4_EXT_FEATURES_BX (V3_EXT_FEATURES_BX | 1 << 16 | 1 << 17 | 1 << 28 | 1 << 30 | 1 << 31) + // OPMASK ZMM +#define V4_OS_SUPPORT_AX (V3_OS_SUPPORT_AX | 1 << 5 | (1 << 6 | 1 << 7)) + +#ifdef GOAMD64_v2 +#define NEED_MAX_CPUID 0x80000001 +#define NEED_FEATURES_CX V2_FEATURES_CX +#define NEED_EXT_FEATURES_CX V2_EXT_FEATURES_CX +#endif + +#ifdef GOAMD64_v3 +#define NEED_MAX_CPUID 0x80000001 +#define NEED_FEATURES_CX V3_FEATURES_CX +#define NEED_EXT_FEATURES_CX V3_EXT_FEATURES_CX +#define NEED_EXT_FEATURES_BX V3_EXT_FEATURES_BX +#define NEED_OS_SUPPORT_AX V3_OS_SUPPORT_AX +#endif + +#ifdef GOAMD64_v4 +#define NEED_MAX_CPUID 0x80000001 +#define NEED_FEATURES_CX V3_FEATURES_CX +#define NEED_EXT_FEATURES_CX V3_EXT_FEATURES_CX +#define NEED_EXT_FEATURES_BX V4_EXT_FEATURES_BX +#define NEED_OS_SUPPORT_AX V4_OS_SUPPORT_AX +#endif + TEXT runtime·rt0_go(SB),NOSPLIT|TOPFRAME,$0 // copy arguments forward on an even stack MOVQ DI, AX // argc @@ -101,8 +157,23 @@ 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" @@ -110,13 +181,51 @@ TEXT runtime·rt0_go(SB),NOSPLIT|TOPFRAME,$0 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 NEED_FEATURES_CX + ANDL $NEED_FEATURES_CX, CX + CMPL CX, $NEED_FEATURES_CX + JNZ bad_proc +#endif + +#ifdef NEED_MAX_CPUID + MOVL $0x80000000, AX + CPUID + CMPL AX, $NEED_MAX_CPUID + JL bad_proc +#endif + +#ifdef NEED_EXT_FEATURES_BX + MOVL $7, AX + MOVL $0, CX + CPUID + ANDL $NEED_EXT_FEATURES_BX, BX + CMPL BX, $NEED_EXT_FEATURES_BX + JNZ bad_proc +#endif + +#ifdef NEED_EXT_FEATURES_CX + MOVL $0x80000001, AX + CPUID + ANDL $NEED_EXT_FEATURES_CX, CX + CMPL CX, $NEED_EXT_FEATURES_CX + JNZ bad_proc +#endif + +#ifdef NEED_OS_SUPPORT_AX + MOVL $0, CX + XGETBV + ANDL $NEED_OS_SUPPORT_AX, AX + CMPL AX, $NEED_OS_SUPPORT_AX + JNZ bad_proc +#endif + nocpuinfo: // if there is an _cgo_init, call it. MOVQ _cgo_init(SB), AX From 504b1876c21bd81646d0e969367de427a9332cb6 Mon Sep 17 00:00:00 2001 From: vpachkov Date: Mon, 25 Oct 2021 16:20:12 +0300 Subject: [PATCH 2/4] remove v4 checks for darwin --- src/runtime/asm_amd64.s | 13 +++++++++++++ 1 file changed, 13 insertions(+) diff --git a/src/runtime/asm_amd64.s b/src/runtime/asm_amd64.s index 508419780eb291..bdadbea28d0c82 100644 --- a/src/runtime/asm_amd64.s +++ b/src/runtime/asm_amd64.s @@ -119,6 +119,17 @@ GLOBL bad_proc_msg<>(SB), RODATA, $78 #endif #ifdef GOAMD64_v3 +#define NEED_V3_CHECK +#endif + +// Excluding v4 checks on Darwin for now, see CL 285572. +#ifdef GOAMD64_v4 +#ifdef GOOS_darwin +#define NEED_V3_CHECK +#endif +#endif + +#ifdef NEED_V3_CHECK #define NEED_MAX_CPUID 0x80000001 #define NEED_FEATURES_CX V3_FEATURES_CX #define NEED_EXT_FEATURES_CX V3_EXT_FEATURES_CX @@ -127,12 +138,14 @@ GLOBL bad_proc_msg<>(SB), RODATA, $78 #endif #ifdef GOAMD64_v4 +#ifndef GOOS_darwin #define NEED_MAX_CPUID 0x80000001 #define NEED_FEATURES_CX V3_FEATURES_CX #define NEED_EXT_FEATURES_CX V3_EXT_FEATURES_CX #define NEED_EXT_FEATURES_BX V4_EXT_FEATURES_BX #define NEED_OS_SUPPORT_AX V4_OS_SUPPORT_AX #endif +#endif TEXT runtime·rt0_go(SB),NOSPLIT|TOPFRAME,$0 // copy arguments forward on an even stack From e4ca98b4da27bdcf59d354112bb904f90bfd9527 Mon Sep 17 00:00:00 2001 From: vpachkov Date: Thu, 28 Oct 2021 21:43:55 +0300 Subject: [PATCH 3/4] fix for old go compilers --- src/runtime/asm_amd64.s | 36 +++++++++++++++++++++++++----------- 1 file changed, 25 insertions(+), 11 deletions(-) diff --git a/src/runtime/asm_amd64.s b/src/runtime/asm_amd64.s index bdadbea28d0c82..19f5cdb72b89a8 100644 --- a/src/runtime/asm_amd64.s +++ b/src/runtime/asm_amd64.s @@ -95,16 +95,16 @@ 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) + // 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) // XMM YMM #define V3_OS_SUPPORT_AX (1 << 1 | 1 << 2) // AVX512F AVX512DQ AVX512CD AVX512BW AVX512VL @@ -147,6 +147,20 @@ GLOBL bad_proc_msg<>(SB), RODATA, $78 #endif #endif +#ifdef GOAMD64_v1 +#define SKIP_GOAMD64_CHECK +#endif + +#ifndef GOAMD64_v1 +#ifndef GOAMD64_v2 +#ifndef GOAMD64_v3 +#ifndef GOAMD64_v4 +#define SKIP_GOAMD64_CHECK +#endif +#endif +#endif +#endif + TEXT runtime·rt0_go(SB),NOSPLIT|TOPFRAME,$0 // copy arguments forward on an even stack MOVQ DI, AX // argc @@ -170,7 +184,7 @@ TEXT runtime·rt0_go(SB),NOSPLIT|TOPFRAME,$0 CPUID MOVL AX, SI CMPL AX, $0 -#ifdef GOAMD64_v1 +#ifdef SKIP_GOAMD64_CHECK JE nocpuinfo #else JNE has_cpuinfo From ba338377f549344b416fbd519576e95ce5d523be Mon Sep 17 00:00:00 2001 From: vpachkov Date: Sun, 31 Oct 2021 14:04:42 +0300 Subject: [PATCH 4/4] resolve comments --- src/runtime/asm_amd64.s | 55 +++++++++++++++++++---------------------- 1 file changed, 26 insertions(+), 29 deletions(-) diff --git a/src/runtime/asm_amd64.s b/src/runtime/asm_amd64.s index 19f5cdb72b89a8..0f0e5be21acac6 100644 --- a/src/runtime/asm_amd64.s +++ b/src/runtime/asm_amd64.s @@ -79,18 +79,18 @@ 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" +DATA bad_cpu_msg<>+0x00(SB)/84, $"This program can only be run on AMD64 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" +DATA bad_cpu_msg<>+0x00(SB)/84, $"This program can only be run on AMD64 processors with v3 microarchitecture support.\n" #endif #ifdef GOAMD64_v4 -DATA bad_proc_msg<>+0x00(SB)/78, $"This program can only be run on processors with v4 microarchitecture support.\n" +DATA bad_cpu_msg<>+0x00(SB)/84, $"This program can only be run on AMD64 processors with v4 microarchitecture support.\n" #endif -GLOBL bad_proc_msg<>(SB), RODATA, $78 +GLOBL bad_cpu_msg<>(SB), RODATA, $84 // Define a list of AMD64 microarchitecture level features // https://en.wikipedia.org/wiki/X86-64#Microarchitecture_levels @@ -107,6 +107,10 @@ GLOBL bad_proc_msg<>(SB), RODATA, $78 #define V3_EXT_FEATURES_BX (1 << 3 | 1 << 5 | 1 << 8) // XMM YMM #define V3_OS_SUPPORT_AX (1 << 1 | 1 << 2) + +#define V4_FEATURES_CX V3_FEATURES_CX + +#define V4_EXT_FEATURES_CX V3_EXT_FEATURES_CX // AVX512F AVX512DQ AVX512CD AVX512BW AVX512VL #define V4_EXT_FEATURES_BX (V3_EXT_FEATURES_BX | 1 << 16 | 1 << 17 | 1 << 28 | 1 << 30 | 1 << 31) // OPMASK ZMM @@ -119,17 +123,6 @@ GLOBL bad_proc_msg<>(SB), RODATA, $78 #endif #ifdef GOAMD64_v3 -#define NEED_V3_CHECK -#endif - -// Excluding v4 checks on Darwin for now, see CL 285572. -#ifdef GOAMD64_v4 -#ifdef GOOS_darwin -#define NEED_V3_CHECK -#endif -#endif - -#ifdef NEED_V3_CHECK #define NEED_MAX_CPUID 0x80000001 #define NEED_FEATURES_CX V3_FEATURES_CX #define NEED_EXT_FEATURES_CX V3_EXT_FEATURES_CX @@ -138,13 +131,18 @@ GLOBL bad_proc_msg<>(SB), RODATA, $78 #endif #ifdef GOAMD64_v4 -#ifndef GOOS_darwin #define NEED_MAX_CPUID 0x80000001 -#define NEED_FEATURES_CX V3_FEATURES_CX -#define NEED_EXT_FEATURES_CX V3_EXT_FEATURES_CX +#define NEED_FEATURES_CX V4_FEATURES_CX +#define NEED_EXT_FEATURES_CX V4_EXT_FEATURES_CX #define NEED_EXT_FEATURES_BX V4_EXT_FEATURES_BX + +// Downgrading v4 OS checks on Darwin for now, see CL 285572. +#ifdef GOOS_darwin +#define NEED_OS_SUPPORT_AX V3_OS_SUPPORT_AX +#else #define NEED_OS_SUPPORT_AX V4_OS_SUPPORT_AX #endif + #endif #ifdef GOAMD64_v1 @@ -182,18 +180,17 @@ TEXT runtime·rt0_go(SB),NOSPLIT|TOPFRAME,$0 // find out information about the processor we're on MOVL $0, AX CPUID - MOVL AX, SI CMPL AX, $0 #ifdef SKIP_GOAMD64_CHECK - JE nocpuinfo + JE nocpuinfo #else JNE has_cpuinfo -bad_proc: // show that the program requires a certain microarchitecture level. +bad_cpu: // show that the program requires a certain microarchitecture level. MOVQ $2, 0(SP) - MOVQ $bad_proc_msg<>(SB), AX + MOVQ $bad_cpu_msg<>(SB), AX MOVQ AX, 8(SP) - MOVQ $78, 16(SP) + MOVQ $84, 16(SP) CALL runtime·write(SB) MOVQ $1, 0(SP) CALL runtime·exit(SB) @@ -218,14 +215,14 @@ notintel: #ifdef NEED_FEATURES_CX ANDL $NEED_FEATURES_CX, CX CMPL CX, $NEED_FEATURES_CX - JNZ bad_proc + JNE bad_cpu #endif #ifdef NEED_MAX_CPUID MOVL $0x80000000, AX CPUID CMPL AX, $NEED_MAX_CPUID - JL bad_proc + JL bad_cpu #endif #ifdef NEED_EXT_FEATURES_BX @@ -234,7 +231,7 @@ notintel: CPUID ANDL $NEED_EXT_FEATURES_BX, BX CMPL BX, $NEED_EXT_FEATURES_BX - JNZ bad_proc + JNE bad_cpu #endif #ifdef NEED_EXT_FEATURES_CX @@ -242,15 +239,15 @@ notintel: CPUID ANDL $NEED_EXT_FEATURES_CX, CX CMPL CX, $NEED_EXT_FEATURES_CX - JNZ bad_proc + JNE bad_cpu #endif #ifdef NEED_OS_SUPPORT_AX - MOVL $0, CX + XORL CX, CX XGETBV ANDL $NEED_OS_SUPPORT_AX, AX CMPL AX, $NEED_OS_SUPPORT_AX - JNZ bad_proc + JNE bad_cpu #endif nocpuinfo: