cpuid.go 33 KB

12345678910111213141516171819202122232425262728293031323334353637383940414243444546474849505152535455565758596061626364656667686970717273747576777879808182838485868788899091929394959697989910010110210310410510610710810911011111211311411511611711811912012112212312412512612712812913013113213313413513613713813914014114214314414514614714814915015115215315415515615715815916016116216316416516616716816917017117217317417517617717817918018118218318418518618718818919019119219319419519619719819920020120220320420520620720820921021121221321421521621721821922022122222322422522622722822923023123223323423523623723823924024124224324424524624724824925025125225325425525625725825926026126226326426526626726826927027127227327427527627727827928028128228328428528628728828929029129229329429529629729829930030130230330430530630730830931031131231331431531631731831932032132232332432532632732832933033133233333433533633733833934034134234334434534634734834935035135235335435535635735835936036136236336436536636736836937037137237337437537637737837938038138238338438538638738838939039139239339439539639739839940040140240340440540640740840941041141241341441541641741841942042142242342442542642742842943043143243343443543643743843944044144244344444544644744844945045145245345445545645745845946046146246346446546646746846947047147247347447547647747847948048148248348448548648748848949049149249349449549649749849950050150250350450550650750850951051151251351451551651751851952052152252352452552652752852953053153253353453553653753853954054154254354454554654754854955055155255355455555655755855956056156256356456556656756856957057157257357457557657757857958058158258358458558658758858959059159259359459559659759859960060160260360460560660760860961061161261361461561661761861962062162262362462562662762862963063163263363463563663763863964064164264364464564664764864965065165265365465565665765865966066166266366466566666766866967067167267367467567667767867968068168268368468568668768868969069169269369469569669769869970070170270370470570670770870971071171271371471571671771871972072172272372472572672772872973073173273373473573673773873974074174274374474574674774874975075175275375475575675775875976076176276376476576676776876977077177277377477577677777877978078178278378478578678778878979079179279379479579679779879980080180280380480580680780880981081181281381481581681781881982082182282382482582682782882983083183283383483583683783883984084184284384484584684784884985085185285385485585685785885986086186286386486586686786886987087187287387487587687787887988088188288388488588688788888989089189289389489589689789889990090190290390490590690790890991091191291391491591691791891992092192292392492592692792892993093193293393493593693793893994094194294394494594694794894995095195295395495595695795895996096196296396496596696796896997097197297397497597697797897998098198298398498598698798898999099199299399499599699799899910001001100210031004100510061007100810091010101110121013101410151016101710181019102010211022102310241025102610271028102910301031103210331034103510361037103810391040104110421043104410451046104710481049105010511052105310541055105610571058105910601061106210631064106510661067106810691070107110721073107410751076107710781079108010811082108310841085108610871088108910901091109210931094109510961097109810991100110111021103110411051106110711081109111011111112111311141115111611171118111911201121112211231124112511261127112811291130113111321133113411351136113711381139114011411142114311441145114611471148114911501151115211531154115511561157115811591160116111621163116411651166116711681169117011711172117311741175117611771178
  1. // Generated, DO NOT EDIT,
  2. // but copy it to your own project and rename the package.
  3. // See more at http://github.com/klauspost/cpuid
  4. package cpuid
  5. import "strings"
  6. // Vendor is a representation of a CPU vendor.
  7. type vendor int
  8. const (
  9. other vendor = iota
  10. intel
  11. amd
  12. via
  13. transmeta
  14. nsc
  15. kvm // Kernel-based Virtual Machine
  16. msvm // Microsoft Hyper-V or Windows Virtual PC
  17. vmware
  18. xenhvm
  19. bhyve
  20. hygon
  21. )
  22. const (
  23. cmov = 1 << iota // i686 CMOV
  24. nx // NX (No-Execute) bit
  25. amd3dnow // AMD 3DNOW
  26. amd3dnowext // AMD 3DNowExt
  27. mmx // standard MMX
  28. mmxext // SSE integer functions or AMD MMX ext
  29. sse // SSE functions
  30. sse2 // P4 SSE functions
  31. sse3 // Prescott SSE3 functions
  32. ssse3 // Conroe SSSE3 functions
  33. sse4 // Penryn SSE4.1 functions
  34. sse4a // AMD Barcelona microarchitecture SSE4a instructions
  35. sse42 // Nehalem SSE4.2 functions
  36. avx // AVX functions
  37. avx2 // AVX2 functions
  38. fma3 // Intel FMA 3
  39. fma4 // Bulldozer FMA4 functions
  40. xop // Bulldozer XOP functions
  41. f16c // Half-precision floating-point conversion
  42. bmi1 // Bit Manipulation Instruction Set 1
  43. bmi2 // Bit Manipulation Instruction Set 2
  44. tbm // AMD Trailing Bit Manipulation
  45. lzcnt // LZCNT instruction
  46. popcnt // POPCNT instruction
  47. aesni // Advanced Encryption Standard New Instructions
  48. clmul // Carry-less Multiplication
  49. htt // Hyperthreading (enabled)
  50. hle // Hardware Lock Elision
  51. rtm // Restricted Transactional Memory
  52. rdrand // RDRAND instruction is available
  53. rdseed // RDSEED instruction is available
  54. adx // Intel ADX (Multi-Precision Add-Carry Instruction Extensions)
  55. sha // Intel SHA Extensions
  56. avx512f // AVX-512 Foundation
  57. avx512dq // AVX-512 Doubleword and Quadword Instructions
  58. avx512ifma // AVX-512 Integer Fused Multiply-Add Instructions
  59. avx512pf // AVX-512 Prefetch Instructions
  60. avx512er // AVX-512 Exponential and Reciprocal Instructions
  61. avx512cd // AVX-512 Conflict Detection Instructions
  62. avx512bw // AVX-512 Byte and Word Instructions
  63. avx512vl // AVX-512 Vector Length Extensions
  64. avx512vbmi // AVX-512 Vector Bit Manipulation Instructions
  65. avx512vbmi2 // AVX-512 Vector Bit Manipulation Instructions, Version 2
  66. avx512vnni // AVX-512 Vector Neural Network Instructions
  67. avx512vpopcntdq // AVX-512 Vector Population Count Doubleword and Quadword
  68. gfni // Galois Field New Instructions
  69. vaes // Vector AES
  70. avx512bitalg // AVX-512 Bit Algorithms
  71. vpclmulqdq // Carry-Less Multiplication Quadword
  72. avx512bf16 // AVX-512 BFLOAT16 Instructions
  73. avx512vp2intersect // AVX-512 Intersect for D/Q
  74. mpx // Intel MPX (Memory Protection Extensions)
  75. erms // Enhanced REP MOVSB/STOSB
  76. rdtscp // RDTSCP Instruction
  77. cx16 // CMPXCHG16B Instruction
  78. sgx // Software Guard Extensions
  79. sgxlc // Software Guard Extensions Launch Control
  80. ibpb // Indirect Branch Restricted Speculation (IBRS) and Indirect Branch Predictor Barrier (IBPB)
  81. stibp // Single Thread Indirect Branch Predictors
  82. vmx // Virtual Machine Extensions
  83. // Performance indicators
  84. sse2slow // SSE2 is supported, but usually not faster
  85. sse3slow // SSE3 is supported, but usually not faster
  86. atom // Atom processor, some SSSE3 instructions are slower
  87. )
  88. var flagNames = map[flags]string{
  89. cmov: "CMOV", // i686 CMOV
  90. nx: "NX", // NX (No-Execute) bit
  91. amd3dnow: "AMD3DNOW", // AMD 3DNOW
  92. amd3dnowext: "AMD3DNOWEXT", // AMD 3DNowExt
  93. mmx: "MMX", // Standard MMX
  94. mmxext: "MMXEXT", // SSE integer functions or AMD MMX ext
  95. sse: "SSE", // SSE functions
  96. sse2: "SSE2", // P4 SSE2 functions
  97. sse3: "SSE3", // Prescott SSE3 functions
  98. ssse3: "SSSE3", // Conroe SSSE3 functions
  99. sse4: "SSE4.1", // Penryn SSE4.1 functions
  100. sse4a: "SSE4A", // AMD Barcelona microarchitecture SSE4a instructions
  101. sse42: "SSE4.2", // Nehalem SSE4.2 functions
  102. avx: "AVX", // AVX functions
  103. avx2: "AVX2", // AVX functions
  104. fma3: "FMA3", // Intel FMA 3
  105. fma4: "FMA4", // Bulldozer FMA4 functions
  106. xop: "XOP", // Bulldozer XOP functions
  107. f16c: "F16C", // Half-precision floating-point conversion
  108. bmi1: "BMI1", // Bit Manipulation Instruction Set 1
  109. bmi2: "BMI2", // Bit Manipulation Instruction Set 2
  110. tbm: "TBM", // AMD Trailing Bit Manipulation
  111. lzcnt: "LZCNT", // LZCNT instruction
  112. popcnt: "POPCNT", // POPCNT instruction
  113. aesni: "AESNI", // Advanced Encryption Standard New Instructions
  114. clmul: "CLMUL", // Carry-less Multiplication
  115. htt: "HTT", // Hyperthreading (enabled)
  116. hle: "HLE", // Hardware Lock Elision
  117. rtm: "RTM", // Restricted Transactional Memory
  118. rdrand: "RDRAND", // RDRAND instruction is available
  119. rdseed: "RDSEED", // RDSEED instruction is available
  120. adx: "ADX", // Intel ADX (Multi-Precision Add-Carry Instruction Extensions)
  121. sha: "SHA", // Intel SHA Extensions
  122. avx512f: "AVX512F", // AVX-512 Foundation
  123. avx512dq: "AVX512DQ", // AVX-512 Doubleword and Quadword Instructions
  124. avx512ifma: "AVX512IFMA", // AVX-512 Integer Fused Multiply-Add Instructions
  125. avx512pf: "AVX512PF", // AVX-512 Prefetch Instructions
  126. avx512er: "AVX512ER", // AVX-512 Exponential and Reciprocal Instructions
  127. avx512cd: "AVX512CD", // AVX-512 Conflict Detection Instructions
  128. avx512bw: "AVX512BW", // AVX-512 Byte and Word Instructions
  129. avx512vl: "AVX512VL", // AVX-512 Vector Length Extensions
  130. avx512vbmi: "AVX512VBMI", // AVX-512 Vector Bit Manipulation Instructions
  131. avx512vbmi2: "AVX512VBMI2", // AVX-512 Vector Bit Manipulation Instructions, Version 2
  132. avx512vnni: "AVX512VNNI", // AVX-512 Vector Neural Network Instructions
  133. avx512vpopcntdq: "AVX512VPOPCNTDQ", // AVX-512 Vector Population Count Doubleword and Quadword
  134. gfni: "GFNI", // Galois Field New Instructions
  135. vaes: "VAES", // Vector AES
  136. avx512bitalg: "AVX512BITALG", // AVX-512 Bit Algorithms
  137. vpclmulqdq: "VPCLMULQDQ", // Carry-Less Multiplication Quadword
  138. avx512bf16: "AVX512BF16", // AVX-512 BFLOAT16 Instruction
  139. avx512vp2intersect: "AVX512VP2INTERSECT", // AVX-512 Intersect for D/Q
  140. mpx: "MPX", // Intel MPX (Memory Protection Extensions)
  141. erms: "ERMS", // Enhanced REP MOVSB/STOSB
  142. rdtscp: "RDTSCP", // RDTSCP Instruction
  143. cx16: "CX16", // CMPXCHG16B Instruction
  144. sgx: "SGX", // Software Guard Extensions
  145. sgxlc: "SGXLC", // Software Guard Extensions Launch Control
  146. ibpb: "IBPB", // Indirect Branch Restricted Speculation and Indirect Branch Predictor Barrier
  147. stibp: "STIBP", // Single Thread Indirect Branch Predictors
  148. vmx: "VMX", // Virtual Machine Extensions
  149. // Performance indicators
  150. sse2slow: "SSE2SLOW", // SSE2 supported, but usually not faster
  151. sse3slow: "SSE3SLOW", // SSE3 supported, but usually not faster
  152. atom: "ATOM", // Atom processor, some SSSE3 instructions are slower
  153. }
  154. // CPUInfo contains information about the detected system CPU.
  155. type cpuInfo struct {
  156. brandname string // Brand name reported by the CPU
  157. vendorid vendor // Comparable CPU vendor ID
  158. features flags // Features of the CPU
  159. physicalcores int // Number of physical processor cores in your CPU. Will be 0 if undetectable.
  160. threadspercore int // Number of threads per physical core. Will be 1 if undetectable.
  161. logicalcores int // Number of physical cores times threads that can run on each core through the use of hyperthreading. Will be 0 if undetectable.
  162. family int // CPU family number
  163. model int // CPU model number
  164. cacheline int // Cache line size in bytes. Will be 0 if undetectable.
  165. cache struct {
  166. l1i int // L1 Instruction Cache (per core or shared). Will be -1 if undetected
  167. l1d int // L1 Data Cache (per core or shared). Will be -1 if undetected
  168. l2 int // L2 Cache (per core or shared). Will be -1 if undetected
  169. l3 int // L3 Instruction Cache (per core or shared). Will be -1 if undetected
  170. }
  171. sgx sgxsupport
  172. maxFunc uint32
  173. maxExFunc uint32
  174. }
  175. var cpuid func(op uint32) (eax, ebx, ecx, edx uint32)
  176. var cpuidex func(op, op2 uint32) (eax, ebx, ecx, edx uint32)
  177. var xgetbv func(index uint32) (eax, edx uint32)
  178. var rdtscpAsm func() (eax, ebx, ecx, edx uint32)
  179. // CPU contains information about the CPU as detected on startup,
  180. // or when Detect last was called.
  181. //
  182. // Use this as the primary entry point to you data,
  183. // this way queries are
  184. var cpu cpuInfo
  185. func init() {
  186. initCPU()
  187. detect()
  188. }
  189. // Detect will re-detect current CPU info.
  190. // This will replace the content of the exported CPU variable.
  191. //
  192. // Unless you expect the CPU to change while you are running your program
  193. // you should not need to call this function.
  194. // If you call this, you must ensure that no other goroutine is accessing the
  195. // exported CPU variable.
  196. func detect() {
  197. cpu.maxFunc = maxFunctionID()
  198. cpu.maxExFunc = maxExtendedFunction()
  199. cpu.brandname = brandName()
  200. cpu.cacheline = cacheLine()
  201. cpu.family, cpu.model = familyModel()
  202. cpu.features = support()
  203. cpu.sgx = hasSGX(cpu.features&sgx != 0, cpu.features&sgxlc != 0)
  204. cpu.threadspercore = threadsPerCore()
  205. cpu.logicalcores = logicalCores()
  206. cpu.physicalcores = physicalCores()
  207. cpu.vendorid = vendorID()
  208. cpu.cacheSize()
  209. }
  210. // Generated here: http://play.golang.org/p/BxFH2Gdc0G
  211. // Cmov indicates support of CMOV instructions
  212. func (c cpuInfo) cmov() bool {
  213. return c.features&cmov != 0
  214. }
  215. // Amd3dnow indicates support of AMD 3DNOW! instructions
  216. func (c cpuInfo) amd3dnow() bool {
  217. return c.features&amd3dnow != 0
  218. }
  219. // Amd3dnowExt indicates support of AMD 3DNOW! Extended instructions
  220. func (c cpuInfo) amd3dnowext() bool {
  221. return c.features&amd3dnowext != 0
  222. }
  223. // VMX indicates support of VMX
  224. func (c cpuInfo) vmx() bool {
  225. return c.features&vmx != 0
  226. }
  227. // MMX indicates support of MMX instructions
  228. func (c cpuInfo) mmx() bool {
  229. return c.features&mmx != 0
  230. }
  231. // MMXExt indicates support of MMXEXT instructions
  232. // (SSE integer functions or AMD MMX ext)
  233. func (c cpuInfo) mmxext() bool {
  234. return c.features&mmxext != 0
  235. }
  236. // SSE indicates support of SSE instructions
  237. func (c cpuInfo) sse() bool {
  238. return c.features&sse != 0
  239. }
  240. // SSE2 indicates support of SSE 2 instructions
  241. func (c cpuInfo) sse2() bool {
  242. return c.features&sse2 != 0
  243. }
  244. // SSE3 indicates support of SSE 3 instructions
  245. func (c cpuInfo) sse3() bool {
  246. return c.features&sse3 != 0
  247. }
  248. // SSSE3 indicates support of SSSE 3 instructions
  249. func (c cpuInfo) ssse3() bool {
  250. return c.features&ssse3 != 0
  251. }
  252. // SSE4 indicates support of SSE 4 (also called SSE 4.1) instructions
  253. func (c cpuInfo) sse4() bool {
  254. return c.features&sse4 != 0
  255. }
  256. // SSE42 indicates support of SSE4.2 instructions
  257. func (c cpuInfo) sse42() bool {
  258. return c.features&sse42 != 0
  259. }
  260. // AVX indicates support of AVX instructions
  261. // and operating system support of AVX instructions
  262. func (c cpuInfo) avx() bool {
  263. return c.features&avx != 0
  264. }
  265. // AVX2 indicates support of AVX2 instructions
  266. func (c cpuInfo) avx2() bool {
  267. return c.features&avx2 != 0
  268. }
  269. // FMA3 indicates support of FMA3 instructions
  270. func (c cpuInfo) fma3() bool {
  271. return c.features&fma3 != 0
  272. }
  273. // FMA4 indicates support of FMA4 instructions
  274. func (c cpuInfo) fma4() bool {
  275. return c.features&fma4 != 0
  276. }
  277. // XOP indicates support of XOP instructions
  278. func (c cpuInfo) xop() bool {
  279. return c.features&xop != 0
  280. }
  281. // F16C indicates support of F16C instructions
  282. func (c cpuInfo) f16c() bool {
  283. return c.features&f16c != 0
  284. }
  285. // BMI1 indicates support of BMI1 instructions
  286. func (c cpuInfo) bmi1() bool {
  287. return c.features&bmi1 != 0
  288. }
  289. // BMI2 indicates support of BMI2 instructions
  290. func (c cpuInfo) bmi2() bool {
  291. return c.features&bmi2 != 0
  292. }
  293. // TBM indicates support of TBM instructions
  294. // (AMD Trailing Bit Manipulation)
  295. func (c cpuInfo) tbm() bool {
  296. return c.features&tbm != 0
  297. }
  298. // Lzcnt indicates support of LZCNT instruction
  299. func (c cpuInfo) lzcnt() bool {
  300. return c.features&lzcnt != 0
  301. }
  302. // Popcnt indicates support of POPCNT instruction
  303. func (c cpuInfo) popcnt() bool {
  304. return c.features&popcnt != 0
  305. }
  306. // HTT indicates the processor has Hyperthreading enabled
  307. func (c cpuInfo) htt() bool {
  308. return c.features&htt != 0
  309. }
  310. // SSE2Slow indicates that SSE2 may be slow on this processor
  311. func (c cpuInfo) sse2slow() bool {
  312. return c.features&sse2slow != 0
  313. }
  314. // SSE3Slow indicates that SSE3 may be slow on this processor
  315. func (c cpuInfo) sse3slow() bool {
  316. return c.features&sse3slow != 0
  317. }
  318. // AesNi indicates support of AES-NI instructions
  319. // (Advanced Encryption Standard New Instructions)
  320. func (c cpuInfo) aesni() bool {
  321. return c.features&aesni != 0
  322. }
  323. // Clmul indicates support of CLMUL instructions
  324. // (Carry-less Multiplication)
  325. func (c cpuInfo) clmul() bool {
  326. return c.features&clmul != 0
  327. }
  328. // NX indicates support of NX (No-Execute) bit
  329. func (c cpuInfo) nx() bool {
  330. return c.features&nx != 0
  331. }
  332. // SSE4A indicates support of AMD Barcelona microarchitecture SSE4a instructions
  333. func (c cpuInfo) sse4a() bool {
  334. return c.features&sse4a != 0
  335. }
  336. // HLE indicates support of Hardware Lock Elision
  337. func (c cpuInfo) hle() bool {
  338. return c.features&hle != 0
  339. }
  340. // RTM indicates support of Restricted Transactional Memory
  341. func (c cpuInfo) rtm() bool {
  342. return c.features&rtm != 0
  343. }
  344. // Rdrand indicates support of RDRAND instruction is available
  345. func (c cpuInfo) rdrand() bool {
  346. return c.features&rdrand != 0
  347. }
  348. // Rdseed indicates support of RDSEED instruction is available
  349. func (c cpuInfo) rdseed() bool {
  350. return c.features&rdseed != 0
  351. }
  352. // ADX indicates support of Intel ADX (Multi-Precision Add-Carry Instruction Extensions)
  353. func (c cpuInfo) adx() bool {
  354. return c.features&adx != 0
  355. }
  356. // SHA indicates support of Intel SHA Extensions
  357. func (c cpuInfo) sha() bool {
  358. return c.features&sha != 0
  359. }
  360. // AVX512F indicates support of AVX-512 Foundation
  361. func (c cpuInfo) avx512f() bool {
  362. return c.features&avx512f != 0
  363. }
  364. // AVX512DQ indicates support of AVX-512 Doubleword and Quadword Instructions
  365. func (c cpuInfo) avx512dq() bool {
  366. return c.features&avx512dq != 0
  367. }
  368. // AVX512IFMA indicates support of AVX-512 Integer Fused Multiply-Add Instructions
  369. func (c cpuInfo) avx512ifma() bool {
  370. return c.features&avx512ifma != 0
  371. }
  372. // AVX512PF indicates support of AVX-512 Prefetch Instructions
  373. func (c cpuInfo) avx512pf() bool {
  374. return c.features&avx512pf != 0
  375. }
  376. // AVX512ER indicates support of AVX-512 Exponential and Reciprocal Instructions
  377. func (c cpuInfo) avx512er() bool {
  378. return c.features&avx512er != 0
  379. }
  380. // AVX512CD indicates support of AVX-512 Conflict Detection Instructions
  381. func (c cpuInfo) avx512cd() bool {
  382. return c.features&avx512cd != 0
  383. }
  384. // AVX512BW indicates support of AVX-512 Byte and Word Instructions
  385. func (c cpuInfo) avx512bw() bool {
  386. return c.features&avx512bw != 0
  387. }
  388. // AVX512VL indicates support of AVX-512 Vector Length Extensions
  389. func (c cpuInfo) avx512vl() bool {
  390. return c.features&avx512vl != 0
  391. }
  392. // AVX512VBMI indicates support of AVX-512 Vector Bit Manipulation Instructions
  393. func (c cpuInfo) avx512vbmi() bool {
  394. return c.features&avx512vbmi != 0
  395. }
  396. // AVX512VBMI2 indicates support of AVX-512 Vector Bit Manipulation Instructions, Version 2
  397. func (c cpuInfo) avx512vbmi2() bool {
  398. return c.features&avx512vbmi2 != 0
  399. }
  400. // AVX512VNNI indicates support of AVX-512 Vector Neural Network Instructions
  401. func (c cpuInfo) avx512vnni() bool {
  402. return c.features&avx512vnni != 0
  403. }
  404. // AVX512VPOPCNTDQ indicates support of AVX-512 Vector Population Count Doubleword and Quadword
  405. func (c cpuInfo) avx512vpopcntdq() bool {
  406. return c.features&avx512vpopcntdq != 0
  407. }
  408. // GFNI indicates support of Galois Field New Instructions
  409. func (c cpuInfo) gfni() bool {
  410. return c.features&gfni != 0
  411. }
  412. // VAES indicates support of Vector AES
  413. func (c cpuInfo) vaes() bool {
  414. return c.features&vaes != 0
  415. }
  416. // AVX512BITALG indicates support of AVX-512 Bit Algorithms
  417. func (c cpuInfo) avx512bitalg() bool {
  418. return c.features&avx512bitalg != 0
  419. }
  420. // VPCLMULQDQ indicates support of Carry-Less Multiplication Quadword
  421. func (c cpuInfo) vpclmulqdq() bool {
  422. return c.features&vpclmulqdq != 0
  423. }
  424. // AVX512BF16 indicates support of
  425. func (c cpuInfo) avx512bf16() bool {
  426. return c.features&avx512bf16 != 0
  427. }
  428. // AVX512VP2INTERSECT indicates support of
  429. func (c cpuInfo) avx512vp2intersect() bool {
  430. return c.features&avx512vp2intersect != 0
  431. }
  432. // MPX indicates support of Intel MPX (Memory Protection Extensions)
  433. func (c cpuInfo) mpx() bool {
  434. return c.features&mpx != 0
  435. }
  436. // ERMS indicates support of Enhanced REP MOVSB/STOSB
  437. func (c cpuInfo) erms() bool {
  438. return c.features&erms != 0
  439. }
  440. // RDTSCP Instruction is available.
  441. func (c cpuInfo) rdtscp() bool {
  442. return c.features&rdtscp != 0
  443. }
  444. // CX16 indicates if CMPXCHG16B instruction is available.
  445. func (c cpuInfo) cx16() bool {
  446. return c.features&cx16 != 0
  447. }
  448. // TSX is split into HLE (Hardware Lock Elision) and RTM (Restricted Transactional Memory) detection.
  449. // So TSX simply checks that.
  450. func (c cpuInfo) tsx() bool {
  451. return c.features&(hle|rtm) == hle|rtm
  452. }
  453. // Atom indicates an Atom processor
  454. func (c cpuInfo) atom() bool {
  455. return c.features&atom != 0
  456. }
  457. // Intel returns true if vendor is recognized as Intel
  458. func (c cpuInfo) intel() bool {
  459. return c.vendorid == intel
  460. }
  461. // AMD returns true if vendor is recognized as AMD
  462. func (c cpuInfo) amd() bool {
  463. return c.vendorid == amd
  464. }
  465. // Hygon returns true if vendor is recognized as Hygon
  466. func (c cpuInfo) hygon() bool {
  467. return c.vendorid == hygon
  468. }
  469. // Transmeta returns true if vendor is recognized as Transmeta
  470. func (c cpuInfo) transmeta() bool {
  471. return c.vendorid == transmeta
  472. }
  473. // NSC returns true if vendor is recognized as National Semiconductor
  474. func (c cpuInfo) nsc() bool {
  475. return c.vendorid == nsc
  476. }
  477. // VIA returns true if vendor is recognized as VIA
  478. func (c cpuInfo) via() bool {
  479. return c.vendorid == via
  480. }
  481. // RTCounter returns the 64-bit time-stamp counter
  482. // Uses the RDTSCP instruction. The value 0 is returned
  483. // if the CPU does not support the instruction.
  484. func (c cpuInfo) rtcounter() uint64 {
  485. if !c.rdtscp() {
  486. return 0
  487. }
  488. a, _, _, d := rdtscpAsm()
  489. return uint64(a) | (uint64(d) << 32)
  490. }
  491. // Ia32TscAux returns the IA32_TSC_AUX part of the RDTSCP.
  492. // This variable is OS dependent, but on Linux contains information
  493. // about the current cpu/core the code is running on.
  494. // If the RDTSCP instruction isn't supported on the CPU, the value 0 is returned.
  495. func (c cpuInfo) ia32tscaux() uint32 {
  496. if !c.rdtscp() {
  497. return 0
  498. }
  499. _, _, ecx, _ := rdtscpAsm()
  500. return ecx
  501. }
  502. // LogicalCPU will return the Logical CPU the code is currently executing on.
  503. // This is likely to change when the OS re-schedules the running thread
  504. // to another CPU.
  505. // If the current core cannot be detected, -1 will be returned.
  506. func (c cpuInfo) logicalcpu() int {
  507. if c.maxFunc < 1 {
  508. return -1
  509. }
  510. _, ebx, _, _ := cpuid(1)
  511. return int(ebx >> 24)
  512. }
  513. // VM Will return true if the cpu id indicates we are in
  514. // a virtual machine. This is only a hint, and will very likely
  515. // have many false negatives.
  516. func (c cpuInfo) vm() bool {
  517. switch c.vendorid {
  518. case msvm, kvm, vmware, xenhvm, bhyve:
  519. return true
  520. }
  521. return false
  522. }
  523. // Flags contains detected cpu features and caracteristics
  524. type flags uint64
  525. // String returns a string representation of the detected
  526. // CPU features.
  527. func (f flags) String() string {
  528. return strings.Join(f.strings(), ",")
  529. }
  530. // Strings returns and array of the detected features.
  531. func (f flags) strings() []string {
  532. s := support()
  533. r := make([]string, 0, 20)
  534. for i := uint(0); i < 64; i++ {
  535. key := flags(1 << i)
  536. val := flagNames[key]
  537. if s&key != 0 {
  538. r = append(r, val)
  539. }
  540. }
  541. return r
  542. }
  543. func maxExtendedFunction() uint32 {
  544. eax, _, _, _ := cpuid(0x80000000)
  545. return eax
  546. }
  547. func maxFunctionID() uint32 {
  548. a, _, _, _ := cpuid(0)
  549. return a
  550. }
  551. func brandName() string {
  552. if maxExtendedFunction() >= 0x80000004 {
  553. v := make([]uint32, 0, 48)
  554. for i := uint32(0); i < 3; i++ {
  555. a, b, c, d := cpuid(0x80000002 + i)
  556. v = append(v, a, b, c, d)
  557. }
  558. return strings.Trim(string(valAsString(v...)), " ")
  559. }
  560. return "unknown"
  561. }
  562. func threadsPerCore() int {
  563. mfi := maxFunctionID()
  564. if mfi < 0x4 || vendorID() != intel {
  565. return 1
  566. }
  567. if mfi < 0xb {
  568. _, b, _, d := cpuid(1)
  569. if (d & (1 << 28)) != 0 {
  570. // v will contain logical core count
  571. v := (b >> 16) & 255
  572. if v > 1 {
  573. a4, _, _, _ := cpuid(4)
  574. // physical cores
  575. v2 := (a4 >> 26) + 1
  576. if v2 > 0 {
  577. return int(v) / int(v2)
  578. }
  579. }
  580. }
  581. return 1
  582. }
  583. _, b, _, _ := cpuidex(0xb, 0)
  584. if b&0xffff == 0 {
  585. return 1
  586. }
  587. return int(b & 0xffff)
  588. }
  589. func logicalCores() int {
  590. mfi := maxFunctionID()
  591. switch vendorID() {
  592. case intel:
  593. // Use this on old Intel processors
  594. if mfi < 0xb {
  595. if mfi < 1 {
  596. return 0
  597. }
  598. // CPUID.1:EBX[23:16] represents the maximum number of addressable IDs (initial APIC ID)
  599. // that can be assigned to logical processors in a physical package.
  600. // The value may not be the same as the number of logical processors that are present in the hardware of a physical package.
  601. _, ebx, _, _ := cpuid(1)
  602. logical := (ebx >> 16) & 0xff
  603. return int(logical)
  604. }
  605. _, b, _, _ := cpuidex(0xb, 1)
  606. return int(b & 0xffff)
  607. case amd, hygon:
  608. _, b, _, _ := cpuid(1)
  609. return int((b >> 16) & 0xff)
  610. default:
  611. return 0
  612. }
  613. }
  614. func familyModel() (int, int) {
  615. if maxFunctionID() < 0x1 {
  616. return 0, 0
  617. }
  618. eax, _, _, _ := cpuid(1)
  619. family := ((eax >> 8) & 0xf) + ((eax >> 20) & 0xff)
  620. model := ((eax >> 4) & 0xf) + ((eax >> 12) & 0xf0)
  621. return int(family), int(model)
  622. }
  623. func physicalCores() int {
  624. switch vendorID() {
  625. case intel:
  626. return logicalCores() / threadsPerCore()
  627. case amd, hygon:
  628. if maxExtendedFunction() >= 0x80000008 {
  629. _, _, c, _ := cpuid(0x80000008)
  630. return int(c&0xff) + 1
  631. }
  632. }
  633. return 0
  634. }
  635. // Except from http://en.wikipedia.org/wiki/CPUID#EAX.3D0:_Get_vendor_ID
  636. var vendorMapping = map[string]vendor{
  637. "AMDisbetter!": amd,
  638. "AuthenticAMD": amd,
  639. "CentaurHauls": via,
  640. "GenuineIntel": intel,
  641. "TransmetaCPU": transmeta,
  642. "GenuineTMx86": transmeta,
  643. "Geode by NSC": nsc,
  644. "VIA VIA VIA ": via,
  645. "KVMKVMKVMKVM": kvm,
  646. "Microsoft Hv": msvm,
  647. "VMwareVMware": vmware,
  648. "XenVMMXenVMM": xenhvm,
  649. "bhyve bhyve ": bhyve,
  650. "HygonGenuine": hygon,
  651. }
  652. func vendorID() vendor {
  653. _, b, c, d := cpuid(0)
  654. v := valAsString(b, d, c)
  655. vend, ok := vendorMapping[string(v)]
  656. if !ok {
  657. return other
  658. }
  659. return vend
  660. }
  661. func cacheLine() int {
  662. if maxFunctionID() < 0x1 {
  663. return 0
  664. }
  665. _, ebx, _, _ := cpuid(1)
  666. cache := (ebx & 0xff00) >> 5 // cflush size
  667. if cache == 0 && maxExtendedFunction() >= 0x80000006 {
  668. _, _, ecx, _ := cpuid(0x80000006)
  669. cache = ecx & 0xff // cacheline size
  670. }
  671. // TODO: Read from Cache and TLB Information
  672. return int(cache)
  673. }
  674. func (c *cpuInfo) cacheSize() {
  675. c.cache.l1d = -1
  676. c.cache.l1i = -1
  677. c.cache.l2 = -1
  678. c.cache.l3 = -1
  679. vendor := vendorID()
  680. switch vendor {
  681. case intel:
  682. if maxFunctionID() < 4 {
  683. return
  684. }
  685. for i := uint32(0); ; i++ {
  686. eax, ebx, ecx, _ := cpuidex(4, i)
  687. cacheType := eax & 15
  688. if cacheType == 0 {
  689. break
  690. }
  691. cacheLevel := (eax >> 5) & 7
  692. coherency := int(ebx&0xfff) + 1
  693. partitions := int((ebx>>12)&0x3ff) + 1
  694. associativity := int((ebx>>22)&0x3ff) + 1
  695. sets := int(ecx) + 1
  696. size := associativity * partitions * coherency * sets
  697. switch cacheLevel {
  698. case 1:
  699. if cacheType == 1 {
  700. // 1 = Data Cache
  701. c.cache.l1d = size
  702. } else if cacheType == 2 {
  703. // 2 = Instruction Cache
  704. c.cache.l1i = size
  705. } else {
  706. if c.cache.l1d < 0 {
  707. c.cache.l1i = size
  708. }
  709. if c.cache.l1i < 0 {
  710. c.cache.l1i = size
  711. }
  712. }
  713. case 2:
  714. c.cache.l2 = size
  715. case 3:
  716. c.cache.l3 = size
  717. }
  718. }
  719. case amd, hygon:
  720. // Untested.
  721. if maxExtendedFunction() < 0x80000005 {
  722. return
  723. }
  724. _, _, ecx, edx := cpuid(0x80000005)
  725. c.cache.l1d = int(((ecx >> 24) & 0xFF) * 1024)
  726. c.cache.l1i = int(((edx >> 24) & 0xFF) * 1024)
  727. if maxExtendedFunction() < 0x80000006 {
  728. return
  729. }
  730. _, _, ecx, _ = cpuid(0x80000006)
  731. c.cache.l2 = int(((ecx >> 16) & 0xFFFF) * 1024)
  732. }
  733. return
  734. }
  735. type sgxepcsection struct {
  736. baseaddress uint64
  737. epcsize uint64
  738. }
  739. type sgxsupport struct {
  740. available bool
  741. launchcontrol bool
  742. sgx1supported bool
  743. sgx2supported bool
  744. maxenclavesizenot64 int64
  745. maxenclavesize64 int64
  746. epcsections []sgxepcsection
  747. }
  748. func hasSGX(available, lc bool) (rval sgxsupport) {
  749. rval.available = available
  750. if !available {
  751. return
  752. }
  753. rval.launchcontrol = lc
  754. a, _, _, d := cpuidex(0x12, 0)
  755. rval.sgx1supported = a&0x01 != 0
  756. rval.sgx2supported = a&0x02 != 0
  757. rval.maxenclavesizenot64 = 1 << (d & 0xFF) // pow 2
  758. rval.maxenclavesize64 = 1 << ((d >> 8) & 0xFF) // pow 2
  759. rval.epcsections = make([]sgxepcsection, 0)
  760. for subleaf := uint32(2); subleaf < 2+8; subleaf++ {
  761. eax, ebx, ecx, edx := cpuidex(0x12, subleaf)
  762. leafType := eax & 0xf
  763. if leafType == 0 {
  764. // Invalid subleaf, stop iterating
  765. break
  766. } else if leafType == 1 {
  767. // EPC Section subleaf
  768. baseAddress := uint64(eax&0xfffff000) + (uint64(ebx&0x000fffff) << 32)
  769. size := uint64(ecx&0xfffff000) + (uint64(edx&0x000fffff) << 32)
  770. section := sgxepcsection{baseaddress: baseAddress, epcsize: size}
  771. rval.epcsections = append(rval.epcsections, section)
  772. }
  773. }
  774. return
  775. }
  776. func support() flags {
  777. mfi := maxFunctionID()
  778. vend := vendorID()
  779. if mfi < 0x1 {
  780. return 0
  781. }
  782. rval := uint64(0)
  783. _, _, c, d := cpuid(1)
  784. if (d & (1 << 15)) != 0 {
  785. rval |= cmov
  786. }
  787. if (d & (1 << 23)) != 0 {
  788. rval |= mmx
  789. }
  790. if (d & (1 << 25)) != 0 {
  791. rval |= mmxext
  792. }
  793. if (d & (1 << 25)) != 0 {
  794. rval |= sse
  795. }
  796. if (d & (1 << 26)) != 0 {
  797. rval |= sse2
  798. }
  799. if (c & 1) != 0 {
  800. rval |= sse3
  801. }
  802. if (c & (1 << 5)) != 0 {
  803. rval |= vmx
  804. }
  805. if (c & 0x00000200) != 0 {
  806. rval |= ssse3
  807. }
  808. if (c & 0x00080000) != 0 {
  809. rval |= sse4
  810. }
  811. if (c & 0x00100000) != 0 {
  812. rval |= sse42
  813. }
  814. if (c & (1 << 25)) != 0 {
  815. rval |= aesni
  816. }
  817. if (c & (1 << 1)) != 0 {
  818. rval |= clmul
  819. }
  820. if c&(1<<23) != 0 {
  821. rval |= popcnt
  822. }
  823. if c&(1<<30) != 0 {
  824. rval |= rdrand
  825. }
  826. if c&(1<<29) != 0 {
  827. rval |= f16c
  828. }
  829. if c&(1<<13) != 0 {
  830. rval |= cx16
  831. }
  832. if vend == intel && (d&(1<<28)) != 0 && mfi >= 4 {
  833. if threadsPerCore() > 1 {
  834. rval |= htt
  835. }
  836. }
  837. // Check XGETBV, OXSAVE and AVX bits
  838. if c&(1<<26) != 0 && c&(1<<27) != 0 && c&(1<<28) != 0 {
  839. // Check for OS support
  840. eax, _ := xgetbv(0)
  841. if (eax & 0x6) == 0x6 {
  842. rval |= avx
  843. if (c & 0x00001000) != 0 {
  844. rval |= fma3
  845. }
  846. }
  847. }
  848. // Check AVX2, AVX2 requires OS support, but BMI1/2 don't.
  849. if mfi >= 7 {
  850. _, ebx, ecx, edx := cpuidex(7, 0)
  851. eax1, _, _, _ := cpuidex(7, 1)
  852. if (rval&avx) != 0 && (ebx&0x00000020) != 0 {
  853. rval |= avx2
  854. }
  855. if (ebx & 0x00000008) != 0 {
  856. rval |= bmi1
  857. if (ebx & 0x00000100) != 0 {
  858. rval |= bmi2
  859. }
  860. }
  861. if ebx&(1<<2) != 0 {
  862. rval |= sgx
  863. }
  864. if ebx&(1<<4) != 0 {
  865. rval |= hle
  866. }
  867. if ebx&(1<<9) != 0 {
  868. rval |= erms
  869. }
  870. if ebx&(1<<11) != 0 {
  871. rval |= rtm
  872. }
  873. if ebx&(1<<14) != 0 {
  874. rval |= mpx
  875. }
  876. if ebx&(1<<18) != 0 {
  877. rval |= rdseed
  878. }
  879. if ebx&(1<<19) != 0 {
  880. rval |= adx
  881. }
  882. if ebx&(1<<29) != 0 {
  883. rval |= sha
  884. }
  885. if edx&(1<<26) != 0 {
  886. rval |= ibpb
  887. }
  888. if ecx&(1<<30) != 0 {
  889. rval |= sgxlc
  890. }
  891. if edx&(1<<27) != 0 {
  892. rval |= stibp
  893. }
  894. // Only detect AVX-512 features if XGETBV is supported
  895. if c&((1<<26)|(1<<27)) == (1<<26)|(1<<27) {
  896. // Check for OS support
  897. eax, _ := xgetbv(0)
  898. // Verify that XCR0[7:5] = ‘111b’ (OPMASK state, upper 256-bit of ZMM0-ZMM15 and
  899. // ZMM16-ZMM31 state are enabled by OS)
  900. /// and that XCR0[2:1] = ‘11b’ (XMM state and YMM state are enabled by OS).
  901. if (eax>>5)&7 == 7 && (eax>>1)&3 == 3 {
  902. if ebx&(1<<16) != 0 {
  903. rval |= avx512f
  904. }
  905. if ebx&(1<<17) != 0 {
  906. rval |= avx512dq
  907. }
  908. if ebx&(1<<21) != 0 {
  909. rval |= avx512ifma
  910. }
  911. if ebx&(1<<26) != 0 {
  912. rval |= avx512pf
  913. }
  914. if ebx&(1<<27) != 0 {
  915. rval |= avx512er
  916. }
  917. if ebx&(1<<28) != 0 {
  918. rval |= avx512cd
  919. }
  920. if ebx&(1<<30) != 0 {
  921. rval |= avx512bw
  922. }
  923. if ebx&(1<<31) != 0 {
  924. rval |= avx512vl
  925. }
  926. // ecx
  927. if ecx&(1<<1) != 0 {
  928. rval |= avx512vbmi
  929. }
  930. if ecx&(1<<6) != 0 {
  931. rval |= avx512vbmi2
  932. }
  933. if ecx&(1<<8) != 0 {
  934. rval |= gfni
  935. }
  936. if ecx&(1<<9) != 0 {
  937. rval |= vaes
  938. }
  939. if ecx&(1<<10) != 0 {
  940. rval |= vpclmulqdq
  941. }
  942. if ecx&(1<<11) != 0 {
  943. rval |= avx512vnni
  944. }
  945. if ecx&(1<<12) != 0 {
  946. rval |= avx512bitalg
  947. }
  948. if ecx&(1<<14) != 0 {
  949. rval |= avx512vpopcntdq
  950. }
  951. // edx
  952. if edx&(1<<8) != 0 {
  953. rval |= avx512vp2intersect
  954. }
  955. // cpuid eax 07h,ecx=1
  956. if eax1&(1<<5) != 0 {
  957. rval |= avx512bf16
  958. }
  959. }
  960. }
  961. }
  962. if maxExtendedFunction() >= 0x80000001 {
  963. _, _, c, d := cpuid(0x80000001)
  964. if (c & (1 << 5)) != 0 {
  965. rval |= lzcnt
  966. rval |= popcnt
  967. }
  968. if (d & (1 << 31)) != 0 {
  969. rval |= amd3dnow
  970. }
  971. if (d & (1 << 30)) != 0 {
  972. rval |= amd3dnowext
  973. }
  974. if (d & (1 << 23)) != 0 {
  975. rval |= mmx
  976. }
  977. if (d & (1 << 22)) != 0 {
  978. rval |= mmxext
  979. }
  980. if (c & (1 << 6)) != 0 {
  981. rval |= sse4a
  982. }
  983. if d&(1<<20) != 0 {
  984. rval |= nx
  985. }
  986. if d&(1<<27) != 0 {
  987. rval |= rdtscp
  988. }
  989. /* Allow for selectively disabling SSE2 functions on AMD processors
  990. with SSE2 support but not SSE4a. This includes Athlon64, some
  991. Opteron, and some Sempron processors. MMX, SSE, or 3DNow! are faster
  992. than SSE2 often enough to utilize this special-case flag.
  993. AV_CPU_FLAG_SSE2 and AV_CPU_FLAG_SSE2SLOW are both set in this case
  994. so that SSE2 is used unless explicitly disabled by checking
  995. AV_CPU_FLAG_SSE2SLOW. */
  996. if vendorID() != intel &&
  997. rval&sse2 != 0 && (c&0x00000040) == 0 {
  998. rval |= sse2slow
  999. }
  1000. /* XOP and FMA4 use the AVX instruction coding scheme, so they can't be
  1001. * used unless the OS has AVX support. */
  1002. if (rval & avx) != 0 {
  1003. if (c & 0x00000800) != 0 {
  1004. rval |= xop
  1005. }
  1006. if (c & 0x00010000) != 0 {
  1007. rval |= fma4
  1008. }
  1009. }
  1010. if vendorID() == intel {
  1011. family, model := familyModel()
  1012. if family == 6 && (model == 9 || model == 13 || model == 14) {
  1013. /* 6/9 (pentium-m "banias"), 6/13 (pentium-m "dothan"), and
  1014. * 6/14 (core1 "yonah") theoretically support sse2, but it's
  1015. * usually slower than mmx. */
  1016. if (rval & sse2) != 0 {
  1017. rval |= sse2slow
  1018. }
  1019. if (rval & sse3) != 0 {
  1020. rval |= sse3slow
  1021. }
  1022. }
  1023. /* The Atom processor has SSSE3 support, which is useful in many cases,
  1024. * but sometimes the SSSE3 version is slower than the SSE2 equivalent
  1025. * on the Atom, but is generally faster on other processors supporting
  1026. * SSSE3. This flag allows for selectively disabling certain SSSE3
  1027. * functions on the Atom. */
  1028. if family == 6 && model == 28 {
  1029. rval |= atom
  1030. }
  1031. }
  1032. }
  1033. return flags(rval)
  1034. }
  1035. func valAsString(values ...uint32) []byte {
  1036. r := make([]byte, 4*len(values))
  1037. for i, v := range values {
  1038. dst := r[i*4:]
  1039. dst[0] = byte(v & 0xff)
  1040. dst[1] = byte((v >> 8) & 0xff)
  1041. dst[2] = byte((v >> 16) & 0xff)
  1042. dst[3] = byte((v >> 24) & 0xff)
  1043. switch {
  1044. case dst[0] == 0:
  1045. return r[:i*4]
  1046. case dst[1] == 0:
  1047. return r[:i*4+1]
  1048. case dst[2] == 0:
  1049. return r[:i*4+2]
  1050. case dst[3] == 0:
  1051. return r[:i*4+3]
  1052. }
  1053. }
  1054. return r
  1055. }