crypto: switch to static calls for CRC-T10DIF
Subsystems (7)
Ard Biesheuvel
reviewercover crypto: switch to static calls for CRC-T10DIF
CRC-T10DIF is a very poor match for the crypto API:
- every user in the kernel calls it via a library wrapper around the shash API, so all callers share a single instance of the transform
- each architecture provides at most a single optimized implementation, based on SIMD instructions for carryless multiplication
In other words, none of the flexibility it provides is put to good use, and so it is better to get rid of this complexity, and expose the optimized implementations via static calls instead. This removes a substantial chunk of code, and also gets rid of any indirect calls on architectures that obsess about those (x86)
If this approach is deemed suitable, there are other places where we might consider adopting it: CRC32 and CRC32(C).
Patch #1 does some preparatory refactoring and removes the library wrapper around the shash transform.
Patch #2 introduces the actual static calls, along with the registration routines to update the crc-t10dif implementation at runtime.
Patch #3 updates the generic CRC-T10DIF shash driver so it distinguishes between the optimized library code and the generic library code.
Patches #4 to #7 update the various arch implementations to switch over to the new method.
Special request to Peter to take a look at patch #2, and in particular, whether synchronize_rcu_tasks() is sufficient to ensure that a module providing the target of a static call can be unloaded safely.
Ard Biesheuvel (7):
crypto: crc-t10dif - turn library wrapper for shash into generic
library
crypto: lib/crc-t10dif - add static call support for optimized
versions
crypto: generic/crc-t10dif - expose both arch and generic shashes
crypto: x86/crc-t10dif - convert to static call library API
crypto: arm/crc-t10dif - convert to static call library API
crypto: arm64/crc-t10dif - convert to static call API
crypto: powerpc/crc-t10dif - convert to static call API
arch/arm/crypto/Kconfig | 2 +- arch/arm/crypto/crct10dif-ce-glue.c | 58 ++------ arch/arm64/crypto/Kconfig | 3 +- arch/arm64/crypto/crct10dif-ce-glue.c | 85 ++--------- arch/powerpc/crypto/crct10dif-vpmsum_glue.c | 51 +------ arch/x86/crypto/crct10dif-pclmul_glue.c | 90 ++---------- crypto/Kconfig | 7 +- crypto/Makefile | 2 +- crypto/crct10dif_common.c | 82 ----------- crypto/crct10dif_generic.c | 100 +++++++++---- include/linux/crc-t10dif.h | 21 ++- lib/Kconfig | 2 - lib/crc-t10dif.c | 152 +++++++++----------- 13 files changed, 204 insertions(+), 451 deletions(-) delete mode 100644 crypto/crct10dif_common.c
Signature · 1 line
2.17.1
Ard Biesheuvel
reviewerPATCH 1/7 crypto: crc-t10dif - turn library wrapper for shash into generic library
As a first step towards moving CRC-T10DIF out of the crypto API, drop the shash wrapping code from the library implementation, and move the generic core CRC-T10DIF into it from the generic crypto SHASH driver.
In a future patch, the library interface will be augmented with the facilities to register and unregister optimized implementations.
--- arch/arm/crypto/Kconfig | 2 +- arch/arm64/crypto/Kconfig | 3 +- crypto/Kconfig | 7 +- crypto/Makefile | 2 +- crypto/crct10dif_common.c | 82 ------------ lib/Kconfig | 2 - lib/crc-t10dif.c | 136 +++++++------------- 7 files changed, 57 insertions(+), 177 deletions(-)
arch/arm/crypto/Kconfig +1 -1
@@ -138,8 +138,8 @@ config CRYPTO_GHASH_ARM_CE config CRYPTO_CRCT10DIF_ARM_CE tristate "CRCT10DIF digest algorithm using PMULL instructions" depends on KERNEL_MODE_NEON - depends on CRC_T10DIF select CRYPTO_HASH + select CRC_T10DIF config CRYPTO_CRC32_ARM_CE tristate "CRC32(C) digest algorithm using CRC and/or PMULL instructions"
arch/arm64/crypto/Kconfig +2 -1
@@ -62,8 +62,9 @@ config CRYPTO_GHASH_ARM64_CE config CRYPTO_CRCT10DIF_ARM64_CE tristate "CRCT10DIF digest algorithm using PMULL instructions" - depends on KERNEL_MODE_NEON && CRC_T10DIF + depends on KERNEL_MODE_NEON select CRYPTO_HASH + select CRC_T10DIF config CRYPTO_AES_ARM64 tristate "AES core cipher using scalar instructions"
crypto/Kconfig +5 -2
@@ -700,6 +700,7 @@ config CRYPTO_BLAKE2S_X86 config CRYPTO_CRCT10DIF tristate "CRCT10DIF algorithm" select CRYPTO_HASH + select CRC_T10DIF help CRC T10 Data Integrity Field computation is being cast as a crypto transform. This allows for faster crc t10 diff
@@ -707,8 +708,9 @@ config CRYPTO_CRCT10DIF config CRYPTO_CRCT10DIF_PCLMUL tristate "CRCT10DIF PCLMULQDQ hardware acceleration" - depends on X86 && 64BIT && CRC_T10DIF + depends on X86 && 64BIT select CRYPTO_HASH + select CRC_T10DIF help For x86_64 processors with SSE4.2 and PCLMULQDQ supported, CRC T10 DIF PCLMULQDQ computation can be hardware
@@ -718,8 +720,9 @@ config CRYPTO_CRCT10DIF_PCLMUL config CRYPTO_CRCT10DIF_VPMSUM tristate "CRC32T10DIF powerpc64 hardware acceleration" - depends on PPC64 && ALTIVEC && CRC_T10DIF + depends on PPC64 && ALTIVEC select CRYPTO_HASH + select CRC_T10DIF help CRC10T10DIF algorithm implemented using vector polynomial multiply-sum (vpmsum) instructions, introduced in POWER8. Enable on
crypto/Makefile +1 -1
@@ -148,7 +148,7 @@ obj-$(CONFIG_CRYPTO_DEFLATE) += deflate.o obj-$(CONFIG_CRYPTO_MICHAEL_MIC) += michael_mic.o obj-$(CONFIG_CRYPTO_CRC32C) += crc32c_generic.o obj-$(CONFIG_CRYPTO_CRC32) += crc32_generic.o -obj-$(CONFIG_CRYPTO_CRCT10DIF) += crct10dif_common.o crct10dif_generic.o +obj-$(CONFIG_CRYPTO_CRCT10DIF) += crct10dif_generic.o obj-$(CONFIG_CRYPTO_AUTHENC) += authenc.o authencesn.o obj-$(CONFIG_CRYPTO_LZO) += lzo.o lzo-rle.o obj-$(CONFIG_CRYPTO_LZ4) += lz4.o
crypto/crct10dif_common.c deleted +0 -82
82 lines not on this page · raw message
lib/Kconfig +0 -2
@@ -120,8 +120,6 @@ config CRC16 config CRC_T10DIF tristate "CRC calculation for the T10 Data Integrity Field" - select CRYPTO - select CRYPTO_CRCT10DIF help This option is only needed if a module that's not in the kernel tree needs to calculate CRC checks for use with the
lib/crc-t10dif.c +48 -88
167 lines not on this page · raw message
Signature · 1 line
2.17.1
Ard Biesheuvel
reviewerPATCH 2/7 crypto: lib/crc-t10dif - add static call support for optimized versions
In reply to Ard BiesheuvelWire up the new static call facility to the CRC-T10DIF library code, so that optimized implementations can be swapped in easily, without having to rely on the complexity of the crypto API shash infrastructure.
--- include/linux/crc-t10dif.h | 21 ++++++++++++-- lib/crc-t10dif.c | 30 +++++++++++++++----- 2 files changed, 42 insertions(+), 9 deletions(-)
include/linux/crc-t10dif.h +19 -2
@@ -3,6 +3,7 @@#define _LINUX_CRC_T10DIF_H#include <linux/types.h> +#include <linux/static_call.h> #define CRC_T10DIF_DIGEST_SIZE 2#define CRC_T10DIF_BLOCK_SIZE 1
@@ -10,7 +11,23 @@extern __u16 crc_t10dif_generic (__u16 crc,const unsigned char *buffer,size_t len); -extern __u16 crc_t10dif (unsigned char const *,size_t ); -extern __u16 crc_t10dif_update (__u16 crc,unsigned char const *,size_t ); + +DECLARE_STATIC_CALL (crc_t10dif_arch, crc_t10dif_generic); + +static inline __u16 crc_t10dif_update (__u16 crc,unsigned char const *buffer, +size_t len) +{ +return static_call (crc_t10dif_arch)(crc, buffer, len); +} + +static inline __u16 crc_t10dif (unsigned char const *buffer,size_t len) +{ +return crc_t10dif_update (0 , buffer, len); +} + +int crc_t10dif_register (__u16 (*)(__u16 ,const unsigned char *,size_t ), +const char *name); + +int crc_t10dif_unregister (void );#endif
lib/crc-t10dif.c +23 -7
@@ -18,6 +18,11 @@#include <linux/static_key.h> #include <linux/notifier.h> +DEFINE_STATIC_CALL (crc_t10dif_arch, crc_t10dif_generic); +EXPORT_STATIC_CALL (crc_t10dif_arch); + +static char const *crc_t10dif_arch_name; +/* Table generated using the following polynomium: * x^16 + x^15 + x^11 + x^9 + x^8 + x^7 + x^5 + x^4 + x^2 + x + 1 * gt: 0x8bb7
@@ -68,21 +73,32 @@ __u16 crc_t10dif_generic(__u16 crc, const unsigned char *buffer, size_t len) }EXPORT_SYMBOL (crc_t10dif_generic); -__u16 crc_t10dif_update (__u16 crc,const unsigned char *buffer,size_t len) +int crc_t10dif_register (__u16 (*func)(__u16 ,const unsigned char *,size_t ), +const char *name) { -return crc_t10dif_generic (crc, buffer, len); +if (!name ||cmpxchg (&crc_t10dif_arch_name,NULL , name) !=NULL ) +return -EBUSY ; + +static_call_update (crc_t10dif_arch, func); +return 0 ; } -EXPORT_SYMBOL (crc_t10dif_update); +EXPORT_SYMBOL_NS (crc_t10dif_register,CRYPTO_INTERNAL ); -__u16 crc_t10dif (const unsigned char *buffer,size_t len) +int crc_t10dif_unregister (void ) { -return crc_t10dif_update (0 , buffer, len); +// revert to generic implementation +static_call_update (crc_t10dif_arch, crc_t10dif_generic); + crc_t10dif_arch_name =NULL ; + +// wait for all potential callers of the unregistered routine to finish +synchronize_rcu_tasks (); +return 0 ; } -EXPORT_SYMBOL (crc_t10dif); +EXPORT_SYMBOL_NS (crc_t10dif_unregister,CRYPTO_INTERNAL );static int crc_t10dif_transform_show (char *buffer,const struct kernel_param *kp) { -return sprintf (buffer,"fallback\n" ); +return sprintf (buffer,"%s\n" , crc_t10dif_arch_name ?:"fallback" ); }module_param_call (transform,NULL , crc_t10dif_transform_show,NULL ,0444 );
Signature · 1 line
2.17.1
Ard Biesheuvel
reviewerPATCH 3/7 crypto: generic/crc-t10dif - expose both arch and generic shashes
In reply to Ard BiesheuvelIn order to retain the ability to check accelerated implementations of CRC-T10DIF against the generic C implementation, expose both via the generic crypto API shash driver. This relies on the arch specific version to be registered beforehand - this will generally be the case, given that the modules in question are autoloaded via CPU feature matching, but let's use a module soft-dependency as well to trigger a load of such modules if they exist on the system.
--- crypto/crct10dif_generic.c | 100 ++++++++++++++------ 1 file changed, 72 insertions(+), 28 deletions(-)
crypto/crct10dif_generic.c +72 -28
@@ -48,8 +48,8 @@ static int chksum_init(struct shash_desc *desc)return 0 ; } -static int chksum_update (struct shash_desc *desc,const u8 *data, -unsigned int length) +static int chksum_generic_update (struct shash_desc *desc,const u8 *data, +unsigned int length) {struct chksum_desc_ctx *ctx =shash_desc_ctx (desc);
@@ -65,54 +65,97 @@ static int chksum_final(struct shash_desc *desc, u8 *out)return 0 ; } -static int __chksum_finup (__u16 crc,const u8 *data,unsigned int len,u8 *out) +static int __chksum_generic_finup (__u16 crc,const u8 *data,unsigned int len, +u8 *out) { *(__u16 *)out =crc_t10dif_generic (crc, data, len);return 0 ; } -static int chksum_finup (struct shash_desc *desc,const u8 *data, -unsigned int len,u8 *out) +static int chksum_generic_finup (struct shash_desc *desc,const u8 *data, +unsigned int len,u8 *out) {struct chksum_desc_ctx *ctx =shash_desc_ctx (desc); -return __chksum_finup (ctx->crc, data, len, out); +return __chksum_generic_finup (ctx->crc, data, len, out); } -static int chksum_digest (struct shash_desc *desc,const u8 *data, -unsigned int length,u8 *out) +static int chksum_generic_digest (struct shash_desc *desc,const u8 *data, +unsigned int length,u8 *out) { -return __chksum_finup (0 , data, length, out); +return __chksum_generic_finup (0 , data, length, out); } -static struct shash_alg alg = { - .digestsize =CRC_T10DIF_DIGEST_SIZE , - .init = chksum_init, - .update = chksum_update, - .final = chksum_final, - .finup = chksum_finup, - .digest = chksum_digest, - .descsize =sizeof (struct chksum_desc_ctx ), - .base = { - .cra_name ="crct10dif" , - .cra_driver_name ="crct10dif-generic" , - .cra_priority =100 , - .cra_blocksize =CRC_T10DIF_BLOCK_SIZE , - .cra_module =THIS_MODULE , - } -}; +static int chksum_arch_update (struct shash_desc *desc,const u8 *data, +unsigned int length) +{ +struct chksum_desc_ctx *ctx =shash_desc_ctx (desc); + + ctx->crc =crc_t10dif_update (ctx->crc, data, length); +return 0 ; +} + +static int __chksum_arch_finup (__u16 crc,const u8 *data,unsigned int len, +u8 *out) +{ + *(__u16 *)out =crc_t10dif_update (crc, data, len); +return 0 ; +} + +static int chksum_arch_finup (struct shash_desc *desc,const u8 *data, +unsigned int len,u8 *out) +{ +struct chksum_desc_ctx *ctx =shash_desc_ctx (desc); + +return __chksum_arch_finup (ctx->crc, data, len, out); +} + +static int chksum_arch_digest (struct shash_desc *desc,const u8 *data, +unsigned int length,u8 *out) +{ +return __chksum_arch_finup (0 , data, length, out); +} + +static struct shash_alg algs[] = {{ + .digestsize =CRC_T10DIF_DIGEST_SIZE , + .init = chksum_init, + .update = chksum_generic_update, + .final = chksum_final, + .finup = chksum_generic_finup, + .digest = chksum_generic_digest, + .descsize =sizeof (struct chksum_desc_ctx ), + + .base.cra_name ="crct10dif" , + .base.cra_driver_name ="crct10dif-generic" , + .base.cra_blocksize =CRC_T10DIF_BLOCK_SIZE , + .base.cra_module =THIS_MODULE , +}, { + .digestsize =CRC_T10DIF_DIGEST_SIZE , + .init = chksum_init, + .update = chksum_arch_update, + .final = chksum_final, + .finup = chksum_arch_finup, + .digest = chksum_arch_digest, + .descsize =sizeof (struct chksum_desc_ctx ), + + .base.cra_name ="crct10dif" , + .base.cra_driver_name ="crct10dif-arch" , + .base.cra_priority =100 , + .base.cra_blocksize =CRC_T10DIF_BLOCK_SIZE , + .base.cra_module =THIS_MODULE , +}};static int __init crct10dif_mod_init (void ) { -return crypto_register_shash (&alg); +return crypto_register_shashes (algs,ARRAY_SIZE (algs)); } static void __exit crct10dif_mod_fini(void) { -crypto_unregister_shash (&alg); +crypto_unregister_shashes (algs,ARRAY_SIZE (algs)); } -subsys_initcall (crct10dif_mod_init); +module_init (crct10dif_mod_init);module_exit (crct10dif_mod_fini);MODULE_AUTHOR ("Tim Chen <[email protected]>" );
@@ -120,3 +163,4 @@ MODULE_DESCRIPTION("T10 DIF CRC calculation.");MODULE_LICENSE ("GPL" );MODULE_ALIAS_CRYPTO ("crct10dif" );MODULE_ALIAS_CRYPTO ("crct10dif-generic" ); +MODULE_SOFTDEP ("pre: crct10dif-arch" );
Signature · 1 line
2.17.1
Ard Biesheuvel
reviewerPATCH 4/7 crypto: x86/crc-t10dif - convert to static call library API
In reply to Ard BiesheuvelGet rid of the shash boilerplate, and register the accelerated x86 version of the CRC-T10DIF algorithm with the library interface instead.
--- arch/x86/crypto/crct10dif-pclmul_glue.c | 90 +++----------------- 1 file changed, 10 insertions(+), 80 deletions(-)
arch/x86/crypto/crct10dif-pclmul_glue.c +10 -80
@@ -25,7 +25,6 @@#include <linux/types.h> #include <linux/module.h> #include <linux/crc-t10dif.h> -#include <crypto/internal/hash.h> #include <crypto/internal/simd.h> #include <linux/init.h> #include <linux/string.h>
@@ -36,82 +35,17 @@ asmlinkage u16 crc_t10dif_pcl(u16 init_crc, const u8 *buf, size_t len); -struct chksum_desc_ctx { -__u16 crc; -}; - -static int chksum_init (struct shash_desc *desc) -{ -struct chksum_desc_ctx *ctx =shash_desc_ctx (desc); - - ctx->crc =0 ; - -return 0 ; -} - -static int chksum_update (struct shash_desc *desc,const u8 *data, -unsigned int length) -{ -struct chksum_desc_ctx *ctx =shash_desc_ctx (desc); - -if (length >=16 &&crypto_simd_usable ()) { -kernel_fpu_begin (); - ctx->crc =crc_t10dif_pcl (ctx->crc, data, length); -kernel_fpu_end (); - }else - ctx->crc =crc_t10dif_generic (ctx->crc, data, length); -return 0 ; -} - -static int chksum_final (struct shash_desc *desc,u8 *out) -{ -struct chksum_desc_ctx *ctx =shash_desc_ctx (desc); - - *(__u16 *)out = ctx->crc; -return 0 ; -} - -static int __chksum_finup (__u16 crc,const u8 *data,unsigned int len,u8 *out) +static u16 crc_t10dif_x86 (u16 crc,const u8 *data,size_t len) {if (len >=16 &&crypto_simd_usable ()) {kernel_fpu_begin (); - *(__u16 *)out =crc_t10dif_pcl (crc, data, len); + crc =crc_t10dif_pcl (crc, data, len);kernel_fpu_end (); - }else - *(__u16 *)out =crc_t10dif_generic (crc, data, len); -return 0 ; -} - -static int chksum_finup (struct shash_desc *desc,const u8 *data, -unsigned int len,u8 *out) -{ -struct chksum_desc_ctx *ctx =shash_desc_ctx (desc); - -return __chksum_finup (ctx->crc, data, len, out); -} - -static int chksum_digest (struct shash_desc *desc,const u8 *data, -unsigned int length,u8 *out) -{ -return __chksum_finup (0 , data, length, out); -} - -static struct shash_alg alg = { - .digestsize =CRC_T10DIF_DIGEST_SIZE , - .init = chksum_init, - .update = chksum_update, - .final = chksum_final, - .finup = chksum_finup, - .digest = chksum_digest, - .descsize =sizeof (struct chksum_desc_ctx ), - .base = { - .cra_name ="crct10dif" , - .cra_driver_name ="crct10dif-pclmul" , - .cra_priority =200 , - .cra_blocksize =CRC_T10DIF_BLOCK_SIZE , - .cra_module =THIS_MODULE , + }else { + crc =crc_t10dif_generic (crc, data, len); } -}; +return crc; +}static const struct x86_cpu_id crct10dif_cpu_id[] = {X86_MATCH_FEATURE (X86_FEATURE_PCLMULQDQ ,NULL ),
@@ -121,15 +55,12 @@ MODULE_DEVICE_TABLE(x86cpu, crct10dif_cpu_id);static int __init crct10dif_intel_mod_init (void ) { -if (!x86_match_cpu (crct10dif_cpu_id)) -return -ENODEV ; - -return crypto_register_shash (&alg); +return crc_t10dif_register (crc_t10dif_x86,"crct10dif-pclmul" ); } static void __exit crct10dif_intel_mod_fini(void) { -crypto_unregister_shash (&alg); +crc_t10dif_unregister (); }module_init (crct10dif_intel_mod_init);
@@ -138,6 +69,5 @@ module_exit(crct10dif_intel_mod_fini);MODULE_AUTHOR ("Tim Chen <[email protected]>" );MODULE_DESCRIPTION ("T10 DIF CRC calculation accelerated with PCLMULQDQ." );MODULE_LICENSE ("GPL" ); - -MODULE_ALIAS_CRYPTO ("crct10dif" ); -MODULE_ALIAS_CRYPTO ("crct10dif-pclmul" ); +MODULE_ALIAS ("crct10dif-arch" ); +MODULE_IMPORT_NS (CRYPTO_INTERNAL );
Signature · 1 line
2.17.1
kernel test robot
build botRe: [PATCH 4/7] crypto: x86/crc-t10dif - convert to static call library API
I love your patch! Perhaps something to improve:
Hi Ard,
I love your patch! Perhaps something to improve:
[auto build test WARNING on cryptodev/master]
[also build test WARNING on crypto/master linus/master v5.11-rc3 next-20210111] [If your patch is applied to the wrong git tree, kindly drop us a note. And when submitting patch, we suggest to use '--base' as documented in
https://git-scm.com/docs/git-format-patch]
url: https://github.com/0day-ci/linux/commits/Ard-Biesheuvel/crypto-switch-to-static-calls-for-CRC-T10DIF/20210112-005632 base: https://git.kernel.org/pub/scm/linux/kernel/git/herbert/cryptodev-2.6.git master config: x86_64-randconfig-a012-20210111 (attached as .config) compiler: clang version 12.0.0 (https://github.com/llvm/llvm-project 7be3285248bf54d0784a76174cf44cf7c1e780a5)
reproduce (this is a W=1 build):
wget https://raw.githubusercontent.com/intel/lkp-tests/master/sbin/make.cross -O ~/bin/make.cross chmod +x ~/bin/make.cross
# install x86_64 cross compiling tool for clang build
# apt-get install binutils-x86-64-linux-gnu
# https://github.com/0day-ci/linux/commit/df3e7f87b3c1edc4daace5f5df09d9a1896b97dc
git remote add linux-review https://github.com/0day-ci/linux
git fetch --no-tags linux-review Ard-Biesheuvel/crypto-switch-to-static-calls-for-CRC-T10DIF/20210112-005632 git checkout df3e7f87b3c1edc4daace5f5df09d9a1896b97dc
# save the attached .config to linux build tree
COMPILER_INSTALL_PATH=$HOME/0day COMPILER=clang make.cross ARCH=x86_64
If you fix the issue, kindly add following tag as appropriate
All warnings (new ones prefixed by >>):
>> arch/x86/crypto/crct10dif-pclmul_glue.c:50:32: warning: unused variable 'crct10dif_cpu_id' [-Wunused-const-variable]
static const struct x86_cpu_id crct10dif_cpu_id[] = {
^1 warning generated.
vim +/crct10dif_cpu_id +50 arch/x86/crypto/crct10dif-pclmul_glue.c
68411521cc6055ed Herbert Xu 2013-09-07 49
68411521cc6055ed Herbert Xu 2013-09-07 @50 static const struct x86_cpu_id crct10dif_cpu_id[] = {
f30cfacad1ee948c Thomas Gleixner 2020-03-20 51 X86_MATCH_FEATURE(X86_FEATURE_PCLMULQDQ, NULL),
68411521cc6055ed Herbert Xu 2013-09-07 52 {}
68411521cc6055ed Herbert Xu 2013-09-07 53 };
68411521cc6055ed Herbert Xu 2013-09-07 54 MODULE_DEVICE_TABLE(x86cpu, crct10dif_cpu_id);68411521cc6055ed Herbert Xu 2013-09-07 55
---
0-DAY CI Kernel Test Service, Intel Corporation
https://lists.01.org/hyperkitty/list/kbuild-all(a)lists.01.org
Ard Biesheuvel
reviewerPATCH 5/7 crypto: arm/crc-t10dif - convert to static call library API
In reply to Ard BiesheuvelGet rid of the shash boilerplate, and register the accelerated ARM version of the CRC-T10DIF algorithm with the library interface instead.
--- arch/arm/crypto/crct10dif-ce-glue.c | 58 ++++---------------- 1 file changed, 11 insertions(+), 47 deletions(-)
arch/arm/crypto/crct10dif-ce-glue.c +11 -47
@@ -5,13 +5,13 @@* Copyright (C) 2016 Linaro Ltd <[email protected]> */ +#include <linux/cpufeature.h> #include <linux/crc-t10dif.h> #include <linux/init.h> #include <linux/kernel.h> #include <linux/module.h> #include <linux/string.h> -#include <crypto/internal/hash.h> #include <crypto/internal/simd.h> #include <asm/neon.h>
@@ -21,68 +21,32 @@ asmlinkage u16 crc_t10dif_pmull(u16 init_crc, const u8 *buf, size_t len); -static int crct10dif_init (struct shash_desc *desc) +static u16 crc_t10dif_arm (u16 crc,const u8 *data,size_t len) { -u16 *crc =shash_desc_ctx (desc); - - *crc =0 ; -return 0 ; -} - -static int crct10dif_update (struct shash_desc *desc,const u8 *data, -unsigned int length) -{ -u16 *crc =shash_desc_ctx (desc); - -if (length >=CRC_T10DIF_PMULL_CHUNK_SIZE &&crypto_simd_usable ()) { +if (len >=CRC_T10DIF_PMULL_CHUNK_SIZE &&crypto_simd_usable ()) {kernel_neon_begin (); - *crc =crc_t10dif_pmull (*crc, data, length); + crc =crc_t10dif_pmull (crc, data, len);kernel_neon_end (); }else { - *crc =crc_t10dif_generic (*crc, data, length); + crc =crc_t10dif_generic (crc, data, len); } - -return 0 ; +return crc; } -static int crct10dif_final (struct shash_desc *desc,u8 *out) -{ -u16 *crc =shash_desc_ctx (desc); - - *(u16 *)out = *crc; -return 0 ; -} - -static struct shash_alg crc_t10dif_alg = { - .digestsize =CRC_T10DIF_DIGEST_SIZE , - .init = crct10dif_init, - .update = crct10dif_update, - .final = crct10dif_final, - .descsize =CRC_T10DIF_DIGEST_SIZE , - - .base.cra_name ="crct10dif" , - .base.cra_driver_name ="crct10dif-arm-ce" , - .base.cra_priority =200 , - .base.cra_blocksize =CRC_T10DIF_BLOCK_SIZE , - .base.cra_module =THIS_MODULE , -}; -static int __init crc_t10dif_mod_init (void ) { -if (!(elf_hwcap2 &HWCAP2_PMULL )) -return -ENODEV ; - -return crypto_register_shash (&crc_t10dif_alg); +return crc_t10dif_register (crc_t10dif_arm,"crct10dif-arm-ce" ); } static void __exit crc_t10dif_mod_exit(void) { -crypto_unregister_shash (&crc_t10dif_alg); +crc_t10dif_unregister (); } -module_init (crc_t10dif_mod_init); +module_cpu_feature_match (PMULL , crc_t10dif_mod_init);module_exit (crc_t10dif_mod_exit);MODULE_AUTHOR ("Ard Biesheuvel <[email protected]>" );MODULE_LICENSE ("GPL v2" ); -MODULE_ALIAS_CRYPTO ("crct10dif" ); +MODULE_ALIAS ("crct10dif-arch" ); +MODULE_IMPORT_NS (CRYPTO_INTERNAL );
Signature · 1 line
2.17.1
Ard Biesheuvel
reviewerPATCH 6/7 crypto: arm64/crc-t10dif - convert to static call API
In reply to Ard BiesheuvelGet rid of the shash boilerplate, and register the accelerated arm64 version of the CRC-T10DIF algorithm with the library interface instead.
--- arch/arm64/crypto/crct10dif-ce-glue.c | 85 ++++---------------- 1 file changed, 15 insertions(+), 70 deletions(-)
arch/arm64/crypto/crct10dif-ce-glue.c +15 -70
@@ -12,7 +12,6 @@#include <linux/module.h> #include <linux/string.h> -#include <crypto/internal/hash.h> #include <crypto/internal/simd.h> #include <asm/neon.h>
@@ -23,97 +22,43 @@ asmlinkage u16 crc_t10dif_pmull_p8(u16 init_crc, const u8 *buf, size_t len); asmlinkage u16 crc_t10dif_pmull_p64(u16 init_crc, const u8 *buf, size_t len); -static int crct10dif_init (struct shash_desc *desc) +static u16 crct10dif_update_pmull_p8 (u16 crc,const u8 *data,size_t length) { -u16 *crc =shash_desc_ctx (desc); - - *crc =0 ; -return 0 ; -} - -static int crct10dif_update_pmull_p8 (struct shash_desc *desc,const u8 *data, -unsigned int length) -{ -u16 *crc =shash_desc_ctx (desc); -if (length >=CRC_T10DIF_PMULL_CHUNK_SIZE &&crypto_simd_usable ()) {kernel_neon_begin (); - *crc =crc_t10dif_pmull_p8 (*crc, data, length); + crc =crc_t10dif_pmull_p8 (crc, data, length);kernel_neon_end (); }else { - *crc =crc_t10dif_generic (*crc, data, length); + crc =crc_t10dif_generic (crc, data, length); } - -return 0 ; +return crc; } -static int crct10dif_update_pmull_p64 (struct shash_desc *desc,const u8 *data, -unsigned int length) +static u16 crct10dif_update_pmull_p64 (u16 crc,const u8 *data,size_t length) { -u16 *crc =shash_desc_ctx (desc); -if (length >=CRC_T10DIF_PMULL_CHUNK_SIZE &&crypto_simd_usable ()) {kernel_neon_begin (); - *crc =crc_t10dif_pmull_p64 (*crc, data, length); + crc =crc_t10dif_pmull_p64 (crc, data, length);kernel_neon_end (); }else { - *crc =crc_t10dif_generic (*crc, data, length); + crc =crc_t10dif_generic (crc, data, length); } - -return 0 ; +return crc; } -static int crct10dif_final (struct shash_desc *desc,u8 *out) -{ -u16 *crc =shash_desc_ctx (desc); - - *(u16 *)out = *crc; -return 0 ; -} - -static struct shash_alg crc_t10dif_alg[] = {{ - .digestsize =CRC_T10DIF_DIGEST_SIZE , - .init = crct10dif_init, - .update = crct10dif_update_pmull_p8, - .final = crct10dif_final, - .descsize =CRC_T10DIF_DIGEST_SIZE , - - .base.cra_name ="crct10dif" , - .base.cra_driver_name ="crct10dif-arm64-neon" , - .base.cra_priority =100 , - .base.cra_blocksize =CRC_T10DIF_BLOCK_SIZE , - .base.cra_module =THIS_MODULE , -}, { - .digestsize =CRC_T10DIF_DIGEST_SIZE , - .init = crct10dif_init, - .update = crct10dif_update_pmull_p64, - .final = crct10dif_final, - .descsize =CRC_T10DIF_DIGEST_SIZE , - - .base.cra_name ="crct10dif" , - .base.cra_driver_name ="crct10dif-arm64-ce" , - .base.cra_priority =200 , - .base.cra_blocksize =CRC_T10DIF_BLOCK_SIZE , - .base.cra_module =THIS_MODULE , -}}; -static int __init crc_t10dif_mod_init (void ) {if (cpu_have_named_feature (PMULL )) -return crypto_register_shashes (crc_t10dif_alg, -ARRAY_SIZE (crc_t10dif_alg)); +return crc_t10dif_register (crct10dif_update_pmull_p64, +"crct10dif-arm64-ce" );else -/* only register the first array element */ -return crypto_register_shash (crc_t10dif_alg); +return crc_t10dif_register (crct10dif_update_pmull_p8, +"crct10dif-arm64-neon" ); } static void __exit crc_t10dif_mod_exit(void) { -if (cpu_have_named_feature (PMULL )) -crypto_unregister_shashes (crc_t10dif_alg, -ARRAY_SIZE (crc_t10dif_alg)); -else -crypto_unregister_shash (crc_t10dif_alg); +crc_t10dif_unregister (); }module_cpu_feature_match (ASIMD , crc_t10dif_mod_init);
@@ -121,5 +66,5 @@ module_exit(crc_t10dif_mod_exit);MODULE_AUTHOR ("Ard Biesheuvel <[email protected]>" );MODULE_LICENSE ("GPL v2" ); -MODULE_ALIAS_CRYPTO ("crct10dif" ); -MODULE_ALIAS_CRYPTO ("crct10dif-arm64-ce" ); +MODULE_ALIAS ("crct10dif-arch" ); +MODULE_IMPORT_NS (CRYPTO_INTERNAL );
Signature · 1 line
2.17.1
Ard Biesheuvel
reviewerPATCH 7/7 crypto: powerpc/crc-t10dif - convert to static call API
In reply to Ard BiesheuvelGet rid of the shash boilerplate, and register the accelerated PowerPC version of the CRC-T10DIF algorithm with the library interface instead.
--- arch/powerpc/crypto/crct10dif-vpmsum_glue.c | 51 ++------------------ 1 file changed, 4 insertions(+), 47 deletions(-)
arch/powerpc/crypto/crct10dif-vpmsum_glue.c +4 -47
@@ -7,7 +7,6 @@*/ #include <linux/crc-t10dif.h> -#include <crypto/internal/hash.h> #include <crypto/internal/simd.h> #include <linux/init.h> #include <linux/module.h>
@@ -61,59 +60,17 @@ static u16 crct10dif_vpmsum(u16 crci, unsigned char const *p, size_t len)return crc &0xffff ; } -static int crct10dif_vpmsum_init (struct shash_desc *desc) -{ -u16 *crc =shash_desc_ctx (desc); - - *crc =0 ; -return 0 ; -} - -static int crct10dif_vpmsum_update (struct shash_desc *desc,const u8 *data, -unsigned int length) -{ -u16 *crc =shash_desc_ctx (desc); - - *crc =crct10dif_vpmsum (*crc, data, length); - -return 0 ; -} - - -static int crct10dif_vpmsum_final (struct shash_desc *desc,u8 *out) -{ -u16 *crcp =shash_desc_ctx (desc); - - *(u16 *)out = *crcp; -return 0 ; -} - -static struct shash_alg alg = { - .init = crct10dif_vpmsum_init, - .update = crct10dif_vpmsum_update, - .final = crct10dif_vpmsum_final, - .descsize =CRC_T10DIF_DIGEST_SIZE , - .digestsize =CRC_T10DIF_DIGEST_SIZE , - .base = { - .cra_name ="crct10dif" , - .cra_driver_name ="crct10dif-vpmsum" , - .cra_priority =200 , - .cra_blocksize =CRC_T10DIF_BLOCK_SIZE , - .cra_module =THIS_MODULE , - } -}; -static int __init crct10dif_vpmsum_mod_init (void ) {if (!cpu_has_feature (CPU_FTR_ARCH_207S ))return -ENODEV ; -return crypto_register_shash (&alg); +return crc_t10dif_register (crct10dif_vpmsum,"crct10dif-vpmsum" ); } static void __exit crct10dif_vpmsum_mod_fini(void) { -crypto_unregister_shash (&alg); +crc_t10dif_unregister (); }module_cpu_feature_match (PPC_MODULE_FEATURE_VEC_CRYPTO , crct10dif_vpmsum_mod_init);
@@ -122,5 +79,5 @@ module_exit(crct10dif_vpmsum_mod_fini);MODULE_AUTHOR ("Daniel Axtens <[email protected]>" );MODULE_DESCRIPTION ("CRCT10DIF using vector polynomial multiply-sum instructions" );MODULE_LICENSE ("GPL" ); -MODULE_ALIAS_CRYPTO ("crct10dif" ); -MODULE_ALIAS_CRYPTO ("crct10dif-vpmsum" ); +MODULE_ALIAS ("crct10dif-arch" ); +MODULE_IMPORT_NS (CRYPTO_INTERNAL );
Signature · 1 line
2.17.1
Ard Biesheuvel
reviewerQuoted 25 lines · Ard Biesheuvel
CRC-T10DIF is a very poor match for the crypto API:
- every user in the kernel calls it via a library wrapper around the shash API, so all callers share a single instance of the transform
- each architecture provides at most a single optimized implementation, based on SIMD instructions for carryless multiplicationIn other words, none of the flexibility it provides is put to good use, and so it is better to get rid of this complexity, and expose the optimized implementations via static calls instead. This removes a substantial chunk of code, and also gets rid of any indirect calls on architectures that obsess about those (x86)
If this approach is deemed suitable, there are other places where we might consider adopting it: CRC32 and CRC32(C).
Patch #1 does some preparatory refactoring and removes the library wrapper around the shash transform.
Patch #2 introduces the actual static calls, along with the registration routines to update the crc-t10dif implementation at runtime.
Patch #3 updates the generic CRC-T10DIF shash driver so it distinguishes between the optimized library code and the generic library code.
Quoted 7 lines
Patches #4 to #7 update the various arch implementations to switch over to the new method.
Special request to Peter to take a look at patch #2, and in particular, whether
synchronize_rcu_tasks()is sufficient to ensure that a module providing the target of a static call can be unloaded safely.
It seems I may have managed to confuse myself slightly here: without an upper bound on the size of the input of the crc_t10dif() routine, I suppose we can never assume that all its callers have finished.
Insights welcome ...
Ard Biesheuvel
reviewerQuoted 30 lines · Ard Biesheuvel
Quoted 28 lines · Ard Biesheuvel
CRC-T10DIF is a very poor match for the crypto API:
- every user in the kernel calls it via a library wrapper around the shash API, so all callers share a single instance of the transform
- each architecture provides at most a single optimized implementation, based on SIMD instructions for carryless multiplicationIn other words, none of the flexibility it provides is put to good use, and so it is better to get rid of this complexity, and expose the optimized implementations via static calls instead. This removes a substantial chunk of code, and also gets rid of any indirect calls on architectures that obsess about those (x86)
If this approach is deemed suitable, there are other places where we might consider adopting it: CRC32 and CRC32(C).
Patch #1 does some preparatory refactoring and removes the library wrapper around the shash transform.
Patch #2 introduces the actual static calls, along with the registration routines to update the crc-t10dif implementation at runtime.
Patch #3 updates the generic CRC-T10DIF shash driver so it distinguishes between the optimized library code and the generic library code.
Patches #4 to #7 update the various arch implementations to switch over to the new method.
Quoted 9 lines
Quoted 4 lines
Special request to Peter to take a look at patch #2, and in particular, whether
synchronize_rcu_tasks()is sufficient to ensure that a module providing the target of a static call can be unloaded safely.It seems I may have managed to confuse myself slightly here: without an upper bound on the size of the input of the
crc_t10dif()routine, I suppose we can never assume that all its callers have finished.
Replying to self again - apologies.
I think this is actually correct after all: synchronize_rcu_tasks() guarantees that all tasks have passed through a 'safe state', i.e., voluntary schedule(), return to userland, etc, which guarantees that no task could be executing the old static call target after synchronize_rcu_tasks() returns.
Quoted 12 lines · Ard Biesheuvel
Quoted 10 lines · Ard Biesheuvel
Quoted 3 lines · Ard Biesheuvel
Special request to Peter to take a look at patch #2, and in particular, whether
synchronize_rcu_tasks()is sufficient to ensure that a module providing the target of a static call can be unloaded safely.It seems I may have managed to confuse myself slightly here: without an upper bound on the size of the input of the
crc_t10dif()routine, I suppose we can never assume that all its callers have finished.
Quoted 7 lines
Replying to self again - apologies.
I think this is actually correct after all:
synchronize_rcu_tasks()guarantees that all tasks have passed through a 'safe state', i.e., voluntaryschedule(), return to userland, etc, which guarantees that no task could be executing the old static call target aftersynchronize_rcu_tasks()returns.
Right, I think it should work.
My initial question was why you'd want to support the unreg at all. AFAICT these implementations are tiny, why bother having them as a module, or if you insist having them as a module, why allowing removal?
Ard Biesheuvel
reviewerQuoted 22 lines · Peter Zijlstra
Quoted 12 lines · Ard Biesheuvel
Quoted 10 lines · Ard Biesheuvel
Quoted 3 lines · Ard Biesheuvel
Special request to Peter to take a look at patch #2, and in particular, whether
synchronize_rcu_tasks()is sufficient to ensure that a module providing the target of a static call can be unloaded safely.It seems I may have managed to confuse myself slightly here: without an upper bound on the size of the input of the
crc_t10dif()routine, I suppose we can never assume that all its callers have finished.Quoted 7 lines
Replying to self again - apologies.
I think this is actually correct after all:
synchronize_rcu_tasks()guarantees that all tasks have passed through a 'safe state', i.e., voluntaryschedule(), return to userland, etc, which guarantees that no task could be executing the old static call target aftersynchronize_rcu_tasks()returns.
Quoted 5 lines
Right, I think it should work.
My initial question was why you'd want to support the unreg at all. AFAICT these implementations are tiny, why bother having them as a module, or if you insist having them as a module, why allowing removal?
Yeah, good question.
Having the accelerated version as a module makes sense imo: it will only be loaded if it is supported on the system, and it can be blacklisted by the user if it does not want it for any reason. Unload is just for completeness/symmetry, but it is unlikely to be crucial to anyone in practice.
In any case, thanks for confirming - if this looks sane to you then we may be able to use this pattern in other places as well.
Eric Biggers
maintainerQuoted 46 lines · Ard Biesheuvel
CRC-T10DIF is a very poor match for the crypto API:
- every user in the kernel calls it via a library wrapper around the shash API, so all callers share a single instance of the transform
- each architecture provides at most a single optimized implementation, based on SIMD instructions for carryless multiplicationIn other words, none of the flexibility it provides is put to good use, and so it is better to get rid of this complexity, and expose the optimized implementations via static calls instead. This removes a substantial chunk of code, and also gets rid of any indirect calls on architectures that obsess about those (x86)
If this approach is deemed suitable, there are other places where we might consider adopting it: CRC32 and CRC32(C).
Patch #1 does some preparatory refactoring and removes the library wrapper around the shash transform.
Patch #2 introduces the actual static calls, along with the registration routines to update the crc-t10dif implementation at runtime.
Patch #3 updates the generic CRC-T10DIF shash driver so it distinguishes between the optimized library code and the generic library code.
Patches #4 to #7 update the various arch implementations to switch over to the new method.
Special request to Peter to take a look at patch #2, and in particular, whether
synchronize_rcu_tasks()is sufficient to ensure that a module providing the target of a static call can be unloaded safely.Cc "Martin K. Petersen" <[email protected]>Cc Eric Biggers <[email protected]>Cc Peter Zijlstra <[email protected]>Ard Biesheuvel (7):
crypto: crc-t10dif - turn library wrapper for shash into generic
library
crypto:lib/crc-t10dif- add static call support for optimized
versions
crypto: generic/crc-t10dif - expose both arch and generic shashes
crypto: x86/crc-t10dif - convert to static call library API
crypto: arm/crc-t10dif - convert to static call library API
crypto: arm64/crc-t10dif - convert to static call API
crypto: powerpc/crc-t10dif - convert to static call API
Quoted 15 lines
arch/arm/crypto/Kconfig | 2 +- arch/arm/crypto/crct10dif-ce-glue.c | 58 ++------ arch/arm64/crypto/Kconfig | 3 +- arch/arm64/crypto/crct10dif-ce-glue.c | 85 ++--------- arch/powerpc/crypto/crct10dif-vpmsum_glue.c | 51 +------ arch/x86/crypto/crct10dif-pclmul_glue.c | 90 ++---------- crypto/Kconfig | 7 +- crypto/Makefile | 2 +- crypto/crct10dif_common.c | 82 ----------- crypto/crct10dif_generic.c | 100 +++++++++---- include/linux/crc-t10dif.h | 21 ++- lib/Kconfig | 2 - lib/crc-t10dif.c | 152 +++++++++----------- 13 files changed, 204 insertions(+), 451 deletions(-) delete mode 100644 crypto/crct10dif_common.c
There is already a library API for two other hash functions, BLAKE2s and Poly1305, which takes advantage of architecture-specific implementations without using static calls. Also, those algorithms are likewise also exposed through the shash API, but in a different way from what this patchset proposes.
Is there a reason not to do things in the same way? What are the advantages of the new approach that you're proposing?
- Eric
Ard Biesheuvel
reviewerQuoted 64 lines · Eric Biggers
Quoted 46 lines · Ard Biesheuvel
CRC-T10DIF is a very poor match for the crypto API:
- every user in the kernel calls it via a library wrapper around the shash API, so all callers share a single instance of the transform
- each architecture provides at most a single optimized implementation, based on SIMD instructions for carryless multiplicationIn other words, none of the flexibility it provides is put to good use, and so it is better to get rid of this complexity, and expose the optimized implementations via static calls instead. This removes a substantial chunk of code, and also gets rid of any indirect calls on architectures that obsess about those (x86)
If this approach is deemed suitable, there are other places where we might consider adopting it: CRC32 and CRC32(C).
Patch #1 does some preparatory refactoring and removes the library wrapper around the shash transform.
Patch #2 introduces the actual static calls, along with the registration routines to update the crc-t10dif implementation at runtime.
Patch #3 updates the generic CRC-T10DIF shash driver so it distinguishes between the optimized library code and the generic library code.
Patches #4 to #7 update the various arch implementations to switch over to the new method.
Special request to Peter to take a look at patch #2, and in particular, whether
synchronize_rcu_tasks()is sufficient to ensure that a module providing the target of a static call can be unloaded safely.Cc "Martin K. Petersen" <[email protected]>Cc Eric Biggers <[email protected]>Cc Peter Zijlstra <[email protected]>Ard Biesheuvel (7):
crypto: crc-t10dif - turn library wrapper for shash into generic
library
crypto:lib/crc-t10dif- add static call support for optimized
versions
crypto: generic/crc-t10dif - expose both arch and generic shashes
crypto: x86/crc-t10dif - convert to static call library API
crypto: arm/crc-t10dif - convert to static call library API
crypto: arm64/crc-t10dif - convert to static call API
crypto: powerpc/crc-t10dif - convert to static call APIQuoted 15 lines
arch/arm/crypto/Kconfig | 2 +- arch/arm/crypto/crct10dif-ce-glue.c | 58 ++------ arch/arm64/crypto/Kconfig | 3 +- arch/arm64/crypto/crct10dif-ce-glue.c | 85 ++--------- arch/powerpc/crypto/crct10dif-vpmsum_glue.c | 51 +------ arch/x86/crypto/crct10dif-pclmul_glue.c | 90 ++---------- crypto/Kconfig | 7 +- crypto/Makefile | 2 +- crypto/crct10dif_common.c | 82 ----------- crypto/crct10dif_generic.c | 100 +++++++++---- include/linux/crc-t10dif.h | 21 ++- lib/Kconfig | 2 - lib/crc-t10dif.c | 152 +++++++++----------- 13 files changed, 204 insertions(+), 451 deletions(-) delete mode 100644 crypto/crct10dif_common.c
Quoted 8 lines
There is already a library API for two other hash functions, BLAKE2s and Poly1305, which takes advantage of architecture-specific implementations without using static calls. Also, those algorithms are likewise also exposed through the shash API, but in a different way from what this patchset proposes.
Is there a reason not to do things in the same way? What are the advantages of the new approach that you're proposing?
The current approach uses build time dependencies - i.e., if you decide to build the accelerated implementation, you always have to load it, even if the accelerated implementation cannot be used on the system in question, and it is up to that code to use fallbacks for everything, This was kind of a compromise on my part when we were having the crypto library vs Wireguard discussion - I mentioned at the time that [in my opinion] it was a temporary approach because static call support was taking so long to arrive. (lwn article here [0] but the links in it seem to be dead). It also results in some nasty Kconfig dependencies because building the generic code into the kernel and building the accelerated code as a module gives problems.
I agree that having different approaches for doing the same thing is suboptimal, but I think the situation may be slightly different for plain SIMD code such as blake2 and poly1305 versus crc implementations based on carryless multiplication instructions which may be rare but 10-20x faster if they are supported.
So in summary, I think this approach is better. The generic code can be built in and superseded by module code, and there are no dependencies going both ways.
There are some complications as well, though:
- module softdeps don't work {afaik) if the depender is builtin
- our poly1305 implementations use a different layout for the state that is passed between the init/update/final calls, so it may be tricky to use a similar approach there.
Ard Biesheuvel
reviewerQuoted 97 lines · Ard Biesheuvel
Quoted 64 lines · Eric Biggers
Quoted 46 lines · Ard Biesheuvel
CRC-T10DIF is a very poor match for the crypto API:
- every user in the kernel calls it via a library wrapper around the shash API, so all callers share a single instance of the transform
- each architecture provides at most a single optimized implementation, based on SIMD instructions for carryless multiplicationIn other words, none of the flexibility it provides is put to good use, and so it is better to get rid of this complexity, and expose the optimized implementations via static calls instead. This removes a substantial chunk of code, and also gets rid of any indirect calls on architectures that obsess about those (x86)
If this approach is deemed suitable, there are other places where we might consider adopting it: CRC32 and CRC32(C).
Patch #1 does some preparatory refactoring and removes the library wrapper around the shash transform.
Patch #2 introduces the actual static calls, along with the registration routines to update the crc-t10dif implementation at runtime.
Patch #3 updates the generic CRC-T10DIF shash driver so it distinguishes between the optimized library code and the generic library code.
Patches #4 to #7 update the various arch implementations to switch over to the new method.
Special request to Peter to take a look at patch #2, and in particular, whether
synchronize_rcu_tasks()is sufficient to ensure that a module providing the target of a static call can be unloaded safely.Cc "Martin K. Petersen" <[email protected]>Cc Eric Biggers <[email protected]>Cc Peter Zijlstra <[email protected]>Ard Biesheuvel (7):
crypto: crc-t10dif - turn library wrapper for shash into generic
library
crypto:lib/crc-t10dif- add static call support for optimized
versions
crypto: generic/crc-t10dif - expose both arch and generic shashes
crypto: x86/crc-t10dif - convert to static call library API
crypto: arm/crc-t10dif - convert to static call library API
crypto: arm64/crc-t10dif - convert to static call API
crypto: powerpc/crc-t10dif - convert to static call APIQuoted 15 lines
arch/arm/crypto/Kconfig | 2 +- arch/arm/crypto/crct10dif-ce-glue.c | 58 ++------ arch/arm64/crypto/Kconfig | 3 +- arch/arm64/crypto/crct10dif-ce-glue.c | 85 ++--------- arch/powerpc/crypto/crct10dif-vpmsum_glue.c | 51 +------ arch/x86/crypto/crct10dif-pclmul_glue.c | 90 ++---------- crypto/Kconfig | 7 +- crypto/Makefile | 2 +- crypto/crct10dif_common.c | 82 ----------- crypto/crct10dif_generic.c | 100 +++++++++---- include/linux/crc-t10dif.h | 21 ++- lib/Kconfig | 2 - lib/crc-t10dif.c | 152 +++++++++----------- 13 files changed, 204 insertions(+), 451 deletions(-) delete mode 100644 crypto/crct10dif_common.cQuoted 8 lines
There is already a library API for two other hash functions, BLAKE2s and Poly1305, which takes advantage of architecture-specific implementations without using static calls. Also, those algorithms are likewise also exposed through the shash API, but in a different way from what this patchset proposes.
Is there a reason not to do things in the same way? What are the advantages of the new approach that you're proposing?
The current approach uses build time dependencies - i.e., if you decide to build the accelerated implementation, you always have to load it, even if the accelerated implementation cannot be used on the system in question, and it is up to that code to use fallbacks for everything, This was kind of a compromise on my part when we were having the crypto library vs Wireguard discussion - I mentioned at the time that [in my opinion] it was a temporary approach because static call support was taking so long to arrive. (lwn article here [0] but the links in it seem to be dead). It also results in some nasty
Kconfigdependencies because building the generic code into the kernel and building the accelerated code as a module gives problems.I agree that having different approaches for doing the same thing is suboptimal, but I think the situation may be slightly different for plain SIMD code such as blake2 and poly1305 versus crc implementations based on carryless multiplication instructions which may be rare but 10-20x faster if they are supported.
So in summary, I think this approach is better. The generic code can be built in and superseded by module code, and there are no dependencies going both ways.
Quoted 7 lines
There are some complications as well, though:
- module softdeps don't work {afaik) if the depender is builtin
- our poly1305 implementations use a different layout for the state that is passed between theinit/update/finalcalls, so it may be tricky to use a similar approach there.
This does not actually work. The kernel_fpu_end() occurring in the CRC-T10 code amounts to a voluntary schedule, which means synchronize_rcu_tasks() does not guarantee that the accelerated code is no longer live after the static call is updated to refer to the generic code again, and so the remove is risky.
There are some other issues I want to focus on first, so I am going to disregard this series for now.