cpu.go raw

   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 go was compiled with GOEXPERIMENT=debugcpu
  10  // and GOOS is Linux or Darwin. This variable is linknamed in runtime/proc.go.
  11  var debugOptions bool
  12  
  13  var X86 x86
  14  
  15  // "Loads data or instructions from memory to the second-level cache.
  16  // To use the streamer, organize the data or instructions in blocks of 128 bytes,
  17  // aligned on 128 bytes."
  18  // From <IntelĀ® 64 and IA-32 architectures optimization reference manual>,
  19  // in section 3.7.3 "Hardware Prefetching for Second-Level Cache"
  20  //
  21  // In practice, I have found use 128bytes can gain better performance than 64bytes (one cache line).
  22  const X86FalseSharingRange = 128
  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  	_            [X86FalseSharingRange]byte
  30  	HasCMPXCHG16B bool
  31  	HasAES       bool
  32  	HasADX       bool
  33  	HasAVX       bool
  34  	HasAVX2      bool
  35  	HasAVX512F   bool
  36  	HasAVX512DQ  bool
  37  	HasAVX512BW  bool
  38  	HasAVX512VL  bool
  39  	HasBMI1      bool
  40  	HasBMI2      bool
  41  	HasERMS      bool
  42  	HasFMA       bool
  43  	HasOSXSAVE   bool
  44  	HasPCLMULQDQ bool
  45  	HasPOPCNT    bool
  46  	HasSSE2      bool
  47  	HasSSE3      bool
  48  	HasSSSE3     bool
  49  	HasSSE41     bool
  50  	HasSSE42     bool
  51  	// The invariant TSC will run at a constant rate in all ACPI P-, C-, and T-states.
  52  	// This is the architectural behavior moving forward. On processors with
  53  	// invariant TSC support, the OS may use the TSC for wall clock timer services (instead of ACPI or HPET timers).
  54  	HasInvariantTSC bool
  55  
  56  	Cache Cache
  57  
  58  	// TSCFrequency only meaningful when HasInvariantTSC == true.
  59  	// Unit: Hz.
  60  	//
  61  	// Warn:
  62  	// 1. If it's 0, means failed to get it from frequency table provided by Intel manual.
  63  	TSCFrequency uint64
  64  
  65  	Name       string
  66  	Signature  string // DisplayFamily_DisplayModel.
  67  	Family     uint32 // CPU family number.
  68  	Model      uint32 // CPU model number.
  69  	SteppingID uint32
  70  
  71  	_ [X86FalseSharingRange]byte
  72  }
  73  
  74  // CPU Cache Size.
  75  // -1 if undetected.
  76  type Cache struct {
  77  	L1I int
  78  	L1D int
  79  	L2  int
  80  	L3  int
  81  }
  82  
  83  var PPC64 ppc64
  84  
  85  // For ppc64x, it is safe to check only for ISA level starting on ISA v3.00,
  86  // since there are no optional categories. There are some exceptions that also
  87  // require kernel support to work (darn, scv), so there are feature bits for
  88  // those as well. The minimum processor requirement is POWER8 (ISA 2.07), so we
  89  // maintain some of the old feature checks for optional categories for
  90  // safety.
  91  // The struct is padded to avoid false sharing.
  92  type ppc64 struct {
  93  	_          [CacheLineSize]byte
  94  	HasVMX     bool // Vector unit (Altivec)
  95  	HasDFP     bool // Decimal Floating Point unit
  96  	HasVSX     bool // Vector-scalar unit
  97  	HasHTM     bool // Hardware Transactional Memory
  98  	HasISEL    bool // Integer select
  99  	HasVCRYPTO bool // Vector cryptography
 100  	HasHTMNOSC bool // HTM: kernel-aborted transaction in syscalls
 101  	HasDARN    bool // Hardware random number generator (requires kernel enablement)
 102  	HasSCV     bool // Syscall vectored (requires kernel enablement)
 103  	IsPOWER8   bool // ISA v2.07 (POWER8)
 104  	IsPOWER9   bool // ISA v3.00 (POWER9)
 105  	_          [CacheLineSize]byte
 106  }
 107  
 108  var ARM64 arm64
 109  
 110  // The booleans in arm64 contain the correspondingly named cpu feature bit.
 111  // The struct is padded to avoid false sharing.
 112  type arm64 struct {
 113  	_           [CacheLineSize]byte
 114  	HasFP       bool
 115  	HasASIMD    bool
 116  	HasEVTSTRM  bool
 117  	HasAES      bool
 118  	HasPMULL    bool
 119  	HasSHA1     bool
 120  	HasSHA2     bool
 121  	HasCRC32    bool
 122  	HasATOMICS  bool
 123  	HasFPHP     bool
 124  	HasASIMDHP  bool
 125  	HasCPUID    bool
 126  	HasASIMDRDM bool
 127  	HasJSCVT    bool
 128  	HasFCMA     bool
 129  	HasLRCPC    bool
 130  	HasDCPOP    bool
 131  	HasSHA3     bool
 132  	HasSM3      bool
 133  	HasSM4      bool
 134  	HasASIMDDP  bool
 135  	HasSHA512   bool
 136  	HasSVE      bool
 137  	HasASIMDFHM bool
 138  	_           [CacheLineSize]byte
 139  }
 140  
 141  var S390X s390x
 142  
 143  type s390x struct {
 144  	_               [CacheLineSize]byte
 145  	HasZArch        bool // z architecture mode is active [mandatory]
 146  	HasSTFLE        bool // store facility list extended [mandatory]
 147  	HasLDisp        bool // long (20-bit) displacements [mandatory]
 148  	HasEImm         bool // 32-bit immediates [mandatory]
 149  	HasDFP          bool // decimal floating point
 150  	HasETF3Enhanced bool // ETF-3 enhanced
 151  	HasMSA          bool // message security assist (CPACF)
 152  	HasAES          bool // KM-AES{128,192,256} functions
 153  	HasAESCBC       bool // KMC-AES{128,192,256} functions
 154  	HasAESCTR       bool // KMCTR-AES{128,192,256} functions
 155  	HasAESGCM       bool // KMA-GCM-AES{128,192,256} functions
 156  	HasGHASH        bool // KIMD-GHASH function
 157  	HasSHA1         bool // K{I,L}MD-SHA-1 functions
 158  	HasSHA256       bool // K{I,L}MD-SHA-256 functions
 159  	HasSHA512       bool // K{I,L}MD-SHA-512 functions
 160  	HasVX           bool // vector facility. Note: the runtime sets this when it processes auxv records.
 161  	_               [CacheLineSize]byte
 162  }
 163  
 164  // initialize examines the processor and sets the relevant variables above.
 165  // This is called by the runtime package early in program initialization,
 166  // before normal init functions are run. env is set by runtime on Linux and Darwin
 167  // if go was compiled with GOEXPERIMENT=debugcpu.
 168  func init() {
 169  	doinit()
 170  	processOptions("")
 171  }
 172  
 173  // options contains the cpu debug options that can be used in GODEBUGCPU.
 174  // Options are arch dependent and are added by the arch specific doinit functions.
 175  // Features that are mandatory for the specific GOARCH should not be added to options
 176  // (e.g. SSE2 on amd64).
 177  var options []option
 178  
 179  // Option names should be lower case. e.g. avx instead of AVX.
 180  type option struct {
 181  	Name    string
 182  	Feature *bool
 183  }
 184  
 185  // processOptions disables CPU feature values based on the parsed env string.
 186  // The env string is expected to be of the form feature1=0,feature2=0...
 187  // where feature names is one of the architecture specifc list stored in the
 188  // cpu packages options variable. If env contains all=0 then all capabilities
 189  // referenced through the options variable are disabled. Other feature
 190  // names and values other than 0 are silently ignored.
 191  func processOptions(env string) {
 192  field:
 193  	for env != "" {
 194  		field := ""
 195  		i := indexByte(env, ',')
 196  		if i < 0 {
 197  			field, env = env, ""
 198  		} else {
 199  			field, env = env[:i], env[i+1:]
 200  		}
 201  		i = indexByte(field, '=')
 202  		if i < 0 {
 203  			continue
 204  		}
 205  		key, value := field[:i], field[i+1:]
 206  
 207  		// Only allow turning off CPU features by specifying '0'.
 208  		if value == "0" {
 209  			if key == "all" {
 210  				for _, v := range options {
 211  					*v.Feature = false
 212  				}
 213  				return
 214  			} else {
 215  				for _, v := range options {
 216  					if v.Name == key {
 217  						*v.Feature = false
 218  						continue field
 219  					}
 220  				}
 221  			}
 222  		}
 223  	}
 224  }
 225  
 226  // indexByte returns the index of the first instance of c in s,
 227  // or -1 if c is not present in s.
 228  func indexByte(s string, c byte) int {
 229  	for i := 0; i < len(s); i++ {
 230  		if s[i] == c {
 231  			return i
 232  		}
 233  	}
 234  	return -1
 235  }
 236