os_linux_arm64.go 6.2 KB

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