x86_64cpuid.pl 9.9 KB

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