]> git.apps.os.sepia.ceph.com Git - ceph-client.git/commitdiff
x86/crc-t10dif: expose CRC-T10DIF function through lib
authorEric Biggers <ebiggers@google.com>
Mon, 2 Dec 2024 01:20:48 +0000 (17:20 -0800)
committerEric Biggers <ebiggers@google.com>
Mon, 2 Dec 2024 01:23:13 +0000 (17:23 -0800)
Move the x86 CRC-T10DIF 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.

Reviewed-by: Ard Biesheuvel <ardb@kernel.org>
Reviewed-by: Martin K. Petersen <martin.petersen@oracle.com>
Link: https://lore.kernel.org/r/20241202012056.209768-5-ebiggers@kernel.org
Signed-off-by: Eric Biggers <ebiggers@google.com>
arch/x86/Kconfig
arch/x86/crypto/Kconfig
arch/x86/crypto/Makefile
arch/x86/crypto/crct10dif-pcl-asm_64.S [deleted file]
arch/x86/crypto/crct10dif-pclmul_glue.c [deleted file]
arch/x86/lib/Makefile
arch/x86/lib/crc-t10dif-glue.c [new file with mode: 0644]
arch/x86/lib/crct10dif-pcl-asm_64.S [new file with mode: 0644]

index 4f4fc67fbce7a69ac630bc553eb99a9e6d0fd5d5..65f8478fe7a9686d516961a86a08c96c10c2c065 100644 (file)
@@ -77,6 +77,7 @@ config X86
        select ARCH_HAS_CPU_FINALIZE_INIT
        select ARCH_HAS_CPU_PASID               if IOMMU_SVA
        select ARCH_HAS_CRC32
+       select ARCH_HAS_CRC_T10DIF              if X86_64
        select ARCH_HAS_CURRENT_STACK_POINTER
        select ARCH_HAS_DEBUG_VIRTUAL
        select ARCH_HAS_DEBUG_VM_PGTABLE        if !X86_PAE
index ba9a7e73cd0847a1c00e9724a6e7401aa8c5f6ba..4757bf922075b664e7a2019cb38ea0193e6a6c2c 100644 (file)
@@ -492,14 +492,4 @@ config CRYPTO_GHASH_CLMUL_NI_INTEL
          Architecture: x86_64 using:
          - CLMUL-NI (carry-less multiplication new instructions)
 
-config CRYPTO_CRCT10DIF_PCLMUL
-       tristate "CRCT10DIF (PCLMULQDQ)"
-       depends on X86 && 64BIT && CRC_T10DIF
-       select CRYPTO_HASH
-       help
-         CRC16 CRC algorithm used for the T10 (SCSI) Data Integrity Field (DIF)
-
-         Architecture: x86_64 using:
-         - PCLMULQDQ (carry-less multiplication)
-
 endmenu
index 030b925ca4e28ab65311d6f0c586faabc0557c88..07b00bfca64b552267e4f8704ad4b2566d9faa43 100644 (file)
@@ -75,9 +75,6 @@ ghash-clmulni-intel-y := ghash-clmulni-intel_asm.o ghash-clmulni-intel_glue.o
 obj-$(CONFIG_CRYPTO_POLYVAL_CLMUL_NI) += polyval-clmulni.o
 polyval-clmulni-y := polyval-clmulni_asm.o polyval-clmulni_glue.o
 
-obj-$(CONFIG_CRYPTO_CRCT10DIF_PCLMUL) += crct10dif-pclmul.o
-crct10dif-pclmul-y := crct10dif-pcl-asm_64.o crct10dif-pclmul_glue.o
-
 obj-$(CONFIG_CRYPTO_POLY1305_X86_64) += poly1305-x86_64.o
 poly1305-x86_64-y := poly1305-x86_64-cryptogams.o poly1305_glue.o
 targets += poly1305-x86_64-cryptogams.S
diff --git a/arch/x86/crypto/crct10dif-pcl-asm_64.S b/arch/x86/crypto/crct10dif-pcl-asm_64.S
deleted file mode 100644 (file)
index 5286db5..0000000
+++ /dev/null
@@ -1,332 +0,0 @@
-########################################################################
-# Implement fast CRC-T10DIF computation with SSE and PCLMULQDQ instructions
-#
-# Copyright (c) 2013, Intel Corporation
-#
-# Authors:
-#     Erdinc Ozturk <erdinc.ozturk@intel.com>
-#     Vinodh Gopal <vinodh.gopal@intel.com>
-#     James Guilford <james.guilford@intel.com>
-#     Tim Chen <tim.c.chen@linux.intel.com>
-#
-# This software is available to you under a choice of one of two
-# licenses.  You may choose to be licensed under the terms of the GNU
-# General Public License (GPL) Version 2, available from the file
-# COPYING in the main directory of this source tree, or the
-# OpenIB.org BSD license below:
-#
-# Redistribution and use in source and binary forms, with or without
-# modification, are permitted provided that the following conditions are
-# met:
-#
-# * Redistributions of source code must retain the above copyright
-#   notice, this list of conditions and the following disclaimer.
-#
-# * Redistributions in binary form must reproduce the above copyright
-#   notice, this list of conditions and the following disclaimer in the
-#   documentation and/or other materials provided with the
-#   distribution.
-#
-# * Neither the name of the Intel Corporation nor the names of its
-#   contributors may be used to endorse or promote products derived from
-#   this software without specific prior written permission.
-#
-#
-# THIS SOFTWARE IS PROVIDED BY INTEL CORPORATION ""AS IS"" AND ANY
-# EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
-# IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
-# PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL INTEL CORPORATION OR
-# CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
-# EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
-# PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
-# PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
-# LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
-# NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
-# SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
-#
-#       Reference paper titled "Fast CRC Computation for Generic
-#      Polynomials Using PCLMULQDQ Instruction"
-#       URL: http://www.intel.com/content/dam/www/public/us/en/documents
-#  /white-papers/fast-crc-computation-generic-polynomials-pclmulqdq-paper.pdf
-#
-
-#include <linux/linkage.h>
-
-.text
-
-#define                init_crc        %edi
-#define                buf             %rsi
-#define                len             %rdx
-
-#define                FOLD_CONSTS     %xmm10
-#define                BSWAP_MASK      %xmm11
-
-# Fold reg1, reg2 into the next 32 data bytes, storing the result back into
-# reg1, reg2.
-.macro fold_32_bytes   offset, reg1, reg2
-       movdqu  \offset(buf), %xmm9
-       movdqu  \offset+16(buf), %xmm12
-       pshufb  BSWAP_MASK, %xmm9
-       pshufb  BSWAP_MASK, %xmm12
-       movdqa  \reg1, %xmm8
-       movdqa  \reg2, %xmm13
-       pclmulqdq       $0x00, FOLD_CONSTS, \reg1
-       pclmulqdq       $0x11, FOLD_CONSTS, %xmm8
-       pclmulqdq       $0x00, FOLD_CONSTS, \reg2
-       pclmulqdq       $0x11, FOLD_CONSTS, %xmm13
-       pxor    %xmm9 , \reg1
-       xorps   %xmm8 , \reg1
-       pxor    %xmm12, \reg2
-       xorps   %xmm13, \reg2
-.endm
-
-# Fold src_reg into dst_reg.
-.macro fold_16_bytes   src_reg, dst_reg
-       movdqa  \src_reg, %xmm8
-       pclmulqdq       $0x11, FOLD_CONSTS, \src_reg
-       pclmulqdq       $0x00, FOLD_CONSTS, %xmm8
-       pxor    %xmm8, \dst_reg
-       xorps   \src_reg, \dst_reg
-.endm
-
-#
-# u16 crc_t10dif_pcl(u16 init_crc, const *u8 buf, size_t len);
-#
-# Assumes len >= 16.
-#
-SYM_FUNC_START(crc_t10dif_pcl)
-
-       movdqa  .Lbswap_mask(%rip), BSWAP_MASK
-
-       # For sizes less than 256 bytes, we can't fold 128 bytes at a time.
-       cmp     $256, len
-       jl      .Lless_than_256_bytes
-
-       # Load the first 128 data bytes.  Byte swapping is necessary to make the
-       # bit order match the polynomial coefficient order.
-       movdqu  16*0(buf), %xmm0
-       movdqu  16*1(buf), %xmm1
-       movdqu  16*2(buf), %xmm2
-       movdqu  16*3(buf), %xmm3
-       movdqu  16*4(buf), %xmm4
-       movdqu  16*5(buf), %xmm5
-       movdqu  16*6(buf), %xmm6
-       movdqu  16*7(buf), %xmm7
-       add     $128, buf
-       pshufb  BSWAP_MASK, %xmm0
-       pshufb  BSWAP_MASK, %xmm1
-       pshufb  BSWAP_MASK, %xmm2
-       pshufb  BSWAP_MASK, %xmm3
-       pshufb  BSWAP_MASK, %xmm4
-       pshufb  BSWAP_MASK, %xmm5
-       pshufb  BSWAP_MASK, %xmm6
-       pshufb  BSWAP_MASK, %xmm7
-
-       # XOR the first 16 data *bits* with the initial CRC value.
-       pxor    %xmm8, %xmm8
-       pinsrw  $7, init_crc, %xmm8
-       pxor    %xmm8, %xmm0
-
-       movdqa  .Lfold_across_128_bytes_consts(%rip), FOLD_CONSTS
-
-       # Subtract 128 for the 128 data bytes just consumed.  Subtract another
-       # 128 to simplify the termination condition of the following loop.
-       sub     $256, len
-
-       # While >= 128 data bytes remain (not counting xmm0-7), fold the 128
-       # bytes xmm0-7 into them, storing the result back into xmm0-7.
-.Lfold_128_bytes_loop:
-       fold_32_bytes   0, %xmm0, %xmm1
-       fold_32_bytes   32, %xmm2, %xmm3
-       fold_32_bytes   64, %xmm4, %xmm5
-       fold_32_bytes   96, %xmm6, %xmm7
-       add     $128, buf
-       sub     $128, len
-       jge     .Lfold_128_bytes_loop
-
-       # Now fold the 112 bytes in xmm0-xmm6 into the 16 bytes in xmm7.
-
-       # Fold across 64 bytes.
-       movdqa  .Lfold_across_64_bytes_consts(%rip), FOLD_CONSTS
-       fold_16_bytes   %xmm0, %xmm4
-       fold_16_bytes   %xmm1, %xmm5
-       fold_16_bytes   %xmm2, %xmm6
-       fold_16_bytes   %xmm3, %xmm7
-       # Fold across 32 bytes.
-       movdqa  .Lfold_across_32_bytes_consts(%rip), FOLD_CONSTS
-       fold_16_bytes   %xmm4, %xmm6
-       fold_16_bytes   %xmm5, %xmm7
-       # Fold across 16 bytes.
-       movdqa  .Lfold_across_16_bytes_consts(%rip), FOLD_CONSTS
-       fold_16_bytes   %xmm6, %xmm7
-
-       # Add 128 to get the correct number of data bytes remaining in 0...127
-       # (not counting xmm7), following the previous extra subtraction by 128.
-       # Then subtract 16 to simplify the termination condition of the
-       # following loop.
-       add     $128-16, len
-
-       # While >= 16 data bytes remain (not counting xmm7), fold the 16 bytes
-       # xmm7 into them, storing the result back into xmm7.
-       jl      .Lfold_16_bytes_loop_done
-.Lfold_16_bytes_loop:
-       movdqa  %xmm7, %xmm8
-       pclmulqdq       $0x11, FOLD_CONSTS, %xmm7
-       pclmulqdq       $0x00, FOLD_CONSTS, %xmm8
-       pxor    %xmm8, %xmm7
-       movdqu  (buf), %xmm0
-       pshufb  BSWAP_MASK, %xmm0
-       pxor    %xmm0 , %xmm7
-       add     $16, buf
-       sub     $16, len
-       jge     .Lfold_16_bytes_loop
-
-.Lfold_16_bytes_loop_done:
-       # Add 16 to get the correct number of data bytes remaining in 0...15
-       # (not counting xmm7), following the previous extra subtraction by 16.
-       add     $16, len
-       je      .Lreduce_final_16_bytes
-
-.Lhandle_partial_segment:
-       # Reduce the last '16 + len' bytes where 1 <= len <= 15 and the first 16
-       # bytes are in xmm7 and the rest are the remaining data in 'buf'.  To do
-       # this without needing a fold constant for each possible 'len', redivide
-       # the bytes into a first chunk of 'len' bytes and a second chunk of 16
-       # bytes, then fold the first chunk into the second.
-
-       movdqa  %xmm7, %xmm2
-
-       # xmm1 = last 16 original data bytes
-       movdqu  -16(buf, len), %xmm1
-       pshufb  BSWAP_MASK, %xmm1
-
-       # xmm2 = high order part of second chunk: xmm7 left-shifted by 'len' bytes.
-       lea     .Lbyteshift_table+16(%rip), %rax
-       sub     len, %rax
-       movdqu  (%rax), %xmm0
-       pshufb  %xmm0, %xmm2
-
-       # xmm7 = first chunk: xmm7 right-shifted by '16-len' bytes.
-       pxor    .Lmask1(%rip), %xmm0
-       pshufb  %xmm0, %xmm7
-
-       # xmm1 = second chunk: 'len' bytes from xmm1 (low-order bytes),
-       # then '16-len' bytes from xmm2 (high-order bytes).
-       pblendvb        %xmm2, %xmm1    #xmm0 is implicit
-
-       # Fold the first chunk into the second chunk, storing the result in xmm7.
-       movdqa  %xmm7, %xmm8
-       pclmulqdq       $0x11, FOLD_CONSTS, %xmm7
-       pclmulqdq       $0x00, FOLD_CONSTS, %xmm8
-       pxor    %xmm8, %xmm7
-       pxor    %xmm1, %xmm7
-
-.Lreduce_final_16_bytes:
-       # Reduce the 128-bit value M(x), stored in xmm7, to the final 16-bit CRC
-
-       # Load 'x^48 * (x^48 mod G(x))' and 'x^48 * (x^80 mod G(x))'.
-       movdqa  .Lfinal_fold_consts(%rip), FOLD_CONSTS
-
-       # Fold the high 64 bits into the low 64 bits, while also multiplying by
-       # x^64.  This produces a 128-bit value congruent to x^64 * M(x) and
-       # whose low 48 bits are 0.
-       movdqa  %xmm7, %xmm0
-       pclmulqdq       $0x11, FOLD_CONSTS, %xmm7 # high bits * x^48 * (x^80 mod G(x))
-       pslldq  $8, %xmm0
-       pxor    %xmm0, %xmm7                      # + low bits * x^64
-
-       # Fold the high 32 bits into the low 96 bits.  This produces a 96-bit
-       # value congruent to x^64 * M(x) and whose low 48 bits are 0.
-       movdqa  %xmm7, %xmm0
-       pand    .Lmask2(%rip), %xmm0              # zero high 32 bits
-       psrldq  $12, %xmm7                        # extract high 32 bits
-       pclmulqdq       $0x00, FOLD_CONSTS, %xmm7 # high 32 bits * x^48 * (x^48 mod G(x))
-       pxor    %xmm0, %xmm7                      # + low bits
-
-       # Load G(x) and floor(x^48 / G(x)).
-       movdqa  .Lbarrett_reduction_consts(%rip), FOLD_CONSTS
-
-       # Use Barrett reduction to compute the final CRC value.
-       movdqa  %xmm7, %xmm0
-       pclmulqdq       $0x11, FOLD_CONSTS, %xmm7 # high 32 bits * floor(x^48 / G(x))
-       psrlq   $32, %xmm7                        # /= x^32
-       pclmulqdq       $0x00, FOLD_CONSTS, %xmm7 # *= G(x)
-       psrlq   $48, %xmm0
-       pxor    %xmm7, %xmm0                 # + low 16 nonzero bits
-       # Final CRC value (x^16 * M(x)) mod G(x) is in low 16 bits of xmm0.
-
-       pextrw  $0, %xmm0, %eax
-       RET
-
-.align 16
-.Lless_than_256_bytes:
-       # Checksumming a buffer of length 16...255 bytes
-
-       # Load the first 16 data bytes.
-       movdqu  (buf), %xmm7
-       pshufb  BSWAP_MASK, %xmm7
-       add     $16, buf
-
-       # XOR the first 16 data *bits* with the initial CRC value.
-       pxor    %xmm0, %xmm0
-       pinsrw  $7, init_crc, %xmm0
-       pxor    %xmm0, %xmm7
-
-       movdqa  .Lfold_across_16_bytes_consts(%rip), FOLD_CONSTS
-       cmp     $16, len
-       je      .Lreduce_final_16_bytes         # len == 16
-       sub     $32, len
-       jge     .Lfold_16_bytes_loop            # 32 <= len <= 255
-       add     $16, len
-       jmp     .Lhandle_partial_segment        # 17 <= len <= 31
-SYM_FUNC_END(crc_t10dif_pcl)
-
-.section       .rodata, "a", @progbits
-.align 16
-
-# Fold constants precomputed from the polynomial 0x18bb7
-# G(x) = x^16 + x^15 + x^11 + x^9 + x^8 + x^7 + x^5 + x^4 + x^2 + x^1 + x^0
-.Lfold_across_128_bytes_consts:
-       .quad           0x0000000000006123      # x^(8*128)     mod G(x)
-       .quad           0x0000000000002295      # x^(8*128+64)  mod G(x)
-.Lfold_across_64_bytes_consts:
-       .quad           0x0000000000001069      # x^(4*128)     mod G(x)
-       .quad           0x000000000000dd31      # x^(4*128+64)  mod G(x)
-.Lfold_across_32_bytes_consts:
-       .quad           0x000000000000857d      # x^(2*128)     mod G(x)
-       .quad           0x0000000000007acc      # x^(2*128+64)  mod G(x)
-.Lfold_across_16_bytes_consts:
-       .quad           0x000000000000a010      # x^(1*128)     mod G(x)
-       .quad           0x0000000000001faa      # x^(1*128+64)  mod G(x)
-.Lfinal_fold_consts:
-       .quad           0x1368000000000000      # x^48 * (x^48 mod G(x))
-       .quad           0x2d56000000000000      # x^48 * (x^80 mod G(x))
-.Lbarrett_reduction_consts:
-       .quad           0x0000000000018bb7      # G(x)
-       .quad           0x00000001f65a57f8      # floor(x^48 / G(x))
-
-.section       .rodata.cst16.mask1, "aM", @progbits, 16
-.align 16
-.Lmask1:
-       .octa   0x80808080808080808080808080808080
-
-.section       .rodata.cst16.mask2, "aM", @progbits, 16
-.align 16
-.Lmask2:
-       .octa   0x00000000FFFFFFFFFFFFFFFFFFFFFFFF
-
-.section       .rodata.cst16.bswap_mask, "aM", @progbits, 16
-.align 16
-.Lbswap_mask:
-       .octa   0x000102030405060708090A0B0C0D0E0F
-
-.section       .rodata.cst32.byteshift_table, "aM", @progbits, 32
-.align 16
-# For 1 <= len <= 15, the 16-byte vector beginning at &byteshift_table[16 - len]
-# is the index vector to shift left by 'len' bytes, and is also {0x80, ...,
-# 0x80} XOR the index vector to shift right by '16 - len' bytes.
-.Lbyteshift_table:
-       .byte            0x0, 0x81, 0x82, 0x83, 0x84, 0x85, 0x86, 0x87
-       .byte           0x88, 0x89, 0x8a, 0x8b, 0x8c, 0x8d, 0x8e, 0x8f
-       .byte            0x0,  0x1,  0x2,  0x3,  0x4,  0x5,  0x6,  0x7
-       .byte            0x8,  0x9,  0xa,  0xb,  0xc,  0xd,  0xe , 0x0
diff --git a/arch/x86/crypto/crct10dif-pclmul_glue.c b/arch/x86/crypto/crct10dif-pclmul_glue.c
deleted file mode 100644 (file)
index 71291d5..0000000
+++ /dev/null
@@ -1,143 +0,0 @@
-/*
- * Cryptographic API.
- *
- * T10 Data Integrity Field CRC16 Crypto Transform using PCLMULQDQ Instructions
- *
- * Copyright (C) 2013 Intel Corporation
- * Author: Tim Chen <tim.c.chen@linux.intel.com>
- *
- * This program is free software; you can redistribute it and/or modify it
- * under the terms of the GNU General Public License as published by the Free
- * Software Foundation; either version 2 of the License, or (at your option)
- * any later version.
- *
- * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
- * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
- * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
- * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS
- * BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN
- * ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
- * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
- * SOFTWARE.
- *
- */
-
-#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>
-#include <linux/kernel.h>
-#include <asm/cpufeatures.h>
-#include <asm/cpu_device_id.h>
-#include <asm/simd.h>
-
-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)
-{
-       if (len >= 16 && crypto_simd_usable()) {
-               kernel_fpu_begin();
-               *(__u16 *)out = 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,
-       }
-};
-
-static const struct x86_cpu_id crct10dif_cpu_id[] = {
-       X86_MATCH_FEATURE(X86_FEATURE_PCLMULQDQ, NULL),
-       {}
-};
-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);
-}
-
-static void __exit crct10dif_intel_mod_fini(void)
-{
-       crypto_unregister_shash(&alg);
-}
-
-module_init(crct10dif_intel_mod_init);
-module_exit(crct10dif_intel_mod_fini);
-
-MODULE_AUTHOR("Tim Chen <tim.c.chen@linux.intel.com>");
-MODULE_DESCRIPTION("T10 DIF CRC calculation accelerated with PCLMULQDQ.");
-MODULE_LICENSE("GPL");
-
-MODULE_ALIAS_CRYPTO("crct10dif");
-MODULE_ALIAS_CRYPTO("crct10dif-pclmul");
index 17510da06c9f94aaacffcc7a046d95171ed24759..8a59c61624c2f3f3580fce8231da86393241e7e9 100644 (file)
@@ -42,6 +42,9 @@ obj-$(CONFIG_CRC32_ARCH) += crc32-x86.o
 crc32-x86-y := crc32-glue.o crc32-pclmul.o
 crc32-x86-$(CONFIG_64BIT) += crc32c-3way.o
 
+obj-$(CONFIG_CRC_T10DIF_ARCH) += crc-t10dif-x86.o
+crc-t10dif-x86-y := crc-t10dif-glue.o crct10dif-pcl-asm_64.o
+
 obj-y += msr.o msr-reg.o msr-reg-export.o hweight.o
 obj-y += iomem.o
 
diff --git a/arch/x86/lib/crc-t10dif-glue.c b/arch/x86/lib/crc-t10dif-glue.c
new file mode 100644 (file)
index 0000000..13f07dd
--- /dev/null
@@ -0,0 +1,51 @@
+// SPDX-License-Identifier: GPL-2.0-or-later
+/*
+ * CRC-T10DIF using PCLMULQDQ instructions
+ *
+ * Copyright 2024 Google LLC
+ */
+
+#include <asm/cpufeatures.h>
+#include <asm/simd.h>
+#include <crypto/internal/simd.h>
+#include <linux/crc-t10dif.h>
+#include <linux/module.h>
+
+static DEFINE_STATIC_KEY_FALSE(have_pclmulqdq);
+
+asmlinkage u16 crc_t10dif_pcl(u16 init_crc, const u8 *buf, size_t len);
+
+u16 crc_t10dif_arch(u16 crc, const u8 *p, size_t len)
+{
+       if (len >= 16 &&
+           static_key_enabled(&have_pclmulqdq) && crypto_simd_usable()) {
+               kernel_fpu_begin();
+               crc = crc_t10dif_pcl(crc, p, len);
+               kernel_fpu_end();
+               return crc;
+       }
+       return crc_t10dif_generic(crc, p, len);
+}
+EXPORT_SYMBOL(crc_t10dif_arch);
+
+static int __init crc_t10dif_x86_init(void)
+{
+       if (boot_cpu_has(X86_FEATURE_PCLMULQDQ))
+               static_branch_enable(&have_pclmulqdq);
+       return 0;
+}
+arch_initcall(crc_t10dif_x86_init);
+
+static void __exit crc_t10dif_x86_exit(void)
+{
+}
+module_exit(crc_t10dif_x86_exit);
+
+bool crc_t10dif_is_optimized(void)
+{
+       return static_key_enabled(&have_pclmulqdq);
+}
+EXPORT_SYMBOL(crc_t10dif_is_optimized);
+
+MODULE_DESCRIPTION("CRC-T10DIF using PCLMULQDQ instructions");
+MODULE_LICENSE("GPL");
diff --git a/arch/x86/lib/crct10dif-pcl-asm_64.S b/arch/x86/lib/crct10dif-pcl-asm_64.S
new file mode 100644 (file)
index 0000000..5286db5
--- /dev/null
@@ -0,0 +1,332 @@
+########################################################################
+# Implement fast CRC-T10DIF computation with SSE and PCLMULQDQ instructions
+#
+# Copyright (c) 2013, Intel Corporation
+#
+# Authors:
+#     Erdinc Ozturk <erdinc.ozturk@intel.com>
+#     Vinodh Gopal <vinodh.gopal@intel.com>
+#     James Guilford <james.guilford@intel.com>
+#     Tim Chen <tim.c.chen@linux.intel.com>
+#
+# This software is available to you under a choice of one of two
+# licenses.  You may choose to be licensed under the terms of the GNU
+# General Public License (GPL) Version 2, available from the file
+# COPYING in the main directory of this source tree, or the
+# OpenIB.org BSD license below:
+#
+# Redistribution and use in source and binary forms, with or without
+# modification, are permitted provided that the following conditions are
+# met:
+#
+# * Redistributions of source code must retain the above copyright
+#   notice, this list of conditions and the following disclaimer.
+#
+# * Redistributions in binary form must reproduce the above copyright
+#   notice, this list of conditions and the following disclaimer in the
+#   documentation and/or other materials provided with the
+#   distribution.
+#
+# * Neither the name of the Intel Corporation nor the names of its
+#   contributors may be used to endorse or promote products derived from
+#   this software without specific prior written permission.
+#
+#
+# THIS SOFTWARE IS PROVIDED BY INTEL CORPORATION ""AS IS"" AND ANY
+# EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+# IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
+# PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL INTEL CORPORATION OR
+# CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
+# EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
+# PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
+# PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
+# LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
+# NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
+# SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+#
+#       Reference paper titled "Fast CRC Computation for Generic
+#      Polynomials Using PCLMULQDQ Instruction"
+#       URL: http://www.intel.com/content/dam/www/public/us/en/documents
+#  /white-papers/fast-crc-computation-generic-polynomials-pclmulqdq-paper.pdf
+#
+
+#include <linux/linkage.h>
+
+.text
+
+#define                init_crc        %edi
+#define                buf             %rsi
+#define                len             %rdx
+
+#define                FOLD_CONSTS     %xmm10
+#define                BSWAP_MASK      %xmm11
+
+# Fold reg1, reg2 into the next 32 data bytes, storing the result back into
+# reg1, reg2.
+.macro fold_32_bytes   offset, reg1, reg2
+       movdqu  \offset(buf), %xmm9
+       movdqu  \offset+16(buf), %xmm12
+       pshufb  BSWAP_MASK, %xmm9
+       pshufb  BSWAP_MASK, %xmm12
+       movdqa  \reg1, %xmm8
+       movdqa  \reg2, %xmm13
+       pclmulqdq       $0x00, FOLD_CONSTS, \reg1
+       pclmulqdq       $0x11, FOLD_CONSTS, %xmm8
+       pclmulqdq       $0x00, FOLD_CONSTS, \reg2
+       pclmulqdq       $0x11, FOLD_CONSTS, %xmm13
+       pxor    %xmm9 , \reg1
+       xorps   %xmm8 , \reg1
+       pxor    %xmm12, \reg2
+       xorps   %xmm13, \reg2
+.endm
+
+# Fold src_reg into dst_reg.
+.macro fold_16_bytes   src_reg, dst_reg
+       movdqa  \src_reg, %xmm8
+       pclmulqdq       $0x11, FOLD_CONSTS, \src_reg
+       pclmulqdq       $0x00, FOLD_CONSTS, %xmm8
+       pxor    %xmm8, \dst_reg
+       xorps   \src_reg, \dst_reg
+.endm
+
+#
+# u16 crc_t10dif_pcl(u16 init_crc, const *u8 buf, size_t len);
+#
+# Assumes len >= 16.
+#
+SYM_FUNC_START(crc_t10dif_pcl)
+
+       movdqa  .Lbswap_mask(%rip), BSWAP_MASK
+
+       # For sizes less than 256 bytes, we can't fold 128 bytes at a time.
+       cmp     $256, len
+       jl      .Lless_than_256_bytes
+
+       # Load the first 128 data bytes.  Byte swapping is necessary to make the
+       # bit order match the polynomial coefficient order.
+       movdqu  16*0(buf), %xmm0
+       movdqu  16*1(buf), %xmm1
+       movdqu  16*2(buf), %xmm2
+       movdqu  16*3(buf), %xmm3
+       movdqu  16*4(buf), %xmm4
+       movdqu  16*5(buf), %xmm5
+       movdqu  16*6(buf), %xmm6
+       movdqu  16*7(buf), %xmm7
+       add     $128, buf
+       pshufb  BSWAP_MASK, %xmm0
+       pshufb  BSWAP_MASK, %xmm1
+       pshufb  BSWAP_MASK, %xmm2
+       pshufb  BSWAP_MASK, %xmm3
+       pshufb  BSWAP_MASK, %xmm4
+       pshufb  BSWAP_MASK, %xmm5
+       pshufb  BSWAP_MASK, %xmm6
+       pshufb  BSWAP_MASK, %xmm7
+
+       # XOR the first 16 data *bits* with the initial CRC value.
+       pxor    %xmm8, %xmm8
+       pinsrw  $7, init_crc, %xmm8
+       pxor    %xmm8, %xmm0
+
+       movdqa  .Lfold_across_128_bytes_consts(%rip), FOLD_CONSTS
+
+       # Subtract 128 for the 128 data bytes just consumed.  Subtract another
+       # 128 to simplify the termination condition of the following loop.
+       sub     $256, len
+
+       # While >= 128 data bytes remain (not counting xmm0-7), fold the 128
+       # bytes xmm0-7 into them, storing the result back into xmm0-7.
+.Lfold_128_bytes_loop:
+       fold_32_bytes   0, %xmm0, %xmm1
+       fold_32_bytes   32, %xmm2, %xmm3
+       fold_32_bytes   64, %xmm4, %xmm5
+       fold_32_bytes   96, %xmm6, %xmm7
+       add     $128, buf
+       sub     $128, len
+       jge     .Lfold_128_bytes_loop
+
+       # Now fold the 112 bytes in xmm0-xmm6 into the 16 bytes in xmm7.
+
+       # Fold across 64 bytes.
+       movdqa  .Lfold_across_64_bytes_consts(%rip), FOLD_CONSTS
+       fold_16_bytes   %xmm0, %xmm4
+       fold_16_bytes   %xmm1, %xmm5
+       fold_16_bytes   %xmm2, %xmm6
+       fold_16_bytes   %xmm3, %xmm7
+       # Fold across 32 bytes.
+       movdqa  .Lfold_across_32_bytes_consts(%rip), FOLD_CONSTS
+       fold_16_bytes   %xmm4, %xmm6
+       fold_16_bytes   %xmm5, %xmm7
+       # Fold across 16 bytes.
+       movdqa  .Lfold_across_16_bytes_consts(%rip), FOLD_CONSTS
+       fold_16_bytes   %xmm6, %xmm7
+
+       # Add 128 to get the correct number of data bytes remaining in 0...127
+       # (not counting xmm7), following the previous extra subtraction by 128.
+       # Then subtract 16 to simplify the termination condition of the
+       # following loop.
+       add     $128-16, len
+
+       # While >= 16 data bytes remain (not counting xmm7), fold the 16 bytes
+       # xmm7 into them, storing the result back into xmm7.
+       jl      .Lfold_16_bytes_loop_done
+.Lfold_16_bytes_loop:
+       movdqa  %xmm7, %xmm8
+       pclmulqdq       $0x11, FOLD_CONSTS, %xmm7
+       pclmulqdq       $0x00, FOLD_CONSTS, %xmm8
+       pxor    %xmm8, %xmm7
+       movdqu  (buf), %xmm0
+       pshufb  BSWAP_MASK, %xmm0
+       pxor    %xmm0 , %xmm7
+       add     $16, buf
+       sub     $16, len
+       jge     .Lfold_16_bytes_loop
+
+.Lfold_16_bytes_loop_done:
+       # Add 16 to get the correct number of data bytes remaining in 0...15
+       # (not counting xmm7), following the previous extra subtraction by 16.
+       add     $16, len
+       je      .Lreduce_final_16_bytes
+
+.Lhandle_partial_segment:
+       # Reduce the last '16 + len' bytes where 1 <= len <= 15 and the first 16
+       # bytes are in xmm7 and the rest are the remaining data in 'buf'.  To do
+       # this without needing a fold constant for each possible 'len', redivide
+       # the bytes into a first chunk of 'len' bytes and a second chunk of 16
+       # bytes, then fold the first chunk into the second.
+
+       movdqa  %xmm7, %xmm2
+
+       # xmm1 = last 16 original data bytes
+       movdqu  -16(buf, len), %xmm1
+       pshufb  BSWAP_MASK, %xmm1
+
+       # xmm2 = high order part of second chunk: xmm7 left-shifted by 'len' bytes.
+       lea     .Lbyteshift_table+16(%rip), %rax
+       sub     len, %rax
+       movdqu  (%rax), %xmm0
+       pshufb  %xmm0, %xmm2
+
+       # xmm7 = first chunk: xmm7 right-shifted by '16-len' bytes.
+       pxor    .Lmask1(%rip), %xmm0
+       pshufb  %xmm0, %xmm7
+
+       # xmm1 = second chunk: 'len' bytes from xmm1 (low-order bytes),
+       # then '16-len' bytes from xmm2 (high-order bytes).
+       pblendvb        %xmm2, %xmm1    #xmm0 is implicit
+
+       # Fold the first chunk into the second chunk, storing the result in xmm7.
+       movdqa  %xmm7, %xmm8
+       pclmulqdq       $0x11, FOLD_CONSTS, %xmm7
+       pclmulqdq       $0x00, FOLD_CONSTS, %xmm8
+       pxor    %xmm8, %xmm7
+       pxor    %xmm1, %xmm7
+
+.Lreduce_final_16_bytes:
+       # Reduce the 128-bit value M(x), stored in xmm7, to the final 16-bit CRC
+
+       # Load 'x^48 * (x^48 mod G(x))' and 'x^48 * (x^80 mod G(x))'.
+       movdqa  .Lfinal_fold_consts(%rip), FOLD_CONSTS
+
+       # Fold the high 64 bits into the low 64 bits, while also multiplying by
+       # x^64.  This produces a 128-bit value congruent to x^64 * M(x) and
+       # whose low 48 bits are 0.
+       movdqa  %xmm7, %xmm0
+       pclmulqdq       $0x11, FOLD_CONSTS, %xmm7 # high bits * x^48 * (x^80 mod G(x))
+       pslldq  $8, %xmm0
+       pxor    %xmm0, %xmm7                      # + low bits * x^64
+
+       # Fold the high 32 bits into the low 96 bits.  This produces a 96-bit
+       # value congruent to x^64 * M(x) and whose low 48 bits are 0.
+       movdqa  %xmm7, %xmm0
+       pand    .Lmask2(%rip), %xmm0              # zero high 32 bits
+       psrldq  $12, %xmm7                        # extract high 32 bits
+       pclmulqdq       $0x00, FOLD_CONSTS, %xmm7 # high 32 bits * x^48 * (x^48 mod G(x))
+       pxor    %xmm0, %xmm7                      # + low bits
+
+       # Load G(x) and floor(x^48 / G(x)).
+       movdqa  .Lbarrett_reduction_consts(%rip), FOLD_CONSTS
+
+       # Use Barrett reduction to compute the final CRC value.
+       movdqa  %xmm7, %xmm0
+       pclmulqdq       $0x11, FOLD_CONSTS, %xmm7 # high 32 bits * floor(x^48 / G(x))
+       psrlq   $32, %xmm7                        # /= x^32
+       pclmulqdq       $0x00, FOLD_CONSTS, %xmm7 # *= G(x)
+       psrlq   $48, %xmm0
+       pxor    %xmm7, %xmm0                 # + low 16 nonzero bits
+       # Final CRC value (x^16 * M(x)) mod G(x) is in low 16 bits of xmm0.
+
+       pextrw  $0, %xmm0, %eax
+       RET
+
+.align 16
+.Lless_than_256_bytes:
+       # Checksumming a buffer of length 16...255 bytes
+
+       # Load the first 16 data bytes.
+       movdqu  (buf), %xmm7
+       pshufb  BSWAP_MASK, %xmm7
+       add     $16, buf
+
+       # XOR the first 16 data *bits* with the initial CRC value.
+       pxor    %xmm0, %xmm0
+       pinsrw  $7, init_crc, %xmm0
+       pxor    %xmm0, %xmm7
+
+       movdqa  .Lfold_across_16_bytes_consts(%rip), FOLD_CONSTS
+       cmp     $16, len
+       je      .Lreduce_final_16_bytes         # len == 16
+       sub     $32, len
+       jge     .Lfold_16_bytes_loop            # 32 <= len <= 255
+       add     $16, len
+       jmp     .Lhandle_partial_segment        # 17 <= len <= 31
+SYM_FUNC_END(crc_t10dif_pcl)
+
+.section       .rodata, "a", @progbits
+.align 16
+
+# Fold constants precomputed from the polynomial 0x18bb7
+# G(x) = x^16 + x^15 + x^11 + x^9 + x^8 + x^7 + x^5 + x^4 + x^2 + x^1 + x^0
+.Lfold_across_128_bytes_consts:
+       .quad           0x0000000000006123      # x^(8*128)     mod G(x)
+       .quad           0x0000000000002295      # x^(8*128+64)  mod G(x)
+.Lfold_across_64_bytes_consts:
+       .quad           0x0000000000001069      # x^(4*128)     mod G(x)
+       .quad           0x000000000000dd31      # x^(4*128+64)  mod G(x)
+.Lfold_across_32_bytes_consts:
+       .quad           0x000000000000857d      # x^(2*128)     mod G(x)
+       .quad           0x0000000000007acc      # x^(2*128+64)  mod G(x)
+.Lfold_across_16_bytes_consts:
+       .quad           0x000000000000a010      # x^(1*128)     mod G(x)
+       .quad           0x0000000000001faa      # x^(1*128+64)  mod G(x)
+.Lfinal_fold_consts:
+       .quad           0x1368000000000000      # x^48 * (x^48 mod G(x))
+       .quad           0x2d56000000000000      # x^48 * (x^80 mod G(x))
+.Lbarrett_reduction_consts:
+       .quad           0x0000000000018bb7      # G(x)
+       .quad           0x00000001f65a57f8      # floor(x^48 / G(x))
+
+.section       .rodata.cst16.mask1, "aM", @progbits, 16
+.align 16
+.Lmask1:
+       .octa   0x80808080808080808080808080808080
+
+.section       .rodata.cst16.mask2, "aM", @progbits, 16
+.align 16
+.Lmask2:
+       .octa   0x00000000FFFFFFFFFFFFFFFFFFFFFFFF
+
+.section       .rodata.cst16.bswap_mask, "aM", @progbits, 16
+.align 16
+.Lbswap_mask:
+       .octa   0x000102030405060708090A0B0C0D0E0F
+
+.section       .rodata.cst32.byteshift_table, "aM", @progbits, 32
+.align 16
+# For 1 <= len <= 15, the 16-byte vector beginning at &byteshift_table[16 - len]
+# is the index vector to shift left by 'len' bytes, and is also {0x80, ...,
+# 0x80} XOR the index vector to shift right by '16 - len' bytes.
+.Lbyteshift_table:
+       .byte            0x0, 0x81, 0x82, 0x83, 0x84, 0x85, 0x86, 0x87
+       .byte           0x88, 0x89, 0x8a, 0x8b, 0x8c, 0x8d, 0x8e, 0x8f
+       .byte            0x0,  0x1,  0x2,  0x3,  0x4,  0x5,  0x6,  0x7
+       .byte            0x8,  0x9,  0xa,  0xb,  0xc,  0xd,  0xe , 0x0