VAES+AVX2 optimized implementation of AES-GCM
Subsystems (2)
cover VAES+AVX2 optimized implementation of AES-GCM
This patchset replaces the 256-bit vector implementation of AES-GCM for x86_64 with one that requires AVX2 rather than AVX512. This greatly improves AES-GCM performance on CPUs that have VAES but not AVX512, for example by up to 74% on AMD Zen 3. For more details, see patch 1.
This patchset also renames the 512-bit vector implementation of AES-GCM for x86_64 to be named after AVX512 rather than AVX10/512, then adds some additional optimizations to it.
This patchset applies to next-20250929 and is targeting 6.19. Herbert, I'd prefer to just apply this myself. But let me know if you'd prefer to take it instead (considering that AES-GCM hasn't been librarified yet). Either way, there's no hurry, since this is targeting 6.19.
Eric Biggers (8):
crypto: x86/aes-gcm - add VAES+AVX2 optimized code
crypto: x86/aes-gcm - remove VAES+AVX10/256 optimized code
crypto: x86/aes-gcm - rename avx10 and avx10_512 to avx512
crypto: x86/aes-gcm - clean up AVX512 code to assume 512-bit vectors
crypto: x86/aes-gcm - reorder AVX512 precompute and aad_update
functions
crypto: x86/aes-gcm - revise some comments in AVX512 code
crypto: x86/aes-gcm - optimize AVX512 precomputation of H^2 from H^1
crypto: x86/aes-gcm - optimize long AAD processing with AVX512
arch/x86/crypto/Makefile | 5 +-
arch/x86/crypto/aes-gcm-aesni-x86_64.S | 12 +-
arch/x86/crypto/aes-gcm-vaes-avx2.S | 1150 +++++++++++++++++
...m-avx10-x86_64.S => aes-gcm-vaes-avx512.S} | 722 +++++------
arch/x86/crypto/aesni-intel_glue.c | 264 ++--
5 files changed, 1667 insertions(+), 486 deletions(-)
create mode 100644 arch/x86/crypto/aes-gcm-vaes-avx2.S
rename arch/x86/crypto/{aes-gcm-avx10-x86_64.S => aes-gcm-vaes-avx512.S} (69%)base-commit: 3b9b1f8df454caa453c7fb07689064edb2eda90a
Signature · 1 line
2.51.0
PATCH 1/8 crypto: x86/aes-gcm - add VAES+AVX2 optimized code
Add an implementation of AES-GCM that uses 256-bit vectors and the following CPU features: Vector AES (VAES), Vector Carryless Multiplication (VPCLMULQDQ), and AVX2.
It doesn't require AVX512. So unlike the existing VAES+AVX512 code, it works on CPUs that support VAES but not AVX512, specifically:
- AMD Zen 3, both client and server
- Intel Alder Lake, Raptor Lake, Meteor Lake, Arrow Lake, and Lunar Lake. (These are client CPUs.)
- Intel Sierra Forest. (This is a server CPU.)
On these CPUs, this VAES+AVX2 code is much faster than the existing AES-NI code. The AES-NI code uses only 128-bit vectors.
These CPUs are widely deployed, making VAES+AVX2 code worthwhile even though hopefully future x86_64 CPUs will uniformly support AVX512.
This implementation will also serve as the fallback 256-bit implementation for older Intel CPUs (Ice Lake and Tiger Lake) that support AVX512 but downclock too eagerly when 512-bit vectors are used. Currently, the VAES+AVX10/256 implementation serves that purpose. A later commit will remove that and just use the VAES+AVX2 one. (Note that AES-XTS and AES-CTR already successfully use this approach.)
I originally wrote this AES-GCM implementation for BoringSSL. It's been in BoringSSL for a while now, including in Chromium. This is a port of it to the Linux kernel. The main changes in the Linux version include:
- Port from "perlasm" to a standard .S file.
- Align all assembly functions with what aesni-intel_glue.c expects, including adding support for lengths not a multiple of 16 bytes.
- Rework the en/decryption of the final 1 to 127 bytes.
This commit increases AES-256-GCM throughput on AMD Milan (Zen 3) by up to 74%, as shown by the following tables:
Table 1: AES-256-GCM encryption throughput change,
CPU vs. message length in bytes:
| 16384 | 4096 | 4095 | 1420 | 512 | 500 |
----------------------+-------+-------+-------+-------+-------+-------+
AMD Milan (Zen 3) | 67% | 59% | 61% | 39% | 23% | 27% |
| 300 | 200 | 64 | 63 | 16 |
----------------------+-------+-------+-------+-------+-------+
AMD Milan (Zen 3) | 14% | 12% | 7% | 7% | 0% |
Table 2: AES-256-GCM decryption throughput change,
CPU vs. message length in bytes:
| 16384 | 4096 | 4095 | 1420 | 512 | 500 |
----------------------+-------+-------+-------+-------+-------+-------+
AMD Milan (Zen 3) | 74% | 65% | 65% | 44% | 23% | 26% |
| 300 | 200 | 64 | 63 | 16 |
----------------------+-------+-------+-------+-------+-------+
AMD Milan (Zen 3) | 12% | 11% | 3% | 2% | -3% |
--- arch/x86/crypto/Makefile | 1 + arch/x86/crypto/aes-gcm-vaes-avx2.S | 1150 +++++++++++++++++++++++++++ arch/x86/crypto/aesni-intel_glue.c | 111 ++- 3 files changed, 1260 insertions(+), 2 deletions(-) create mode 100644 arch/x86/crypto/aes-gcm-vaes-avx2.S
arch/x86/crypto/Makefile +1 -0
@@ -44,10 +44,11 @@ aegis128-aesni-y := aegis128-aesni-asm.o aegis128-aesni-glue.o obj-$(CONFIG_CRYPTO_AES_NI_INTEL) += aesni-intel.o aesni-intel-y := aesni-intel_asm.o aesni-intel_glue.o aesni-intel-$(CONFIG_64BIT) += aes-ctr-avx-x86_64.o \ aes-gcm-aesni-x86_64.o \ + aes-gcm-vaes-avx2.o \ aes-xts-avx-x86_64.o \ aes-gcm-avx10-x86_64.o obj-$(CONFIG_CRYPTO_GHASH_CLMUL_NI_INTEL) += ghash-clmulni-intel.o ghash-clmulni-intel-y := ghash-clmulni-intel_asm.o ghash-clmulni-intel_glue.o
arch/x86/crypto/aes-gcm-vaes-avx2.S new file +1150 -0
1,150 lines not on this page · raw message
arch/x86/crypto/aesni-intel_glue.c +109 -2
305 lines not on this page · raw message
Signature · 1 line
2.51.0
Re: [PATCH 1/8] crypto: x86/aes-gcm - add VAES+AVX2 optimized code
Quoted 3 lines · Eric Biggers
Add an implementation of AES-GCM that uses 256-bit vectors and the following CPU features: Vector AES (VAES), Vector Carryless Multiplication (VPCLMULQDQ), and AVX2.
A few non-functional cleanups I applied after reading over the assembly file again (wasn't worth resending the whole patchset):
arch/x86/crypto/aes-gcm-vaes-avx2.S +2 -7
@@ -231,11 +231,10 @@ SYM_FUNC_START(aes_gcm_precompute_vaes_avx2) .set TMP2, %ymm2 .set TMP2_XMM, %xmm2 .set H_CUR, %ymm3 .set H_CUR_XMM, %xmm3 .set H_CUR2, %ymm4 - .set H_CUR2_XMM, %xmm4 .set H_INC, %ymm5 .set H_INC_XMM, %xmm5 .set GFPOLY, %ymm6 .set GFPOLY_XMM, %xmm6
@@ -576,11 +575,10 @@ SYM_FUNC_START(aes_gcm_aad_update_vaes_avx2) jz .Laad_done cmp $16, AADLEN jle .Laad_lastblock -.Laad_last2blocks: // Update GHASH with the remaining 17 <= AADLEN <= 31 bytes of AAD. mov AADLEN, AADLEN // Zero-extend AADLEN to AADLEN64. vmovdqu (AAD), TMP0_XMM vmovdqu -16(AAD, AADLEN64), TMP1_XMM vpshufb BSWAP_MASK_XMM, TMP0_XMM, TMP0_XMM
@@ -632,11 +630,11 @@ SYM_FUNC_END(aes_gcm_aad_update_vaes_avx2) vpxor RNDKEY0, AESDATA\i, AESDATA\i .endr .endm // Generate and encrypt counter blocks in the given AESDATA vectors, excluding -// the last AES round. Clobbers TMP0. +// the last AES round. Clobbers %rax and TMP0. .macro _aesenc_loop vecs:vararg _ctr_begin \vecs lea 16(KEY), %rax .Laesenc_loop\@: vbroadcasti128 (%rax), TMP0
@@ -687,11 +685,11 @@ SYM_FUNC_END(aes_gcm_aad_update_vaes_avx2) .set KEY, %rdi .set LE_CTR_PTR, %rsi .set LE_CTR_PTR32, %esi .set GHASH_ACC_PTR, %rdx .set SRC, %rcx // Assumed to be %rcx. - // See .Ltail_xor_and_ghash_partial_vec + // See .Ltail_xor_and_ghash_1to16bytes .set DST, %r8 .set DATALEN, %r9d .set DATALEN64, %r9 // Zero-extend DATALEN before using! // Additional local variables
@@ -734,11 +732,10 @@ SYM_FUNC_END(aes_gcm_aad_update_vaes_avx2) // H_POW[2-1]_XORED contain cached values from KEY->h_powers_xored. The // descending numbering reflects the order of the key powers. .set H_POW2_XORED, %ymm7 .set H_POW2_XORED_XMM, %xmm7 .set H_POW1_XORED, %ymm8 - .set H_POW1_XORED_XMM, %xmm8 // RNDKEY0 caches the zero-th round key, and RNDKEYLAST the last one. .set RNDKEY0, %ymm9 .set RNDKEYLAST, %ymm10
@@ -749,13 +746,11 @@ SYM_FUNC_END(aes_gcm_aad_update_vaes_avx2) .set AESDATA0, %ymm12 .set AESDATA0_XMM, %xmm12 .set AESDATA1, %ymm13 .set AESDATA1_XMM, %xmm13 .set AESDATA2, %ymm14 - .set AESDATA2_XMM, %xmm14 .set AESDATA3, %ymm15 - .set AESDATA3_XMM, %xmm15 .if \enc .set GHASHDATA_PTR, DST .else .set GHASHDATA_PTR, SRC
PATCH 2/8 crypto: x86/aes-gcm - remove VAES+AVX10/256 optimized code
In reply to Eric BiggersRemove the VAES+AVX10/256 optimized implementation of AES-GCM.
It's no longer expected to be useful for future CPUs, since Intel changed the AVX10 specification to require 512-bit vectors.
In addition, it's no longer very useful to serve as the 256-bit fallback for older Intel CPUs (Ice Lake and Tiger Lake) that downclock too eagerly when 512-bit vectors are used. This is because I ended up writing another 256-bit implementation anyway, using VAES+AVX2. The VAES+AVX2 implementation is almost as fast as the VAES+AVX10/256 one, as shown by the following tables. So, let's just use it instead.
Table 1: AES-256-GCM encryption throughput change,
CPU vs. message length in bytes:
| 16384 | 4096 | 4095 | 1420 | 512 | 500 |
----------------------+-------+-------+-------+-------+-------+-------+
Intel Ice Lake Server | -2% | -1% | 0% | -2% | -2% | 3% |
| 300 | 200 | 64 | 63 | 16 |
----------------------+-------+-------+-------+-------+-------+
Intel Ice Lake Server | 1% | 0% | 4% | 2% | -6% |
Table 2: AES-256-GCM decryption throughput change,
CPU vs. message length in bytes:
| 16384 | 4096 | 4095 | 1420 | 512 | 500 |
----------------------+-------+-------+-------+-------+-------+-------+
Intel Ice Lake Server | -1% | -1% | 1% | -2% | 0% | 2% |
| 300 | 200 | 64 | 63 | 16 |
----------------------+-------+-------+-------+-------+-------+
Intel Ice Lake Server | -1% | 4% | 1% | 0% | -5% |
--- arch/x86/crypto/aes-gcm-avx10-x86_64.S | 11 ------ arch/x86/crypto/aesni-intel_glue.c | 54 +++----------------------- 2 files changed, 6 insertions(+), 59 deletions(-)
arch/x86/crypto/aes-gcm-avx10-x86_64.S +0 -11
@@ -1079,21 +1079,10 @@ .endif // No need for vzeroupper here, since only used xmm registers were used. RET .endm -_set_veclen 32 -SYM_FUNC_START(aes_gcm_precompute_vaes_avx10_256) - _aes_gcm_precompute -SYM_FUNC_END(aes_gcm_precompute_vaes_avx10_256) -SYM_FUNC_START(aes_gcm_enc_update_vaes_avx10_256) - _aes_gcm_update 1 -SYM_FUNC_END(aes_gcm_enc_update_vaes_avx10_256) -SYM_FUNC_START(aes_gcm_dec_update_vaes_avx10_256) - _aes_gcm_update 0 -SYM_FUNC_END(aes_gcm_dec_update_vaes_avx10_256) - _set_veclen 64 SYM_FUNC_START(aes_gcm_precompute_vaes_avx10_512) _aes_gcm_precompute SYM_FUNC_END(aes_gcm_precompute_vaes_avx10_512) SYM_FUNC_START(aes_gcm_enc_update_vaes_avx10_512)
arch/x86/crypto/aesni-intel_glue.c +6 -48
194 lines not on this page · raw message
Signature · 1 line
2.51.0
PATCH 3/8 crypto: x86/aes-gcm - rename avx10 and avx10_512 to avx512
In reply to Eric BiggersWith the "avx10_256" code removed and the AVX10 specification having been changed to basically just be a re-packaged AVX512, the "avx10_512" name no longer makes sense. Replace it with "avx512".
While doing this, also add the "vaes_" prefix in places that didn't already have it. The result is that the two VAES optimized implementations are consistently called vaes_avx2 and vaes_avx512. (Also drop the "-x86_64" part of the assembly filename, to keep it from getting too long. There's no 32-bit version of this code, and the fact that it's 64-bit is unremarkable; it's the norm for new code.)
Note: although aes_gcm_aad_update_vaes_avx512() (previously called aes_gcm_aad_update_vaes_avx10()) uses at most 256-bit vectors, it still depends on the AVX512 CPU feature. So its new name is still accurate. Also, a later commit will make it sometimes use 512-bit vectors anyway.
---
arch/x86/crypto/Makefile | 4 +-
arch/x86/crypto/aes-gcm-aesni-x86_64.S | 12 +-
arch/x86/crypto/aes-gcm-vaes-avx2.S | 12 +-
...m-avx10-x86_64.S => aes-gcm-vaes-avx512.S} | 92 +++++--------
arch/x86/crypto/aesni-intel_glue.c | 123 +++++++++---------
5 files changed, 105 insertions(+), 138 deletions(-)
rename arch/x86/crypto/{aes-gcm-avx10-x86_64.S => aes-gcm-vaes-avx512.S} (92%)arch/x86/crypto/Makefile +2 -2
@@ -45,12 +45,12 @@ aegis128-aesni-y := aegis128-aesni-asm.o aegis128-aesni-glue.o obj-$(CONFIG_CRYPTO_AES_NI_INTEL) += aesni-intel.o aesni-intel-y := aesni-intel_asm.o aesni-intel_glue.o aesni-intel-$(CONFIG_64BIT) += aes-ctr-avx-x86_64.o \ aes-gcm-aesni-x86_64.o \ aes-gcm-vaes-avx2.o \ - aes-xts-avx-x86_64.o \ - aes-gcm-avx10-x86_64.o + aes-gcm-vaes-avx512.o \ + aes-xts-avx-x86_64.o obj-$(CONFIG_CRYPTO_GHASH_CLMUL_NI_INTEL) += ghash-clmulni-intel.o ghash-clmulni-intel-y := ghash-clmulni-intel_asm.o ghash-clmulni-intel_glue.o obj-$(CONFIG_CRYPTO_POLYVAL_CLMUL_NI) += polyval-clmulni.o
arch/x86/crypto/aes-gcm-aesni-x86_64.S +6 -6
@@ -59,19 +59,19 @@ // // The specific CPU feature prerequisites are AES-NI and PCLMULQDQ, plus SSE4.1 // for the *_aesni functions or AVX for the *_aesni_avx ones. (But it seems // there are no CPUs that support AES-NI without also PCLMULQDQ and SSE4.1.) // -// The design generally follows that of aes-gcm-avx10-x86_64.S, and that file is +// The design generally follows that of aes-gcm-vaes-avx512.S, and that file is // more thoroughly commented. This file has the following notable changes: // // - The vector length is fixed at 128-bit, i.e. xmm registers. This means // there is only one AES block (and GHASH block) per register. // -// - Without AVX512 / AVX10, only 16 SIMD registers are available instead of -// 32. We work around this by being much more careful about using -// registers, relying heavily on loads to load values as they are needed. +// - Without AVX512, only 16 SIMD registers are available instead of 32. We +// work around this by being much more careful about using registers, +// relying heavily on loads to load values as they are needed. // // - Masking is not available either. We work around this by implementing // partial block loads and stores using overlapping scalar loads and stores // combined with shifts and SSE4.1 insertion and extraction instructions. //
@@ -88,12 +88,12 @@ // // - We implement the GHASH multiplications in the main loop using Karatsuba // multiplication instead of schoolbook multiplication. This saves one // pclmulqdq instruction per block, at the cost of one 64-bit load, one // pshufd, and 0.25 pxors per block. (This is without the three-argument -// XOR support that would be provided by AVX512 / AVX10, which would be -// more beneficial to schoolbook than Karatsuba.) +// XOR support that would be provided by AVX512, which would be more +// beneficial to schoolbook than Karatsuba.) // // As a rough approximation, we can assume that Karatsuba multiplication is // faster than schoolbook multiplication in this context if one pshufd and // 0.25 pxors are cheaper than a pclmulqdq. (We assume that the 64-bit // load is "free" due to running in parallel with arithmetic instructions.)
arch/x86/crypto/aes-gcm-vaes-avx2.S +6 -6
@@ -47,16 +47,16 @@ // ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE // POSSIBILITY OF SUCH DAMAGE. // // ----------------------------------------------------------------------------- // -// This is similar to aes-gcm-avx10-x86_64.S, but it uses AVX2 instead of -// AVX512. This means it can only use 16 vector registers instead of 32, the -// maximum vector length is 32 bytes, and some instructions such as vpternlogd -// and masked loads/stores are unavailable. However, it is able to run on CPUs -// that have VAES without AVX512, namely AMD Zen 3 (including "Milan" server -// CPUs), various Intel client CPUs such as Alder Lake, and Intel Sierra Forest. +// This is similar to aes-gcm-vaes-avx512.S, but it uses AVX2 instead of AVX512. +// This means it can only use 16 vector registers instead of 32, the maximum +// vector length is 32 bytes, and some instructions such as vpternlogd and +// masked loads/stores are unavailable. However, it is able to run on CPUs that +// have VAES without AVX512, namely AMD Zen 3 (including "Milan" server CPUs), +// various Intel client CPUs such as Alder Lake, and Intel Sierra Forest. // // This implementation also uses Karatsuba multiplication instead of schoolbook // multiplication for GHASH in its main loop. This does not help much on Intel, // but it improves performance by ~5% on AMD Zen 3. Other factors weighing // slightly in favor of Karatsuba multiplication in this implementation are the
arch/x86/crypto/aes-gcm-vaes-avx512.S renamed from arch/x86/crypto/aes-gcm-avx10-x86_64.S +29 -63
171 lines not on this page · raw message
arch/x86/crypto/aesni-intel_glue.c +62 -61
312 lines not on this page · raw message
Signature · 1 line
2.51.0
PATCH 4/8 crypto: x86/aes-gcm - clean up AVX512 code to assume 512-bit vectors
In reply to Eric Biggersaes-gcm-vaes-avx512.S (originally aes-gcm-avx10-x86_64.S) was designed to support multiple maximum vector lengths, while still utilizing AVX512 / AVX10 features such as the increased number of vector registers. However, the support for multiple maximum vector lengths turned out to not be useful. Support for maximum vector lengths other than 512 bits was removed from the AVX10 specification, which leaves "avoiding overly-eager downclocking" as the only remaining use case for limiting AVX512 / AVX10 code to 256-bit vectors. But this issue has gone away in new CPUs, and the separate VAES+AVX2 code which I ended up having to write anyway provides nearly as good 256-bit support.
Therefore, clean up this code to not be written in terms of a generic vector length, but rather just assume 512-bit vectors.
--- arch/x86/crypto/aes-gcm-vaes-avx512.S | 353 +++++++++++--------------- 1 file changed, 153 insertions(+), 200 deletions(-)
arch/x86/crypto/aes-gcm-vaes-avx512.S +153 -200
@@ -68,20 +68,18 @@ // Same as above, but with the (1 << 64) bit set. .Lgfpoly_and_internal_carrybit: .octa 0xc2000000000000010000000000000001 - // The below constants are used for incrementing the counter blocks. - // ctr_pattern points to the four 128-bit values [0, 1, 2, 3]. - // inc_2blocks and inc_4blocks point to the single 128-bit values 2 and - // 4. Note that the same '2' is reused in ctr_pattern and inc_2blocks. + // Values needed to prepare the initial vector of counter blocks. .Lctr_pattern: .octa 0 .octa 1 -.Linc_2blocks: .octa 2 .octa 3 + + // The number of AES blocks per vector, as a 128-bit value. .Linc_4blocks: .octa 4 // Number of powers of the hash key stored in the key struct. The powers are // stored from highest (H^NUM_H_POWERS) to lowest (H^1).
@@ -94,33 +92,17 @@ #define OFFSETOF_H_POWERS 512 // Offset to end of hash key powers array in the key struct. // // This is immediately followed by three zeroized padding blocks, which are -// included so that partial vectors can be handled more easily. E.g. if VL=64 -// and two blocks remain, we load the 4 values [H^2, H^1, 0, 0]. The most -// padding blocks needed is 3, which occurs if [H^1, 0, 0, 0] is loaded. +// included so that partial vectors can be handled more easily. E.g. if two +// blocks remain, we load the 4 values [H^2, H^1, 0, 0]. The most padding +// blocks needed is 3, which occurs if [H^1, 0, 0, 0] is loaded. #define OFFSETOFEND_H_POWERS (OFFSETOF_H_POWERS + (NUM_H_POWERS * 16)) .text -// Set the vector length in bytes. This sets the VL variable and defines -// register aliases V0-V31 that map to the ymm or zmm registers. -.macro _set_veclen vl - .set VL, \vl -.irp i, 0,1,2,3,4,5,6,7,8,9,10,11,12,13,14,15, \ - 16,17,18,19,20,21,22,23,24,25,26,27,28,29,30,31 -.if VL == 32 - .set V\i, %ymm\i -.elseif VL == 64 - .set V\i, %zmm\i -.else - .error "Unsupported vector length" -.endif -.endr -.endm - // The _ghash_mul_step macro does one step of GHASH multiplication of the // 128-bit lanes of \a by the corresponding 128-bit lanes of \b and storing the // reduced products in \dst. \t0, \t1, and \t2 are temporary registers of the // same size as \a and \b. To complete all steps, this must invoked with \i=0 // through \i=9. The division into steps allows users of this macro to
@@ -284,35 +266,31 @@ // subkey and initializes |key->ghash_key_powers| with powers of it. // // The number of key powers initialized is NUM_H_POWERS, and they are stored in // the order H^NUM_H_POWERS to H^1. The zeroized padding blocks after the key // powers themselves are also initialized. -// -// This macro supports both VL=32 and VL=64. _set_veclen must have been invoked -// with the desired length. In the VL=32 case, the function computes twice as -// many key powers than are actually used by the VL=32 GCM update functions. -// This is done to keep the key format the same regardless of vector length. .macro _aes_gcm_precompute // Function arguments .set KEY, %rdi - // Additional local variables. V0-V2 and %rax are used as temporaries. + // Additional local variables. + // %zmm[0-2] and %rax are used as temporaries. .set POWERS_PTR, %rsi .set RNDKEYLAST_PTR, %rdx - .set H_CUR, V3 + .set H_CUR, %zmm3 .set H_CUR_YMM, %ymm3 .set H_CUR_XMM, %xmm3 - .set H_INC, V4 + .set H_INC, %zmm4 .set H_INC_YMM, %ymm4 .set H_INC_XMM, %xmm4 - .set GFPOLY, V5 + .set GFPOLY, %zmm5 .set GFPOLY_YMM, %ymm5 .set GFPOLY_XMM, %xmm5 // Get pointer to lowest set of key powers (located at end of array). - lea OFFSETOFEND_H_POWERS-VL(KEY), POWERS_PTR + lea OFFSETOFEND_H_POWERS-64(KEY), POWERS_PTR // Encrypt an all-zeroes block to get the raw hash subkey. movl OFFSETOF_AESKEYLEN(KEY), %eax lea 6*16(KEY,%rax,4), RNDKEYLAST_PTR vmovdqu (KEY), %xmm0 // Zero-th round key XOR all-zeroes block
@@ -327,12 +305,12 @@ // Reflect the bytes of the raw hash subkey. vpshufb .Lbswap_mask(%rip), %xmm0, H_CUR_XMM // Zeroize the padding blocks. vpxor %xmm0, %xmm0, %xmm0 - vmovdqu %ymm0, VL(POWERS_PTR) - vmovdqu %xmm0, VL+2*16(POWERS_PTR) + vmovdqu %ymm0, 64(POWERS_PTR) + vmovdqu %xmm0, 64+2*16(POWERS_PTR) // Finish preprocessing the first key power, H^1. Since this GHASH // implementation operates directly on values with the backwards bit // order specified by the GCM standard, it's necessary to preprocess the // raw key as follows. First, reflect its bytes. Second, multiply it
@@ -368,29 +346,26 @@ // Create H_CUR_YMM = [H^2, H^1] and H_INC_YMM = [H^2, H^2]. vinserti128 $1, H_CUR_XMM, H_INC_YMM, H_CUR_YMM vinserti128 $1, H_INC_XMM, H_INC_YMM, H_INC_YMM -.if VL == 64 // Create H_CUR = [H^4, H^3, H^2, H^1] and H_INC = [H^4, H^4, H^4, H^4]. _ghash_mul H_INC_YMM, H_CUR_YMM, H_INC_YMM, GFPOLY_YMM, \ %ymm0, %ymm1, %ymm2 vinserti64x4 $1, H_CUR_YMM, H_INC, H_CUR vshufi64x2 $0, H_INC, H_INC, H_INC -.endif // Store the lowest set of key powers. vmovdqu8 H_CUR, (POWERS_PTR) - // Compute and store the remaining key powers. With VL=32, repeatedly - // multiply [H^(i+1), H^i] by [H^2, H^2] to get [H^(i+3), H^(i+2)]. - // With VL=64, repeatedly multiply [H^(i+3), H^(i+2), H^(i+1), H^i] by + // Compute and store the remaining key powers. + // Repeatedly multiply [H^(i+3), H^(i+2), H^(i+1), H^i] by // [H^4, H^4, H^4, H^4] to get [H^(i+7), H^(i+6), H^(i+5), H^(i+4)]. - mov $(NUM_H_POWERS*16/VL) - 1, %eax + mov $3, %eax .Lprecompute_next\@: - sub $VL, POWERS_PTR - _ghash_mul H_INC, H_CUR, H_CUR, GFPOLY, V0, V1, V2 + sub $64, POWERS_PTR + _ghash_mul H_INC, H_CUR, H_CUR, GFPOLY, %zmm0, %zmm1, %zmm2 vmovdqu8 H_CUR, (POWERS_PTR) dec %eax jnz .Lprecompute_next\@ vzeroupper // This is needed after using ymm or zmm registers.
@@ -399,20 +374,14 @@ // XOR together the 128-bit lanes of \src (whose low lane is \src_xmm) and store // the result in \dst_xmm. This implicitly zeroizes the other lanes of dst. .macro _horizontal_xor src, src_xmm, dst_xmm, t0_xmm, t1_xmm, t2_xmm vextracti32x4 $1, \src, \t0_xmm -.if VL == 32 - vpxord \t0_xmm, \src_xmm, \dst_xmm -.elseif VL == 64 vextracti32x4 $2, \src, \t1_xmm vextracti32x4 $3, \src, \t2_xmm vpxord \t0_xmm, \src_xmm, \dst_xmm vpternlogd $0x96, \t1_xmm, \t2_xmm, \dst_xmm -.else - .error "Unsupported vector length" -.endif .endm // Do one step of the GHASH update of the data blocks given in the vector // registers GHASHDATA[0-3]. \i specifies the step to do, 0 through 9. The // division into steps allows users of this macro to optionally interleave the
@@ -422,29 +391,25 @@ // GHASHTMP[0-2] as temporaries. This macro handles the byte-reflection of the // data blocks. The parameter registers must be preserved across steps. // // The GHASH update does: GHASH_ACC = H_POW4*(GHASHDATA0 + GHASH_ACC) + // H_POW3*GHASHDATA1 + H_POW2*GHASHDATA2 + H_POW1*GHASHDATA3, where the -// operations are vectorized operations on vectors of 16-byte blocks. E.g., -// with VL=32 there are 2 blocks per vector and the vectorized terms correspond -// to the following non-vectorized terms: -// -// H_POW4*(GHASHDATA0 + GHASH_ACC) => H^8*(blk0 + GHASH_ACC_XMM) and H^7*(blk1 + 0) -// H_POW3*GHASHDATA1 => H^6*blk2 and H^5*blk3 -// H_POW2*GHASHDATA2 => H^4*blk4 and H^3*blk5 -// H_POW1*GHASHDATA3 => H^2*blk6 and H^1*blk7 +// operations are vectorized operations on 512-bit vectors of 128-bit blocks. +// The vectorized terms correspond to the following non-vectorized terms: // -// With VL=64, we use 4 blocks/vector, H^16 through H^1, and blk0 through blk15. +// H_POW4*(GHASHDATA0 + GHASH_ACC) => H^16*(blk0 + GHASH_ACC_XMM), +// H^15*(blk1 + 0), H^14*(blk2 + 0), and H^13*(blk3 + 0) +// H_POW3*GHASHDATA1 => H^12*blk4, H^11*blk5, H^10*blk6, and H^9*blk7 +// H_POW2*GHASHDATA2 => H^8*blk8, H^7*blk9, H^6*blk10, and H^5*blk11 +// H_POW1*GHASHDATA3 => H^4*blk12, H^3*blk13, H^2*blk14, and H^1*blk15 // // More concretely, this code does: // - Do vectorized "schoolbook" multiplications to compute the intermediate // 256-bit product of each block and its corresponding hash key power. -// There are 4*VL/16 of these intermediate products. -// - Sum (XOR) the intermediate 256-bit products across vectors. This leaves -// VL/16 256-bit intermediate values. +// - Sum (XOR) the intermediate 256-bit products across vectors. // - Do a vectorized reduction of these 256-bit intermediate values to -// 128-bits each. This leaves VL/16 128-bit intermediate values. +// 128-bits each. // - Sum (XOR) these values and store the 128-bit result in GHASH_ACC_XMM. // // See _ghash_mul_step for the full explanation of the operations performed for // each individual finite field multiplication and reduction. .macro _ghash_step_4x i
@@ -496,78 +461,76 @@ _horizontal_xor GHASH_ACC, GHASH_ACC_XMM, GHASH_ACC_XMM, \ GHASHDATA0_XMM, GHASHDATA1_XMM, GHASHDATA2_XMM .endif .endm -// Do one non-last round of AES encryption on the counter blocks in V0-V3 using -// the round key that has been broadcast to all 128-bit lanes of \round_key. +// Do one non-last round of AES encryption on the blocks in %zmm[0-3] using the +// round key that has been broadcast to all 128-bit lanes of \round_key. .macro _vaesenc_4x round_key - vaesenc \round_key, V0, V0 - vaesenc \round_key, V1, V1 - vaesenc \round_key, V2, V2 - vaesenc \round_key, V3, V3 + vaesenc \round_key, %zmm0, %zmm0 + vaesenc \round_key, %zmm1, %zmm1 + vaesenc \round_key, %zmm2, %zmm2 + vaesenc \round_key, %zmm3, %zmm3 .endm // Start the AES encryption of four vectors of counter blocks. .macro _ctr_begin_4x // Increment LE_CTR four times to generate four vectors of little-endian - // counter blocks, swap each to big-endian, and store them in V0-V3. - vpshufb BSWAP_MASK, LE_CTR, V0 + // counter blocks, swap each to big-endian, and store them in %zmm[0-3]. + vpshufb BSWAP_MASK, LE_CTR, %zmm0 vpaddd LE_CTR_INC, LE_CTR, LE_CTR - vpshufb BSWAP_MASK, LE_CTR, V1 + vpshufb BSWAP_MASK, LE_CTR, %zmm1 vpaddd LE_CTR_INC, LE_CTR, LE_CTR - vpshufb BSWAP_MASK, LE_CTR, V2 + vpshufb BSWAP_MASK, LE_CTR, %zmm2 vpaddd LE_CTR_INC, LE_CTR, LE_CTR - vpshufb BSWAP_MASK, LE_CTR, V3 + vpshufb BSWAP_MASK, LE_CTR, %zmm3 vpaddd LE_CTR_INC, LE_CTR, LE_CTR // AES "round zero": XOR in the zero-th round key. - vpxord RNDKEY0, V0, V0 - vpxord RNDKEY0, V1, V1 - vpxord RNDKEY0, V2, V2 - vpxord RNDKEY0, V3, V3 + vpxord RNDKEY0, %zmm0, %zmm0 + vpxord RNDKEY0, %zmm1, %zmm1 + vpxord RNDKEY0, %zmm2, %zmm2 + vpxord RNDKEY0, %zmm3, %zmm3 .endm -// Do the last AES round for four vectors of counter blocks V0-V3, XOR source -// data with the resulting keystream, and write the result to DST and +// Do the last AES round for four vectors of counter blocks %zmm[0-3], XOR +// source data with the resulting keystream, and write the result to DST and // GHASHDATA[0-3]. (Implementation differs slightly, but has the same effect.) .macro _aesenclast_and_xor_4x // XOR the source data with the last round key, saving the result in // GHASHDATA[0-3]. This reduces latency by taking advantage of the // property vaesenclast(key, a) ^ b == vaesenclast(key ^ b, a). - vpxord 0*VL(SRC), RNDKEYLAST, GHASHDATA0 - vpxord 1*VL(SRC), RNDKEYLAST, GHASHDATA1 - vpxord 2*VL(SRC), RNDKEYLAST, GHASHDATA2 - vpxord 3*VL(SRC), RNDKEYLAST, GHASHDATA3 + vpxord 0*64(SRC), RNDKEYLAST, GHASHDATA0 + vpxord 1*64(SRC), RNDKEYLAST, GHASHDATA1 + vpxord 2*64(SRC), RNDKEYLAST, GHASHDATA2 + vpxord 3*64(SRC), RNDKEYLAST, GHASHDATA3 // Do the last AES round. This handles the XOR with the source data // too, as per the optimization described above. - vaesenclast GHASHDATA0, V0, GHASHDATA0 - vaesenclast GHASHDATA1, V1, GHASHDATA1 - vaesenclast GHASHDATA2, V2, GHASHDATA2 - vaesenclast GHASHDATA3, V3, GHASHDATA3 + vaesenclast GHASHDATA0, %zmm0, GHASHDATA0 + vaesenclast GHASHDATA1, %zmm1, GHASHDATA1 + vaesenclast GHASHDATA2, %zmm2, GHASHDATA2 + vaesenclast GHASHDATA3, %zmm3, GHASHDATA3 // Store the en/decrypted data to DST. - vmovdqu8 GHASHDATA0, 0*VL(DST) - vmovdqu8 GHASHDATA1, 1*VL(DST) - vmovdqu8 GHASHDATA2, 2*VL(DST) - vmovdqu8 GHASHDATA3, 3*VL(DST) + vmovdqu8 GHASHDATA0, 0*64(DST) + vmovdqu8 GHASHDATA1, 1*64(DST) + vmovdqu8 GHASHDATA2, 2*64(DST) + vmovdqu8 GHASHDATA3, 3*64(DST) .endm // void aes_gcm_{enc,dec}_update_vaes_avx512(const struct aes_gcm_key_vaes_avx512 *key, // const u32 le_ctr[4], u8 ghash_acc[16], // const u8 *src, u8 *dst, int datalen); // // This macro generates a GCM encryption or decryption update function with the -// above prototype (with \enc selecting which one). This macro supports both -// VL=32 and VL=64. _set_veclen must have been invoked with the desired length. -// -// This function computes the next portion of the CTR keystream, XOR's it with -// |datalen| bytes from |src|, and writes the resulting encrypted or decrypted -// data to |dst|. It also updates the GHASH accumulator |ghash_acc| using the -// next |datalen| ciphertext bytes. +// above prototype (with \enc selecting which one). The function computes the +// next portion of the CTR keystream, XOR's it with |datalen| bytes from |src|, +// and writes the resulting encrypted or decrypted data to |dst|. It also +// updates the GHASH accumulator |ghash_acc| using the next |datalen| ciphertext +// bytes. // // |datalen| must be a multiple of 16, except on the last call where it can be // any length. The caller must do any buffering needed to ensure this. Both // in-place and out-of-place en/decryption are supported. //
@@ -598,73 +561,73 @@ .set AESKEYLEN64, %r10 // Pointer to the last AES round key for the chosen AES variant .set RNDKEYLAST_PTR, %r11 - // In the main loop, V0-V3 are used as AES input and output. Elsewhere - // they are used as temporary registers. + // In the main loop, %zmm[0-3] are used as AES input and output. + // Elsewhere they are used as temporary registers. // GHASHDATA[0-3] hold the ciphertext blocks and GHASH input data. - .set GHASHDATA0, V4 + .set GHASHDATA0, %zmm4 .set GHASHDATA0_XMM, %xmm4 - .set GHASHDATA1, V5 + .set GHASHDATA1, %zmm5 .set GHASHDATA1_XMM, %xmm5 - .set GHASHDATA2, V6 + .set GHASHDATA2, %zmm6 .set GHASHDATA2_XMM, %xmm6 - .set GHASHDATA3, V7 + .set GHASHDATA3, %zmm7 // BSWAP_MASK is the shuffle mask for byte-reflecting 128-bit values // using vpshufb, copied to all 128-bit lanes. - .set BSWAP_MASK, V8 + .set BSWAP_MASK, %zmm8 // RNDKEY temporarily holds the next AES round key. - .set RNDKEY, V9 + .set RNDKEY, %zmm9 // GHASH_ACC is the accumulator variable for GHASH. When fully reduced, // only the lowest 128-bit lane can be nonzero. When not fully reduced, // more than one lane may be used, and they need to be XOR'd together. - .set GHASH_ACC, V10 + .set GHASH_ACC, %zmm10 .set GHASH_ACC_XMM, %xmm10 // LE_CTR_INC is the vector of 32-bit words that need to be added to a // vector of little-endian counter blocks to advance it forwards. - .set LE_CTR_INC, V11 + .set LE_CTR_INC, %zmm11 // LE_CTR contains the next set of little-endian counter blocks. - .set LE_CTR, V12 + .set LE_CTR, %zmm12 // RNDKEY0, RNDKEYLAST, and RNDKEY_M[9-1] contain cached AES round keys, // copied to all 128-bit lanes. RNDKEY0 is the zero-th round key, // RNDKEYLAST the last, and RNDKEY_M\i the one \i-th from the last. - .set RNDKEY0, V13 - .set RNDKEYLAST, V14 - .set RNDKEY_M9, V15 - .set RNDKEY_M8, V16 - .set RNDKEY_M7, V17 - .set RNDKEY_M6, V18 - .set RNDKEY_M5, V19 - .set RNDKEY_M4, V20 - .set RNDKEY_M3, V21 - .set RNDKEY_M2, V22 - .set RNDKEY_M1, V23 + .set RNDKEY0, %zmm13 + .set RNDKEYLAST, %zmm14 + .set RNDKEY_M9, %zmm15 + .set RNDKEY_M8, %zmm16 + .set RNDKEY_M7, %zmm17 + .set RNDKEY_M6, %zmm18 + .set RNDKEY_M5, %zmm19 + .set RNDKEY_M4, %zmm20 + .set RNDKEY_M3, %zmm21 + .set RNDKEY_M2, %zmm22 + .set RNDKEY_M1, %zmm23 // GHASHTMP[0-2] are temporary variables used by _ghash_step_4x. These // cannot coincide with anything used for AES encryption, since for // performance reasons GHASH and AES encryption are interleaved. - .set GHASHTMP0, V24 - .set GHASHTMP1, V25 - .set GHASHTMP2, V26 + .set GHASHTMP0, %zmm24 + .set GHASHTMP1, %zmm25 + .set GHASHTMP2, %zmm26 - // H_POW[4-1] contain the powers of the hash key H^(4*VL/16)...H^1. The + // H_POW[4-1] contain the powers of the hash key H^16...H^1. The // descending numbering reflects the order of the key powers. - .set H_POW4, V27 - .set H_POW3, V28 - .set H_POW2, V29 - .set H_POW1, V30 + .set H_POW4, %zmm27 + .set H_POW3, %zmm28 + .set H_POW2, %zmm29 + .set H_POW1, %zmm30 // GFPOLY contains the .Lgfpoly constant, copied to all 128-bit lanes. - .set GFPOLY, V31 + .set GFPOLY, %zmm31 // Load some constants. vbroadcasti32x4 .Lbswap_mask(%rip), BSWAP_MASK vbroadcasti32x4 .Lgfpoly(%rip), GFPOLY
@@ -683,33 +646,27 @@ vbroadcasti32x4 (RNDKEYLAST_PTR), RNDKEYLAST // Finish initializing LE_CTR by adding [0, 1, ...] to its low words. vpaddd .Lctr_pattern(%rip), LE_CTR, LE_CTR - // Initialize LE_CTR_INC to contain VL/16 in all 128-bit lanes. -.if VL == 32 - vbroadcasti32x4 .Linc_2blocks(%rip), LE_CTR_INC -.elseif VL == 64 + // Load 4 into all 128-bit lanes of LE_CTR_INC. vbroadcasti32x4 .Linc_4blocks(%rip), LE_CTR_INC -.else - .error "Unsupported vector length" -.endif - // If there are at least 4*VL bytes of data, then continue into the loop - // that processes 4*VL bytes of data at a time. Otherwise skip it. + // If there are at least 256 bytes of data, then continue into the loop + // that processes 256 bytes of data at a time. Otherwise skip it. // - // Pre-subtracting 4*VL from DATALEN saves an instruction from the main + // Pre-subtracting 256 from DATALEN saves an instruction from the main // loop and also ensures that at least one write always occurs to // DATALEN, zero-extending it and allowing DATALEN64 to be used later. - add $-4*VL, DATALEN // shorter than 'sub 4*VL' when VL=32 + sub $256, DATALEN jl .Lcrypt_loop_4x_done\@ // Load powers of the hash key. - vmovdqu8 OFFSETOFEND_H_POWERS-4*VL(KEY), H_POW4 - vmovdqu8 OFFSETOFEND_H_POWERS-3*VL(KEY), H_POW3 - vmovdqu8 OFFSETOFEND_H_POWERS-2*VL(KEY), H_POW2 - vmovdqu8 OFFSETOFEND_H_POWERS-1*VL(KEY), H_POW1 + vmovdqu8 OFFSETOFEND_H_POWERS-4*64(KEY), H_POW4 + vmovdqu8 OFFSETOFEND_H_POWERS-3*64(KEY), H_POW3 + vmovdqu8 OFFSETOFEND_H_POWERS-2*64(KEY), H_POW2 + vmovdqu8 OFFSETOFEND_H_POWERS-1*64(KEY), H_POW1 // Main loop: en/decrypt and hash 4 vectors at a time. // // When possible, interleave the AES encryption of the counter blocks // with the GHASH update of the ciphertext blocks. This improves
@@ -734,13 +691,13 @@ _vaesenc_4x RNDKEY add $16, %rax cmp %rax, RNDKEYLAST_PTR jne 1b _aesenclast_and_xor_4x - sub $-4*VL, SRC // shorter than 'add 4*VL' when VL=32 - sub $-4*VL, DST - add $-4*VL, DATALEN + add $256, SRC + add $256, DST + sub $256, DATALEN jl .Lghash_last_ciphertext_4x\@ .endif // Cache as many additional AES round keys as possible. .irp i, 9,8,7,6,5,4,3,2,1
@@ -750,14 +707,14 @@ .Lcrypt_loop_4x\@: // If decrypting, load more ciphertext blocks into GHASHDATA[0-3]. If // encrypting, GHASHDATA[0-3] already contain the previous ciphertext. .if !\enc - vmovdqu8 0*VL(SRC), GHASHDATA0 - vmovdqu8 1*VL(SRC), GHASHDATA1 - vmovdqu8 2*VL(SRC), GHASHDATA2 - vmovdqu8 3*VL(SRC), GHASHDATA3 + vmovdqu8 0*64(SRC), GHASHDATA0 + vmovdqu8 1*64(SRC), GHASHDATA1 + vmovdqu8 2*64(SRC), GHASHDATA2 + vmovdqu8 3*64(SRC), GHASHDATA3 .endif // Start the AES encryption of the counter blocks. _ctr_begin_4x cmp $24, AESKEYLEN
@@ -773,21 +730,22 @@ _vaesenc_4x RNDKEY vbroadcasti32x4 -10*16(RNDKEYLAST_PTR), RNDKEY _vaesenc_4x RNDKEY 128: - // Finish the AES encryption of the counter blocks in V0-V3, interleaved - // with the GHASH update of the ciphertext blocks in GHASHDATA[0-3]. + // Finish the AES encryption of the counter blocks in %zmm[0-3], + // interleaved with the GHASH update of the ciphertext blocks in + // GHASHDATA[0-3]. .irp i, 9,8,7,6,5,4,3,2,1 _ghash_step_4x (9 - \i) _vaesenc_4x RNDKEY_M\i .endr _ghash_step_4x 9 _aesenclast_and_xor_4x - sub $-4*VL, SRC // shorter than 'add 4*VL' when VL=32 - sub $-4*VL, DST - add $-4*VL, DATALEN + add $256, SRC + add $256, DST + sub $256, DATALEN jge .Lcrypt_loop_4x\@ .if \enc .Lghash_last_ciphertext_4x\@: // Update GHASH with the last set of ciphertext blocks.
@@ -796,25 +754,26 @@ .endr .endif .Lcrypt_loop_4x_done\@: - // Undo the extra subtraction by 4*VL and check whether data remains. - sub $-4*VL, DATALEN // shorter than 'add 4*VL' when VL=32 + // Undo the extra subtraction by 256 and check whether data remains. + add $256, DATALEN jz .Ldone\@ - // The data length isn't a multiple of 4*VL. Process the remaining data - // of length 1 <= DATALEN < 4*VL, up to one vector (VL bytes) at a time. - // Going one vector at a time may seem inefficient compared to having - // separate code paths for each possible number of vectors remaining. - // However, using a loop keeps the code size down, and it performs - // surprising well; modern CPUs will start executing the next iteration - // before the previous one finishes and also predict the number of loop - // iterations. For a similar reason, we roll up the AES rounds. + // The data length isn't a multiple of 256 bytes. Process the remaining + // data of length 1 <= DATALEN < 256, up to one 64-byte vector at a + // time. Going one vector at a time may seem inefficient compared to + // having separate code paths for each possible number of vectors + // remaining. However, using a loop keeps the code size down, and it + // performs surprising well; modern CPUs will start executing the next + // iteration before the previous one finishes and also predict the + // number of loop iterations. For a similar reason, we roll up the AES + // rounds. // - // On the last iteration, the remaining length may be less than VL. - // Handle this using masking. + // On the last iteration, the remaining length may be less than 64 + // bytes. Handle this using masking. // // Since there are enough key powers available for all remaining data, // there is no need to do a GHASH reduction after each iteration. // Instead, multiply each remaining block by its own key power, and only // do a GHASH reduction at the very end.
@@ -839,69 +798,64 @@ vpxor HI_XMM, HI_XMM, HI_XMM .Lcrypt_loop_1x\@: // Select the appropriate mask for this iteration: all 1's if - // DATALEN >= VL, otherwise DATALEN 1's. Do this branchlessly using the + // DATALEN >= 64, otherwise DATALEN 1's. Do this branchlessly using the // bzhi instruction from BMI2. (This relies on DATALEN <= 255.) -.if VL < 64 - mov $-1, %eax - bzhi DATALEN, %eax, %eax - kmovd %eax, %k1 -.else mov $-1, %rax bzhi DATALEN64, %rax, %rax kmovq %rax, %k1 -.endif // Encrypt a vector of counter blocks. This does not need to be masked. - vpshufb BSWAP_MASK, LE_CTR, V0 + vpshufb BSWAP_MASK, LE_CTR, %zmm0 vpaddd LE_CTR_INC, LE_CTR, LE_CTR - vpxord RNDKEY0, V0, V0 + vpxord RNDKEY0, %zmm0, %zmm0 lea 16(KEY), %rax 1: vbroadcasti32x4 (%rax), RNDKEY - vaesenc RNDKEY, V0, V0 + vaesenc RNDKEY, %zmm0, %zmm0 add $16, %rax cmp %rax, RNDKEYLAST_PTR jne 1b - vaesenclast RNDKEYLAST, V0, V0 + vaesenclast RNDKEYLAST, %zmm0, %zmm0 // XOR the data with the appropriate number of keystream bytes. - vmovdqu8 (SRC), V1{%k1}{z} - vpxord V1, V0, V0 - vmovdqu8 V0, (DST){%k1} + vmovdqu8 (SRC), %zmm1{%k1}{z} + vpxord %zmm1, %zmm0, %zmm0 + vmovdqu8 %zmm0, (DST){%k1} // Update GHASH with the ciphertext block(s), without reducing. // - // In the case of DATALEN < VL, the ciphertext is zero-padded to VL. - // (If decrypting, it's done by the above masked load. If encrypting, - // it's done by the below masked register-to-register move.) Note that - // if DATALEN <= VL - 16, there will be additional padding beyond the - // padding of the last block specified by GHASH itself; i.e., there may - // be whole block(s) that get processed by the GHASH multiplication and - // reduction instructions but should not actually be included in the + // In the case of DATALEN < 64, the ciphertext is zero-padded to 64 + // bytes. (If decrypting, it's done by the above masked load. If + // encrypting, it's done by the below masked register-to-register move.) + // Note that if DATALEN <= 48, there will be additional padding beyond + // the padding of the last block specified by GHASH itself; i.e., there + // may be whole block(s) that get processed by the GHASH multiplication + // and reduction instructions but should not actually be included in the // GHASH. However, any such blocks are all-zeroes, and the values that // they're multiplied with are also all-zeroes. Therefore they just add // 0 * 0 = 0 to the final GHASH result, which makes no difference. vmovdqu8 (POWERS_PTR), H_POW1 .if \enc - vmovdqu8 V0, V1{%k1}{z} + vmovdqu8 %zmm0, %zmm1{%k1}{z} .endif - vpshufb BSWAP_MASK, V1, V0 - vpxord GHASH_ACC, V0, V0 - _ghash_mul_noreduce H_POW1, V0, LO, MI, HI, GHASHDATA3, V1, V2, V3 + vpshufb BSWAP_MASK, %zmm1, %zmm0 + vpxord GHASH_ACC, %zmm0, %zmm0 + _ghash_mul_noreduce H_POW1, %zmm0, LO, MI, HI, \ + GHASHDATA3, %zmm1, %zmm2, %zmm3 vpxor GHASH_ACC_XMM, GHASH_ACC_XMM, GHASH_ACC_XMM - add $VL, POWERS_PTR - add $VL, SRC - add $VL, DST - sub $VL, DATALEN + add $64, POWERS_PTR + add $64, SRC + add $64, DST + sub $64, DATALEN jg .Lcrypt_loop_1x\@ // Finally, do the GHASH reduction. - _ghash_reduce LO, MI, HI, GFPOLY, V0 + _ghash_reduce LO, MI, HI, GFPOLY, %zmm0 _horizontal_xor HI, HI_XMM, GHASH_ACC_XMM, %xmm0, %xmm1, %xmm2 .Ldone\@: // Store the updated GHASH accumulator back to memory. vmovdqu GHASH_ACC_XMM, (GHASH_ACC_PTR)
@@ -1045,11 +999,10 @@ .endif // No need for vzeroupper here, since only used xmm registers were used. RET .endm -_set_veclen 64 SYM_FUNC_START(aes_gcm_precompute_vaes_avx512) _aes_gcm_precompute SYM_FUNC_END(aes_gcm_precompute_vaes_avx512) SYM_FUNC_START(aes_gcm_enc_update_vaes_avx512) _aes_gcm_update 1
Signature · 1 line
2.51.0
PATCH 5/8 crypto: x86/aes-gcm - reorder AVX512 precompute and aad_update functions
In reply to Eric BiggersNow that the _aes_gcm_precompute macro is instantiated only once, replace it directly with a function definition.
Also, move aes_gcm_aad_update_vaes_avx512() to a different location in the file so that it's consistent with aes-gcm-vaes-avx2.S and also the BoringSSL port of this code.
No functional changes.
--- arch/x86/crypto/aes-gcm-vaes-avx512.S | 187 +++++++++++++------------- 1 file changed, 92 insertions(+), 95 deletions(-)
arch/x86/crypto/aes-gcm-vaes-avx512.S +92 -95
@@ -266,11 +266,11 @@ // subkey and initializes |key->ghash_key_powers| with powers of it. // // The number of key powers initialized is NUM_H_POWERS, and they are stored in // the order H^NUM_H_POWERS to H^1. The zeroized padding blocks after the key // powers themselves are also initialized. -.macro _aes_gcm_precompute +SYM_FUNC_START(aes_gcm_precompute_vaes_avx512) // Function arguments .set KEY, %rdi // Additional local variables.
@@ -359,20 +359,20 @@ // Compute and store the remaining key powers. // Repeatedly multiply [H^(i+3), H^(i+2), H^(i+1), H^i] by // [H^4, H^4, H^4, H^4] to get [H^(i+7), H^(i+6), H^(i+5), H^(i+4)]. mov $3, %eax -.Lprecompute_next\@: +.Lprecompute_next: sub $64, POWERS_PTR _ghash_mul H_INC, H_CUR, H_CUR, GFPOLY, %zmm0, %zmm1, %zmm2 vmovdqu8 H_CUR, (POWERS_PTR) dec %eax - jnz .Lprecompute_next\@ + jnz .Lprecompute_next vzeroupper // This is needed after using ymm or zmm registers. RET -.endm +SYM_FUNC_END(aes_gcm_precompute_vaes_avx512) // XOR together the 128-bit lanes of \src (whose low lane is \src_xmm) and store // the result in \dst_xmm. This implicitly zeroizes the other lanes of dst. .macro _horizontal_xor src, src_xmm, dst_xmm, t0_xmm, t1_xmm, t2_xmm vextracti32x4 $1, \src, \t0_xmm
@@ -461,10 +461,98 @@ _horizontal_xor GHASH_ACC, GHASH_ACC_XMM, GHASH_ACC_XMM, \ GHASHDATA0_XMM, GHASHDATA1_XMM, GHASHDATA2_XMM .endif .endm +// void aes_gcm_aad_update_vaes_avx512(const struct aes_gcm_key_vaes_avx512 *key, +// u8 ghash_acc[16], +// const u8 *aad, int aadlen); +// +// This function processes the AAD (Additional Authenticated Data) in GCM. +// Using the key |key|, it updates the GHASH accumulator |ghash_acc| with the +// data given by |aad| and |aadlen|. |key->ghash_key_powers| must have been +// initialized. On the first call, |ghash_acc| must be all zeroes. |aadlen| +// must be a multiple of 16, except on the last call where it can be any length. +// The caller must do any buffering needed to ensure this. +// +// AES-GCM is almost always used with small amounts of AAD, less than 32 bytes. +// Therefore, for AAD processing we currently only provide this implementation +// which uses 256-bit vectors (ymm registers) and only has a 1x-wide loop. This +// keeps the code size down, and it enables some micro-optimizations, e.g. using +// VEX-coded instructions instead of EVEX-coded to save some instruction bytes. +// To optimize for large amounts of AAD, we could implement a 4x-wide loop and +// provide a version using 512-bit vectors, but that doesn't seem to be useful. +SYM_FUNC_START(aes_gcm_aad_update_vaes_avx512) + + // Function arguments + .set KEY, %rdi + .set GHASH_ACC_PTR, %rsi + .set AAD, %rdx + .set AADLEN, %ecx + .set AADLEN64, %rcx // Zero-extend AADLEN before using! + + // Additional local variables. + // %rax, %ymm0-%ymm3, and %k1 are used as temporary registers. + .set BSWAP_MASK, %ymm4 + .set GFPOLY, %ymm5 + .set GHASH_ACC, %ymm6 + .set GHASH_ACC_XMM, %xmm6 + .set H_POW1, %ymm7 + + // Load some constants. + vbroadcasti128 .Lbswap_mask(%rip), BSWAP_MASK + vbroadcasti128 .Lgfpoly(%rip), GFPOLY + + // Load the GHASH accumulator. + vmovdqu (GHASH_ACC_PTR), GHASH_ACC_XMM + + // Update GHASH with 32 bytes of AAD at a time. + // + // Pre-subtracting 32 from AADLEN saves an instruction from the loop and + // also ensures that at least one write always occurs to AADLEN, + // zero-extending it and allowing AADLEN64 to be used later. + sub $32, AADLEN + jl .Laad_loop_1x_done + vmovdqu8 OFFSETOFEND_H_POWERS-32(KEY), H_POW1 // [H^2, H^1] +.Laad_loop_1x: + vmovdqu (AAD), %ymm0 + vpshufb BSWAP_MASK, %ymm0, %ymm0 + vpxor %ymm0, GHASH_ACC, GHASH_ACC + _ghash_mul H_POW1, GHASH_ACC, GHASH_ACC, GFPOLY, \ + %ymm0, %ymm1, %ymm2 + vextracti128 $1, GHASH_ACC, %xmm0 + vpxor %xmm0, GHASH_ACC_XMM, GHASH_ACC_XMM + add $32, AAD + sub $32, AADLEN + jge .Laad_loop_1x +.Laad_loop_1x_done: + add $32, AADLEN + jz .Laad_done + + // Update GHASH with the remaining 1 <= AADLEN < 32 bytes of AAD. + mov $-1, %eax + bzhi AADLEN, %eax, %eax + kmovd %eax, %k1 + vmovdqu8 (AAD), %ymm0{%k1}{z} + neg AADLEN64 + and $~15, AADLEN64 // -round_up(AADLEN, 16) + vmovdqu8 OFFSETOFEND_H_POWERS(KEY,AADLEN64), H_POW1 + vpshufb BSWAP_MASK, %ymm0, %ymm0 + vpxor %ymm0, GHASH_ACC, GHASH_ACC + _ghash_mul H_POW1, GHASH_ACC, GHASH_ACC, GFPOLY, \ + %ymm0, %ymm1, %ymm2 + vextracti128 $1, GHASH_ACC, %xmm0 + vpxor %xmm0, GHASH_ACC_XMM, GHASH_ACC_XMM + +.Laad_done: + // Store the updated GHASH accumulator back to memory. + vmovdqu GHASH_ACC_XMM, (GHASH_ACC_PTR) + + vzeroupper // This is needed after using ymm or zmm registers. + RET +SYM_FUNC_END(aes_gcm_aad_update_vaes_avx512) + // Do one non-last round of AES encryption on the blocks in %zmm[0-3] using the // round key that has been broadcast to all 128-bit lanes of \round_key. .macro _vaesenc_4x round_key vaesenc \round_key, %zmm0, %zmm0 vaesenc \round_key, %zmm1, %zmm1
@@ -999,108 +1087,17 @@ .endif // No need for vzeroupper here, since only used xmm registers were used. RET .endm -SYM_FUNC_START(aes_gcm_precompute_vaes_avx512) - _aes_gcm_precompute -SYM_FUNC_END(aes_gcm_precompute_vaes_avx512) SYM_FUNC_START(aes_gcm_enc_update_vaes_avx512) _aes_gcm_update 1 SYM_FUNC_END(aes_gcm_enc_update_vaes_avx512) SYM_FUNC_START(aes_gcm_dec_update_vaes_avx512) _aes_gcm_update 0 SYM_FUNC_END(aes_gcm_dec_update_vaes_avx512) -// void aes_gcm_aad_update_vaes_avx512(const struct aes_gcm_key_vaes_avx512 *key, -// u8 ghash_acc[16], -// const u8 *aad, int aadlen); -// -// This function processes the AAD (Additional Authenticated Data) in GCM. -// Using the key |key|, it updates the GHASH accumulator |ghash_acc| with the -// data given by |aad| and |aadlen|. |key->ghash_key_powers| must have been -// initialized. On the first call, |ghash_acc| must be all zeroes. |aadlen| -// must be a multiple of 16, except on the last call where it can be any length. -// The caller must do any buffering needed to ensure this. -// -// AES-GCM is almost always used with small amounts of AAD, less than 32 bytes. -// Therefore, for AAD processing we currently only provide this implementation -// which uses 256-bit vectors (ymm registers) and only has a 1x-wide loop. This -// keeps the code size down, and it enables some micro-optimizations, e.g. using -// VEX-coded instructions instead of EVEX-coded to save some instruction bytes. -// To optimize for large amounts of AAD, we could implement a 4x-wide loop and -// provide a version using 512-bit vectors, but that doesn't seem to be useful. -SYM_FUNC_START(aes_gcm_aad_update_vaes_avx512) - - // Function arguments - .set KEY, %rdi - .set GHASH_ACC_PTR, %rsi - .set AAD, %rdx - .set AADLEN, %ecx - .set AADLEN64, %rcx // Zero-extend AADLEN before using! - - // Additional local variables. - // %rax, %ymm0-%ymm3, and %k1 are used as temporary registers. - .set BSWAP_MASK, %ymm4 - .set GFPOLY, %ymm5 - .set GHASH_ACC, %ymm6 - .set GHASH_ACC_XMM, %xmm6 - .set H_POW1, %ymm7 - - // Load some constants. - vbroadcasti128 .Lbswap_mask(%rip), BSWAP_MASK - vbroadcasti128 .Lgfpoly(%rip), GFPOLY - - // Load the GHASH accumulator. - vmovdqu (GHASH_ACC_PTR), GHASH_ACC_XMM - - // Update GHASH with 32 bytes of AAD at a time. - // - // Pre-subtracting 32 from AADLEN saves an instruction from the loop and - // also ensures that at least one write always occurs to AADLEN, - // zero-extending it and allowing AADLEN64 to be used later. - sub $32, AADLEN - jl .Laad_loop_1x_done - vmovdqu8 OFFSETOFEND_H_POWERS-32(KEY), H_POW1 // [H^2, H^1] -.Laad_loop_1x: - vmovdqu (AAD), %ymm0 - vpshufb BSWAP_MASK, %ymm0, %ymm0 - vpxor %ymm0, GHASH_ACC, GHASH_ACC - _ghash_mul H_POW1, GHASH_ACC, GHASH_ACC, GFPOLY, \ - %ymm0, %ymm1, %ymm2 - vextracti128 $1, GHASH_ACC, %xmm0 - vpxor %xmm0, GHASH_ACC_XMM, GHASH_ACC_XMM - add $32, AAD - sub $32, AADLEN - jge .Laad_loop_1x -.Laad_loop_1x_done: - add $32, AADLEN - jz .Laad_done - - // Update GHASH with the remaining 1 <= AADLEN < 32 bytes of AAD. - mov $-1, %eax - bzhi AADLEN, %eax, %eax - kmovd %eax, %k1 - vmovdqu8 (AAD), %ymm0{%k1}{z} - neg AADLEN64 - and $~15, AADLEN64 // -round_up(AADLEN, 16) - vmovdqu8 OFFSETOFEND_H_POWERS(KEY,AADLEN64), H_POW1 - vpshufb BSWAP_MASK, %ymm0, %ymm0 - vpxor %ymm0, GHASH_ACC, GHASH_ACC - _ghash_mul H_POW1, GHASH_ACC, GHASH_ACC, GFPOLY, \ - %ymm0, %ymm1, %ymm2 - vextracti128 $1, GHASH_ACC, %xmm0 - vpxor %xmm0, GHASH_ACC_XMM, GHASH_ACC_XMM - -.Laad_done: - // Store the updated GHASH accumulator back to memory. - vmovdqu GHASH_ACC_XMM, (GHASH_ACC_PTR) - - vzeroupper // This is needed after using ymm or zmm registers. - RET -SYM_FUNC_END(aes_gcm_aad_update_vaes_avx512) - SYM_FUNC_START(aes_gcm_enc_final_vaes_avx512) _aes_gcm_final 1 SYM_FUNC_END(aes_gcm_enc_final_vaes_avx512) SYM_FUNC_START(aes_gcm_dec_final_vaes_avx512) _aes_gcm_final 0
Signature · 1 line
2.51.0
PATCH 6/8 crypto: x86/aes-gcm - revise some comments in AVX512 code
In reply to Eric Biggers- Fix some references to field names in struct aes_gcm_key_vaes_avx512.
- Remove the mention of the counter having to start at 2. The assembly code doesn't actually assume that it does.
Note that these changes improve consistency with aes-gcm-vaes-avx2.S.
--- arch/x86/crypto/aes-gcm-vaes-avx512.S | 27 +++++++++++---------------- 1 file changed, 11 insertions(+), 16 deletions(-)
arch/x86/crypto/aes-gcm-vaes-avx512.S +11 -16
@@ -260,16 +260,12 @@ vpternlogd $0x96, \t0, \mi, \hi .endm // void aes_gcm_precompute_vaes_avx512(struct aes_gcm_key_vaes_avx512 *key); // -// Given the expanded AES key |key->aes_key|, this function derives the GHASH -// subkey and initializes |key->ghash_key_powers| with powers of it. -// -// The number of key powers initialized is NUM_H_POWERS, and they are stored in -// the order H^NUM_H_POWERS to H^1. The zeroized padding blocks after the key -// powers themselves are also initialized. +// Given the expanded AES key |key->base.aes_key|, derive the GHASH subkey and +// initialize |key->h_powers| and |key->padding|. SYM_FUNC_START(aes_gcm_precompute_vaes_avx512) // Function arguments .set KEY, %rdi
@@ -467,14 +463,13 @@ SYM_FUNC_END(aes_gcm_precompute_vaes_avx512) // u8 ghash_acc[16], // const u8 *aad, int aadlen); // // This function processes the AAD (Additional Authenticated Data) in GCM. // Using the key |key|, it updates the GHASH accumulator |ghash_acc| with the -// data given by |aad| and |aadlen|. |key->ghash_key_powers| must have been -// initialized. On the first call, |ghash_acc| must be all zeroes. |aadlen| -// must be a multiple of 16, except on the last call where it can be any length. -// The caller must do any buffering needed to ensure this. +// data given by |aad| and |aadlen|. On the first call, |ghash_acc| must be all +// zeroes. |aadlen| must be a multiple of 16, except on the last call where it +// can be any length. The caller must do any buffering needed to ensure this. // // AES-GCM is almost always used with small amounts of AAD, less than 32 bytes. // Therefore, for AAD processing we currently only provide this implementation // which uses 256-bit vectors (ymm registers) and only has a 1x-wide loop. This // keeps the code size down, and it enables some micro-optimizations, e.g. using
@@ -620,16 +615,16 @@ SYM_FUNC_END(aes_gcm_aad_update_vaes_avx512) // // |datalen| must be a multiple of 16, except on the last call where it can be // any length. The caller must do any buffering needed to ensure this. Both // in-place and out-of-place en/decryption are supported. // -// |le_ctr| must give the current counter in little-endian format. For a new -// message, the low word of the counter must be 2. This function loads the -// counter from |le_ctr| and increments the loaded counter as needed, but it -// does *not* store the updated counter back to |le_ctr|. The caller must -// update |le_ctr| if any more data segments follow. Internally, only the low -// 32-bit word of the counter is incremented, following the GCM standard. +// |le_ctr| must give the current counter in little-endian format. This +// function loads the counter from |le_ctr| and increments the loaded counter as +// needed, but it does *not* store the updated counter back to |le_ctr|. The +// caller must update |le_ctr| if any more data segments follow. Internally, +// only the low 32-bit word of the counter is incremented, following the GCM +// standard. .macro _aes_gcm_update enc // Function arguments .set KEY, %rdi .set LE_CTR_PTR, %rsi
Signature · 1 line
2.51.0
PATCH 7/8 crypto: x86/aes-gcm - optimize AVX512 precomputation of H^2 from H^1
In reply to Eric BiggersSquaring in GF(2^128) requires fewer instructions than a generic multiplication in GF(2^128). Take advantage of this when computing H^2 from H^1 in aes_gcm_precompute_vaes_avx512().
Note that aes_gcm_precompute_vaes_avx2() already uses this optimization.
--- arch/x86/crypto/aes-gcm-vaes-avx512.S | 16 ++++++++++++++-- 1 file changed, 14 insertions(+), 2 deletions(-)
arch/x86/crypto/aes-gcm-vaes-avx512.S +14 -2
@@ -258,10 +258,23 @@ vpclmulqdq $0x01, \mi, \gfpoly, \t0 vpshufd $0x4e, \mi, \mi vpternlogd $0x96, \t0, \mi, \hi .endm +// This is a specialized version of _ghash_mul that computes \a * \a, i.e. it +// squares \a. It skips computing MI = (a_L * a_H) + (a_H * a_L) = 0. +.macro _ghash_square a, dst, gfpoly, t0, t1 + vpclmulqdq $0x00, \a, \a, \t0 // LO = a_L * a_L + vpclmulqdq $0x11, \a, \a, \dst // HI = a_H * a_H + vpclmulqdq $0x01, \t0, \gfpoly, \t1 // LO_L*(x^63 + x^62 + x^57) + vpshufd $0x4e, \t0, \t0 // Swap halves of LO + vpxord \t0, \t1, \t1 // Fold LO into MI + vpclmulqdq $0x01, \t1, \gfpoly, \t0 // MI_L*(x^63 + x^62 + x^57) + vpshufd $0x4e, \t1, \t1 // Swap halves of MI + vpternlogd $0x96, \t0, \t1, \dst // Fold MI into HI +.endm + // void aes_gcm_precompute_vaes_avx512(struct aes_gcm_key_vaes_avx512 *key); // // Given the expanded AES key |key->base.aes_key|, derive the GHASH subkey and // initialize |key->h_powers| and |key->padding|. SYM_FUNC_START(aes_gcm_precompute_vaes_avx512)
@@ -335,12 +348,11 @@ SYM_FUNC_START(aes_gcm_precompute_vaes_avx512) // Note that as with H^1, all higher key powers also need an extra // factor of x^-1 (or x using the natural interpretation). Nothing // special needs to be done to make this happen, though: H^1 * H^1 would // end up with two factors of x^-1, but the multiplication consumes one. // So the product H^2 ends up with the desired one factor of x^-1. - _ghash_mul H_CUR_XMM, H_CUR_XMM, H_INC_XMM, GFPOLY_XMM, \ - %xmm0, %xmm1, %xmm2 + _ghash_square H_CUR_XMM, H_INC_XMM, GFPOLY_XMM, %xmm0, %xmm1 // Create H_CUR_YMM = [H^2, H^1] and H_INC_YMM = [H^2, H^2]. vinserti128 $1, H_CUR_XMM, H_INC_YMM, H_CUR_YMM vinserti128 $1, H_INC_XMM, H_INC_YMM, H_INC_YMM
Signature · 1 line
2.51.0
PATCH 8/8 crypto: x86/aes-gcm - optimize long AAD processing with AVX512
In reply to Eric BiggersImprove the performance of aes_gcm_aad_update_vaes_avx512() on large AAD (additional authenticated data) lengths by 4-8 times by making it use up to 512-bit vectors and a 4-vector-wide loop. Previously, it used only 256-bit vectors and a 1-vector-wide loop.
Originally, I assumed that the case of large AADLEN was unimportant. When reviewing the users of BoringSSL's AES-GCM code, I found that some callers use BoringSSL's AES-GCM API to just compute GMAC, using large amounts of AAD with zero bytes en/decrypted. Thus, I included a similar optimization in the BoringSSL port of this code. I believe it's wise to include this optimization in the kernel port too for similar reasons, and to align it more closely with the BoringSSL port.
Another reason this function originally used 256-bit vectors was so that separate *_avx10_256 and *_avx10_512 versions of it wouldn't be needed. However, that's no longer applicable.
To avoid a slight performance regression in the common case of AADLEN <= 16, also add a fast path for that case which uses 128-bit vectors. In fact, this case actually gets slightly faster too, since it saves a couple instructions over the original 256-bit code.
--- arch/x86/crypto/aes-gcm-vaes-avx512.S | 146 +++++++++++++++++--------- 1 file changed, 99 insertions(+), 47 deletions(-)
arch/x86/crypto/aes-gcm-vaes-avx512.S +99 -47
@@ -469,88 +469,142 @@ SYM_FUNC_END(aes_gcm_precompute_vaes_avx512) _horizontal_xor GHASH_ACC, GHASH_ACC_XMM, GHASH_ACC_XMM, \ GHASHDATA0_XMM, GHASHDATA1_XMM, GHASHDATA2_XMM .endif .endm +// Update GHASH with four vectors of data blocks. See _ghash_step_4x for full +// explanation. +.macro _ghash_4x +.irp i, 0,1,2,3,4,5,6,7,8,9 + _ghash_step_4x \i +.endr +.endm + // void aes_gcm_aad_update_vaes_avx512(const struct aes_gcm_key_vaes_avx512 *key, // u8 ghash_acc[16], // const u8 *aad, int aadlen); // // This function processes the AAD (Additional Authenticated Data) in GCM. // Using the key |key|, it updates the GHASH accumulator |ghash_acc| with the // data given by |aad| and |aadlen|. On the first call, |ghash_acc| must be all // zeroes. |aadlen| must be a multiple of 16, except on the last call where it // can be any length. The caller must do any buffering needed to ensure this. // -// AES-GCM is almost always used with small amounts of AAD, less than 32 bytes. -// Therefore, for AAD processing we currently only provide this implementation -// which uses 256-bit vectors (ymm registers) and only has a 1x-wide loop. This -// keeps the code size down, and it enables some micro-optimizations, e.g. using -// VEX-coded instructions instead of EVEX-coded to save some instruction bytes. -// To optimize for large amounts of AAD, we could implement a 4x-wide loop and -// provide a version using 512-bit vectors, but that doesn't seem to be useful. +// This handles large amounts of AAD efficiently, while also keeping overhead +// low for small amounts which is the common case. TLS and IPsec use less than +// one block of AAD, but (uncommonly) other use cases may use much more. SYM_FUNC_START(aes_gcm_aad_update_vaes_avx512) // Function arguments .set KEY, %rdi .set GHASH_ACC_PTR, %rsi .set AAD, %rdx .set AADLEN, %ecx .set AADLEN64, %rcx // Zero-extend AADLEN before using! // Additional local variables. - // %rax, %ymm0-%ymm3, and %k1 are used as temporary registers. - .set BSWAP_MASK, %ymm4 - .set GFPOLY, %ymm5 - .set GHASH_ACC, %ymm6 - .set GHASH_ACC_XMM, %xmm6 - .set H_POW1, %ymm7 - - // Load some constants. - vbroadcasti128 .Lbswap_mask(%rip), BSWAP_MASK - vbroadcasti128 .Lgfpoly(%rip), GFPOLY + // %rax and %k1 are used as temporary registers. + .set GHASHDATA0, %zmm0 + .set GHASHDATA0_XMM, %xmm0 + .set GHASHDATA1, %zmm1 + .set GHASHDATA1_XMM, %xmm1 + .set GHASHDATA2, %zmm2 + .set GHASHDATA2_XMM, %xmm2 + .set GHASHDATA3, %zmm3 + .set BSWAP_MASK, %zmm4 + .set BSWAP_MASK_XMM, %xmm4 + .set GHASH_ACC, %zmm5 + .set GHASH_ACC_XMM, %xmm5 + .set H_POW4, %zmm6 + .set H_POW3, %zmm7 + .set H_POW2, %zmm8 + .set H_POW1, %zmm9 + .set H_POW1_XMM, %xmm9 + .set GFPOLY, %zmm10 + .set GFPOLY_XMM, %xmm10 + .set GHASHTMP0, %zmm11 + .set GHASHTMP1, %zmm12 + .set GHASHTMP2, %zmm13 // Load the GHASH accumulator. vmovdqu (GHASH_ACC_PTR), GHASH_ACC_XMM - // Update GHASH with 32 bytes of AAD at a time. - // - // Pre-subtracting 32 from AADLEN saves an instruction from the loop and - // also ensures that at least one write always occurs to AADLEN, - // zero-extending it and allowing AADLEN64 to be used later. - sub $32, AADLEN + // Check for the common case of AADLEN <= 16, as well as AADLEN == 0. + cmp $16, AADLEN + jg .Laad_more_than_16bytes + test AADLEN, AADLEN + jz .Laad_done + + // Fast path: update GHASH with 1 <= AADLEN <= 16 bytes of AAD. + vmovdqu .Lbswap_mask(%rip), BSWAP_MASK_XMM + vmovdqu .Lgfpoly(%rip), GFPOLY_XMM + mov $-1, %eax + bzhi AADLEN, %eax, %eax + kmovd %eax, %k1 + vmovdqu8 (AAD), GHASHDATA0_XMM{%k1}{z} + vmovdqu OFFSETOFEND_H_POWERS-16(KEY), H_POW1_XMM + vpshufb BSWAP_MASK_XMM, GHASHDATA0_XMM, GHASHDATA0_XMM + vpxor GHASHDATA0_XMM, GHASH_ACC_XMM, GHASH_ACC_XMM + _ghash_mul H_POW1_XMM, GHASH_ACC_XMM, GHASH_ACC_XMM, GFPOLY_XMM, \ + GHASHDATA0_XMM, GHASHDATA1_XMM, GHASHDATA2_XMM + jmp .Laad_done + +.Laad_more_than_16bytes: + vbroadcasti32x4 .Lbswap_mask(%rip), BSWAP_MASK + vbroadcasti32x4 .Lgfpoly(%rip), GFPOLY + + // If AADLEN >= 256, update GHASH with 256 bytes of AAD at a time. + sub $256, AADLEN + jl .Laad_loop_4x_done + vmovdqu8 OFFSETOFEND_H_POWERS-4*64(KEY), H_POW4 + vmovdqu8 OFFSETOFEND_H_POWERS-3*64(KEY), H_POW3 + vmovdqu8 OFFSETOFEND_H_POWERS-2*64(KEY), H_POW2 + vmovdqu8 OFFSETOFEND_H_POWERS-1*64(KEY), H_POW1 +.Laad_loop_4x: + vmovdqu8 0*64(AAD), GHASHDATA0 + vmovdqu8 1*64(AAD), GHASHDATA1 + vmovdqu8 2*64(AAD), GHASHDATA2 + vmovdqu8 3*64(AAD), GHASHDATA3 + _ghash_4x + add $256, AAD + sub $256, AADLEN + jge .Laad_loop_4x +.Laad_loop_4x_done: + + // If AADLEN >= 64, update GHASH with 64 bytes of AAD at a time. + add $192, AADLEN jl .Laad_loop_1x_done - vmovdqu8 OFFSETOFEND_H_POWERS-32(KEY), H_POW1 // [H^2, H^1] + vmovdqu8 OFFSETOFEND_H_POWERS-1*64(KEY), H_POW1 .Laad_loop_1x: - vmovdqu (AAD), %ymm0 - vpshufb BSWAP_MASK, %ymm0, %ymm0 - vpxor %ymm0, GHASH_ACC, GHASH_ACC + vmovdqu8 (AAD), GHASHDATA0 + vpshufb BSWAP_MASK, GHASHDATA0, GHASHDATA0 + vpxord GHASHDATA0, GHASH_ACC, GHASH_ACC _ghash_mul H_POW1, GHASH_ACC, GHASH_ACC, GFPOLY, \ - %ymm0, %ymm1, %ymm2 - vextracti128 $1, GHASH_ACC, %xmm0 - vpxor %xmm0, GHASH_ACC_XMM, GHASH_ACC_XMM - add $32, AAD - sub $32, AADLEN + GHASHDATA0, GHASHDATA1, GHASHDATA2 + _horizontal_xor GHASH_ACC, GHASH_ACC_XMM, GHASH_ACC_XMM, \ + GHASHDATA0_XMM, GHASHDATA1_XMM, GHASHDATA2_XMM + add $64, AAD + sub $64, AADLEN jge .Laad_loop_1x .Laad_loop_1x_done: - add $32, AADLEN - jz .Laad_done - // Update GHASH with the remaining 1 <= AADLEN < 32 bytes of AAD. - mov $-1, %eax - bzhi AADLEN, %eax, %eax - kmovd %eax, %k1 - vmovdqu8 (AAD), %ymm0{%k1}{z} + // Update GHASH with the remaining 0 <= AADLEN < 64 bytes of AAD. + add $64, AADLEN + jz .Laad_done + mov $-1, %rax + bzhi AADLEN64, %rax, %rax + kmovq %rax, %k1 + vmovdqu8 (AAD), GHASHDATA0{%k1}{z} neg AADLEN64 and $~15, AADLEN64 // -round_up(AADLEN, 16) vmovdqu8 OFFSETOFEND_H_POWERS(KEY,AADLEN64), H_POW1 - vpshufb BSWAP_MASK, %ymm0, %ymm0 - vpxor %ymm0, GHASH_ACC, GHASH_ACC + vpshufb BSWAP_MASK, GHASHDATA0, GHASHDATA0 + vpxord GHASHDATA0, GHASH_ACC, GHASH_ACC _ghash_mul H_POW1, GHASH_ACC, GHASH_ACC, GFPOLY, \ - %ymm0, %ymm1, %ymm2 - vextracti128 $1, GHASH_ACC, %xmm0 - vpxor %xmm0, GHASH_ACC_XMM, GHASH_ACC_XMM + GHASHDATA0, GHASHDATA1, GHASHDATA2 + _horizontal_xor GHASH_ACC, GHASH_ACC_XMM, GHASH_ACC_XMM, \ + GHASHDATA0_XMM, GHASHDATA1_XMM, GHASHDATA2_XMM .Laad_done: // Store the updated GHASH accumulator back to memory. vmovdqu GHASH_ACC_XMM, (GHASH_ACC_PTR)
@@ -842,13 +896,11 @@ SYM_FUNC_END(aes_gcm_aad_update_vaes_avx512) jge .Lcrypt_loop_4x\@ .if \enc .Lghash_last_ciphertext_4x\@: // Update GHASH with the last set of ciphertext blocks. -.irp i, 0,1,2,3,4,5,6,7,8,9 - _ghash_step_4x \i -.endr + _ghash_4x .endif .Lcrypt_loop_4x_done\@: // Undo the extra subtraction by 256 and check whether data remains.
Signature · 1 line
2.51.0
Quoted 15 lines · Eric Biggers
This patchset replaces the 256-bit vector implementation of AES-GCM for
x86_64with one that requires AVX2 rather than AVX512. This greatly improves AES-GCM performance on CPUs that have VAES but not AVX512, for example by up to 74% on AMD Zen 3. For more details, see patch 1.This patchset also renames the 512-bit vector implementation of AES-GCM for
x86_64to be named after AVX512 rather than AVX10/512, then adds some additional optimizations to it.This patchset applies to next-20250929 and is targeting 6.19. Herbert, I'd prefer to just apply this myself. But let me know if you'd prefer to take it instead (considering that AES-GCM hasn't been librarified yet). Either way, there's no hurry, since this is targeting 6.19.
Quoted 11 lines
Eric Biggers (8):
crypto: x86/aes-gcm - add VAES+AVX2 optimized code
crypto: x86/aes-gcm - remove VAES+AVX10/256 optimized code
crypto: x86/aes-gcm - rename avx10 andavx10_512to avx512
crypto: x86/aes-gcm - clean up AVX512 code to assume 512-bit vectors
crypto: x86/aes-gcm - reorder AVX512 precompute andaad_update
functions
crypto: x86/aes-gcm - revise some comments in AVX512 code
crypto: x86/aes-gcm - optimize AVX512 precomputation of H^2 from H^1
crypto: x86/aes-gcm - optimize long AAD processing with AVX512
Eric Biggers
AppliedQuoted 34 lines · Eric Biggers
This patchset replaces the 256-bit vector implementation of AES-GCM for
x86_64with one that requires AVX2 rather than AVX512. This greatly improves AES-GCM performance on CPUs that have VAES but not AVX512, for example by up to 74% on AMD Zen 3. For more details, see patch 1.This patchset also renames the 512-bit vector implementation of AES-GCM for
x86_64to be named after AVX512 rather than AVX10/512, then adds some additional optimizations to it.This patchset applies to next-20250929 and is targeting 6.19. Herbert, I'd prefer to just apply this myself. But let me know if you'd prefer to take it instead (considering that AES-GCM hasn't been librarified yet). Either way, there's no hurry, since this is targeting 6.19.
Eric Biggers (8):
crypto: x86/aes-gcm - add VAES+AVX2 optimized code
crypto: x86/aes-gcm - remove VAES+AVX10/256 optimized code
crypto: x86/aes-gcm - rename avx10 andavx10_512to avx512
crypto: x86/aes-gcm - clean up AVX512 code to assume 512-bit vectors
crypto: x86/aes-gcm - reorder AVX512 precompute andaad_update
functions
crypto: x86/aes-gcm - revise some comments in AVX512 code
crypto: x86/aes-gcm - optimize AVX512 precomputation of H^2 from H^1
crypto: x86/aes-gcm - optimize long AAD processing with AVX512arch/x86/crypto/Makefile | 5 +- arch/x86/crypto/aes-gcm-aesni-x86_64.S | 12 +- arch/x86/crypto/aes-gcm-vaes-avx2.S | 1150 +++++++++++++++++ ...m-avx10-x86_64.S => aes-gcm-vaes-avx512.S} | 722 +++++------ arch/x86/crypto/aesni-intel_glue.c | 264 ++-- 5 files changed, 1667 insertions(+), 486 deletions(-) create mode 100644 arch/x86/crypto/aes-gcm-vaes-avx2.S rename arch/x86/crypto/{aes-gcm-avx10-x86_64.S => aes-gcm-vaes-avx512.S} (69%)
Quoted 1 line
base-commit:
3b9b1f8df454caa453c7fb07689064edb2eda90a
Applied to https://git.kernel.org/pub/scm/linux/kernel/git/ebiggers/linux.git/log/?h=libcrypto-next
- Eric
Herbert Xu
maintainerQuoted 35 lines · Eric Biggers
Quoted 34 lines · Eric Biggers
This patchset replaces the 256-bit vector implementation of AES-GCM for
x86_64with one that requires AVX2 rather than AVX512. This greatly improves AES-GCM performance on CPUs that have VAES but not AVX512, for example by up to 74% on AMD Zen 3. For more details, see patch 1.This patchset also renames the 512-bit vector implementation of AES-GCM for
x86_64to be named after AVX512 rather than AVX10/512, then adds some additional optimizations to it.This patchset applies to next-20250929 and is targeting 6.19. Herbert, I'd prefer to just apply this myself. But let me know if you'd prefer to take it instead (considering that AES-GCM hasn't been librarified yet). Either way, there's no hurry, since this is targeting 6.19.
Eric Biggers (8):
crypto: x86/aes-gcm - add VAES+AVX2 optimized code
crypto: x86/aes-gcm - remove VAES+AVX10/256 optimized code
crypto: x86/aes-gcm - rename avx10 andavx10_512to avx512
crypto: x86/aes-gcm - clean up AVX512 code to assume 512-bit vectors
crypto: x86/aes-gcm - reorder AVX512 precompute andaad_update
functions
crypto: x86/aes-gcm - revise some comments in AVX512 code
crypto: x86/aes-gcm - optimize AVX512 precomputation of H^2 from H^1
crypto: x86/aes-gcm - optimize long AAD processing with AVX512arch/x86/crypto/Makefile | 5 +- arch/x86/crypto/aes-gcm-aesni-x86_64.S | 12 +- arch/x86/crypto/aes-gcm-vaes-avx2.S | 1150 +++++++++++++++++ ...m-avx10-x86_64.S => aes-gcm-vaes-avx512.S} | 722 +++++------ arch/x86/crypto/aesni-intel_glue.c | 264 ++-- 5 files changed, 1667 insertions(+), 486 deletions(-) create mode 100644 arch/x86/crypto/aes-gcm-vaes-avx2.S rename arch/x86/crypto/{aes-gcm-avx10-x86_64.S => aes-gcm-vaes-avx512.S} (69%)
Quoted 3 lines
Quoted 1 line
base-commit:
3b9b1f8df454caa453c7fb07689064edb2eda90aApplied to https://git.kernel.org/pub/scm/linux/kernel/git/ebiggers/linux.git/log/?h=libcrypto-next
Oops, I didn't see this email until it was too late. Since the patches should be identical I don't think it matters.
Cheers,
Signature · 3 lines
Email: Herbert Xu <[email protected]> Home Page: http://gondor.apana.org.au/~herbert/ PGP Key: http://gondor.apana.org.au/~herbert/pubkey.txt
Quoted 37 lines · Herbert Xu
Quoted 35 lines · Eric Biggers
Quoted 34 lines · Eric Biggers
This patchset replaces the 256-bit vector implementation of AES-GCM for
x86_64with one that requires AVX2 rather than AVX512. This greatly improves AES-GCM performance on CPUs that have VAES but not AVX512, for example by up to 74% on AMD Zen 3. For more details, see patch 1.This patchset also renames the 512-bit vector implementation of AES-GCM for
x86_64to be named after AVX512 rather than AVX10/512, then adds some additional optimizations to it.This patchset applies to next-20250929 and is targeting 6.19. Herbert, I'd prefer to just apply this myself. But let me know if you'd prefer to take it instead (considering that AES-GCM hasn't been librarified yet). Either way, there's no hurry, since this is targeting 6.19.
Eric Biggers (8):
crypto: x86/aes-gcm - add VAES+AVX2 optimized code
crypto: x86/aes-gcm - remove VAES+AVX10/256 optimized code
crypto: x86/aes-gcm - rename avx10 andavx10_512to avx512
crypto: x86/aes-gcm - clean up AVX512 code to assume 512-bit vectors
crypto: x86/aes-gcm - reorder AVX512 precompute andaad_update
functions
crypto: x86/aes-gcm - revise some comments in AVX512 code
crypto: x86/aes-gcm - optimize AVX512 precomputation of H^2 from H^1
crypto: x86/aes-gcm - optimize long AAD processing with AVX512arch/x86/crypto/Makefile | 5 +- arch/x86/crypto/aes-gcm-aesni-x86_64.S | 12 +- arch/x86/crypto/aes-gcm-vaes-avx2.S | 1150 +++++++++++++++++ ...m-avx10-x86_64.S => aes-gcm-vaes-avx512.S} | 722 +++++------ arch/x86/crypto/aesni-intel_glue.c | 264 ++-- 5 files changed, 1667 insertions(+), 486 deletions(-) create mode 100644 arch/x86/crypto/aes-gcm-vaes-avx2.S rename arch/x86/crypto/{aes-gcm-avx10-x86_64.S => aes-gcm-vaes-avx512.S} (69%)
Quoted 7 lines
Quoted 3 lines
Quoted 1 line
base-commit:
3b9b1f8df454caa453c7fb07689064edb2eda90aApplied to https://git.kernel.org/pub/scm/linux/kernel/git/ebiggers/linux.git/log/?h=libcrypto-next
Oops, I didn't see this email until it was too late. Since the patches should be identical I don't think it matters.
You also failed to apply my acked-by/tested-by so perhaps you should just drop the patches from your tree again.
Quoted 38 lines · Ard Biesheuvel
Quoted 37 lines · Herbert Xu
Quoted 35 lines · Eric Biggers
Quoted 34 lines · Eric Biggers
This patchset replaces the 256-bit vector implementation of AES-GCM for
x86_64with one that requires AVX2 rather than AVX512. This greatly improves AES-GCM performance on CPUs that have VAES but not AVX512, for example by up to 74% on AMD Zen 3. For more details, see patch 1.This patchset also renames the 512-bit vector implementation of AES-GCM for
x86_64to be named after AVX512 rather than AVX10/512, then adds some additional optimizations to it.This patchset applies to next-20250929 and is targeting 6.19. Herbert, I'd prefer to just apply this myself. But let me know if you'd prefer to take it instead (considering that AES-GCM hasn't been librarified yet). Either way, there's no hurry, since this is targeting 6.19.
Eric Biggers (8):
crypto: x86/aes-gcm - add VAES+AVX2 optimized code
crypto: x86/aes-gcm - remove VAES+AVX10/256 optimized code
crypto: x86/aes-gcm - rename avx10 andavx10_512to avx512
crypto: x86/aes-gcm - clean up AVX512 code to assume 512-bit vectors
crypto: x86/aes-gcm - reorder AVX512 precompute andaad_update
functions
crypto: x86/aes-gcm - revise some comments in AVX512 code
crypto: x86/aes-gcm - optimize AVX512 precomputation of H^2 from H^1
crypto: x86/aes-gcm - optimize long AAD processing with AVX512arch/x86/crypto/Makefile | 5 +- arch/x86/crypto/aes-gcm-aesni-x86_64.S | 12 +- arch/x86/crypto/aes-gcm-vaes-avx2.S | 1150 +++++++++++++++++ ...m-avx10-x86_64.S => aes-gcm-vaes-avx512.S} | 722 +++++------ arch/x86/crypto/aesni-intel_glue.c | 264 ++-- 5 files changed, 1667 insertions(+), 486 deletions(-) create mode 100644 arch/x86/crypto/aes-gcm-vaes-avx2.S rename arch/x86/crypto/{aes-gcm-avx10-x86_64.S => aes-gcm-vaes-avx512.S} (69%)
Quoted 6 lines
Quoted 6 lines
Quoted 3 lines
Quoted 1 line
base-commit:
3b9b1f8df454caa453c7fb07689064edb2eda90aApplied to https://git.kernel.org/pub/scm/linux/kernel/git/ebiggers/linux.git/log/?h=libcrypto-next
Oops, I didn't see this email until it was too late. Since the patches should be identical I don't think it matters.
Well, it seems you didn't read the patchset (even the cover letter) or any of the replies to it. So maybe I should just take it, as I already said I preferred, and later did do since you hadn't said you wanted to take it. It would have been okay if you had volunteered to take this, but you need to actually read the patches and replies.
As for the patches being identical, besides correctly applying Ard's tags, I made a couple very minor changes that weren't worth sending a v2
for: clarifying one of the commit messages, and correcting two comments and dropping some unused aliases from aes-gcm-vaes-avx2.S.
- Eric
Quoted 52 lines · Eric Biggers
Quoted 38 lines · Ard Biesheuvel
Quoted 37 lines · Herbert Xu
Quoted 35 lines · Eric Biggers
Quoted 34 lines · Eric Biggers
This patchset replaces the 256-bit vector implementation of AES-GCM for
x86_64with one that requires AVX2 rather than AVX512. This greatly improves AES-GCM performance on CPUs that have VAES but not AVX512, for example by up to 74% on AMD Zen 3. For more details, see patch 1.This patchset also renames the 512-bit vector implementation of AES-GCM for
x86_64to be named after AVX512 rather than AVX10/512, then adds some additional optimizations to it.This patchset applies to next-20250929 and is targeting 6.19. Herbert, I'd prefer to just apply this myself. But let me know if you'd prefer to take it instead (considering that AES-GCM hasn't been librarified yet). Either way, there's no hurry, since this is targeting 6.19.
Eric Biggers (8):
crypto: x86/aes-gcm - add VAES+AVX2 optimized code
crypto: x86/aes-gcm - remove VAES+AVX10/256 optimized code
crypto: x86/aes-gcm - rename avx10 andavx10_512to avx512
crypto: x86/aes-gcm - clean up AVX512 code to assume 512-bit vectors
crypto: x86/aes-gcm - reorder AVX512 precompute andaad_update
functions
crypto: x86/aes-gcm - revise some comments in AVX512 code
crypto: x86/aes-gcm - optimize AVX512 precomputation of H^2 from H^1
crypto: x86/aes-gcm - optimize long AAD processing with AVX512arch/x86/crypto/Makefile | 5 +- arch/x86/crypto/aes-gcm-aesni-x86_64.S | 12 +- arch/x86/crypto/aes-gcm-vaes-avx2.S | 1150 +++++++++++++++++ ...m-avx10-x86_64.S => aes-gcm-vaes-avx512.S} | 722 +++++------ arch/x86/crypto/aesni-intel_glue.c | 264 ++-- 5 files changed, 1667 insertions(+), 486 deletions(-) create mode 100644 arch/x86/crypto/aes-gcm-vaes-avx2.S rename arch/x86/crypto/{aes-gcm-avx10-x86_64.S => aes-gcm-vaes-avx512.S} (69%)Quoted 6 lines
Quoted 6 lines
Quoted 3 lines
Quoted 1 line
base-commit:
3b9b1f8df454caa453c7fb07689064edb2eda90aApplied to https://git.kernel.org/pub/scm/linux/kernel/git/ebiggers/linux.git/log/?h=libcrypto-next
Oops, I didn't see this email until it was too late. Since the patches should be identical I don't think it matters.
Well, it seems you didn't read the patchset (even the cover letter) or any of the replies to it. So maybe I should just take it, as I already said I preferred, and later did do since you hadn't said you wanted to take it. It would have been okay if you had volunteered to take this, but you need to actually read the patches and replies.
Quoted 4 lines
As for the patches being identical, besides correctly applying Ard's tags, I made a couple very minor changes that weren't worth sending a v2
for: clarifying one of the commit messages, and correcting two comments and dropping some unused aliases fromaes-gcm-vaes-avx2.S.
And to be clear, these aren't going to go through two trees. That would be silly. If you really want to take them after all, then ask me to drop them first, and make sure to apply them properly with Acked-by and Tested-by tags. Otherwise, please drop your duplicate copy.
Thanks,
- Eric
Herbert Xu
maintainerQuoted 6 lines · Eric Biggers
Well, it seems you didn't read the patchset (even the cover letter) or any of the replies to it. So maybe I should just take it, as I already said I preferred, and later did do since you hadn't said you wanted to take it. It would have been okay if you had volunteered to take this, but you need to actually read the patches and replies.
The reason I didn't see your cover-letter is because you didn't send it to me. Your To/CC list was:
To: [email protected]
Cc: [email protected],
[email protected],
Ard Biesheuvel <[email protected]>,
"Jason A . Donenfeld" <[email protected]>,
Eric Biggers <[email protected]>
So all I get is the patches without the cover letter. Of course anybody who replies to the cover letter won't be visible to me either.
Please consider adding my email address to the Cc list next time.
I will drop this patch-set.
Cheers,
Signature · 3 lines
Email: Herbert Xu <[email protected]> Home Page: http://gondor.apana.org.au/~herbert/ PGP Key: http://gondor.apana.org.au/~herbert/pubkey.txt
Quoted 18 lines · Herbert Xu
Quoted 6 lines · Eric Biggers
Well, it seems you didn't read the patchset (even the cover letter) or any of the replies to it. So maybe I should just take it, as I already said I preferred, and later did do since you hadn't said you wanted to take it. It would have been okay if you had volunteered to take this, but you need to actually read the patches and replies.
The reason I didn't see your cover-letter is because you didn't send it to me. Your To/CC list was:
To: [email protected]
Cc: [email protected],
[email protected],
Ard Biesheuvel <[email protected]>,
"Jason A . Donenfeld" <[email protected]>,
Eric Biggers <[email protected]>
Quoted 5 lines
So all I get is the patches without the cover letter. Of course anybody who replies to the cover letter won't be visible to me either.
Please consider adding my email address to the Cc list next time.
Well, one would think you would be subscribed to linux-crypto. But whatever, I'll Cc you explicitly on future patches.
Quoted 1 line
I will drop this patch-set.
Thanks,
- Eric
Herbert Xu
maintainerQuoted 3 lines · Eric Biggers
Well, one would think you would be subscribed to linux-crypto. But whatever, I'll Cc you explicitly on future patches.
I never said that I'm not subscribed to linux-crypto. I will eventually see it, but it could be too late if you wanted me to action on an item that's only in the cover letter.
Thanks,
Signature · 3 lines
Email: Herbert Xu <[email protected]> Home Page: http://gondor.apana.org.au/~herbert/ PGP Key: http://gondor.apana.org.au/~herbert/pubkey.txt
Herbert Xu
maintainerQuoted 31 lines · Eric Biggers
This patchset replaces the 256-bit vector implementation of AES-GCM for
x86_64with one that requires AVX2 rather than AVX512. This greatly improves AES-GCM performance on CPUs that have VAES but not AVX512, for example by up to 74% on AMD Zen 3. For more details, see patch 1.This patchset also renames the 512-bit vector implementation of AES-GCM for
x86_64to be named after AVX512 rather than AVX10/512, then adds some additional optimizations to it.This patchset applies to next-20250929 and is targeting 6.19. Herbert, I'd prefer to just apply this myself. But let me know if you'd prefer to take it instead (considering that AES-GCM hasn't been librarified yet). Either way, there's no hurry, since this is targeting 6.19.
Eric Biggers (8):
crypto: x86/aes-gcm - add VAES+AVX2 optimized code
crypto: x86/aes-gcm - remove VAES+AVX10/256 optimized code
crypto: x86/aes-gcm - rename avx10 andavx10_512to avx512
crypto: x86/aes-gcm - clean up AVX512 code to assume 512-bit vectors
crypto: x86/aes-gcm - reorder AVX512 precompute andaad_update
functions
crypto: x86/aes-gcm - revise some comments in AVX512 code
crypto: x86/aes-gcm - optimize AVX512 precomputation of H^2 from H^1
crypto: x86/aes-gcm - optimize long AAD processing with AVX512arch/x86/crypto/Makefile | 5 +- arch/x86/crypto/aes-gcm-aesni-x86_64.S | 12 +- arch/x86/crypto/aes-gcm-vaes-avx2.S | 1150 +++++++++++++++++ ...m-avx10-x86_64.S => aes-gcm-vaes-avx512.S} | 722 +++++------ arch/x86/crypto/aesni-intel_glue.c | 264 ++-- 5 files changed, 1667 insertions(+), 486 deletions(-)
Quoted 4 lines
create mode 100644
arch/x86/crypto/aes-gcm-vaes-avx2.S
renamearch/x86/crypto/{aes-gcm-avx10-x86_64.S=>aes-gcm-vaes-avx512.S} (69%)base-commit:
3b9b1f8df454caa453c7fb07689064edb2eda90a
All applied. Thanks.
Signature · 3 lines
Email: Herbert Xu <[email protected]> Home Page: http://gondor.apana.org.au/~herbert/ PGP Key: http://gondor.apana.org.au/~herbert/pubkey.txt