]> Cypherpunks repositories - gostls13.git/commitdiff
internal/cpu: add invalid option warnings and support to enable cpu features
authorMartin Möhrmann <moehrmann@google.com>
Fri, 12 Oct 2018 17:17:21 +0000 (19:17 +0200)
committerMartin Möhrmann <moehrmann@google.com>
Mon, 15 Oct 2018 21:46:44 +0000 (21:46 +0000)
This CL adds the ability to enable the cpu feature FEATURE by specifying
FEATURE=on in GODEBUGCPU. Syntax support to enable cpu features is useful
in combination with a preceeding all=off to disable all but some specific
cpu features. Example:

GODEBUGCPU=all=off,sse3=on

This CL implements printing of warnings for invalid GODEBUGCPU settings:
- requests enabling features that are not supported with the current CPU
- specifying values different than 'on' or 'off' for a feature
- settings for unkown cpu feature names

Updates #27218

Change-Id: Ic13e5c4c35426a390c50eaa4bd2a408ef2ee21be
Reviewed-on: https://go-review.googlesource.com/c/141800
Run-TryBot: Martin Möhrmann <moehrmann@google.com>
TryBot-Result: Gobot Gobot <gobot@golang.org>
Reviewed-by: Keith Randall <khr@golang.org>
src/internal/cpu/cpu.go
src/internal/cpu/cpu_arm.go
src/internal/cpu/cpu_arm64.go
src/internal/cpu/cpu_ppc64x.go
src/internal/cpu/cpu_s390x.go
src/internal/cpu/cpu_test.go
src/internal/cpu/cpu_x86.go
src/internal/cpu/cpu_x86_test.go

index 1f3411cc7200ddb2d72ca66dfc3bf47a1ccef686..925e4f7f6e786bbe3ca32ef49f8d1088e40aede1 100644 (file)
@@ -153,16 +153,18 @@ var options []option
 
 // Option names should be lower case. e.g. avx instead of AVX.
 type option struct {
-       Name    string
-       Feature *bool
+       Name      string
+       Feature   *bool
+       Specified bool // Stores if feature value was specified in GODEBUGCPU.
+       Enable    bool // Stores if feature should be enabled.
 }
 
-// processOptions disables CPU feature values based on the parsed env string.
-// The env string is expected to be of the form feature1=off,feature2=off...
+// processOptions enables or disables CPU feature values based on the parsed env string.
+// The env string is expected to be of the form feature1=value1,feature2=value2...
 // where feature names is one of the architecture specifc list stored in the
-// cpu packages options variable. If env contains all=off then all capabilities
-// referenced through the options variable are disabled. Other feature
-// names and values other than 'off' are silently ignored.
+// cpu packages options variable and values are either 'on' or 'off'.
+// If env contains all=off then all cpu features referenced through the options
+// variable are disabled. Other feature names and values result in warning messages.
 func processOptions(env string) {
 field:
        for env != "" {
@@ -175,26 +177,52 @@ field:
                }
                i = indexByte(field, '=')
                if i < 0 {
+                       print("GODEBUGCPU: no value specified for \"", field, "\"\n")
                        continue
                }
                key, value := field[:i], field[i+1:]
 
-               // Only allow turning off CPU features by specifying 'off'.
-               if value == "off" {
-                       if key == "all" {
-                               for _, v := range options {
-                                       *v.Feature = false
-                               }
-                               return
-                       } else {
-                               for _, v := range options {
-                                       if v.Name == key {
-                                               *v.Feature = false
-                                               continue field
-                                       }
-                               }
+               var enable bool
+               switch value {
+               case "on":
+                       enable = true
+               case "off":
+                       enable = false
+               default:
+                       print("GODEBUGCPU: value \"", value, "\" not supported for option ", key, "\n")
+                       continue field
+               }
+
+               if key == "all" {
+                       for i := range options {
+                               options[i].Specified = true
+                               options[i].Enable = enable
                        }
+                       continue field
+               }
+
+               for i := range options {
+                       if options[i].Name == key {
+                               options[i].Specified = true
+                               options[i].Enable = enable
+                               continue field
+                       }
+               }
+
+               print("GODEBUGCPU: unknown cpu feature \"", key, "\"\n")
+       }
+
+       for _, o := range options {
+               if !o.Specified {
+                       continue
                }
+
+               if o.Enable && !*o.Feature {
+                       print("GODEBUGCPU: can not enable \"", o.Name, "\", missing hardware support\n")
+                       continue
+               }
+
+               *o.Feature = o.Enable
        }
 }
 
index 1c3e529190af43c06e694bab0b6e1c2eaff11f8b..772b67147c8d3a06cc08111fd8359470056f4239 100644 (file)
@@ -21,8 +21,8 @@ const (
 
 func doinit() {
        options = []option{
-               {"vfpv4", &ARM.HasVFPv4},
-               {"idiva", &ARM.HasIDIVA},
+               {Name: "vfpv4", Feature: &ARM.HasVFPv4},
+               {Name: "idiva", Feature: &ARM.HasIDIVA},
        }
 
        // HWCAP feature bits
index ad930af005f11263505e7f2cf1186f3bbff291f7..25482a1f7ef1a4a9d0006018e5595fd0dbd901b9 100644 (file)
@@ -42,32 +42,32 @@ const (
 
 func doinit() {
        options = []option{
-               {"evtstrm", &ARM64.HasEVTSTRM},
-               {"aes", &ARM64.HasAES},
-               {"pmull", &ARM64.HasPMULL},
-               {"sha1", &ARM64.HasSHA1},
-               {"sha2", &ARM64.HasSHA2},
-               {"crc32", &ARM64.HasCRC32},
-               {"atomics", &ARM64.HasATOMICS},
-               {"fphp", &ARM64.HasFPHP},
-               {"asimdhp", &ARM64.HasASIMDHP},
-               {"cpuid", &ARM64.HasCPUID},
-               {"asimdrdm", &ARM64.HasASIMDRDM},
-               {"jscvt", &ARM64.HasJSCVT},
-               {"fcma", &ARM64.HasFCMA},
-               {"lrcpc", &ARM64.HasLRCPC},
-               {"dcpop", &ARM64.HasDCPOP},
-               {"sha3", &ARM64.HasSHA3},
-               {"sm3", &ARM64.HasSM3},
-               {"sm4", &ARM64.HasSM4},
-               {"asimddp", &ARM64.HasASIMDDP},
-               {"sha512", &ARM64.HasSHA512},
-               {"sve", &ARM64.HasSVE},
-               {"asimdfhm", &ARM64.HasASIMDFHM},
+               {Name: "evtstrm", Feature: &ARM64.HasEVTSTRM},
+               {Name: "aes", Feature: &ARM64.HasAES},
+               {Name: "pmull", Feature: &ARM64.HasPMULL},
+               {Name: "sha1", Feature: &ARM64.HasSHA1},
+               {Name: "sha2", Feature: &ARM64.HasSHA2},
+               {Name: "crc32", Feature: &ARM64.HasCRC32},
+               {Name: "atomics", Feature: &ARM64.HasATOMICS},
+               {Name: "fphp", Feature: &ARM64.HasFPHP},
+               {Name: "asimdhp", Feature: &ARM64.HasASIMDHP},
+               {Name: "cpuid", Feature: &ARM64.HasCPUID},
+               {Name: "asimdrdm", Feature: &ARM64.HasASIMDRDM},
+               {Name: "jscvt", Feature: &ARM64.HasJSCVT},
+               {Name: "fcma", Feature: &ARM64.HasFCMA},
+               {Name: "lrcpc", Feature: &ARM64.HasLRCPC},
+               {Name: "dcpop", Feature: &ARM64.HasDCPOP},
+               {Name: "sha3", Feature: &ARM64.HasSHA3},
+               {Name: "sm3", Feature: &ARM64.HasSM3},
+               {Name: "sm4", Feature: &ARM64.HasSM4},
+               {Name: "asimddp", Feature: &ARM64.HasASIMDDP},
+               {Name: "sha512", Feature: &ARM64.HasSHA512},
+               {Name: "sve", Feature: &ARM64.HasSVE},
+               {Name: "asimdfhm", Feature: &ARM64.HasASIMDFHM},
 
                // These capabilities should always be enabled on arm64:
-               //  {"fp", &ARM64.HasFP},
-               //  {"asimd", &ARM64.HasASIMD},
+               //  {Name: "fp", Feature: &ARM64.HasFP},
+               //  {Name: "asimd", Feature: &ARM64.HasASIMD},
        }
 
        // HWCAP feature bits
index 0195e663c60d73c0d8e0b73ad5d47e302ed45c13..b39f5f5bbbb7af9a133988e07f48ee608e14d38a 100644 (file)
@@ -34,17 +34,17 @@ const (
 
 func doinit() {
        options = []option{
-               {"htm", &PPC64.HasHTM},
-               {"htmnosc", &PPC64.HasHTMNOSC},
-               {"darn", &PPC64.HasDARN},
-               {"scv", &PPC64.HasSCV},
+               {Name: "htm", Feature: &PPC64.HasHTM},
+               {Name: "htmnosc", Feature: &PPC64.HasHTMNOSC},
+               {Name: "darn", Feature: &PPC64.HasDARN},
+               {Name: "scv", Feature: &PPC64.HasSCV},
 
                // These capabilities should always be enabled on ppc64 and ppc64le:
-               //  {"vmx", &PPC64.HasVMX},
-               //  {"dfp", &PPC64.HasDFP},
-               //  {"vsx", &PPC64.HasVSX},
-               //  {"isel", &PPC64.HasISEL},
-               //  {"vcrypto", &PPC64.HasVCRYPTO},
+               //  {Name: "vmx", Feature: &PPC64.HasVMX},
+               //  {Name: "dfp", Feature: &PPC64.HasDFP},
+               //  {Name: "vsx", Feature: &PPC64.HasVSX},
+               //  {Name: "isel", Feature: &PPC64.HasISEL},
+               //  {Name: "vcrypto", Feature: &PPC64.HasVCRYPTO},
        }
 
        // HWCAP feature bits
index 23484b2950878de59cd16badec7383e616876a29..eab77e6ee544177559de4c5e38794096b1b6d9d8 100644 (file)
@@ -107,14 +107,14 @@ func klmdQuery() queryResult
 
 func doinit() {
        options = []option{
-               {"zarch", &S390X.HasZArch},
-               {"stfle", &S390X.HasSTFLE},
-               {"ldisp", &S390X.HasLDisp},
-               {"msa", &S390X.HasMSA},
-               {"eimm", &S390X.HasEImm},
-               {"dfp", &S390X.HasDFP},
-               {"etf3eh", &S390X.HasETF3Enhanced},
-               {"vx", &S390X.HasVX},
+               {Name: "zarch", Feature: &S390X.HasZArch},
+               {Name: "stfle", Feature: &S390X.HasSTFLE},
+               {Name: "ldisp", Feature: &S390X.HasLDisp},
+               {Name: "msa", Feature: &S390X.HasMSA},
+               {Name: "eimm", Feature: &S390X.HasEImm},
+               {Name: "dfp", Feature: &S390X.HasDFP},
+               {Name: "etf3eh", Feature: &S390X.HasETF3Enhanced},
+               {Name: "vx", Feature: &S390X.HasVX},
        }
 
        aes := []function{aes128, aes192, aes256}
index 6e7375fa7cdc3a92b6dddf8f3d2b48573c3df2f5..6b4baa169412cdace0e8e4f555bf6e975cde3f26 100644 (file)
@@ -30,7 +30,10 @@ func runDebugOptionsTest(t *testing.T, test string, options string) {
        cmd.Env = append(cmd.Env, env)
 
        output, err := cmd.CombinedOutput()
-       got := strings.TrimSpace(string(output))
+       lines := strings.Fields(string(output))
+       lastline := lines[len(lines)-1]
+
+       got := strings.TrimSpace(lastline)
        want := "PASS"
        if err != nil || got != want {
                t.Fatalf("%s with %s: want %s, got %v", test, env, want, got)
index 0b00779a906411d49047f613994d04d2760f3248..014c8018f3660fc74f4d988840ce411795a85c50 100644 (file)
@@ -40,23 +40,23 @@ const (
 
 func doinit() {
        options = []option{
-               {"adx", &X86.HasADX},
-               {"aes", &X86.HasAES},
-               {"avx", &X86.HasAVX},
-               {"avx2", &X86.HasAVX2},
-               {"bmi1", &X86.HasBMI1},
-               {"bmi2", &X86.HasBMI2},
-               {"erms", &X86.HasERMS},
-               {"fma", &X86.HasFMA},
-               {"pclmulqdq", &X86.HasPCLMULQDQ},
-               {"popcnt", &X86.HasPOPCNT},
-               {"sse3", &X86.HasSSE3},
-               {"sse41", &X86.HasSSE41},
-               {"sse42", &X86.HasSSE42},
-               {"ssse3", &X86.HasSSSE3},
+               {Name: "adx", Feature: &X86.HasADX},
+               {Name: "aes", Feature: &X86.HasAES},
+               {Name: "avx", Feature: &X86.HasAVX},
+               {Name: "avx2", Feature: &X86.HasAVX2},
+               {Name: "bmi1", Feature: &X86.HasBMI1},
+               {Name: "bmi2", Feature: &X86.HasBMI2},
+               {Name: "erms", Feature: &X86.HasERMS},
+               {Name: "fma", Feature: &X86.HasFMA},
+               {Name: "pclmulqdq", Feature: &X86.HasPCLMULQDQ},
+               {Name: "popcnt", Feature: &X86.HasPOPCNT},
+               {Name: "sse3", Feature: &X86.HasSSE3},
+               {Name: "sse41", Feature: &X86.HasSSE41},
+               {Name: "sse42", Feature: &X86.HasSSE42},
+               {Name: "ssse3", Feature: &X86.HasSSSE3},
 
                // sse2 set as last element so it can easily be removed again. See code below.
-               {"sse2", &X86.HasSSE2},
+               {Name: "sse2", Feature: &X86.HasSSE2},
        }
 
        // Remove sse2 from options on amd64(p32) because SSE2 is a mandatory feature for these GOARCHs.
index 59c51770c5a8948a17044ab73dc054083371d546..a8d0466e06fc26f925a09051a63f602cd38a63fd 100644 (file)
@@ -45,3 +45,20 @@ func TestSSE2DebugOption(t *testing.T) {
                t.Errorf("X86.HasSSE2 on %s expected %v, got %v", runtime.GOARCH, want, got)
        }
 }
+
+func TestDisableSSE3(t *testing.T) {
+       runDebugOptionsTest(t, "TestSSE3DebugOption", "sse3=off")
+}
+
+func TestSSE3DebugOption(t *testing.T) {
+       MustHaveDebugOptionsSupport(t)
+
+       if os.Getenv("GODEBUGCPU") != "sse3=off" {
+               t.Skipf("skipping test: GODEBUGCPU=sse3=off not set")
+       }
+
+       want := false
+       if got := X86.HasSSE3; got != want {
+               t.Errorf("X86.HasSSE3 expected %v, got %v", want, got)
+       }
+}