瀏覽代碼

Use CPUID to get information about CPU capabilities

Using golang.org/x/sys/cpu would be really great, but it makes it
hard to vendor the library with go 1.10.
This patch gets information about CPU capabilities directly from CPUID
trials/PERF_try3
Kris Kwiatkowski 6 年之前
committed by Kris Kwiatkowski
父節點
當前提交
e33ddfeb80
共有 7 個檔案被更改,包括 64 行新增17 行删除
  1. +1
    -2
      Makefile
  2. +34
    -0
      internal/utils/cpuid.go
  3. +13
    -0
      internal/utils/cpuid.s
  4. +5
    -5
      p503/arith_amd64_test.go
  5. +3
    -3
      p503/arith_decl.go
  6. +5
    -4
      p751/arith_amd64_test.go
  7. +3
    -3
      p751/arith_decl.go

+ 1
- 2
Makefile 查看文件

@@ -4,7 +4,6 @@ PRJ_DIR = $(abspath $(dir $(MK_FILE_PATH)))
GOPATH_LOCAL = $(PRJ_DIR)/build
GOPATH_DIR = github.com/cloudflare/p751sidh
CSHAKE_PKG ?= github.com/henrydcase/nobs/hash/sha3
CPU_PKG = golang.org/x/sys/cpu
TARGETS = p503 p751 sidh sike
GO ?= go
GOARCH ?=
@@ -32,7 +31,7 @@ clean:
rm -rf coverage*.txt

build_env:
GOPATH=$(GOPATH_LOCAL) $(GO) get $(CSHAKE_PKG) $(CPU_PKG)
GOPATH=$(GOPATH_LOCAL) $(GO) get $(CSHAKE_PKG)
mkdir -p $(GOPATH_LOCAL)/src/$(GOPATH_DIR)
cp -rf internal $(GOPATH_LOCAL)/src/$(GOPATH_DIR)
cp -rf etc $(GOPATH_LOCAL)/src/$(GOPATH_DIR)


+ 34
- 0
internal/utils/cpuid.go 查看文件

@@ -0,0 +1,34 @@
// +build amd64, !noasm

// Sets capabilities flags for x86 according to information received from
// CPUID. It was written in accordance with
// "Intel® 64 and IA-32 Architectures Developer's Manual: Vol. 2A".
// https://www.intel.com/content/www/us/en/architecture-and-technology/64-ia-32-architectures-software-developer-vol-2a-manual.html

package utils

// Signals support for MULX which is in BMI2
var HasBMI2 bool
// Signals support for MULX and BMI2
var HasADX bool

// Performs CPUID and returns values of registers
// go:nosplit
func cpuid(eaxArg, ecxArg uint32) (eax, ebx, ecx, edx uint32)

// Returns true in case bit 'n' in 'bits' is set, otherwise false
func bitn(bits uint32, n uint8) bool {
return (bits>>n)&1 == 1
}

func init() {
// CPUID returns max possible input that can be requested
max, _, _, _ := cpuid(0,0)
if max < 7 {
return
}

_, ebx, _, _ := cpuid(7,0)
HasBMI2 = bitn(ebx, 19)
HasADX = bitn(ebx, 7)
}

+ 13
- 0
internal/utils/cpuid.s 查看文件

@@ -0,0 +1,13 @@
// +build amd64,!noasm

#include "textflag.h"

TEXT ·cpuid(SB), NOSPLIT, $0-4
MOVL eaxArg+0(FP), AX
MOVL ecxArg+4(FP), CX
CPUID
MOVL AX, eax+8(FP)
MOVL BX, ebx+12(FP)
MOVL CX, ecx+16(FP)
MOVL DX, edx+20(FP)
RET

+ 5
- 5
p503/arith_amd64_test.go 查看文件

@@ -4,7 +4,7 @@ package p503

import (
. "github.com/cloudflare/p751sidh/internal/isogeny"
"golang.org/x/sys/cpu"
cpu "github.com/cloudflare/p751sidh/internal/utils"
"reflect"
"testing"
"testing/quick"
@@ -43,7 +43,7 @@ func testRedc(t *testing.T, redcFunc func(z *FpElement, x *FpElementX2)) {

// Ensures corretness of implementation of mul operation which uses MULX
func TestMulWithMULX(t *testing.T) {
if !cpu.X86.HasBMI2 {
if !cpu.HasBMI2 {
t.Skip("MULX not supported by the platform")
}
testMul(t, mulWithMULX)
@@ -51,7 +51,7 @@ func TestMulWithMULX(t *testing.T) {

// Ensures corretness of implementation of mul operation which uses MULX and ADOX/ADCX
func TestMulWithMULXADX(t *testing.T) {
if !(cpu.X86.HasADX && cpu.X86.HasBMI2) {
if !(cpu.HasADX && cpu.HasBMI2) {
t.Skip("MULX, ADCX and ADOX not supported by the platform")
}
testMul(t, mulWithMULXADX)
@@ -59,7 +59,7 @@ func TestMulWithMULXADX(t *testing.T) {

// Ensures corretness of Montgomery reduction implementation which uses MULX
func TestRedcWithMULX(t *testing.T) {
if !cpu.X86.HasBMI2 {
if !cpu.HasBMI2 {
t.Skip("MULX not supported by the platform")
}
testRedc(t, redcWithMULX)
@@ -67,7 +67,7 @@ func TestRedcWithMULX(t *testing.T) {

// Ensures corretness of Montgomery reduction implementation which uses MULX
func TestRedcWithMULXADX(t *testing.T) {
if !(cpu.X86.HasADX && cpu.X86.HasBMI2) {
if !(cpu.HasADX && cpu.HasBMI2) {
t.Skip("MULX, ADCX and ADOX not supported by the platform")
}
testRedc(t, redcWithMULXADX)


+ 3
- 3
p503/arith_decl.go 查看文件

@@ -4,7 +4,7 @@ package p503

import (
. "github.com/cloudflare/p751sidh/internal/isogeny"
"golang.org/x/sys/cpu"
cpu "github.com/cloudflare/p751sidh/internal/utils"
)

// If choice = 0, leave x,y unchanged. If choice = 1, set x,y = y,x.
@@ -74,8 +74,8 @@ func redcWithMULXADX(z *FpElement, x *FpElementX2)
// On initialization, set the fp503Mul function pointer to the
// fastest implementation depending on CPU capabilities.
func init() {
if cpu.X86.HasBMI2 {
if cpu.X86.HasADX {
if cpu.HasBMI2 {
if cpu.HasADX {
fp503Mul = mulWithMULXADX
fp503MontgomeryReduce = redcWithMULXADX
} else {


+ 5
- 4
p751/arith_amd64_test.go 查看文件

@@ -3,10 +3,11 @@
package p751

import (
"golang.org/x/sys/cpu"
. "github.com/cloudflare/p751sidh/internal/isogeny"
cpu "github.com/cloudflare/p751sidh/internal/utils"

"testing"
"testing/quick"
. "github.com/cloudflare/p751sidh/internal/isogeny"
)

func TestFp751MontgomeryReduce(t *testing.T) {
@@ -15,7 +16,7 @@ func TestFp751MontgomeryReduce(t *testing.T) {
fp751MontgomeryReduce = fp751MontgomeryReduceFallback
t.Run("PrimeFieldElementToBigInt", TestPrimeFieldElementToBigInt)

if !cpu.X86.HasBMI2 {
if !cpu.HasBMI2 {
return
}

@@ -43,7 +44,7 @@ func TestFp751MontgomeryReduce(t *testing.T) {
t.Error(err)
}

if !cpu.X86.HasADX {
if !cpu.HasADX {
return
}



+ 3
- 3
p751/arith_decl.go 查看文件

@@ -3,7 +3,7 @@
package p751

import (
"golang.org/x/sys/cpu"
cpu "github.com/cloudflare/p751sidh/internal/utils"
. "github.com/cloudflare/p751sidh/internal/isogeny"
)

@@ -59,8 +59,8 @@ func fp751StrongReduce(x *FpElement)
// On initialization, set the fp751MontgomeryReduce function pointer to the
// fastest implementation depending on CPU capabilities.
func init() {
if cpu.X86.HasBMI2 {
if cpu.X86.HasADX {
if cpu.HasBMI2 {
if cpu.HasADX {
fp751MontgomeryReduce = fp751MontgomeryReduceBMI2ADX
} else {
fp751MontgomeryReduce = fp751MontgomeryReduceBMI2


Loading…
取消
儲存