Skip to content

Commit

Permalink
crypto/{blake2b,blake2s,argon2,chacha20poly1305}: replace CPU feature…
Browse files Browse the repository at this point in the history
… 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>
  • Loading branch information
Andreas Auernhammer authored and bradfitz committed Apr 30, 2018
1 parent 0301113 commit 41ac450
Show file tree
Hide file tree
Showing 11 changed files with 41 additions and 182 deletions.
7 changes: 3 additions & 4 deletions argon2/blamka_amd64.go
Original file line number Diff line number Diff line change
Expand Up @@ -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)

Expand Down
9 changes: 0 additions & 9 deletions argon2/blamka_amd64.s
Original file line number Diff line number Diff line change
Expand Up @@ -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
26 changes: 10 additions & 16 deletions blake2b/blake2bAVX2_amd64.go
Original file line number Diff line number Diff line change
Expand Up @@ -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)

Expand All @@ -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)
}
}
12 changes: 0 additions & 12 deletions blake2b/blake2bAVX2_amd64.s
Original file line number Diff line number Diff line change
Expand Up @@ -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
7 changes: 3 additions & 4 deletions blake2b/blake2b_amd64.go
Original file line number Diff line number Diff line change
Expand Up @@ -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)

Expand Down
9 changes: 0 additions & 9 deletions blake2b/blake2b_amd64.s
Original file line number Diff line number Diff line change
Expand Up @@ -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
19 changes: 8 additions & 11 deletions blake2s/blake2s_386.go
Original file line number Diff line number Diff line change
Expand Up @@ -6,30 +6,27 @@

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)

//go:noescape
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)
}
}
25 changes: 0 additions & 25 deletions blake2s/blake2s_386.s
Original file line number Diff line number Diff line change
Expand Up @@ -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
23 changes: 10 additions & 13 deletions blake2s/blake2s_amd64.go
Original file line number Diff line number Diff line change
Expand Up @@ -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)

Expand All @@ -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)
}
}
25 changes: 0 additions & 25 deletions blake2s/blake2s_amd64.s
Original file line number Diff line number Diff line change
Expand Up @@ -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
61 changes: 7 additions & 54 deletions chacha20poly1305/chacha20poly1305_amd64.go
Original file line number Diff line number Diff line change
Expand Up @@ -6,70 +6,23 @@

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

//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) {
Expand Down

0 comments on commit 41ac450

Please sign in to comment.