Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
10 changes: 9 additions & 1 deletion src/internal/cpu/cpu_x86.go
Original file line number Diff line number Diff line change
Expand Up @@ -74,6 +74,7 @@ func doinit() {
{Name: "aes", Feature: &X86.HasAES},
{Name: "erms", Feature: &X86.HasERMS},
{Name: "fsrm", Feature: &X86.HasFSRM},
{Name: "gfni", Feature: &X86.HasGFNI},
{Name: "pclmulqdq", Feature: &X86.HasPCLMULQDQ},
{Name: "rdtscp", Feature: &X86.HasRDTSCP},
{Name: "sha", Feature: &X86.HasSHA},
Expand Down Expand Up @@ -175,6 +176,14 @@ func doinit() {
X86.HasSHA = isSet(ebx7, cpuid_SHA)
X86.HasVAES = isSet(ecx7, cpuid_VAES) && X86.HasAVX

// GFNI is available in VEX-encoded form on every CPU that reports the
// GFNI bit (CPUID leaf 7 ECX bit 8) and supports YMM, regardless of
// AVX-512. Gate on HasAVX (which requires OSXSAVE + YMM OS support) so
// callers can safely emit VEX-256 VGF2P8AFFINEQB on YMM. The
// EVEX-encoded form additionally requires AVX-512F; see HasAVX512GFNI
// below.
X86.HasGFNI = isSet(ecx7, cpuid_GFNI) && X86.HasAVX

X86.HasAVX512F = isSet(ebx7, cpuid_AVX512F) && osSupportsAVX512
if X86.HasAVX512F {
X86.HasAVX512CD = isSet(ebx7, cpuid_AVX512CD)
Expand All @@ -191,7 +200,6 @@ func doinit() {
X86.HasAVX512VPCLMULQDQ = isSet(ecx7, cpuid_AVX512VPCLMULQDQ)
X86.HasAVX512VBMI = isSet(ecx7, cpuid_AVX512_VBMI)
X86.HasAVX512VBMI2 = isSet(ecx7, cpuid_AVX512_VBMI2)
X86.HasGFNI = isSet(ecx7, cpuid_GFNI)
X86.HasAVX512BITALG = isSet(ecx7, cpuid_AVX512_BITALG)
}

Expand Down
60 changes: 60 additions & 0 deletions src/internal/cpu/cpu_x86_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -36,6 +36,46 @@ func TestX86ifAVX512VLhasAVX512F(t *testing.T) {
}
}

func TestX86ifGFNIhasAVX(t *testing.T) {
if X86.HasGFNI && !X86.HasAVX {
t.Fatalf("HasAVX expected true when HasGFNI is true, got false")
}
}

func TestX86ifAVX512GFNIhasGFNI(t *testing.T) {
// Skip if GODEBUG explicitly disabled gfni (directly or via cpu.all=off);
// processOptions would have cleared X86.HasGFNI but not X86.HasAVX512GFNI
// (which is not in the options table), so the invariant below would
// spuriously fire even though the hardware reports both bits.
if godebug.New("#cpu.gfni").Value() == "off" || godebug.New("#cpu.all").Value() == "off" {
t.Skip("skipping test: GODEBUG=cpu.gfni=off set")
}
if X86.HasAVX512GFNI && !X86.HasGFNI {
t.Fatalf("HasGFNI expected true when HasAVX512GFNI is true, got false")
}
}

func TestX86ifCPUIDGFNIhasGFNI(t *testing.T) {
if !X86.HasAVX {
t.Skip("skipping test: requires AVX (and thus YMM OS support)")
}
// Skip if GODEBUG explicitly disabled gfni (directly or via cpu.all=off);
// processOptions would have cleared X86.HasGFNI regardless of hardware
// state, so the CPUID comparison below would spuriously fire.
if godebug.New("#cpu.gfni").Value() == "off" || godebug.New("#cpu.all").Value() == "off" {
t.Skip("skipping test: GODEBUG=cpu.gfni=off set")
}
maxID, _, _, _ := Cpuid(0, 0)
if maxID < 7 {
t.Skip("skipping test: CPUID leaf 7 unavailable")
}
_, _, ecx7, _ := Cpuid(7, 0)
const gfniBit = 1 << 8
if ecx7&gfniBit != 0 && !X86.HasGFNI {
t.Fatalf("HasGFNI expected true when CPUID leaf 7 ECX bit 8 is set, got false")
}
}

func TestDisableSSE3(t *testing.T) {
if GetGOAMD64level() > 1 {
t.Skip("skipping test: can't run on GOAMD64>v1 machines")
Expand All @@ -55,3 +95,23 @@ func TestSSE3DebugOption(t *testing.T) {
t.Errorf("X86.HasSSE3 expected %v, got %v", want, got)
}
}

func TestDisableGFNI(t *testing.T) {
if !X86.HasGFNI {
t.Skip("skipping test: host does not advertise GFNI")
}
runDebugOptionsTest(t, "TestGFNIDebugOption", "cpu.gfni=off")
}

func TestGFNIDebugOption(t *testing.T) {
MustHaveDebugOptionsSupport(t)

if godebug.New("#cpu.gfni").Value() != "off" {
t.Skipf("skipping test: GODEBUG=cpu.gfni=off not set")
}

want := false
if got := X86.HasGFNI; got != want {
t.Errorf("X86.HasGFNI expected %v, got %v", want, got)
}
}
1 change: 1 addition & 0 deletions src/internal/cpu/export_x86_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -8,4 +8,5 @@ package cpu

var (
GetGOAMD64level = getGOAMD64level
Cpuid = cpuid
)