]> git.ipfire.org Git - thirdparty/linux.git/commitdiff
arm/crc32: expose CRC32 functions through lib
authorEric Biggers <ebiggers@google.com>
Mon, 2 Dec 2024 01:08:30 +0000 (17:08 -0800)
committerEric Biggers <ebiggers@google.com>
Mon, 2 Dec 2024 01:23:01 +0000 (17:23 -0800)
Move the arm CRC32 assembly code into the lib directory and wire it up
to the library interface.  This allows it to be used without going
through the crypto API.  It remains usable via the crypto API too via
the shash algorithms that use the library interface.  Thus all the
arch-specific "shash" code becomes unnecessary and is removed.

Note: to see the diff from arch/arm/crypto/crc32-ce-glue.c to
arch/arm/lib/crc32-glue.c, view this commit with 'git show -M10'.

Reviewed-by: Ard Biesheuvel <ardb@kernel.org>
Link: https://lore.kernel.org/r/20241202010844.144356-6-ebiggers@kernel.org
Signed-off-by: Eric Biggers <ebiggers@google.com>
arch/arm/Kconfig
arch/arm/configs/milbeaut_m10v_defconfig
arch/arm/configs/multi_v7_defconfig
arch/arm/crypto/Kconfig
arch/arm/crypto/Makefile
arch/arm/crypto/crc32-ce-glue.c [deleted file]
arch/arm/lib/Makefile
arch/arm/lib/crc32-core.S [moved from arch/arm/crypto/crc32-ce-core.S with 98% similarity]
arch/arm/lib/crc32-glue.c [new file with mode: 0644]

index 202397be76d8037b531b34dee16c7dfcfd0124ef..f817ca317b02a90b6a903d20f6c03ca5f02bf613 100644 (file)
@@ -7,6 +7,7 @@ config ARM
        select ARCH_HAS_BINFMT_FLAT
        select ARCH_HAS_CPU_CACHE_ALIASING
        select ARCH_HAS_CPU_FINALIZE_INIT if MMU
+       select ARCH_HAS_CRC32 if KERNEL_MODE_NEON
        select ARCH_HAS_CURRENT_STACK_POINTER
        select ARCH_HAS_DEBUG_VIRTUAL if MMU
        select ARCH_HAS_DMA_ALLOC if MMU
index f5eeac9c65c323c63850f10ecb4f46a3d73b7008..acd16204f8d7f814d5447684db9e6a027b48b476 100644 (file)
@@ -107,7 +107,6 @@ CONFIG_CRYPTO_AES_ARM=m
 CONFIG_CRYPTO_AES_ARM_BS=m
 CONFIG_CRYPTO_AES_ARM_CE=m
 CONFIG_CRYPTO_CHACHA20_NEON=m
-CONFIG_CRYPTO_CRC32_ARM_CE=m
 # CONFIG_CRYPTO_HW is not set
 CONFIG_CRC_CCITT=m
 CONFIG_CRC_ITU_T=m
index 758276027dbcd0d444dac995745076b4e33457ff..9d4336261e450ce5bf99a1aa53e603bd7c0037bb 100644 (file)
@@ -1306,7 +1306,6 @@ CONFIG_CRYPTO_AES_ARM=m
 CONFIG_CRYPTO_AES_ARM_BS=m
 CONFIG_CRYPTO_AES_ARM_CE=m
 CONFIG_CRYPTO_CHACHA20_NEON=m
-CONFIG_CRYPTO_CRC32_ARM_CE=m
 CONFIG_CRYPTO_DEV_SUN4I_SS=m
 CONFIG_CRYPTO_DEV_FSL_CAAM=m
 CONFIG_CRYPTO_DEV_EXYNOS_RNG=m
index 5ff49a5e9afc9db3278db94c6d01adb61c3dca0c..ea0ebf336d0dee98cf36db0426889b8ad0f20da1 100644 (file)
@@ -222,20 +222,6 @@ config CRYPTO_CHACHA20_NEON
          Architecture: arm using:
          - NEON (Advanced SIMD) extensions
 
-config CRYPTO_CRC32_ARM_CE
-       tristate "CRC32C and CRC32"
-       depends on KERNEL_MODE_NEON
-       depends on CRC32
-       select CRYPTO_HASH
-       help
-         CRC32c CRC algorithm with the iSCSI polynomial (RFC 3385 and RFC 3720)
-         and CRC32 CRC algorithm (IEEE 802.3)
-
-         Architecture: arm using:
-         - CRC and/or PMULL instructions
-
-         Drivers: crc32-arm-ce and crc32c-arm-ce
-
 config CRYPTO_CRCT10DIF_ARM_CE
        tristate "CRCT10DIF"
        depends on KERNEL_MODE_NEON
index 13e62c7c25dca8e103527f776f9fb094b7b350e7..38ec5cc1e8442d98cea6ff006a93af5e0975c437 100644 (file)
@@ -21,7 +21,6 @@ obj-$(CONFIG_CRYPTO_SHA1_ARM_CE) += sha1-arm-ce.o
 obj-$(CONFIG_CRYPTO_SHA2_ARM_CE) += sha2-arm-ce.o
 obj-$(CONFIG_CRYPTO_GHASH_ARM_CE) += ghash-arm-ce.o
 obj-$(CONFIG_CRYPTO_CRCT10DIF_ARM_CE) += crct10dif-arm-ce.o
-obj-$(CONFIG_CRYPTO_CRC32_ARM_CE) += crc32-arm-ce.o
 
 aes-arm-y      := aes-cipher-core.o aes-cipher-glue.o
 aes-arm-bs-y   := aes-neonbs-core.o aes-neonbs-glue.o
@@ -38,7 +37,6 @@ sha2-arm-ce-y := sha2-ce-core.o sha2-ce-glue.o
 aes-arm-ce-y   := aes-ce-core.o aes-ce-glue.o
 ghash-arm-ce-y := ghash-ce-core.o ghash-ce-glue.o
 crct10dif-arm-ce-y     := crct10dif-ce-core.o crct10dif-ce-glue.o
-crc32-arm-ce-y:= crc32-ce-core.o crc32-ce-glue.o
 chacha-neon-y := chacha-scalar-core.o chacha-glue.o
 chacha-neon-$(CONFIG_KERNEL_MODE_NEON) += chacha-neon-core.o
 poly1305-arm-y := poly1305-core.o poly1305-glue.o
diff --git a/arch/arm/crypto/crc32-ce-glue.c b/arch/arm/crypto/crc32-ce-glue.c
deleted file mode 100644 (file)
index 20b4dff..0000000
+++ /dev/null
@@ -1,247 +0,0 @@
-// SPDX-License-Identifier: GPL-2.0-only
-/*
- * Accelerated CRC32(C) using ARM CRC, NEON and Crypto Extensions instructions
- *
- * Copyright (C) 2016 Linaro Ltd <ard.biesheuvel@linaro.org>
- */
-
-#include <linux/cpufeature.h>
-#include <linux/crc32.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/hwcap.h>
-#include <asm/neon.h>
-#include <asm/simd.h>
-#include <linux/unaligned.h>
-
-#define PMULL_MIN_LEN          64L     /* minimum size of buffer
-                                        * for crc32_pmull_le_16 */
-#define SCALE_F                        16L     /* size of NEON register */
-
-asmlinkage u32 crc32_pmull_le(const u8 buf[], u32 len, u32 init_crc);
-asmlinkage u32 crc32_armv8_le(u32 init_crc, const u8 buf[], u32 len);
-
-asmlinkage u32 crc32c_pmull_le(const u8 buf[], u32 len, u32 init_crc);
-asmlinkage u32 crc32c_armv8_le(u32 init_crc, const u8 buf[], u32 len);
-
-static u32 (*fallback_crc32)(u32 init_crc, const u8 buf[], u32 len);
-static u32 (*fallback_crc32c)(u32 init_crc, const u8 buf[], u32 len);
-
-static int crc32_cra_init(struct crypto_tfm *tfm)
-{
-       u32 *key = crypto_tfm_ctx(tfm);
-
-       *key = 0;
-       return 0;
-}
-
-static int crc32c_cra_init(struct crypto_tfm *tfm)
-{
-       u32 *key = crypto_tfm_ctx(tfm);
-
-       *key = ~0;
-       return 0;
-}
-
-static int crc32_setkey(struct crypto_shash *hash, const u8 *key,
-                       unsigned int keylen)
-{
-       u32 *mctx = crypto_shash_ctx(hash);
-
-       if (keylen != sizeof(u32))
-               return -EINVAL;
-       *mctx = le32_to_cpup((__le32 *)key);
-       return 0;
-}
-
-static int crc32_init(struct shash_desc *desc)
-{
-       u32 *mctx = crypto_shash_ctx(desc->tfm);
-       u32 *crc = shash_desc_ctx(desc);
-
-       *crc = *mctx;
-       return 0;
-}
-
-static int crc32_update(struct shash_desc *desc, const u8 *data,
-                       unsigned int length)
-{
-       u32 *crc = shash_desc_ctx(desc);
-
-       *crc = crc32_armv8_le(*crc, data, length);
-       return 0;
-}
-
-static int crc32c_update(struct shash_desc *desc, const u8 *data,
-                        unsigned int length)
-{
-       u32 *crc = shash_desc_ctx(desc);
-
-       *crc = crc32c_armv8_le(*crc, data, length);
-       return 0;
-}
-
-static int crc32_final(struct shash_desc *desc, u8 *out)
-{
-       u32 *crc = shash_desc_ctx(desc);
-
-       put_unaligned_le32(*crc, out);
-       return 0;
-}
-
-static int crc32c_final(struct shash_desc *desc, u8 *out)
-{
-       u32 *crc = shash_desc_ctx(desc);
-
-       put_unaligned_le32(~*crc, out);
-       return 0;
-}
-
-static int crc32_pmull_update(struct shash_desc *desc, const u8 *data,
-                             unsigned int length)
-{
-       u32 *crc = shash_desc_ctx(desc);
-       unsigned int l;
-
-       if (crypto_simd_usable()) {
-               if ((u32)data % SCALE_F) {
-                       l = min_t(u32, length, SCALE_F - ((u32)data % SCALE_F));
-
-                       *crc = fallback_crc32(*crc, data, l);
-
-                       data += l;
-                       length -= l;
-               }
-
-               if (length >= PMULL_MIN_LEN) {
-                       l = round_down(length, SCALE_F);
-
-                       kernel_neon_begin();
-                       *crc = crc32_pmull_le(data, l, *crc);
-                       kernel_neon_end();
-
-                       data += l;
-                       length -= l;
-               }
-       }
-
-       if (length > 0)
-               *crc = fallback_crc32(*crc, data, length);
-
-       return 0;
-}
-
-static int crc32c_pmull_update(struct shash_desc *desc, const u8 *data,
-                              unsigned int length)
-{
-       u32 *crc = shash_desc_ctx(desc);
-       unsigned int l;
-
-       if (crypto_simd_usable()) {
-               if ((u32)data % SCALE_F) {
-                       l = min_t(u32, length, SCALE_F - ((u32)data % SCALE_F));
-
-                       *crc = fallback_crc32c(*crc, data, l);
-
-                       data += l;
-                       length -= l;
-               }
-
-               if (length >= PMULL_MIN_LEN) {
-                       l = round_down(length, SCALE_F);
-
-                       kernel_neon_begin();
-                       *crc = crc32c_pmull_le(data, l, *crc);
-                       kernel_neon_end();
-
-                       data += l;
-                       length -= l;
-               }
-       }
-
-       if (length > 0)
-               *crc = fallback_crc32c(*crc, data, length);
-
-       return 0;
-}
-
-static struct shash_alg crc32_pmull_algs[] = { {
-       .setkey                 = crc32_setkey,
-       .init                   = crc32_init,
-       .update                 = crc32_update,
-       .final                  = crc32_final,
-       .descsize               = sizeof(u32),
-       .digestsize             = sizeof(u32),
-
-       .base.cra_ctxsize       = sizeof(u32),
-       .base.cra_init          = crc32_cra_init,
-       .base.cra_name          = "crc32",
-       .base.cra_driver_name   = "crc32-arm-ce",
-       .base.cra_priority      = 200,
-       .base.cra_flags         = CRYPTO_ALG_OPTIONAL_KEY,
-       .base.cra_blocksize     = 1,
-       .base.cra_module        = THIS_MODULE,
-}, {
-       .setkey                 = crc32_setkey,
-       .init                   = crc32_init,
-       .update                 = crc32c_update,
-       .final                  = crc32c_final,
-       .descsize               = sizeof(u32),
-       .digestsize             = sizeof(u32),
-
-       .base.cra_ctxsize       = sizeof(u32),
-       .base.cra_init          = crc32c_cra_init,
-       .base.cra_name          = "crc32c",
-       .base.cra_driver_name   = "crc32c-arm-ce",
-       .base.cra_priority      = 200,
-       .base.cra_flags         = CRYPTO_ALG_OPTIONAL_KEY,
-       .base.cra_blocksize     = 1,
-       .base.cra_module        = THIS_MODULE,
-} };
-
-static int __init crc32_pmull_mod_init(void)
-{
-       if (elf_hwcap2 & HWCAP2_PMULL) {
-               crc32_pmull_algs[0].update = crc32_pmull_update;
-               crc32_pmull_algs[1].update = crc32c_pmull_update;
-
-               if (elf_hwcap2 & HWCAP2_CRC32) {
-                       fallback_crc32 = crc32_armv8_le;
-                       fallback_crc32c = crc32c_armv8_le;
-               } else {
-                       fallback_crc32 = crc32_le;
-                       fallback_crc32c = __crc32c_le;
-               }
-       } else if (!(elf_hwcap2 & HWCAP2_CRC32)) {
-               return -ENODEV;
-       }
-
-       return crypto_register_shashes(crc32_pmull_algs,
-                                      ARRAY_SIZE(crc32_pmull_algs));
-}
-
-static void __exit crc32_pmull_mod_exit(void)
-{
-       crypto_unregister_shashes(crc32_pmull_algs,
-                                 ARRAY_SIZE(crc32_pmull_algs));
-}
-
-static const struct cpu_feature __maybe_unused crc32_cpu_feature[] = {
-       { cpu_feature(CRC32) }, { cpu_feature(PMULL) }, { }
-};
-MODULE_DEVICE_TABLE(cpu, crc32_cpu_feature);
-
-module_init(crc32_pmull_mod_init);
-module_exit(crc32_pmull_mod_exit);
-
-MODULE_AUTHOR("Ard Biesheuvel <ard.biesheuvel@linaro.org>");
-MODULE_DESCRIPTION("Accelerated CRC32(C) using ARM CRC, NEON and Crypto Extensions");
-MODULE_LICENSE("GPL v2");
-MODULE_ALIAS_CRYPTO("crc32");
-MODULE_ALIAS_CRYPTO("crc32c");
index 0ca5aae1bcc3e380d0ca5a01412d83e74b13a3b0..01cd4db2ed472bf3aadb2a0a3b1f3f7d3d48b905 100644 (file)
@@ -45,3 +45,6 @@ ifeq ($(CONFIG_KERNEL_MODE_NEON),y)
 endif
 
 obj-$(CONFIG_FUNCTION_ERROR_INJECTION) += error-inject.o
+
+obj-$(CONFIG_CRC32_ARCH) += crc32-arm.o
+crc32-arm-y := crc32-glue.o crc32-core.o
similarity index 98%
rename from arch/arm/crypto/crc32-ce-core.S
rename to arch/arm/lib/crc32-core.S
index 88f9edf94e951c9c114ab3b65ec5363640e7e389..6f674f30c70b3327c5ce8955bee971852152cd73 100644 (file)
@@ -48,7 +48,6 @@
  */
 
 #include <linux/linkage.h>
-#include <linux/cfi_types.h>
 #include <asm/assembler.h>
 
        .text
@@ -297,11 +296,11 @@ ARM_BE8(rev16             r3, r3          )
        .endm
 
        .align          5
-SYM_TYPED_FUNC_START(crc32_armv8_le)
+SYM_FUNC_START(crc32_armv8_le)
        __crc32
 SYM_FUNC_END(crc32_armv8_le)
 
        .align          5
-SYM_TYPED_FUNC_START(crc32c_armv8_le)
+SYM_FUNC_START(crc32c_armv8_le)
        __crc32         c
 SYM_FUNC_END(crc32c_armv8_le)
diff --git a/arch/arm/lib/crc32-glue.c b/arch/arm/lib/crc32-glue.c
new file mode 100644 (file)
index 0000000..2c30ba3
--- /dev/null
@@ -0,0 +1,123 @@
+// SPDX-License-Identifier: GPL-2.0-only
+/*
+ * Accelerated CRC32(C) using ARM CRC, NEON and Crypto Extensions instructions
+ *
+ * Copyright (C) 2016 Linaro Ltd <ard.biesheuvel@linaro.org>
+ */
+
+#include <linux/cpufeature.h>
+#include <linux/crc32.h>
+#include <linux/init.h>
+#include <linux/kernel.h>
+#include <linux/module.h>
+#include <linux/string.h>
+
+#include <crypto/internal/simd.h>
+
+#include <asm/hwcap.h>
+#include <asm/neon.h>
+#include <asm/simd.h>
+
+static DEFINE_STATIC_KEY_FALSE(have_crc32);
+static DEFINE_STATIC_KEY_FALSE(have_pmull);
+
+#define PMULL_MIN_LEN  64      /* min size of buffer for pmull functions */
+
+asmlinkage u32 crc32_pmull_le(const u8 buf[], u32 len, u32 init_crc);
+asmlinkage u32 crc32_armv8_le(u32 init_crc, const u8 buf[], u32 len);
+
+asmlinkage u32 crc32c_pmull_le(const u8 buf[], u32 len, u32 init_crc);
+asmlinkage u32 crc32c_armv8_le(u32 init_crc, const u8 buf[], u32 len);
+
+static u32 crc32_le_scalar(u32 crc, const u8 *p, size_t len)
+{
+       if (static_branch_likely(&have_crc32))
+               return crc32_armv8_le(crc, p, len);
+       return crc32_le_base(crc, p, len);
+}
+
+u32 crc32_le_arch(u32 crc, const u8 *p, size_t len)
+{
+       if (len >= PMULL_MIN_LEN + 15 &&
+           static_branch_likely(&have_pmull) && crypto_simd_usable()) {
+               size_t n = -(uintptr_t)p & 15;
+
+               /* align p to 16-byte boundary */
+               if (n) {
+                       crc = crc32_le_scalar(crc, p, n);
+                       p += n;
+                       len -= n;
+               }
+               n = round_down(len, 16);
+               kernel_neon_begin();
+               crc = crc32_pmull_le(p, n, crc);
+               kernel_neon_end();
+               p += n;
+               len -= n;
+       }
+       return crc32_le_scalar(crc, p, len);
+}
+EXPORT_SYMBOL(crc32_le_arch);
+
+static u32 crc32c_le_scalar(u32 crc, const u8 *p, size_t len)
+{
+       if (static_branch_likely(&have_crc32))
+               return crc32c_armv8_le(crc, p, len);
+       return crc32c_le_base(crc, p, len);
+}
+
+u32 crc32c_le_arch(u32 crc, const u8 *p, size_t len)
+{
+       if (len >= PMULL_MIN_LEN + 15 &&
+           static_branch_likely(&have_pmull) && crypto_simd_usable()) {
+               size_t n = -(uintptr_t)p & 15;
+
+               /* align p to 16-byte boundary */
+               if (n) {
+                       crc = crc32c_le_scalar(crc, p, n);
+                       p += n;
+                       len -= n;
+               }
+               n = round_down(len, 16);
+               kernel_neon_begin();
+               crc = crc32c_pmull_le(p, n, crc);
+               kernel_neon_end();
+               p += n;
+               len -= n;
+       }
+       return crc32c_le_scalar(crc, p, len);
+}
+EXPORT_SYMBOL(crc32c_le_arch);
+
+u32 crc32_be_arch(u32 crc, const u8 *p, size_t len)
+{
+       return crc32_be_base(crc, p, len);
+}
+EXPORT_SYMBOL(crc32_be_arch);
+
+static int __init crc32_arm_init(void)
+{
+       if (elf_hwcap2 & HWCAP2_CRC32)
+               static_branch_enable(&have_crc32);
+       if (elf_hwcap2 & HWCAP2_PMULL)
+               static_branch_enable(&have_pmull);
+       return 0;
+}
+arch_initcall(crc32_arm_init);
+
+static void __exit crc32_arm_exit(void)
+{
+}
+module_exit(crc32_arm_exit);
+
+u32 crc32_optimizations(void)
+{
+       if (elf_hwcap2 & (HWCAP2_CRC32 | HWCAP2_PMULL))
+               return CRC32_LE_OPTIMIZATION | CRC32C_OPTIMIZATION;
+       return 0;
+}
+EXPORT_SYMBOL(crc32_optimizations);
+
+MODULE_AUTHOR("Ard Biesheuvel <ard.biesheuvel@linaro.org>");
+MODULE_DESCRIPTION("Accelerated CRC32(C) using ARM CRC, NEON and Crypto Extensions");
+MODULE_LICENSE("GPL v2");