detect_arm64.go 9.7 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247
  1. // Copyright (c) 2015 Klaus Post, released under MIT License. See LICENSE file.
  2. //go:build arm64 && !gccgo && !noasm && !appengine
  3. // +build arm64,!gccgo,!noasm,!appengine
  4. package cpuid
  5. import "runtime"
  6. func getMidr() (midr uint64)
  7. func getProcFeatures() (procFeatures uint64)
  8. func getInstAttributes() (instAttrReg0, instAttrReg1 uint64)
  9. func initCPU() {
  10. cpuid = func(uint32) (a, b, c, d uint32) { return 0, 0, 0, 0 }
  11. cpuidex = func(x, y uint32) (a, b, c, d uint32) { return 0, 0, 0, 0 }
  12. xgetbv = func(uint32) (a, b uint32) { return 0, 0 }
  13. rdtscpAsm = func() (a, b, c, d uint32) { return 0, 0, 0, 0 }
  14. }
  15. func addInfo(c *CPUInfo, safe bool) {
  16. // Seems to be safe to assume on ARM64
  17. c.CacheLine = 64
  18. detectOS(c)
  19. // ARM64 disabled since it may crash if interrupt is not intercepted by OS.
  20. if safe && !c.Supports(ARMCPUID) && runtime.GOOS != "freebsd" {
  21. return
  22. }
  23. midr := getMidr()
  24. // MIDR_EL1 - Main ID Register
  25. // https://developer.arm.com/docs/ddi0595/h/aarch64-system-registers/midr_el1
  26. // x--------------------------------------------------x
  27. // | Name | bits | visible |
  28. // |--------------------------------------------------|
  29. // | Implementer | [31-24] | y |
  30. // |--------------------------------------------------|
  31. // | Variant | [23-20] | y |
  32. // |--------------------------------------------------|
  33. // | Architecture | [19-16] | y |
  34. // |--------------------------------------------------|
  35. // | PartNum | [15-4] | y |
  36. // |--------------------------------------------------|
  37. // | Revision | [3-0] | y |
  38. // x--------------------------------------------------x
  39. switch (midr >> 24) & 0xff {
  40. case 0xC0:
  41. c.VendorString = "Ampere Computing"
  42. c.VendorID = Ampere
  43. case 0x41:
  44. c.VendorString = "Arm Limited"
  45. c.VendorID = ARM
  46. case 0x42:
  47. c.VendorString = "Broadcom Corporation"
  48. c.VendorID = Broadcom
  49. case 0x43:
  50. c.VendorString = "Cavium Inc"
  51. c.VendorID = Cavium
  52. case 0x44:
  53. c.VendorString = "Digital Equipment Corporation"
  54. c.VendorID = DEC
  55. case 0x46:
  56. c.VendorString = "Fujitsu Ltd"
  57. c.VendorID = Fujitsu
  58. case 0x49:
  59. c.VendorString = "Infineon Technologies AG"
  60. c.VendorID = Infineon
  61. case 0x4D:
  62. c.VendorString = "Motorola or Freescale Semiconductor Inc"
  63. c.VendorID = Motorola
  64. case 0x4E:
  65. c.VendorString = "NVIDIA Corporation"
  66. c.VendorID = NVIDIA
  67. case 0x50:
  68. c.VendorString = "Applied Micro Circuits Corporation"
  69. c.VendorID = AMCC
  70. case 0x51:
  71. c.VendorString = "Qualcomm Inc"
  72. c.VendorID = Qualcomm
  73. case 0x56:
  74. c.VendorString = "Marvell International Ltd"
  75. c.VendorID = Marvell
  76. case 0x69:
  77. c.VendorString = "Intel Corporation"
  78. c.VendorID = Intel
  79. }
  80. // Lower 4 bits: Architecture
  81. // Architecture Meaning
  82. // 0b0001 Armv4.
  83. // 0b0010 Armv4T.
  84. // 0b0011 Armv5 (obsolete).
  85. // 0b0100 Armv5T.
  86. // 0b0101 Armv5TE.
  87. // 0b0110 Armv5TEJ.
  88. // 0b0111 Armv6.
  89. // 0b1111 Architectural features are individually identified in the ID_* registers, see 'ID registers'.
  90. // Upper 4 bit: Variant
  91. // An IMPLEMENTATION DEFINED variant number.
  92. // Typically, this field is used to distinguish between different product variants, or major revisions of a product.
  93. c.Family = int(midr>>16) & 0xff
  94. // PartNum, bits [15:4]
  95. // An IMPLEMENTATION DEFINED primary part number for the device.
  96. // On processors implemented by Arm, if the top four bits of the primary
  97. // part number are 0x0 or 0x7, the variant and architecture are encoded differently.
  98. // Revision, bits [3:0]
  99. // An IMPLEMENTATION DEFINED revision number for the device.
  100. c.Model = int(midr) & 0xffff
  101. procFeatures := getProcFeatures()
  102. // ID_AA64PFR0_EL1 - Processor Feature Register 0
  103. // x--------------------------------------------------x
  104. // | Name | bits | visible |
  105. // |--------------------------------------------------|
  106. // | DIT | [51-48] | y |
  107. // |--------------------------------------------------|
  108. // | SVE | [35-32] | y |
  109. // |--------------------------------------------------|
  110. // | GIC | [27-24] | n |
  111. // |--------------------------------------------------|
  112. // | AdvSIMD | [23-20] | y |
  113. // |--------------------------------------------------|
  114. // | FP | [19-16] | y |
  115. // |--------------------------------------------------|
  116. // | EL3 | [15-12] | n |
  117. // |--------------------------------------------------|
  118. // | EL2 | [11-8] | n |
  119. // |--------------------------------------------------|
  120. // | EL1 | [7-4] | n |
  121. // |--------------------------------------------------|
  122. // | EL0 | [3-0] | n |
  123. // x--------------------------------------------------x
  124. var f flagSet
  125. // if procFeatures&(0xf<<48) != 0 {
  126. // fmt.Println("DIT")
  127. // }
  128. f.setIf(procFeatures&(0xf<<32) != 0, SVE)
  129. if procFeatures&(0xf<<20) != 15<<20 {
  130. f.set(ASIMD)
  131. // https://developer.arm.com/docs/ddi0595/b/aarch64-system-registers/id_aa64pfr0_el1
  132. // 0b0001 --> As for 0b0000, and also includes support for half-precision floating-point arithmetic.
  133. f.setIf(procFeatures&(0xf<<20) == 1<<20, FPHP, ASIMDHP)
  134. }
  135. f.setIf(procFeatures&(0xf<<16) != 0, FP)
  136. instAttrReg0, instAttrReg1 := getInstAttributes()
  137. // https://developer.arm.com/docs/ddi0595/b/aarch64-system-registers/id_aa64isar0_el1
  138. //
  139. // ID_AA64ISAR0_EL1 - Instruction Set Attribute Register 0
  140. // x--------------------------------------------------x
  141. // | Name | bits | visible |
  142. // |--------------------------------------------------|
  143. // | TS | [55-52] | y |
  144. // |--------------------------------------------------|
  145. // | FHM | [51-48] | y |
  146. // |--------------------------------------------------|
  147. // | DP | [47-44] | y |
  148. // |--------------------------------------------------|
  149. // | SM4 | [43-40] | y |
  150. // |--------------------------------------------------|
  151. // | SM3 | [39-36] | y |
  152. // |--------------------------------------------------|
  153. // | SHA3 | [35-32] | y |
  154. // |--------------------------------------------------|
  155. // | RDM | [31-28] | y |
  156. // |--------------------------------------------------|
  157. // | ATOMICS | [23-20] | y |
  158. // |--------------------------------------------------|
  159. // | CRC32 | [19-16] | y |
  160. // |--------------------------------------------------|
  161. // | SHA2 | [15-12] | y |
  162. // |--------------------------------------------------|
  163. // | SHA1 | [11-8] | y |
  164. // |--------------------------------------------------|
  165. // | AES | [7-4] | y |
  166. // x--------------------------------------------------x
  167. // if instAttrReg0&(0xf<<52) != 0 {
  168. // fmt.Println("TS")
  169. // }
  170. // if instAttrReg0&(0xf<<48) != 0 {
  171. // fmt.Println("FHM")
  172. // }
  173. f.setIf(instAttrReg0&(0xf<<44) != 0, ASIMDDP)
  174. f.setIf(instAttrReg0&(0xf<<40) != 0, SM4)
  175. f.setIf(instAttrReg0&(0xf<<36) != 0, SM3)
  176. f.setIf(instAttrReg0&(0xf<<32) != 0, SHA3)
  177. f.setIf(instAttrReg0&(0xf<<28) != 0, ASIMDRDM)
  178. f.setIf(instAttrReg0&(0xf<<20) != 0, ATOMICS)
  179. f.setIf(instAttrReg0&(0xf<<16) != 0, CRC32)
  180. f.setIf(instAttrReg0&(0xf<<12) != 0, SHA2)
  181. // https://developer.arm.com/docs/ddi0595/b/aarch64-system-registers/id_aa64isar0_el1
  182. // 0b0010 --> As 0b0001, plus SHA512H, SHA512H2, SHA512SU0, and SHA512SU1 instructions implemented.
  183. f.setIf(instAttrReg0&(0xf<<12) == 2<<12, SHA512)
  184. f.setIf(instAttrReg0&(0xf<<8) != 0, SHA1)
  185. f.setIf(instAttrReg0&(0xf<<4) != 0, AESARM)
  186. // https://developer.arm.com/docs/ddi0595/b/aarch64-system-registers/id_aa64isar0_el1
  187. // 0b0010 --> As for 0b0001, plus PMULL/PMULL2 instructions operating on 64-bit data quantities.
  188. f.setIf(instAttrReg0&(0xf<<4) == 2<<4, PMULL)
  189. // https://developer.arm.com/docs/ddi0595/b/aarch64-system-registers/id_aa64isar1_el1
  190. //
  191. // ID_AA64ISAR1_EL1 - Instruction set attribute register 1
  192. // x--------------------------------------------------x
  193. // | Name | bits | visible |
  194. // |--------------------------------------------------|
  195. // | GPI | [31-28] | y |
  196. // |--------------------------------------------------|
  197. // | GPA | [27-24] | y |
  198. // |--------------------------------------------------|
  199. // | LRCPC | [23-20] | y |
  200. // |--------------------------------------------------|
  201. // | FCMA | [19-16] | y |
  202. // |--------------------------------------------------|
  203. // | JSCVT | [15-12] | y |
  204. // |--------------------------------------------------|
  205. // | API | [11-8] | y |
  206. // |--------------------------------------------------|
  207. // | APA | [7-4] | y |
  208. // |--------------------------------------------------|
  209. // | DPB | [3-0] | y |
  210. // x--------------------------------------------------x
  211. // if instAttrReg1&(0xf<<28) != 0 {
  212. // fmt.Println("GPI")
  213. // }
  214. f.setIf(instAttrReg1&(0xf<<28) != 24, GPA)
  215. f.setIf(instAttrReg1&(0xf<<20) != 0, LRCPC)
  216. f.setIf(instAttrReg1&(0xf<<16) != 0, FCMA)
  217. f.setIf(instAttrReg1&(0xf<<12) != 0, JSCVT)
  218. // if instAttrReg1&(0xf<<8) != 0 {
  219. // fmt.Println("API")
  220. // }
  221. // if instAttrReg1&(0xf<<4) != 0 {
  222. // fmt.Println("APA")
  223. // }
  224. f.setIf(instAttrReg1&(0xf<<0) != 0, DCPOP)
  225. // Store
  226. c.featureSet.or(f)
  227. }