github.com/FISCO-BCOS/crypto@v0.0.0-20200202032121-bd8ab0b5d4f1/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 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  }