detect_arm64.go 10 KB

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