hwaccel_amd64.go 2.3 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687
  1. // hwaccel_amd64.go - Hardware acceleration hooks
  2. //
  3. // To the extent possible under law, Yawning Angel has waived all copyright
  4. // and related or neighboring rights to the software, using the Creative
  5. // Commons "CC0" public domain dedication. See LICENSE or
  6. // <http://creativecommons.org/publicdomain/zero/1.0/> for full details.
  7. // +build amd64,!gccgo,!noasm,go1.10
  8. package hs1siv
  9. //go:noescape
  10. func cpuidAmd64(cpuidParams *uint32)
  11. //go:noescape
  12. func xgetbv0Amd64(xcrVec *uint32)
  13. //go:noescape
  14. func chachaXORKeyStreamAVX2(s *chachaState, in, out []byte)
  15. //go:noescape
  16. func hashStepAVX2(ctx *hs1Ctx, in []byte, accum *[hs1HashRounds]uint64)
  17. func supportsAVX2BMI2() bool {
  18. // https://software.intel.com/en-us/articles/how-to-detect-new-instruction-support-in-the-4th-generation-intel-core-processor-family
  19. const (
  20. osXsaveBit = 1 << 27
  21. avx2Bit = 1 << 5
  22. bmi2Bit = 1 << 8
  23. )
  24. // Check to see if CPUID actually supports the leaf required.
  25. // CPUID.(EAX=0H, ECX=0H) >= 7
  26. regs := [4]uint32{0x00}
  27. cpuidAmd64(&regs[0])
  28. if regs[0] < 7 {
  29. return false
  30. }
  31. // Check to see if the OS knows how to save/restore XMM/YMM state.
  32. // CPUID.(EAX=01H, ECX=0H):ECX.OSXSAVE[bit 27]==1
  33. regs = [4]uint32{0x01}
  34. cpuidAmd64(&regs[0])
  35. if regs[2]&osXsaveBit == 0 {
  36. return false
  37. }
  38. xcrRegs := [2]uint32{}
  39. xgetbv0Amd64(&xcrRegs[0])
  40. if xcrRegs[0]&6 != 6 {
  41. return false
  42. }
  43. // Check for AVX2 and BMI2 support.
  44. // CPUID.(EAX=07H, ECX=0H):EBX.AVX2[bit 5]==1
  45. // CPUID.(EAX=07H, ECX=0H):EBX.BMI2[bit 8]==1
  46. //
  47. // WARNING: Intel Skylake errata SKL052 implies that certain steppings
  48. // of Skylake Pentium/Celeron will lie and claim BMI2 support. Said
  49. // parts do not have AVX2 support so this check is fine, since we care
  50. // about both.
  51. regs = [4]uint32{0x07}
  52. cpuidAmd64(&regs[0])
  53. return regs[1]&avx2Bit != 0 && regs[1]&bmi2Bit != 0
  54. }
  55. func hashStep(ctx *hs1Ctx, in []byte, accum *[hs1HashRounds]uint64) {
  56. if isHardwareAccelerated {
  57. hashStepAVX2(ctx, in, accum)
  58. return
  59. }
  60. hashStepRef(ctx, in, accum)
  61. }
  62. func chachaXORKeyStream(s *chachaState, in, out []byte) {
  63. if isHardwareAccelerated {
  64. chachaXORKeyStreamAVX2(s, in, out)
  65. return
  66. }
  67. chachaXORKeyStreamRef(s, in, out)
  68. }
  69. func initHardwareAcceleration() {
  70. if supportsAVX2BMI2() {
  71. hardwareAccelImpl = "AVX2"
  72. isHardwareAccelerated = true
  73. }
  74. }