...

Source file src/internal/cpu/cpu.go

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

View as plain text