Skip to content

Commit 31b160f

Browse files
ICP: Improve AES-GCM performance
Currently SIMD accelerated AES-GCM performance is limited by two factors: a. The need to disable preemption and interrupts and save the FPU state before using it and to do the reverse when done. Due to the way the code is organized (see (b) below) we have to pay this price twice for each 16 byte GCM block processed. b. Most processing is done in C, operating on single GCM blocks. The use of SIMD instructions is limited to the AES encryption of the counter block (AES-NI) and the Galois multiplication (PCLMULQDQ). This leads to the FPU not being fully utilized for crypto operations. To solve (a) we do crypto processing in larger chunks while owning the FPU. An `icp_gcm_avx_chunk_size` module parameter was introduced to make this chunk size tweakable. It defaults to 32 KiB. This step alone roughly doubles performance. (b) is tackled by porting and using the highly optimized openssl AES-GCM assembler routines, which do all the processing (CTR, AES, GMULT) in a single routine. Both steps together result in up to 32x reduction of the time spend in the en/decryption routines, leading up to approximately 12x throughput increase for large (128 KiB) blocks. Lastly, this commit changes the default encryption algorithm from AES-CCM to AES-GCM when setting the `encryption=on` property. Reviewed-By: Brian Behlendorf <[email protected]> Reviewed-By: Jason King <[email protected]> Reviewed-By: Tom Caputi <[email protected]> Reviewed-By: Richard Laager <[email protected]> Signed-off-by: Attila Fülöp <[email protected]> Closes openzfs#9749
1 parent fa3922d commit 31b160f

File tree

20 files changed

+2654
-31
lines changed

20 files changed

+2654
-31
lines changed

COPYRIGHT

+4
Original file line numberDiff line numberDiff line change
@@ -20,6 +20,10 @@ notable exceptions and their respective licenses include:
2020
* AES Implementation: module/icp/asm-x86_64/aes/THIRDPARTYLICENSE.openssl
2121
* PBKDF2 Implementation: lib/libzfs/THIRDPARTYLICENSE.openssl
2222
* SPL Implementation: module/os/linux/spl/THIRDPARTYLICENSE.gplv2
23+
* GCM Implementaion: module/icp/asm-x86_64/modes/THIRDPARTYLICENSE.cryptogams
24+
* GCM Implementaion: module/icp/asm-x86_64/modes/THIRDPARTYLICENSE.openssl
25+
* GHASH Implementaion: module/icp/asm-x86_64/modes/THIRDPARTYLICENSE.cryptogams
26+
* GHASH Implementaion: module/icp/asm-x86_64/modes/THIRDPARTYLICENSE.openssl
2327

2428
This product includes software developed by the OpenSSL Project for use
2529
in the OpenSSL Toolkit (http://www.openssl.org/)

config/toolchain-simd.m4

+21
Original file line numberDiff line numberDiff line change
@@ -23,6 +23,7 @@ AC_DEFUN([ZFS_AC_CONFIG_ALWAYS_TOOLCHAIN_SIMD], [
2323
ZFS_AC_CONFIG_TOOLCHAIN_CAN_BUILD_AVX512VL
2424
ZFS_AC_CONFIG_TOOLCHAIN_CAN_BUILD_AES
2525
ZFS_AC_CONFIG_TOOLCHAIN_CAN_BUILD_PCLMULQDQ
26+
ZFS_AC_CONFIG_TOOLCHAIN_CAN_BUILD_MOVBE
2627
;;
2728
esac
2829
])
@@ -401,3 +402,23 @@ AC_DEFUN([ZFS_AC_CONFIG_TOOLCHAIN_CAN_BUILD_PCLMULQDQ], [
401402
AC_MSG_RESULT([no])
402403
])
403404
])
405+
406+
dnl #
407+
dnl # ZFS_AC_CONFIG_TOOLCHAIN_CAN_BUILD_MOVBE
408+
dnl #
409+
AC_DEFUN([ZFS_AC_CONFIG_TOOLCHAIN_CAN_BUILD_MOVBE], [
410+
AC_MSG_CHECKING([whether host toolchain supports MOVBE])
411+
412+
AC_LINK_IFELSE([AC_LANG_SOURCE([
413+
[
414+
void main()
415+
{
416+
__asm__ __volatile__("movbe 0(%eax), %eax");
417+
}
418+
]])], [
419+
AC_MSG_RESULT([yes])
420+
AC_DEFINE([HAVE_MOVBE], 1, [Define if host toolchain supports MOVBE])
421+
], [
422+
AC_MSG_RESULT([no])
423+
])
424+
])

include/os/linux/kernel/linux/simd_x86.h

+13
Original file line numberDiff line numberDiff line change
@@ -477,6 +477,19 @@ zfs_pclmulqdq_available(void)
477477
#endif
478478
}
479479

480+
/*
481+
* Check if MOVBE instruction is available
482+
*/
483+
static inline boolean_t
484+
zfs_movbe_available(void)
485+
{
486+
#if defined(X86_FEATURE_MOVBE)
487+
return (!!boot_cpu_has(X86_FEATURE_MOVBE));
488+
#else
489+
return (B_FALSE);
490+
#endif
491+
}
492+
480493
/*
481494
* AVX-512 family of instruction sets:
482495
*

include/sys/zio.h

+1-1
Original file line numberDiff line numberDiff line change
@@ -119,7 +119,7 @@ enum zio_encrypt {
119119
ZIO_CRYPT_FUNCTIONS
120120
};
121121

122-
#define ZIO_CRYPT_ON_VALUE ZIO_CRYPT_AES_256_CCM
122+
#define ZIO_CRYPT_ON_VALUE ZIO_CRYPT_AES_256_GCM
123123
#define ZIO_CRYPT_DEFAULT ZIO_CRYPT_OFF
124124

125125
/* macros defining encryption lengths */

lib/libicp/Makefile.am

+2
Original file line numberDiff line numberDiff line change
@@ -15,6 +15,8 @@ ASM_SOURCES_AS = \
1515
asm-x86_64/aes/aes_amd64.S \
1616
asm-x86_64/aes/aes_aesni.S \
1717
asm-x86_64/modes/gcm_pclmulqdq.S \
18+
asm-x86_64/modes/aesni-gcm-x86_64.S \
19+
asm-x86_64/modes/ghash-x86_64.S \
1820
asm-x86_64/sha1/sha1-x86_64.S \
1921
asm-x86_64/sha2/sha256_impl.S \
2022
asm-x86_64/sha2/sha512_impl.S

lib/libspl/include/sys/simd.h

+14-1
Original file line numberDiff line numberDiff line change
@@ -77,7 +77,8 @@ typedef enum cpuid_inst_sets {
7777
AVX512ER,
7878
AVX512VL,
7979
AES,
80-
PCLMULQDQ
80+
PCLMULQDQ,
81+
MOVBE
8182
} cpuid_inst_sets_t;
8283

8384
/*
@@ -101,6 +102,7 @@ typedef struct cpuid_feature_desc {
101102
#define _AVX512VL_BIT (1U << 31) /* if used also check other levels */
102103
#define _AES_BIT (1U << 25)
103104
#define _PCLMULQDQ_BIT (1U << 1)
105+
#define _MOVBE_BIT (1U << 22)
104106

105107
/*
106108
* Descriptions of supported instruction sets
@@ -128,6 +130,7 @@ static const cpuid_feature_desc_t cpuid_features[] = {
128130
[AVX512VL] = {7U, 0U, _AVX512ER_BIT, EBX },
129131
[AES] = {1U, 0U, _AES_BIT, ECX },
130132
[PCLMULQDQ] = {1U, 0U, _PCLMULQDQ_BIT, ECX },
133+
[MOVBE] = {1U, 0U, _MOVBE_BIT, ECX },
131134
};
132135

133136
/*
@@ -200,6 +203,7 @@ CPUID_FEATURE_CHECK(avx512er, AVX512ER);
200203
CPUID_FEATURE_CHECK(avx512vl, AVX512VL);
201204
CPUID_FEATURE_CHECK(aes, AES);
202205
CPUID_FEATURE_CHECK(pclmulqdq, PCLMULQDQ);
206+
CPUID_FEATURE_CHECK(movbe, MOVBE);
203207

204208
/*
205209
* Detect register set support
@@ -332,6 +336,15 @@ zfs_pclmulqdq_available(void)
332336
return (__cpuid_has_pclmulqdq());
333337
}
334338

339+
/*
340+
* Check if MOVBE instruction is available
341+
*/
342+
static inline boolean_t
343+
zfs_movbe_available(void)
344+
{
345+
return (__cpuid_has_movbe());
346+
}
347+
335348
/*
336349
* AVX-512 family of instruction sets:
337350
*

man/man8/zfsprops.8

+1-1
Original file line numberDiff line numberDiff line change
@@ -1010,7 +1010,7 @@ Selecting
10101010
.Sy encryption Ns = Ns Sy on
10111011
when creating a dataset indicates that the default encryption suite will be
10121012
selected, which is currently
1013-
.Sy aes-256-ccm .
1013+
.Sy aes-256-gcm .
10141014
In order to provide consistent data protection, encryption must be specified at
10151015
dataset creation time and it cannot be changed afterwards.
10161016
.Pp

module/icp/Makefile.in

+9
Original file line numberDiff line numberDiff line change
@@ -51,6 +51,8 @@ $(MODULE)-$(CONFIG_X86_64) += asm-x86_64/aes/aeskey.o
5151
$(MODULE)-$(CONFIG_X86_64) += asm-x86_64/aes/aes_amd64.o
5252
$(MODULE)-$(CONFIG_X86_64) += asm-x86_64/aes/aes_aesni.o
5353
$(MODULE)-$(CONFIG_X86_64) += asm-x86_64/modes/gcm_pclmulqdq.o
54+
$(MODULE)-$(CONFIG_X86_64) += asm-x86_64/modes/aesni-gcm-x86_64.o
55+
$(MODULE)-$(CONFIG_X86_64) += asm-x86_64/modes/ghash-x86_64.o
5456
$(MODULE)-$(CONFIG_X86_64) += asm-x86_64/sha1/sha1-x86_64.o
5557
$(MODULE)-$(CONFIG_X86_64) += asm-x86_64/sha2/sha256_impl.o
5658
$(MODULE)-$(CONFIG_X86_64) += asm-x86_64/sha2/sha512_impl.o
@@ -59,6 +61,13 @@ $(MODULE)-$(CONFIG_X86) += algs/modes/gcm_pclmulqdq.o
5961
$(MODULE)-$(CONFIG_X86) += algs/aes/aes_impl_aesni.o
6062
$(MODULE)-$(CONFIG_X86) += algs/aes/aes_impl_x86-64.o
6163

64+
# Suppress objtool "can't find jump dest instruction at" warnings. They
65+
# are caused by the constants which are defined in the text section of the
66+
# assembly file using .byte instructions (e.g. bswap_mask). The objtool
67+
# utility tries to interpret them as opcodes and obviously fails doing so.
68+
OBJECT_FILES_NON_STANDARD_aesni-gcm-x86_64.o := y
69+
OBJECT_FILES_NON_STANDARD_ghash-x86_64.o := y
70+
6271
ICP_DIRS = \
6372
api \
6473
core \

0 commit comments

Comments
 (0)