os_linux_arm64.go raw

   1  // Copyright (c) 2020 Klaus Post, released under MIT License. See LICENSE file.
   2  
   3  // Copyright 2018 The Go Authors. All rights reserved.
   4  // Use of this source code is governed by a BSD-style
   5  // license that can be found in the LICENSE file located
   6  // here https://github.com/golang/sys/blob/master/LICENSE
   7  
   8  package cpuid
   9  
  10  import (
  11  	"encoding/binary"
  12  	"io/ioutil"
  13  	"runtime"
  14  )
  15  
  16  // HWCAP bits.
  17  const (
  18  	hwcap_FP       = 1 << 0
  19  	hwcap_ASIMD    = 1 << 1
  20  	hwcap_EVTSTRM  = 1 << 2
  21  	hwcap_AES      = 1 << 3
  22  	hwcap_PMULL    = 1 << 4
  23  	hwcap_SHA1     = 1 << 5
  24  	hwcap_SHA2     = 1 << 6
  25  	hwcap_CRC32    = 1 << 7
  26  	hwcap_ATOMICS  = 1 << 8
  27  	hwcap_FPHP     = 1 << 9
  28  	hwcap_ASIMDHP  = 1 << 10
  29  	hwcap_CPUID    = 1 << 11
  30  	hwcap_ASIMDRDM = 1 << 12
  31  	hwcap_JSCVT    = 1 << 13
  32  	hwcap_FCMA     = 1 << 14
  33  	hwcap_LRCPC    = 1 << 15
  34  	hwcap_DCPOP    = 1 << 16
  35  	hwcap_SHA3     = 1 << 17
  36  	hwcap_SM3      = 1 << 18
  37  	hwcap_SM4      = 1 << 19
  38  	hwcap_ASIMDDP  = 1 << 20
  39  	hwcap_SHA512   = 1 << 21
  40  	hwcap_SVE      = 1 << 22
  41  	hwcap_ASIMDFHM = 1 << 23
  42  	hwcap_DIT      = 1 << 24
  43  	hwcap_USCAT    = 1 << 25
  44  	hwcap_ILRCPC   = 1 << 26
  45  	hwcap_FLAGM    = 1 << 27
  46  	hwcap_SSBS     = 1 << 28
  47  	hwcap_SB       = 1 << 29
  48  	hwcap_PACA     = 1 << 30
  49  	hwcap_PACG     = 1 << 31
  50  	hwcap_GCS      = 1 << 32
  51  
  52  	hwcap2_DCPODP      = 1 << 0
  53  	hwcap2_SVE2        = 1 << 1
  54  	hwcap2_SVEAES      = 1 << 2
  55  	hwcap2_SVEPMULL    = 1 << 3
  56  	hwcap2_SVEBITPERM  = 1 << 4
  57  	hwcap2_SVESHA3     = 1 << 5
  58  	hwcap2_SVESM4      = 1 << 6
  59  	hwcap2_FLAGM2      = 1 << 7
  60  	hwcap2_FRINT       = 1 << 8
  61  	hwcap2_SVEI8MM     = 1 << 9
  62  	hwcap2_SVEF32MM    = 1 << 10
  63  	hwcap2_SVEF64MM    = 1 << 11
  64  	hwcap2_SVEBF16     = 1 << 12
  65  	hwcap2_I8MM        = 1 << 13
  66  	hwcap2_BF16        = 1 << 14
  67  	hwcap2_DGH         = 1 << 15
  68  	hwcap2_RNG         = 1 << 16
  69  	hwcap2_BTI         = 1 << 17
  70  	hwcap2_MTE         = 1 << 18
  71  	hwcap2_ECV         = 1 << 19
  72  	hwcap2_AFP         = 1 << 20
  73  	hwcap2_RPRES       = 1 << 21
  74  	hwcap2_MTE3        = 1 << 22
  75  	hwcap2_SME         = 1 << 23
  76  	hwcap2_SME_I16I64  = 1 << 24
  77  	hwcap2_SME_F64F64  = 1 << 25
  78  	hwcap2_SME_I8I32   = 1 << 26
  79  	hwcap2_SME_F16F32  = 1 << 27
  80  	hwcap2_SME_B16F32  = 1 << 28
  81  	hwcap2_SME_F32F32  = 1 << 29
  82  	hwcap2_SME_FA64    = 1 << 30
  83  	hwcap2_WFXT        = 1 << 31
  84  	hwcap2_EBF16       = 1 << 32
  85  	hwcap2_SVE_EBF16   = 1 << 33
  86  	hwcap2_CSSC        = 1 << 34
  87  	hwcap2_RPRFM       = 1 << 35
  88  	hwcap2_SVE2P1      = 1 << 36
  89  	hwcap2_SME2        = 1 << 37
  90  	hwcap2_SME2P1      = 1 << 38
  91  	hwcap2_SME_I16I32  = 1 << 39
  92  	hwcap2_SME_BI32I32 = 1 << 40
  93  	hwcap2_SME_B16B16  = 1 << 41
  94  	hwcap2_SME_F16F16  = 1 << 42
  95  	hwcap2_MOPS        = 1 << 43
  96  	hwcap2_HBC         = 1 << 44
  97  	hwcap2_SVE_B16B16  = 1 << 45
  98  	hwcap2_LRCPC3      = 1 << 46
  99  	hwcap2_LSE128      = 1 << 47
 100  	hwcap2_FPMR        = 1 << 48
 101  	hwcap2_LUT         = 1 << 49
 102  	hwcap2_FAMINMAX    = 1 << 50
 103  	hwcap2_F8CVT       = 1 << 51
 104  	hwcap2_F8FMA       = 1 << 52
 105  	hwcap2_F8DP4       = 1 << 53
 106  	hwcap2_F8DP2       = 1 << 54
 107  	hwcap2_F8E4M3      = 1 << 55
 108  	hwcap2_F8E5M2      = 1 << 56
 109  	hwcap2_SME_LUTV2   = 1 << 57
 110  	hwcap2_SME_F8F16   = 1 << 58
 111  	hwcap2_SME_F8F32   = 1 << 59
 112  	hwcap2_SME_SF8FMA  = 1 << 60
 113  	hwcap2_SME_SF8DP4  = 1 << 61
 114  	hwcap2_SME_SF8DP2  = 1 << 62
 115  	hwcap2_POE         = 1 << 63
 116  )
 117  
 118  func detectOS(c *CPUInfo) bool {
 119  	// For now assuming no hyperthreading is reasonable.
 120  	c.LogicalCores = runtime.NumCPU()
 121  	c.PhysicalCores = c.LogicalCores
 122  	c.ThreadsPerCore = 1
 123  	if hwcap == 0 {
 124  		// We did not get values from the runtime.
 125  		// Try reading /proc/self/auxv
 126  
 127  		// From https://github.com/golang/sys
 128  		const (
 129  			_AT_HWCAP  = 16
 130  			_AT_HWCAP2 = 26
 131  
 132  			uintSize = int(32 << (^uint(0) >> 63))
 133  		)
 134  
 135  		buf, err := ioutil.ReadFile("/proc/self/auxv")
 136  		if err != nil {
 137  			// e.g. on android /proc/self/auxv is not accessible, so silently
 138  			// ignore the error and leave Initialized = false. On some
 139  			// architectures (e.g. arm64) doinit() implements a fallback
 140  			// readout and will set Initialized = true again.
 141  			return false
 142  		}
 143  		bo := binary.LittleEndian
 144  		for len(buf) >= 2*(uintSize/8) {
 145  			var tag, val uint
 146  			switch uintSize {
 147  			case 32:
 148  				tag = uint(bo.Uint32(buf[0:]))
 149  				val = uint(bo.Uint32(buf[4:]))
 150  				buf = buf[8:]
 151  			case 64:
 152  				tag = uint(bo.Uint64(buf[0:]))
 153  				val = uint(bo.Uint64(buf[8:]))
 154  				buf = buf[16:]
 155  			}
 156  			switch tag {
 157  			case _AT_HWCAP:
 158  				hwcap = val
 159  			case _AT_HWCAP2:
 160  				// Not used
 161  			}
 162  		}
 163  		if hwcap == 0 {
 164  			return false
 165  		}
 166  	}
 167  
 168  	// HWCap was populated by the runtime from the auxiliary vector.
 169  	// Use HWCap information since reading aarch64 system registers
 170  	// is not supported in user space on older linux kernels.
 171  	c.featureSet.setIf(isSet(hwcap, hwcap_AES), AESARM)
 172  	c.featureSet.setIf(isSet(hwcap, hwcap_ASIMD), ASIMD)
 173  	c.featureSet.setIf(isSet(hwcap, hwcap_ASIMDDP), ASIMDDP)
 174  	c.featureSet.setIf(isSet(hwcap, hwcap_ASIMDHP), ASIMDHP)
 175  	c.featureSet.setIf(isSet(hwcap, hwcap_ASIMDRDM), ASIMDRDM)
 176  	c.featureSet.setIf(isSet(hwcap, hwcap_CPUID), ARMCPUID)
 177  	c.featureSet.setIf(isSet(hwcap, hwcap_CRC32), CRC32)
 178  	c.featureSet.setIf(isSet(hwcap, hwcap_DCPOP), DCPOP)
 179  	c.featureSet.setIf(isSet(hwcap, hwcap_EVTSTRM), EVTSTRM)
 180  	c.featureSet.setIf(isSet(hwcap, hwcap_FCMA), FCMA)
 181  	c.featureSet.setIf(isSet(hwcap, hwcap_ASIMDFHM), FHM)
 182  	c.featureSet.setIf(isSet(hwcap, hwcap_FP), FP)
 183  	c.featureSet.setIf(isSet(hwcap, hwcap_FPHP), FPHP)
 184  	c.featureSet.setIf(isSet(hwcap, hwcap_JSCVT), JSCVT)
 185  	c.featureSet.setIf(isSet(hwcap, hwcap_LRCPC), LRCPC)
 186  	c.featureSet.setIf(isSet(hwcap, hwcap_PMULL), PMULL)
 187  	c.featureSet.setIf(isSet(hwcap, hwcap2_RNG), RNDR)
 188  	// c.featureSet.setIf(isSet(hwcap, hwcap_), TLB)
 189  	// c.featureSet.setIf(isSet(hwcap, hwcap_), TS)
 190  	c.featureSet.setIf(isSet(hwcap, hwcap_SHA1), SHA1)
 191  	c.featureSet.setIf(isSet(hwcap, hwcap_SHA2), SHA2)
 192  	c.featureSet.setIf(isSet(hwcap, hwcap_SHA3), SHA3)
 193  	c.featureSet.setIf(isSet(hwcap, hwcap_SHA512), SHA512)
 194  	c.featureSet.setIf(isSet(hwcap, hwcap_SM3), SM3)
 195  	c.featureSet.setIf(isSet(hwcap, hwcap_SM4), SM4)
 196  	c.featureSet.setIf(isSet(hwcap, hwcap_SVE), SVE)
 197  
 198  	// The Samsung S9+ kernel reports support for atomics, but not all cores
 199  	// actually support them, resulting in SIGILL. See issue #28431.
 200  	// TODO(elias.naur): Only disable the optimization on bad chipsets on android.
 201  	c.featureSet.setIf(isSet(hwcap, hwcap_ATOMICS) && runtime.GOOS != "android", ATOMICS)
 202  
 203  	return true
 204  }
 205  
 206  func isSet(hwc uint, value uint) bool {
 207  	return hwc&value != 0
 208  }
 209