]> git.ipfire.org Git - thirdparty/linux.git/commitdiff
powerpc/crc32: expose CRC32 functions through lib
authorEric Biggers <ebiggers@google.com>
Mon, 2 Dec 2024 01:08:33 +0000 (17:08 -0800)
committerEric Biggers <ebiggers@google.com>
Mon, 2 Dec 2024 01:23:01 +0000 (17:23 -0800)
Move the powerpc CRC32C 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/powerpc/crypto/crc32c-vpmsum_glue.c to
arch/powerpc/lib/crc32-glue.c, view this commit with 'git show -M10'.

Reviewed-by: Ard Biesheuvel <ardb@kernel.org>
Acked-by: Michael Ellerman <mpe@ellerman.id.au>
Link: https://lore.kernel.org/r/20241202010844.144356-9-ebiggers@kernel.org
Signed-off-by: Eric Biggers <ebiggers@google.com>
arch/powerpc/Kconfig
arch/powerpc/configs/powernv_defconfig
arch/powerpc/configs/ppc64_defconfig
arch/powerpc/crypto/Kconfig
arch/powerpc/crypto/Makefile
arch/powerpc/crypto/crc32c-vpmsum_glue.c [deleted file]
arch/powerpc/crypto/crct10dif-vpmsum_asm.S
arch/powerpc/lib/Makefile
arch/powerpc/lib/crc32-glue.c [new file with mode: 0644]
arch/powerpc/lib/crc32-vpmsum_core.S [moved from arch/powerpc/crypto/crc32-vpmsum_core.S with 100% similarity]
arch/powerpc/lib/crc32c-vpmsum_asm.S [moved from arch/powerpc/crypto/crc32c-vpmsum_asm.S with 100% similarity]

index a0ce777f97063bf858942c60654d8411bcf2a3dc..b5050a09a27f85f313ba279ed7111ffd00725c32 100644 (file)
@@ -127,6 +127,7 @@ config PPC
        select ARCH_ENABLE_MEMORY_HOTPLUG
        select ARCH_ENABLE_MEMORY_HOTREMOVE
        select ARCH_HAS_COPY_MC                 if PPC64
+       select ARCH_HAS_CRC32                   if PPC64 && ALTIVEC
        select ARCH_HAS_CURRENT_STACK_POINTER
        select ARCH_HAS_DEBUG_VIRTUAL
        select ARCH_HAS_DEBUG_VM_PGTABLE
index ee84ade7a0339e03694c445fca233ef8bd971ec5..4a7ddea05b4db7c943c72a761628783e7cbec544 100644 (file)
@@ -320,7 +320,6 @@ CONFIG_XMON=y
 CONFIG_CRYPTO_TEST=m
 CONFIG_CRYPTO_PCBC=m
 CONFIG_CRYPTO_HMAC=y
-CONFIG_CRYPTO_CRC32C_VPMSUM=m
 CONFIG_CRYPTO_CRCT10DIF_VPMSUM=m
 CONFIG_CRYPTO_MD5_PPC=m
 CONFIG_CRYPTO_MICHAEL_MIC=m
index f39c0d000c4386dc77fe36965e38a96f5f11daac..58e5f4488da467b8c69467c88bbc25728fc61c0e 100644 (file)
@@ -389,7 +389,6 @@ CONFIG_CRYPTO_MICHAEL_MIC=m
 CONFIG_CRYPTO_SHA256=y
 CONFIG_CRYPTO_WP512=m
 CONFIG_CRYPTO_LZO=m
-CONFIG_CRYPTO_CRC32C_VPMSUM=m
 CONFIG_CRYPTO_CRCT10DIF_VPMSUM=m
 CONFIG_CRYPTO_VPMSUM_TESTER=m
 CONFIG_CRYPTO_MD5_PPC=m
index 951a437264611523099437e275b79f113271409f..2d89e35b3cddd0efed4511af710bf9509ed55e6c 100644 (file)
@@ -13,19 +13,6 @@ config CRYPTO_CURVE25519_PPC64
          Architecture: PowerPC64
          - Little-endian
 
-config CRYPTO_CRC32C_VPMSUM
-       tristate "CRC32c"
-       depends on PPC64 && ALTIVEC
-       select CRYPTO_HASH
-       select CRC32
-       help
-         CRC32c CRC algorithm with the iSCSI polynomial (RFC 3385 and RFC 3720)
-
-         Architecture: powerpc64 using
-         - AltiVec extensions
-
-         Enable on POWER8 and newer processors for improved performance.
-
 config CRYPTO_CRCT10DIF_VPMSUM
        tristate "CRC32T10DIF"
        depends on PPC64 && ALTIVEC && CRC_T10DIF
@@ -40,7 +27,7 @@ config CRYPTO_CRCT10DIF_VPMSUM
 
 config CRYPTO_VPMSUM_TESTER
        tristate "CRC32c and CRC32T10DIF hardware acceleration tester"
-       depends on CRYPTO_CRCT10DIF_VPMSUM && CRYPTO_CRC32C_VPMSUM
+       depends on CRYPTO_CRCT10DIF_VPMSUM && CRYPTO_CRC32C && CRC32_ARCH
        help
          Stress test for CRC32c and CRCT10DIF algorithms implemented with
          powerpc64 AltiVec extensions (POWER8 vpmsum instructions).
index 59808592f0a1b55db570d2df049e6a4d836c2109..54486192273c24856a6e1b2b0447061ca6175c66 100644 (file)
@@ -10,7 +10,6 @@ obj-$(CONFIG_CRYPTO_MD5_PPC) += md5-ppc.o
 obj-$(CONFIG_CRYPTO_SHA1_PPC) += sha1-powerpc.o
 obj-$(CONFIG_CRYPTO_SHA1_PPC_SPE) += sha1-ppc-spe.o
 obj-$(CONFIG_CRYPTO_SHA256_PPC_SPE) += sha256-ppc-spe.o
-obj-$(CONFIG_CRYPTO_CRC32C_VPMSUM) += crc32c-vpmsum.o
 obj-$(CONFIG_CRYPTO_CRCT10DIF_VPMSUM) += crct10dif-vpmsum.o
 obj-$(CONFIG_CRYPTO_VPMSUM_TESTER) += crc-vpmsum_test.o
 obj-$(CONFIG_CRYPTO_AES_GCM_P10) += aes-gcm-p10-crypto.o
@@ -24,7 +23,6 @@ md5-ppc-y := md5-asm.o md5-glue.o
 sha1-powerpc-y := sha1-powerpc-asm.o sha1.o
 sha1-ppc-spe-y := sha1-spe-asm.o sha1-spe-glue.o
 sha256-ppc-spe-y := sha256-spe-asm.o sha256-spe-glue.o
-crc32c-vpmsum-y := crc32c-vpmsum_asm.o crc32c-vpmsum_glue.o
 crct10dif-vpmsum-y := crct10dif-vpmsum_asm.o crct10dif-vpmsum_glue.o
 aes-gcm-p10-crypto-y := aes-gcm-p10-glue.o aes-gcm-p10.o ghashp10-ppc.o aesp10-ppc.o
 chacha-p10-crypto-y := chacha-p10-glue.o chacha-p10le-8x.o
diff --git a/arch/powerpc/crypto/crc32c-vpmsum_glue.c b/arch/powerpc/crypto/crc32c-vpmsum_glue.c
deleted file mode 100644 (file)
index 63760b7..0000000
+++ /dev/null
@@ -1,173 +0,0 @@
-// SPDX-License-Identifier: GPL-2.0-only
-#include <linux/crc32.h>
-#include <crypto/internal/hash.h>
-#include <crypto/internal/simd.h>
-#include <linux/init.h>
-#include <linux/module.h>
-#include <linux/string.h>
-#include <linux/kernel.h>
-#include <linux/cpufeature.h>
-#include <asm/simd.h>
-#include <asm/switch_to.h>
-
-#define CHKSUM_BLOCK_SIZE      1
-#define CHKSUM_DIGEST_SIZE     4
-
-#define VMX_ALIGN              16
-#define VMX_ALIGN_MASK         (VMX_ALIGN-1)
-
-#define VECTOR_BREAKPOINT      512
-
-u32 __crc32c_vpmsum(u32 crc, unsigned char const *p, size_t len);
-
-static u32 crc32c_vpmsum(u32 crc, unsigned char const *p, size_t len)
-{
-       unsigned int prealign;
-       unsigned int tail;
-
-       if (len < (VECTOR_BREAKPOINT + VMX_ALIGN) || !crypto_simd_usable())
-               return __crc32c_le(crc, p, len);
-
-       if ((unsigned long)p & VMX_ALIGN_MASK) {
-               prealign = VMX_ALIGN - ((unsigned long)p & VMX_ALIGN_MASK);
-               crc = __crc32c_le(crc, p, prealign);
-               len -= prealign;
-               p += prealign;
-       }
-
-       if (len & ~VMX_ALIGN_MASK) {
-               preempt_disable();
-               pagefault_disable();
-               enable_kernel_altivec();
-               crc = __crc32c_vpmsum(crc, p, len & ~VMX_ALIGN_MASK);
-               disable_kernel_altivec();
-               pagefault_enable();
-               preempt_enable();
-       }
-
-       tail = len & VMX_ALIGN_MASK;
-       if (tail) {
-               p += len & ~VMX_ALIGN_MASK;
-               crc = __crc32c_le(crc, p, tail);
-       }
-
-       return crc;
-}
-
-static int crc32c_vpmsum_cra_init(struct crypto_tfm *tfm)
-{
-       u32 *key = crypto_tfm_ctx(tfm);
-
-       *key = ~0;
-
-       return 0;
-}
-
-/*
- * Setting the seed allows arbitrary accumulators and flexible XOR policy
- * If your algorithm starts with ~0, then XOR with ~0 before you set
- * the seed.
- */
-static int crc32c_vpmsum_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 crc32c_vpmsum_init(struct shash_desc *desc)
-{
-       u32 *mctx = crypto_shash_ctx(desc->tfm);
-       u32 *crcp = shash_desc_ctx(desc);
-
-       *crcp = *mctx;
-
-       return 0;
-}
-
-static int crc32c_vpmsum_update(struct shash_desc *desc, const u8 *data,
-                              unsigned int len)
-{
-       u32 *crcp = shash_desc_ctx(desc);
-
-       *crcp = crc32c_vpmsum(*crcp, data, len);
-
-       return 0;
-}
-
-static int __crc32c_vpmsum_finup(u32 *crcp, const u8 *data, unsigned int len,
-                               u8 *out)
-{
-       *(__le32 *)out = ~cpu_to_le32(crc32c_vpmsum(*crcp, data, len));
-
-       return 0;
-}
-
-static int crc32c_vpmsum_finup(struct shash_desc *desc, const u8 *data,
-                             unsigned int len, u8 *out)
-{
-       return __crc32c_vpmsum_finup(shash_desc_ctx(desc), data, len, out);
-}
-
-static int crc32c_vpmsum_final(struct shash_desc *desc, u8 *out)
-{
-       u32 *crcp = shash_desc_ctx(desc);
-
-       *(__le32 *)out = ~cpu_to_le32p(crcp);
-
-       return 0;
-}
-
-static int crc32c_vpmsum_digest(struct shash_desc *desc, const u8 *data,
-                              unsigned int len, u8 *out)
-{
-       return __crc32c_vpmsum_finup(crypto_shash_ctx(desc->tfm), data, len,
-                                    out);
-}
-
-static struct shash_alg alg = {
-       .setkey         = crc32c_vpmsum_setkey,
-       .init           = crc32c_vpmsum_init,
-       .update         = crc32c_vpmsum_update,
-       .final          = crc32c_vpmsum_final,
-       .finup          = crc32c_vpmsum_finup,
-       .digest         = crc32c_vpmsum_digest,
-       .descsize       = sizeof(u32),
-       .digestsize     = CHKSUM_DIGEST_SIZE,
-       .base           = {
-               .cra_name               = "crc32c",
-               .cra_driver_name        = "crc32c-vpmsum",
-               .cra_priority           = 200,
-               .cra_flags              = CRYPTO_ALG_OPTIONAL_KEY,
-               .cra_blocksize          = CHKSUM_BLOCK_SIZE,
-               .cra_ctxsize            = sizeof(u32),
-               .cra_module             = THIS_MODULE,
-               .cra_init               = crc32c_vpmsum_cra_init,
-       }
-};
-
-static int __init crc32c_vpmsum_mod_init(void)
-{
-       if (!cpu_has_feature(CPU_FTR_ARCH_207S))
-               return -ENODEV;
-
-       return crypto_register_shash(&alg);
-}
-
-static void __exit crc32c_vpmsum_mod_fini(void)
-{
-       crypto_unregister_shash(&alg);
-}
-
-module_cpu_feature_match(PPC_MODULE_FEATURE_VEC_CRYPTO, crc32c_vpmsum_mod_init);
-module_exit(crc32c_vpmsum_mod_fini);
-
-MODULE_AUTHOR("Anton Blanchard <anton@samba.org>");
-MODULE_DESCRIPTION("CRC32C using vector polynomial multiply-sum instructions");
-MODULE_LICENSE("GPL");
-MODULE_ALIAS_CRYPTO("crc32c");
-MODULE_ALIAS_CRYPTO("crc32c-vpmsum");
index f0b93a0fe168aa65ab459b01ded6e3e5a600cd1e..0a52261bf859970325b2efb9f4664114087f7c75 100644 (file)
        .octa 0x0000000000000000000000018bb70000
 
 #define CRC_FUNCTION_NAME __crct10dif_vpmsum
-#include "crc32-vpmsum_core.S"
+#include "../lib/crc32-vpmsum_core.S"
index f14ecab674a34081785eb995fca045958eca193b..da9381a1c95b3174524d06ec90dab227a7d5f710 100644 (file)
@@ -78,4 +78,7 @@ CFLAGS_xor_vmx.o += -mhard-float -maltivec $(call cc-option,-mabi=altivec)
 # Enable <altivec.h>
 CFLAGS_xor_vmx.o += -isystem $(shell $(CC) -print-file-name=include)
 
+obj-$(CONFIG_CRC32_ARCH) += crc32-powerpc.o
+crc32-powerpc-y := crc32-glue.o crc32c-vpmsum_asm.o
+
 obj-$(CONFIG_PPC64) += $(obj64-y)
diff --git a/arch/powerpc/lib/crc32-glue.c b/arch/powerpc/lib/crc32-glue.c
new file mode 100644 (file)
index 0000000..79cc954
--- /dev/null
@@ -0,0 +1,92 @@
+// SPDX-License-Identifier: GPL-2.0-only
+#include <linux/crc32.h>
+#include <crypto/internal/simd.h>
+#include <linux/init.h>
+#include <linux/module.h>
+#include <linux/kernel.h>
+#include <linux/cpufeature.h>
+#include <asm/simd.h>
+#include <asm/switch_to.h>
+
+#define VMX_ALIGN              16
+#define VMX_ALIGN_MASK         (VMX_ALIGN-1)
+
+#define VECTOR_BREAKPOINT      512
+
+static DEFINE_STATIC_KEY_FALSE(have_vec_crypto);
+
+u32 __crc32c_vpmsum(u32 crc, const u8 *p, size_t len);
+
+u32 crc32_le_arch(u32 crc, const u8 *p, size_t len)
+{
+       return crc32_le_base(crc, p, len);
+}
+EXPORT_SYMBOL(crc32_le_arch);
+
+u32 crc32c_le_arch(u32 crc, const u8 *p, size_t len)
+{
+       unsigned int prealign;
+       unsigned int tail;
+
+       if (len < (VECTOR_BREAKPOINT + VMX_ALIGN) ||
+           !static_branch_likely(&have_vec_crypto) || !crypto_simd_usable())
+               return crc32c_le_base(crc, p, len);
+
+       if ((unsigned long)p & VMX_ALIGN_MASK) {
+               prealign = VMX_ALIGN - ((unsigned long)p & VMX_ALIGN_MASK);
+               crc = crc32c_le_base(crc, p, prealign);
+               len -= prealign;
+               p += prealign;
+       }
+
+       if (len & ~VMX_ALIGN_MASK) {
+               preempt_disable();
+               pagefault_disable();
+               enable_kernel_altivec();
+               crc = __crc32c_vpmsum(crc, p, len & ~VMX_ALIGN_MASK);
+               disable_kernel_altivec();
+               pagefault_enable();
+               preempt_enable();
+       }
+
+       tail = len & VMX_ALIGN_MASK;
+       if (tail) {
+               p += len & ~VMX_ALIGN_MASK;
+               crc = crc32c_le_base(crc, p, tail);
+       }
+
+       return crc;
+}
+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_powerpc_init(void)
+{
+       if (cpu_has_feature(CPU_FTR_ARCH_207S) &&
+           (cur_cpu_spec->cpu_user_features2 & PPC_FEATURE2_VEC_CRYPTO))
+               static_branch_enable(&have_vec_crypto);
+       return 0;
+}
+arch_initcall(crc32_powerpc_init);
+
+static void __exit crc32_powerpc_exit(void)
+{
+}
+module_exit(crc32_powerpc_exit);
+
+u32 crc32_optimizations(void)
+{
+       if (static_key_enabled(&have_vec_crypto))
+               return CRC32C_OPTIMIZATION;
+       return 0;
+}
+EXPORT_SYMBOL(crc32_optimizations);
+
+MODULE_AUTHOR("Anton Blanchard <anton@samba.org>");
+MODULE_DESCRIPTION("CRC32C using vector polynomial multiply-sum instructions");
+MODULE_LICENSE("GPL");