From a2b615d5270f0bc2ee1dfcdd7849bdd05ee76a14 Mon Sep 17 00:00:00 2001 From: Lion Yang Date: Thu, 5 Jan 2017 05:13:53 +0800 Subject: crypto: detect BMI usability on AMD64 for sha1 and sha256 The existing implementations on AMD64 only detects AVX2 usability, when they also contains BMI (bit-manipulation instructions). These instructions crash the running program as 'unknown instructions' on the architecture, e.g. i3-4000M, which supports AVX2 but not support BMI. This change added the detections for BMI1 and BMI2 to AMD64 runtime with two flags as the result, `support_bmi1` and `support_bmi2`, in runtime/runtime2.go. It also completed the condition to run AVX2 version in packages crypto/sha1 and crypto/sha256. Fixes #18512 Change-Id: I917bf0de365237740999de3e049d2e8f2a4385ad Reviewed-on: https://go-review.googlesource.com/34850 Reviewed-by: Ian Lance Taylor Run-TryBot: Ian Lance Taylor TryBot-Result: Gobot Gobot --- src/crypto/sha1/sha1block_amd64.s | 18 +++++++++++------- src/crypto/sha256/sha256block_amd64.s | 5 ++++- src/runtime/asm_amd64.s | 15 ++++++++++++++- src/runtime/runtime2.go | 2 ++ 4 files changed, 31 insertions(+), 9 deletions(-) diff --git a/src/crypto/sha1/sha1block_amd64.s b/src/crypto/sha1/sha1block_amd64.s index 0cdb43b422..77c8ec3906 100644 --- a/src/crypto/sha1/sha1block_amd64.s +++ b/src/crypto/sha1/sha1block_amd64.s @@ -225,7 +225,7 @@ end: RET -// This is the implementation using AVX2. It is based on: +// This is the implementation using AVX2, BMI1 and BMI2. It is based on: // "SHA-1 implementation with Intel(R) AVX2 instruction set extensions" // From http://software.intel.com/en-us/articles // (look for improving-the-performance-of-the-secure-hash-algorithm-1) @@ -1459,15 +1459,19 @@ TEXT ·blockAVX2(SB),$1408-32 // func checkAVX2() bool -// returns whether AVX2 is supported +// returns whether AVX2, BMI1 and BMI2 are supported TEXT ·checkAVX2(SB),NOSPLIT,$0 - CMPB runtime·support_avx2(SB), $1 - JE has - MOVB $0, ret+0(FP) - RET -has: + CMPB runtime·support_avx2(SB), $0 + JE noavx2 + CMPB runtime·support_bmi1(SB), $0 // check for ANDNL instruction + JE noavx2 + CMPB runtime·support_bmi2(SB), $0 // check for RORXL instruction + JE noavx2 MOVB $1, ret+0(FP) RET +noavx2: + MOVB $0, ret+0(FP) + RET DATA K_XMM_AR<>+0x00(SB)/4,$0x5a827999 diff --git a/src/crypto/sha256/sha256block_amd64.s b/src/crypto/sha256/sha256block_amd64.s index edf7ad1a3b..e9705b94b1 100644 --- a/src/crypto/sha256/sha256block_amd64.s +++ b/src/crypto/sha256/sha256block_amd64.s @@ -559,8 +559,11 @@ ADDL y3, h // h = t1 + S0 + MAJ // -- TEXT ·block(SB), 0, $536-32 - CMPB runtime·support_avx2(SB), $1 + CMPB runtime·support_avx2(SB), $0 + JE noavx2bmi2 + CMPB runtime·support_bmi2(SB), $1 // check for RORXL instruction JE avx2 +noavx2bmi2: MOVQ p_base+8(FP), SI MOVQ p_len+16(FP), DX diff --git a/src/runtime/asm_amd64.s b/src/runtime/asm_amd64.s index 0070e9d203..cb428d6de3 100644 --- a/src/runtime/asm_amd64.s +++ b/src/runtime/asm_amd64.s @@ -75,11 +75,24 @@ no7: TESTL $(1<<5), runtime·cpuid_ebx7(SB) // check for AVX2 bit JEQ noavx2 MOVB $1, runtime·support_avx2(SB) - JMP nocpuinfo + JMP testbmi1 noavx: MOVB $0, runtime·support_avx(SB) noavx2: MOVB $0, runtime·support_avx2(SB) +testbmi1: + // Detect BMI1 and BMI2 extensions as per + // 5.1.16.1 Detection of VEX-encoded GPR Instructions, + // LZCNT and TZCNT, PREFETCHW chapter of [1] + MOVB $0, runtime·support_bmi1(SB) + TESTL $(1<<3), runtime·cpuid_ebx7(SB) // check for BMI1 bit + JEQ testbmi2 + MOVB $1, runtime·support_bmi1(SB) +testbmi2: + MOVB $0, runtime·support_bmi2(SB) + TESTL $(1<<8), runtime·cpuid_ebx7(SB) // check for BMI2 bit + JEQ nocpuinfo + MOVB $1, runtime·support_bmi2(SB) nocpuinfo: // if there is an _cgo_init, call it. diff --git a/src/runtime/runtime2.go b/src/runtime/runtime2.go index acc9426142..1ceab0ad8c 100644 --- a/src/runtime/runtime2.go +++ b/src/runtime/runtime2.go @@ -745,6 +745,8 @@ var ( lfenceBeforeRdtsc bool support_avx bool support_avx2 bool + support_bmi1 bool + support_bmi2 bool goarm uint8 // set by cmd/link on arm systems framepointer_enabled bool // set by cmd/link -- cgit v1.2.3-54-g00ecf