Browse Source

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 <ilya.tocar@intel.com>
TryBot-Result: Gobot Gobot <gobot@golang.org>
Reviewed-by: Brad Fitzpatrick <bradfitz@golang.org>
Andreas Auernhammer 7 years ago
parent
commit
ae8bce0030

+ 3 - 4
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)
 

+ 0 - 9
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

+ 10 - 16
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)
 	}
 }

+ 0 - 12
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

+ 3 - 4
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)
 

+ 0 - 9
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

+ 8 - 11
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)
 	}
 }

+ 0 - 25
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

+ 10 - 13
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)
 	}
 }

+ 0 - 25
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

+ 7 - 54
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<<bitpos) != 0
-}
-
 // setupState writes a ChaCha20 input matrix to state. See
 // https://tools.ietf.org/html/rfc7539#section-2.3.
 func setupState(state *[16]uint32, key *[8]uint32, nonce []byte) {