github.com/hikaru7719/go@v0.0.0-20181025140707-c8b2ac68906a/src/internal/cpu/cpu.go (about)

     1  // Copyright 2017 The Go Authors. All rights reserved.
     2  // Use of this source code is governed by a BSD-style
     3  // license that can be found in the LICENSE file.
     4  
     5  // Package cpu implements processor feature detection
     6  // used by the Go standard library.
     7  package cpu
     8  
     9  // DebugOptions is set to true by the runtime if the OS supports GODEBUGCPU.
    10  // This should not be changed after it is initialized.
    11  var DebugOptions bool
    12  
    13  // CacheLinePad is used to pad structs to avoid false sharing.
    14  type CacheLinePad struct{ _ [CacheLinePadSize]byte }
    15  
    16  // CacheLineSize is the CPU's assumed cache line size.
    17  // There is currently no runtime detection of the real cache line size
    18  // so we use the constant per GOARCH CacheLinePadSize as an approximation.
    19  var CacheLineSize uintptr = CacheLinePadSize
    20  
    21  var X86 x86
    22  
    23  // The booleans in x86 contain the correspondingly named cpuid feature bit.
    24  // HasAVX and HasAVX2 are only set if the OS does support XMM and YMM registers
    25  // in addition to the cpuid feature bit being set.
    26  // The struct is padded to avoid false sharing.
    27  type x86 struct {
    28  	_            CacheLinePad
    29  	HasAES       bool
    30  	HasADX       bool
    31  	HasAVX       bool
    32  	HasAVX2      bool
    33  	HasBMI1      bool
    34  	HasBMI2      bool
    35  	HasERMS      bool
    36  	HasFMA       bool
    37  	HasOSXSAVE   bool
    38  	HasPCLMULQDQ bool
    39  	HasPOPCNT    bool
    40  	HasSSE2      bool
    41  	HasSSE3      bool
    42  	HasSSSE3     bool
    43  	HasSSE41     bool
    44  	HasSSE42     bool
    45  	_            CacheLinePad
    46  }
    47  
    48  var PPC64 ppc64
    49  
    50  // For ppc64x, it is safe to check only for ISA level starting on ISA v3.00,
    51  // since there are no optional categories. There are some exceptions that also
    52  // require kernel support to work (darn, scv), so there are feature bits for
    53  // those as well. The minimum processor requirement is POWER8 (ISA 2.07), so we
    54  // maintain some of the old feature checks for optional categories for
    55  // safety.
    56  // The struct is padded to avoid false sharing.
    57  type ppc64 struct {
    58  	_          CacheLinePad
    59  	HasVMX     bool // Vector unit (Altivec)
    60  	HasDFP     bool // Decimal Floating Point unit
    61  	HasVSX     bool // Vector-scalar unit
    62  	HasHTM     bool // Hardware Transactional Memory
    63  	HasISEL    bool // Integer select
    64  	HasVCRYPTO bool // Vector cryptography
    65  	HasHTMNOSC bool // HTM: kernel-aborted transaction in syscalls
    66  	HasDARN    bool // Hardware random number generator (requires kernel enablement)
    67  	HasSCV     bool // Syscall vectored (requires kernel enablement)
    68  	IsPOWER8   bool // ISA v2.07 (POWER8)
    69  	IsPOWER9   bool // ISA v3.00 (POWER9)
    70  	_          CacheLinePad
    71  }
    72  
    73  var ARM arm
    74  
    75  // The booleans in arm contain the correspondingly named cpu feature bit.
    76  // The struct is padded to avoid false sharing.
    77  type arm struct {
    78  	_        CacheLinePad
    79  	HasVFPv4 bool
    80  	HasIDIVA bool
    81  	_        CacheLinePad
    82  }
    83  
    84  var ARM64 arm64
    85  
    86  // The booleans in arm64 contain the correspondingly named cpu feature bit.
    87  // The struct is padded to avoid false sharing.
    88  type arm64 struct {
    89  	_           CacheLinePad
    90  	HasFP       bool
    91  	HasASIMD    bool
    92  	HasEVTSTRM  bool
    93  	HasAES      bool
    94  	HasPMULL    bool
    95  	HasSHA1     bool
    96  	HasSHA2     bool
    97  	HasCRC32    bool
    98  	HasATOMICS  bool
    99  	HasFPHP     bool
   100  	HasASIMDHP  bool
   101  	HasCPUID    bool
   102  	HasASIMDRDM bool
   103  	HasJSCVT    bool
   104  	HasFCMA     bool
   105  	HasLRCPC    bool
   106  	HasDCPOP    bool
   107  	HasSHA3     bool
   108  	HasSM3      bool
   109  	HasSM4      bool
   110  	HasASIMDDP  bool
   111  	HasSHA512   bool
   112  	HasSVE      bool
   113  	HasASIMDFHM bool
   114  	_           CacheLinePad
   115  }
   116  
   117  var S390X s390x
   118  
   119  type s390x struct {
   120  	_               CacheLinePad
   121  	HasZArch        bool // z architecture mode is active [mandatory]
   122  	HasSTFLE        bool // store facility list extended [mandatory]
   123  	HasLDisp        bool // long (20-bit) displacements [mandatory]
   124  	HasEImm         bool // 32-bit immediates [mandatory]
   125  	HasDFP          bool // decimal floating point
   126  	HasETF3Enhanced bool // ETF-3 enhanced
   127  	HasMSA          bool // message security assist (CPACF)
   128  	HasAES          bool // KM-AES{128,192,256} functions
   129  	HasAESCBC       bool // KMC-AES{128,192,256} functions
   130  	HasAESCTR       bool // KMCTR-AES{128,192,256} functions
   131  	HasAESGCM       bool // KMA-GCM-AES{128,192,256} functions
   132  	HasGHASH        bool // KIMD-GHASH function
   133  	HasSHA1         bool // K{I,L}MD-SHA-1 functions
   134  	HasSHA256       bool // K{I,L}MD-SHA-256 functions
   135  	HasSHA512       bool // K{I,L}MD-SHA-512 functions
   136  	HasVX           bool // vector facility. Note: the runtime sets this when it processes auxv records.
   137  	_               CacheLinePad
   138  }
   139  
   140  // Initialize examines the processor and sets the relevant variables above.
   141  // This is called by the runtime package early in program initialization,
   142  // before normal init functions are run. env is set by runtime if the OS supports GODEBUGCPU.
   143  func Initialize(env string) {
   144  	doinit()
   145  	processOptions(env)
   146  }
   147  
   148  // options contains the cpu debug options that can be used in GODEBUGCPU.
   149  // Options are arch dependent and are added by the arch specific doinit functions.
   150  // Features that are mandatory for the specific GOARCH should not be added to options
   151  // (e.g. SSE2 on amd64).
   152  var options []option
   153  
   154  // Option names should be lower case. e.g. avx instead of AVX.
   155  type option struct {
   156  	Name      string
   157  	Feature   *bool
   158  	Specified bool // whether feature value was specified in GODEBUGCPU
   159  	Enable    bool // whether feature should be enabled
   160  	Required  bool // whether feature is mandatory and can not be disabled
   161  }
   162  
   163  // processOptions enables or disables CPU feature values based on the parsed env string.
   164  // The env string is expected to be of the form feature1=value1,feature2=value2...
   165  // where feature names is one of the architecture specifc list stored in the
   166  // cpu packages options variable and values are either 'on' or 'off'.
   167  // If env contains all=off then all cpu features referenced through the options
   168  // variable are disabled. Other feature names and values result in warning messages.
   169  func processOptions(env string) {
   170  field:
   171  	for env != "" {
   172  		field := ""
   173  		i := indexByte(env, ',')
   174  		if i < 0 {
   175  			field, env = env, ""
   176  		} else {
   177  			field, env = env[:i], env[i+1:]
   178  		}
   179  		i = indexByte(field, '=')
   180  		if i < 0 {
   181  			print("GODEBUGCPU: no value specified for \"", field, "\"\n")
   182  			continue
   183  		}
   184  		key, value := field[:i], field[i+1:]
   185  
   186  		var enable bool
   187  		switch value {
   188  		case "on":
   189  			enable = true
   190  		case "off":
   191  			enable = false
   192  		default:
   193  			print("GODEBUGCPU: value \"", value, "\" not supported for option ", key, "\n")
   194  			continue field
   195  		}
   196  
   197  		if key == "all" {
   198  			for i := range options {
   199  				options[i].Specified = true
   200  				options[i].Enable = enable || options[i].Required
   201  			}
   202  			continue field
   203  		}
   204  
   205  		for i := range options {
   206  			if options[i].Name == key {
   207  				options[i].Specified = true
   208  				options[i].Enable = enable
   209  				continue field
   210  			}
   211  		}
   212  
   213  		print("GODEBUGCPU: unknown cpu feature \"", key, "\"\n")
   214  	}
   215  
   216  	for _, o := range options {
   217  		if !o.Specified {
   218  			continue
   219  		}
   220  
   221  		if o.Enable && !*o.Feature {
   222  			print("GODEBUGCPU: can not enable \"", o.Name, "\", missing hardware support\n")
   223  			continue
   224  		}
   225  
   226  		if !o.Enable && o.Required {
   227  			print("GODEBUGCPU: can not disable \"", o.Name, "\", required feature\n")
   228  			continue
   229  		}
   230  
   231  		*o.Feature = o.Enable
   232  	}
   233  }
   234  
   235  // indexByte returns the index of the first instance of c in s,
   236  // or -1 if c is not present in s.
   237  func indexByte(s string, c byte) int {
   238  	for i := 0; i < len(s); i++ {
   239  		if s[i] == c {
   240  			return i
   241  		}
   242  	}
   243  	return -1
   244  }