]> Cypherpunks repositories - gostls13.git/commitdiff
internal/cpu: disable FMA when OSXSAVE is not enabled on x86
authorMartin Möhrmann <moehrmann@google.com>
Thu, 3 Dec 2020 15:41:57 +0000 (16:41 +0100)
committerMartin Möhrmann <moehrmann@google.com>
Thu, 3 Dec 2020 16:31:53 +0000 (16:31 +0000)
All instructions in the FMA extension on x86 are VEX prefixed.
VEX prefixed instructions generally require OSXSAVE to be enabled.

The execution of FMA instructions emitted by the Go compiler on amd64
will generate an invalid opcode exception if OSXSAVE is not enabled.

Fixes #41022

Change-Id: I49881630e7195c804110a2bd81b5bec8cac31ba8
Reviewed-on: https://go-review.googlesource.com/c/go/+/274479
Trust: Martin Möhrmann <moehrmann@google.com>
Run-TryBot: Martin Möhrmann <moehrmann@google.com>
TryBot-Result: Go Bot <gobot@golang.org>
Reviewed-by: Keith Randall <khr@golang.org>
src/internal/cpu/cpu_x86.go

index fb414adaf84440864142659baf7d9e8e4bafdf09..ba6bf690342f43785fd1dad3c9ee703ae3ea40c2 100644 (file)
@@ -75,13 +75,22 @@ func doinit() {
        X86.HasSSE3 = isSet(ecx1, cpuid_SSE3)
        X86.HasPCLMULQDQ = isSet(ecx1, cpuid_PCLMULQDQ)
        X86.HasSSSE3 = isSet(ecx1, cpuid_SSSE3)
-       X86.HasFMA = isSet(ecx1, cpuid_FMA)
        X86.HasSSE41 = isSet(ecx1, cpuid_SSE41)
        X86.HasSSE42 = isSet(ecx1, cpuid_SSE42)
        X86.HasPOPCNT = isSet(ecx1, cpuid_POPCNT)
        X86.HasAES = isSet(ecx1, cpuid_AES)
+
+       // OSXSAVE can be false when using older Operating Systems
+       // or when explicitly disabled on newer Operating Systems by
+       // e.g. setting the xsavedisable boot option on Windows 10.
        X86.HasOSXSAVE = isSet(ecx1, cpuid_OSXSAVE)
 
+       // The FMA instruction set extension only has VEX prefixed instructions.
+       // VEX prefixed instructions require OSXSAVE to be enabled.
+       // See Intel 64 and IA-32 Architecture Software Developer’s Manual Volume 2
+       // Section 2.4 "AVX and SSE Instruction Exception Specification"
+       X86.HasFMA = isSet(ecx1, cpuid_FMA) && X86.HasOSXSAVE
+
        osSupportsAVX := false
        // For XGETBV, OSXSAVE bit is required and sufficient.
        if X86.HasOSXSAVE {