From 136d6548885341fcf2aaf36ab6a4a55cd396ed79 Mon Sep 17 00:00:00 2001 From: Andreas Auernhammer <1977446+desdeel2d0m@users.noreply.github.com> Date: Mon, 30 Apr 2018 19:54:52 +0200 Subject: [PATCH] crypto/{blake2b,blake2s,argon2,chacha20poly1305}: replace CPU feature detection This change removes package specific CPU-feature detection code and replaces it with x/sys/cpu. Fixes golang/go#24843 Change-Id: I150dd7b3aeb8eef428c91f9b1df741ceb8a87a24 Reviewed-on: https://go-review.googlesource.com/110355 Run-TryBot: Ilya Tocar TryBot-Result: Gobot Gobot Reviewed-by: Brad Fitzpatrick --- argon2/blamka_amd64.go | 7 ++- argon2/blamka_amd64.s | 9 ---- blake2b/blake2bAVX2_amd64.go | 26 ++++----- blake2b/blake2bAVX2_amd64.s | 12 ----- blake2b/blake2b_amd64.go | 7 ++- blake2b/blake2b_amd64.s | 9 ---- blake2s/blake2s_386.go | 19 +++---- blake2s/blake2s_386.s | 25 --------- blake2s/blake2s_amd64.go | 23 ++++---- blake2s/blake2s_amd64.s | 25 --------- chacha20poly1305/chacha20poly1305_amd64.go | 61 +++------------------- 11 files changed, 41 insertions(+), 182 deletions(-) diff --git a/argon2/blamka_amd64.go b/argon2/blamka_amd64.go index bb2b0d8..2fc1ec0 100644 --- a/argon2/blamka_amd64.go +++ b/argon2/blamka_amd64.go @@ -6,13 +6,12 @@ package argon2 +import "golang.org/x/sys/cpu" + func init() { - useSSE4 = supportsSSE4() + useSSE4 = cpu.X86.HasSSE41 } -//go:noescape -func supportsSSE4() bool - //go:noescape func mixBlocksSSE2(out, a, b, c *block) diff --git a/argon2/blamka_amd64.s b/argon2/blamka_amd64.s index 8a83f7c..74a6e73 100644 --- a/argon2/blamka_amd64.s +++ b/argon2/blamka_amd64.s @@ -241,12 +241,3 @@ loop: SUBQ $2, BP JA loop RET - -// func supportsSSE4() bool -TEXT ·supportsSSE4(SB), 4, $0-1 - MOVL $1, AX - CPUID - SHRL $19, CX // Bit 19 indicates SSE4 support - ANDL $1, CX // CX != 0 if support SSE4 - MOVB CX, ret+0(FP) - RET diff --git a/blake2b/blake2bAVX2_amd64.go b/blake2b/blake2bAVX2_amd64.go index 8c41cf6..4d31dd0 100644 --- a/blake2b/blake2bAVX2_amd64.go +++ b/blake2b/blake2bAVX2_amd64.go @@ -6,21 +6,14 @@ package blake2b +import "golang.org/x/sys/cpu" + func init() { - useAVX2 = supportsAVX2() - useAVX = supportsAVX() - useSSE4 = supportsSSE4() + useAVX2 = cpu.X86.HasAVX2 + useAVX = cpu.X86.HasAVX + useSSE4 = cpu.X86.HasSSE41 } -//go:noescape -func supportsSSE4() bool - -//go:noescape -func supportsAVX() bool - -//go:noescape -func supportsAVX2() bool - //go:noescape func hashBlocksAVX2(h *[8]uint64, c *[2]uint64, flag uint64, blocks []byte) @@ -31,13 +24,14 @@ func hashBlocksAVX(h *[8]uint64, c *[2]uint64, flag uint64, blocks []byte) func hashBlocksSSE4(h *[8]uint64, c *[2]uint64, flag uint64, blocks []byte) func hashBlocks(h *[8]uint64, c *[2]uint64, flag uint64, blocks []byte) { - if useAVX2 { + switch { + case useAVX2: hashBlocksAVX2(h, c, flag, blocks) - } else if useAVX { + case useAVX: hashBlocksAVX(h, c, flag, blocks) - } else if useSSE4 { + case useSSE4: hashBlocksSSE4(h, c, flag, blocks) - } else { + default: hashBlocksGeneric(h, c, flag, blocks) } } diff --git a/blake2b/blake2bAVX2_amd64.s b/blake2b/blake2bAVX2_amd64.s index 784bce6..5593b1b 100644 --- a/blake2b/blake2bAVX2_amd64.s +++ b/blake2b/blake2bAVX2_amd64.s @@ -748,15 +748,3 @@ noinc: MOVQ BP, SP RET - -// func supportsAVX2() bool -TEXT ·supportsAVX2(SB), 4, $0-1 - MOVQ runtime·support_avx2(SB), AX - MOVB AX, ret+0(FP) - RET - -// func supportsAVX() bool -TEXT ·supportsAVX(SB), 4, $0-1 - MOVQ runtime·support_avx(SB), AX - MOVB AX, ret+0(FP) - RET diff --git a/blake2b/blake2b_amd64.go b/blake2b/blake2b_amd64.go index 2ab7c30..30e2fcd 100644 --- a/blake2b/blake2b_amd64.go +++ b/blake2b/blake2b_amd64.go @@ -6,13 +6,12 @@ package blake2b +import "golang.org/x/sys/cpu" + func init() { - useSSE4 = supportsSSE4() + useSSE4 = cpu.X86.HasSSE41 } -//go:noescape -func supportsSSE4() bool - //go:noescape func hashBlocksSSE4(h *[8]uint64, c *[2]uint64, flag uint64, blocks []byte) diff --git a/blake2b/blake2b_amd64.s b/blake2b/blake2b_amd64.s index 6453074..578e947 100644 --- a/blake2b/blake2b_amd64.s +++ b/blake2b/blake2b_amd64.s @@ -279,12 +279,3 @@ noinc: MOVQ BP, SP RET - -// func supportsSSE4() bool -TEXT ·supportsSSE4(SB), 4, $0-1 - MOVL $1, AX - CPUID - SHRL $19, CX // Bit 19 indicates SSE4 support - ANDL $1, CX // CX != 0 if support SSE4 - MOVB CX, ret+0(FP) - RET diff --git a/blake2s/blake2s_386.go b/blake2s/blake2s_386.go index 45ae546..d8f9cea 100644 --- a/blake2s/blake2s_386.go +++ b/blake2s/blake2s_386.go @@ -6,18 +6,14 @@ package blake2s +import "golang.org/x/sys/cpu" + var ( useSSE4 = false - useSSSE3 = supportSSSE3() - useSSE2 = supportSSE2() + useSSSE3 = cpu.X86.HasSSSE3 + useSSE2 = cpu.X86.HasSSE2 ) -//go:noescape -func supportSSE2() bool - -//go:noescape -func supportSSSE3() bool - //go:noescape func hashBlocksSSE2(h *[8]uint32, c *[2]uint32, flag uint32, blocks []byte) @@ -25,11 +21,12 @@ func hashBlocksSSE2(h *[8]uint32, c *[2]uint32, flag uint32, blocks []byte) func hashBlocksSSSE3(h *[8]uint32, c *[2]uint32, flag uint32, blocks []byte) func hashBlocks(h *[8]uint32, c *[2]uint32, flag uint32, blocks []byte) { - if useSSSE3 { + switch { + case useSSSE3: hashBlocksSSSE3(h, c, flag, blocks) - } else if useSSE2 { + case useSSE2: hashBlocksSSE2(h, c, flag, blocks) - } else { + default: hashBlocksGeneric(h, c, flag, blocks) } } diff --git a/blake2s/blake2s_386.s b/blake2s/blake2s_386.s index 0bb65c7..c123e5d 100644 --- a/blake2s/blake2s_386.s +++ b/blake2s/blake2s_386.s @@ -433,28 +433,3 @@ loop: MOVL BP, SP RET - -// func supportSSSE3() bool -TEXT ·supportSSSE3(SB), 4, $0-1 - MOVL $1, AX - CPUID - MOVL CX, BX - ANDL $0x1, BX // supports SSE3 - JZ FALSE - ANDL $0x200, CX // supports SSSE3 - JZ FALSE - MOVB $1, ret+0(FP) - RET - -FALSE: - MOVB $0, ret+0(FP) - RET - -// func supportSSE2() bool -TEXT ·supportSSE2(SB), 4, $0-1 - MOVL $1, AX - CPUID - SHRL $26, DX - ANDL $1, DX // DX != 0 if support SSE2 - MOVB DX, ret+0(FP) - RET diff --git a/blake2s/blake2s_amd64.go b/blake2s/blake2s_amd64.go index a925e6b..4e8d2d7 100644 --- a/blake2s/blake2s_amd64.go +++ b/blake2s/blake2s_amd64.go @@ -6,18 +6,14 @@ package blake2s +import "golang.org/x/sys/cpu" + var ( - useSSE4 = supportSSE4() - useSSSE3 = supportSSSE3() - useSSE2 = true // Always available on amd64 + useSSE4 = cpu.X86.HasSSE41 + useSSSE3 = cpu.X86.HasSSSE3 + useSSE2 = cpu.X86.HasSSE2 ) -//go:noescape -func supportSSSE3() bool - -//go:noescape -func supportSSE4() bool - //go:noescape func hashBlocksSSE2(h *[8]uint32, c *[2]uint32, flag uint32, blocks []byte) @@ -28,13 +24,14 @@ func hashBlocksSSSE3(h *[8]uint32, c *[2]uint32, flag uint32, blocks []byte) func hashBlocksSSE4(h *[8]uint32, c *[2]uint32, flag uint32, blocks []byte) func hashBlocks(h *[8]uint32, c *[2]uint32, flag uint32, blocks []byte) { - if useSSE4 { + switch { + case useSSE4: hashBlocksSSE4(h, c, flag, blocks) - } else if useSSSE3 { + case useSSSE3: hashBlocksSSSE3(h, c, flag, blocks) - } else if useSSE2 { + case useSSE2: hashBlocksSSE2(h, c, flag, blocks) - } else { + default: hashBlocksGeneric(h, c, flag, blocks) } } diff --git a/blake2s/blake2s_amd64.s b/blake2s/blake2s_amd64.s index 6cdf5a9..8da2802 100644 --- a/blake2s/blake2s_amd64.s +++ b/blake2s/blake2s_amd64.s @@ -436,28 +436,3 @@ TEXT ·hashBlocksSSSE3(SB), 0, $672-48 // frame = 656 + 16 byte alignment TEXT ·hashBlocksSSE4(SB), 0, $32-48 // frame = 16 + 16 byte alignment HASH_BLOCKS(h+0(FP), c+8(FP), flag+16(FP), blocks_base+24(FP), blocks_len+32(FP), BLAKE2s_SSE4) RET - -// func supportSSE4() bool -TEXT ·supportSSE4(SB), 4, $0-1 - MOVL $1, AX - CPUID - SHRL $19, CX // Bit 19 indicates SSE4.1. - ANDL $1, CX - MOVB CX, ret+0(FP) - RET - -// func supportSSSE3() bool -TEXT ·supportSSSE3(SB), 4, $0-1 - MOVL $1, AX - CPUID - MOVL CX, BX - ANDL $0x1, BX // Bit zero indicates SSE3 support. - JZ FALSE - ANDL $0x200, CX // Bit nine indicates SSSE3 support. - JZ FALSE - MOVB $1, ret+0(FP) - RET - -FALSE: - MOVB $0, ret+0(FP) - RET diff --git a/chacha20poly1305/chacha20poly1305_amd64.go b/chacha20poly1305/chacha20poly1305_amd64.go index 17f94e9..ff21390 100644 --- a/chacha20poly1305/chacha20poly1305_amd64.go +++ b/chacha20poly1305/chacha20poly1305_amd64.go @@ -6,7 +6,11 @@ package chacha20poly1305 -import "encoding/binary" +import ( + "encoding/binary" + + "golang.org/x/sys/cpu" +) //go:noescape func chacha20Poly1305Open(dst []byte, key []uint32, src, ad []byte) bool @@ -14,62 +18,11 @@ func chacha20Poly1305Open(dst []byte, key []uint32, src, ad []byte) bool //go:noescape func chacha20Poly1305Seal(dst []byte, key []uint32, src, ad []byte) -// cpuid is implemented in chacha20poly1305_amd64.s. -func cpuid(eaxArg, ecxArg uint32) (eax, ebx, ecx, edx uint32) - -// xgetbv with ecx = 0 is implemented in chacha20poly1305_amd64.s. -func xgetbv() (eax, edx uint32) - var ( - useASM bool - useAVX2 bool + useASM = cpu.X86.HasSSSE3 + useAVX2 = cpu.X86.HasAVX2 ) -func init() { - detectCPUFeatures() -} - -// detectCPUFeatures is used to detect if cpu instructions -// used by the functions implemented in assembler in -// chacha20poly1305_amd64.s are supported. -func detectCPUFeatures() { - maxID, _, _, _ := cpuid(0, 0) - if maxID < 1 { - return - } - - _, _, ecx1, _ := cpuid(1, 0) - - haveSSSE3 := isSet(9, ecx1) - useASM = haveSSSE3 - - haveOSXSAVE := isSet(27, ecx1) - - osSupportsAVX := false - // For XGETBV, OSXSAVE bit is required and sufficient. - if haveOSXSAVE { - eax, _ := xgetbv() - // Check if XMM and YMM registers have OS support. - osSupportsAVX = isSet(1, eax) && isSet(2, eax) - } - haveAVX := isSet(28, ecx1) && osSupportsAVX - - if maxID < 7 { - return - } - - _, ebx7, _, _ := cpuid(7, 0) - haveAVX2 := isSet(5, ebx7) && haveAVX - haveBMI2 := isSet(8, ebx7) - - useAVX2 = haveAVX2 && haveBMI2 -} - -// isSet checks if bit at bitpos is set in value. -func isSet(bitpos uint, value uint32) bool { - return value&(1<