x86_64cpuid.pl 10 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511
  1. #! /usr/bin/env perl
  2. # Copyright 2005-2020 The OpenSSL Project Authors. All Rights Reserved.
  3. #
  4. # Licensed under the OpenSSL license (the "License"). You may not use
  5. # this file except in compliance with the License. You can obtain a copy
  6. # in the file LICENSE in the source distribution or at
  7. # https://www.openssl.org/source/license.html
  8. $flavour = shift;
  9. $output = shift;
  10. if ($flavour =~ /\./) { $output = $flavour; undef $flavour; }
  11. $win64=0; $win64=1 if ($flavour =~ /[nm]asm|mingw64/ || $output =~ /\.asm$/);
  12. $0 =~ m/(.*[\/\\])[^\/\\]+$/; $dir=$1;
  13. ( $xlate="${dir}x86_64-xlate.pl" and -f $xlate ) or
  14. ( $xlate="${dir}perlasm/x86_64-xlate.pl" and -f $xlate) or
  15. die "can't locate x86_64-xlate.pl";
  16. open OUT,"| \"$^X\" \"$xlate\" $flavour \"$output\"";
  17. *STDOUT=*OUT;
  18. ($arg1,$arg2,$arg3,$arg4)=$win64?("%rcx","%rdx","%r8", "%r9") : # Win64 order
  19. ("%rdi","%rsi","%rdx","%rcx"); # Unix order
  20. print<<___;
  21. .extern OPENSSL_cpuid_setup
  22. .hidden OPENSSL_cpuid_setup
  23. .section .init
  24. call OPENSSL_cpuid_setup
  25. .hidden OPENSSL_ia32cap_P
  26. .comm OPENSSL_ia32cap_P,16,4
  27. .text
  28. .globl OPENSSL_atomic_add
  29. .type OPENSSL_atomic_add,\@abi-omnipotent
  30. .align 16
  31. OPENSSL_atomic_add:
  32. .cfi_startproc
  33. movl ($arg1),%eax
  34. .Lspin: leaq ($arg2,%rax),%r8
  35. .byte 0xf0 # lock
  36. cmpxchgl %r8d,($arg1)
  37. jne .Lspin
  38. movl %r8d,%eax
  39. .byte 0x48,0x98 # cltq/cdqe
  40. ret
  41. .cfi_endproc
  42. .size OPENSSL_atomic_add,.-OPENSSL_atomic_add
  43. .globl OPENSSL_rdtsc
  44. .type OPENSSL_rdtsc,\@abi-omnipotent
  45. .align 16
  46. OPENSSL_rdtsc:
  47. .cfi_startproc
  48. rdtsc
  49. shl \$32,%rdx
  50. or %rdx,%rax
  51. ret
  52. .cfi_endproc
  53. .size OPENSSL_rdtsc,.-OPENSSL_rdtsc
  54. .globl OPENSSL_ia32_cpuid
  55. .type OPENSSL_ia32_cpuid,\@function,1
  56. .align 16
  57. OPENSSL_ia32_cpuid:
  58. .cfi_startproc
  59. mov %rbx,%r8 # save %rbx
  60. .cfi_register %rbx,%r8
  61. xor %eax,%eax
  62. mov %rax,8(%rdi) # clear extended feature flags
  63. cpuid
  64. mov %eax,%r11d # max value for standard query level
  65. xor %eax,%eax
  66. cmp \$0x756e6547,%ebx # "Genu"
  67. setne %al
  68. mov %eax,%r9d
  69. cmp \$0x49656e69,%edx # "ineI"
  70. setne %al
  71. or %eax,%r9d
  72. cmp \$0x6c65746e,%ecx # "ntel"
  73. setne %al
  74. or %eax,%r9d # 0 indicates Intel CPU
  75. jz .Lintel
  76. cmp \$0x68747541,%ebx # "Auth"
  77. setne %al
  78. mov %eax,%r10d
  79. cmp \$0x69746E65,%edx # "enti"
  80. setne %al
  81. or %eax,%r10d
  82. cmp \$0x444D4163,%ecx # "cAMD"
  83. setne %al
  84. or %eax,%r10d # 0 indicates AMD CPU
  85. jnz .Lintel
  86. # AMD specific
  87. mov \$0x80000000,%eax
  88. cpuid
  89. cmp \$0x80000001,%eax
  90. jb .Lintel
  91. mov %eax,%r10d
  92. mov \$0x80000001,%eax
  93. cpuid
  94. or %ecx,%r9d
  95. and \$0x00000801,%r9d # isolate AMD XOP bit, 1<<11
  96. cmp \$0x80000008,%r10d
  97. jb .Lintel
  98. mov \$0x80000008,%eax
  99. cpuid
  100. movzb %cl,%r10 # number of cores - 1
  101. inc %r10 # number of cores
  102. mov \$1,%eax
  103. cpuid
  104. bt \$28,%edx # test hyper-threading bit
  105. jnc .Lgeneric
  106. shr \$16,%ebx # number of logical processors
  107. cmp %r10b,%bl
  108. ja .Lgeneric
  109. and \$0xefffffff,%edx # ~(1<<28)
  110. jmp .Lgeneric
  111. .Lintel:
  112. cmp \$4,%r11d
  113. mov \$-1,%r10d
  114. jb .Lnocacheinfo
  115. mov \$4,%eax
  116. mov \$0,%ecx # query L1D
  117. cpuid
  118. mov %eax,%r10d
  119. shr \$14,%r10d
  120. and \$0xfff,%r10d # number of cores -1 per L1D
  121. .Lnocacheinfo:
  122. mov \$1,%eax
  123. cpuid
  124. movd %eax,%xmm0 # put aside processor id
  125. and \$0xbfefffff,%edx # force reserved bits to 0
  126. cmp \$0,%r9d
  127. jne .Lnotintel
  128. or \$0x40000000,%edx # set reserved bit#30 on Intel CPUs
  129. and \$15,%ah
  130. cmp \$15,%ah # examine Family ID
  131. jne .LnotP4
  132. or \$0x00100000,%edx # set reserved bit#20 to engage RC4_CHAR
  133. .LnotP4:
  134. cmp \$6,%ah
  135. jne .Lnotintel
  136. and \$0x0fff0ff0,%eax
  137. cmp \$0x00050670,%eax # Knights Landing
  138. je .Lknights
  139. cmp \$0x00080650,%eax # Knights Mill (according to sde)
  140. jne .Lnotintel
  141. .Lknights:
  142. and \$0xfbffffff,%ecx # clear XSAVE flag to mimic Silvermont
  143. .Lnotintel:
  144. bt \$28,%edx # test hyper-threading bit
  145. jnc .Lgeneric
  146. and \$0xefffffff,%edx # ~(1<<28)
  147. cmp \$0,%r10d
  148. je .Lgeneric
  149. or \$0x10000000,%edx # 1<<28
  150. shr \$16,%ebx
  151. cmp \$1,%bl # see if cache is shared
  152. ja .Lgeneric
  153. and \$0xefffffff,%edx # ~(1<<28)
  154. .Lgeneric:
  155. and \$0x00000800,%r9d # isolate AMD XOP flag
  156. and \$0xfffff7ff,%ecx
  157. or %ecx,%r9d # merge AMD XOP flag
  158. mov %edx,%r10d # %r9d:%r10d is copy of %ecx:%edx
  159. cmp \$7,%r11d
  160. jb .Lno_extended_info
  161. mov \$7,%eax
  162. xor %ecx,%ecx
  163. cpuid
  164. bt \$26,%r9d # check XSAVE bit, cleared on Knights
  165. jc .Lnotknights
  166. and \$0xfff7ffff,%ebx # clear ADCX/ADOX flag
  167. .Lnotknights:
  168. movd %xmm0,%eax # restore processor id
  169. and \$0x0fff0ff0,%eax
  170. cmp \$0x00050650,%eax # Skylake-X
  171. jne .Lnotskylakex
  172. and \$0xfffeffff,%ebx # ~(1<<16)
  173. # suppress AVX512F flag on Skylake-X
  174. .Lnotskylakex:
  175. mov %ebx,8(%rdi) # save extended feature flags
  176. mov %ecx,12(%rdi)
  177. .Lno_extended_info:
  178. bt \$27,%r9d # check OSXSAVE bit
  179. jnc .Lclear_avx
  180. xor %ecx,%ecx # XCR0
  181. .byte 0x0f,0x01,0xd0 # xgetbv
  182. and \$0xe6,%eax # isolate XMM, YMM and ZMM state support
  183. cmp \$0xe6,%eax
  184. je .Ldone
  185. andl \$0x3fdeffff,8(%rdi) # ~(1<<31|1<<30|1<<21|1<<16)
  186. # clear AVX512F+BW+VL+FIMA, all of
  187. # them are EVEX-encoded, which requires
  188. # ZMM state support even if one uses
  189. # only XMM and YMM :-(
  190. and \$6,%eax # isolate XMM and YMM state support
  191. cmp \$6,%eax
  192. je .Ldone
  193. .Lclear_avx:
  194. mov \$0xefffe7ff,%eax # ~(1<<28|1<<12|1<<11)
  195. and %eax,%r9d # clear AVX, FMA and AMD XOP bits
  196. mov \$0x3fdeffdf,%eax # ~(1<<31|1<<30|1<<21|1<<16|1<<5)
  197. and %eax,8(%rdi) # clear AVX2 and AVX512* bits
  198. .Ldone:
  199. shl \$32,%r9
  200. mov %r10d,%eax
  201. mov %r8,%rbx # restore %rbx
  202. .cfi_restore %rbx
  203. or %r9,%rax
  204. ret
  205. .cfi_endproc
  206. .size OPENSSL_ia32_cpuid,.-OPENSSL_ia32_cpuid
  207. .globl OPENSSL_cleanse
  208. .type OPENSSL_cleanse,\@abi-omnipotent
  209. .align 16
  210. OPENSSL_cleanse:
  211. .cfi_startproc
  212. xor %rax,%rax
  213. cmp \$15,$arg2
  214. jae .Lot
  215. cmp \$0,$arg2
  216. je .Lret
  217. .Little:
  218. mov %al,($arg1)
  219. sub \$1,$arg2
  220. lea 1($arg1),$arg1
  221. jnz .Little
  222. .Lret:
  223. ret
  224. .align 16
  225. .Lot:
  226. test \$7,$arg1
  227. jz .Laligned
  228. mov %al,($arg1)
  229. lea -1($arg2),$arg2
  230. lea 1($arg1),$arg1
  231. jmp .Lot
  232. .Laligned:
  233. mov %rax,($arg1)
  234. lea -8($arg2),$arg2
  235. test \$-8,$arg2
  236. lea 8($arg1),$arg1
  237. jnz .Laligned
  238. cmp \$0,$arg2
  239. jne .Little
  240. ret
  241. .cfi_endproc
  242. .size OPENSSL_cleanse,.-OPENSSL_cleanse
  243. .globl CRYPTO_memcmp
  244. .type CRYPTO_memcmp,\@abi-omnipotent
  245. .align 16
  246. CRYPTO_memcmp:
  247. .cfi_startproc
  248. xor %rax,%rax
  249. xor %r10,%r10
  250. cmp \$0,$arg3
  251. je .Lno_data
  252. cmp \$16,$arg3
  253. jne .Loop_cmp
  254. mov ($arg1),%r10
  255. mov 8($arg1),%r11
  256. mov \$1,$arg3
  257. xor ($arg2),%r10
  258. xor 8($arg2),%r11
  259. or %r11,%r10
  260. cmovnz $arg3,%rax
  261. ret
  262. .align 16
  263. .Loop_cmp:
  264. mov ($arg1),%r10b
  265. lea 1($arg1),$arg1
  266. xor ($arg2),%r10b
  267. lea 1($arg2),$arg2
  268. or %r10b,%al
  269. dec $arg3
  270. jnz .Loop_cmp
  271. neg %rax
  272. shr \$63,%rax
  273. .Lno_data:
  274. ret
  275. .cfi_endproc
  276. .size CRYPTO_memcmp,.-CRYPTO_memcmp
  277. ___
  278. print<<___ if (!$win64);
  279. .globl OPENSSL_wipe_cpu
  280. .type OPENSSL_wipe_cpu,\@abi-omnipotent
  281. .align 16
  282. OPENSSL_wipe_cpu:
  283. .cfi_startproc
  284. pxor %xmm0,%xmm0
  285. pxor %xmm1,%xmm1
  286. pxor %xmm2,%xmm2
  287. pxor %xmm3,%xmm3
  288. pxor %xmm4,%xmm4
  289. pxor %xmm5,%xmm5
  290. pxor %xmm6,%xmm6
  291. pxor %xmm7,%xmm7
  292. pxor %xmm8,%xmm8
  293. pxor %xmm9,%xmm9
  294. pxor %xmm10,%xmm10
  295. pxor %xmm11,%xmm11
  296. pxor %xmm12,%xmm12
  297. pxor %xmm13,%xmm13
  298. pxor %xmm14,%xmm14
  299. pxor %xmm15,%xmm15
  300. xorq %rcx,%rcx
  301. xorq %rdx,%rdx
  302. xorq %rsi,%rsi
  303. xorq %rdi,%rdi
  304. xorq %r8,%r8
  305. xorq %r9,%r9
  306. xorq %r10,%r10
  307. xorq %r11,%r11
  308. leaq 8(%rsp),%rax
  309. ret
  310. .cfi_endproc
  311. .size OPENSSL_wipe_cpu,.-OPENSSL_wipe_cpu
  312. ___
  313. print<<___ if ($win64);
  314. .globl OPENSSL_wipe_cpu
  315. .type OPENSSL_wipe_cpu,\@abi-omnipotent
  316. .align 16
  317. OPENSSL_wipe_cpu:
  318. pxor %xmm0,%xmm0
  319. pxor %xmm1,%xmm1
  320. pxor %xmm2,%xmm2
  321. pxor %xmm3,%xmm3
  322. pxor %xmm4,%xmm4
  323. pxor %xmm5,%xmm5
  324. xorq %rcx,%rcx
  325. xorq %rdx,%rdx
  326. xorq %r8,%r8
  327. xorq %r9,%r9
  328. xorq %r10,%r10
  329. xorq %r11,%r11
  330. leaq 8(%rsp),%rax
  331. ret
  332. .size OPENSSL_wipe_cpu,.-OPENSSL_wipe_cpu
  333. ___
  334. {
  335. my $out="%r10";
  336. my $cnt="%rcx";
  337. my $max="%r11";
  338. my $lasttick="%r8d";
  339. my $lastdiff="%r9d";
  340. my $redzone=win64?8:-8;
  341. print<<___;
  342. .globl OPENSSL_instrument_bus
  343. .type OPENSSL_instrument_bus,\@abi-omnipotent
  344. .align 16
  345. OPENSSL_instrument_bus:
  346. .cfi_startproc
  347. mov $arg1,$out # tribute to Win64
  348. mov $arg2,$cnt
  349. mov $arg2,$max
  350. rdtsc # collect 1st tick
  351. mov %eax,$lasttick # lasttick = tick
  352. mov \$0,$lastdiff # lastdiff = 0
  353. clflush ($out)
  354. .byte 0xf0 # lock
  355. add $lastdiff,($out)
  356. jmp .Loop
  357. .align 16
  358. .Loop: rdtsc
  359. mov %eax,%edx
  360. sub $lasttick,%eax
  361. mov %edx,$lasttick
  362. mov %eax,$lastdiff
  363. clflush ($out)
  364. .byte 0xf0 # lock
  365. add %eax,($out)
  366. lea 4($out),$out
  367. sub \$1,$cnt
  368. jnz .Loop
  369. mov $max,%rax
  370. ret
  371. .cfi_endproc
  372. .size OPENSSL_instrument_bus,.-OPENSSL_instrument_bus
  373. .globl OPENSSL_instrument_bus2
  374. .type OPENSSL_instrument_bus2,\@abi-omnipotent
  375. .align 16
  376. OPENSSL_instrument_bus2:
  377. .cfi_startproc
  378. mov $arg1,$out # tribute to Win64
  379. mov $arg2,$cnt
  380. mov $arg3,$max
  381. mov $cnt,$redzone(%rsp)
  382. rdtsc # collect 1st tick
  383. mov %eax,$lasttick # lasttick = tick
  384. mov \$0,$lastdiff # lastdiff = 0
  385. clflush ($out)
  386. .byte 0xf0 # lock
  387. add $lastdiff,($out)
  388. rdtsc # collect 1st diff
  389. mov %eax,%edx
  390. sub $lasttick,%eax # diff
  391. mov %edx,$lasttick # lasttick = tick
  392. mov %eax,$lastdiff # lastdiff = diff
  393. .Loop2:
  394. clflush ($out)
  395. .byte 0xf0 # lock
  396. add %eax,($out) # accumulate diff
  397. sub \$1,$max
  398. jz .Ldone2
  399. rdtsc
  400. mov %eax,%edx
  401. sub $lasttick,%eax # diff
  402. mov %edx,$lasttick # lasttick = tick
  403. cmp $lastdiff,%eax
  404. mov %eax,$lastdiff # lastdiff = diff
  405. mov \$0,%edx
  406. setne %dl
  407. sub %rdx,$cnt # conditional --$cnt
  408. lea ($out,%rdx,4),$out # conditional ++$out
  409. jnz .Loop2
  410. .Ldone2:
  411. mov $redzone(%rsp),%rax
  412. sub $cnt,%rax
  413. ret
  414. .cfi_endproc
  415. .size OPENSSL_instrument_bus2,.-OPENSSL_instrument_bus2
  416. ___
  417. }
  418. sub gen_random {
  419. my $rdop = shift;
  420. print<<___;
  421. .globl OPENSSL_ia32_${rdop}_bytes
  422. .type OPENSSL_ia32_${rdop}_bytes,\@abi-omnipotent
  423. .align 16
  424. OPENSSL_ia32_${rdop}_bytes:
  425. .cfi_startproc
  426. xor %rax, %rax # return value
  427. cmp \$0,$arg2
  428. je .Ldone_${rdop}_bytes
  429. mov \$8,%r11
  430. .Loop_${rdop}_bytes:
  431. ${rdop} %r10
  432. jc .Lbreak_${rdop}_bytes
  433. dec %r11
  434. jnz .Loop_${rdop}_bytes
  435. jmp .Ldone_${rdop}_bytes
  436. .align 16
  437. .Lbreak_${rdop}_bytes:
  438. cmp \$8,$arg2
  439. jb .Ltail_${rdop}_bytes
  440. mov %r10,($arg1)
  441. lea 8($arg1),$arg1
  442. add \$8,%rax
  443. sub \$8,$arg2
  444. jz .Ldone_${rdop}_bytes
  445. mov \$8,%r11
  446. jmp .Loop_${rdop}_bytes
  447. .align 16
  448. .Ltail_${rdop}_bytes:
  449. mov %r10b,($arg1)
  450. lea 1($arg1),$arg1
  451. inc %rax
  452. shr \$8,%r10
  453. dec $arg2
  454. jnz .Ltail_${rdop}_bytes
  455. .Ldone_${rdop}_bytes:
  456. xor %r10,%r10 # Clear sensitive data from register
  457. ret
  458. .cfi_endproc
  459. .size OPENSSL_ia32_${rdop}_bytes,.-OPENSSL_ia32_${rdop}_bytes
  460. ___
  461. }
  462. gen_random("rdrand");
  463. gen_random("rdseed");
  464. close STDOUT or die "error closing STDOUT: $!"; # flush