os_linux_arm64.go 3.9 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130
  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. )
  39. func detectOS(c *CPUInfo) bool {
  40. // For now assuming no hyperthreading is reasonable.
  41. c.LogicalCores = runtime.NumCPU()
  42. c.PhysicalCores = c.LogicalCores
  43. c.ThreadsPerCore = 1
  44. if hwcap == 0 {
  45. // We did not get values from the runtime.
  46. // Try reading /proc/self/auxv
  47. // From https://github.com/golang/sys
  48. const (
  49. _AT_HWCAP = 16
  50. _AT_HWCAP2 = 26
  51. uintSize = int(32 << (^uint(0) >> 63))
  52. )
  53. buf, err := ioutil.ReadFile("/proc/self/auxv")
  54. if err != nil {
  55. // e.g. on android /proc/self/auxv is not accessible, so silently
  56. // ignore the error and leave Initialized = false. On some
  57. // architectures (e.g. arm64) doinit() implements a fallback
  58. // readout and will set Initialized = true again.
  59. return false
  60. }
  61. bo := binary.LittleEndian
  62. for len(buf) >= 2*(uintSize/8) {
  63. var tag, val uint
  64. switch uintSize {
  65. case 32:
  66. tag = uint(bo.Uint32(buf[0:]))
  67. val = uint(bo.Uint32(buf[4:]))
  68. buf = buf[8:]
  69. case 64:
  70. tag = uint(bo.Uint64(buf[0:]))
  71. val = uint(bo.Uint64(buf[8:]))
  72. buf = buf[16:]
  73. }
  74. switch tag {
  75. case _AT_HWCAP:
  76. hwcap = val
  77. case _AT_HWCAP2:
  78. // Not used
  79. }
  80. }
  81. if hwcap == 0 {
  82. return false
  83. }
  84. }
  85. // HWCap was populated by the runtime from the auxiliary vector.
  86. // Use HWCap information since reading aarch64 system registers
  87. // is not supported in user space on older linux kernels.
  88. c.featureSet.setIf(isSet(hwcap, hwcap_AES), AESARM)
  89. c.featureSet.setIf(isSet(hwcap, hwcap_ASIMD), ASIMD)
  90. c.featureSet.setIf(isSet(hwcap, hwcap_ASIMDDP), ASIMDDP)
  91. c.featureSet.setIf(isSet(hwcap, hwcap_ASIMDHP), ASIMDHP)
  92. c.featureSet.setIf(isSet(hwcap, hwcap_ASIMDRDM), ASIMDRDM)
  93. c.featureSet.setIf(isSet(hwcap, hwcap_CPUID), ARMCPUID)
  94. c.featureSet.setIf(isSet(hwcap, hwcap_CRC32), CRC32)
  95. c.featureSet.setIf(isSet(hwcap, hwcap_DCPOP), DCPOP)
  96. c.featureSet.setIf(isSet(hwcap, hwcap_EVTSTRM), EVTSTRM)
  97. c.featureSet.setIf(isSet(hwcap, hwcap_FCMA), FCMA)
  98. c.featureSet.setIf(isSet(hwcap, hwcap_FP), FP)
  99. c.featureSet.setIf(isSet(hwcap, hwcap_FPHP), FPHP)
  100. c.featureSet.setIf(isSet(hwcap, hwcap_JSCVT), JSCVT)
  101. c.featureSet.setIf(isSet(hwcap, hwcap_LRCPC), LRCPC)
  102. c.featureSet.setIf(isSet(hwcap, hwcap_PMULL), PMULL)
  103. c.featureSet.setIf(isSet(hwcap, hwcap_SHA1), SHA1)
  104. c.featureSet.setIf(isSet(hwcap, hwcap_SHA2), SHA2)
  105. c.featureSet.setIf(isSet(hwcap, hwcap_SHA3), SHA3)
  106. c.featureSet.setIf(isSet(hwcap, hwcap_SHA512), SHA512)
  107. c.featureSet.setIf(isSet(hwcap, hwcap_SM3), SM3)
  108. c.featureSet.setIf(isSet(hwcap, hwcap_SM4), SM4)
  109. c.featureSet.setIf(isSet(hwcap, hwcap_SVE), SVE)
  110. // The Samsung S9+ kernel reports support for atomics, but not all cores
  111. // actually support them, resulting in SIGILL. See issue #28431.
  112. // TODO(elias.naur): Only disable the optimization on bad chipsets on android.
  113. c.featureSet.setIf(isSet(hwcap, hwcap_ATOMICS) && runtime.GOOS != "android", ATOMICS)
  114. return true
  115. }
  116. func isSet(hwc uint, value uint) bool {
  117. return hwc&value != 0
  118. }