Back to home page

OSCL-LXR

 
 

    


0001 /* SPDX-License-Identifier: GPL-2.0 */
0002 /*
0003  * Hardware-accelerated CRC-32 variants for Linux on z Systems
0004  *
0005  * Use the z/Architecture Vector Extension Facility to accelerate the
0006  * computing of CRC-32 checksums.
0007  *
0008  * This CRC-32 implementation algorithm processes the most-significant
0009  * bit first (BE).
0010  *
0011  * Copyright IBM Corp. 2015
0012  * Author(s): Hendrik Brueckner <brueckner@linux.vnet.ibm.com>
0013  */
0014 
0015 #include <linux/linkage.h>
0016 #include <asm/nospec-insn.h>
0017 #include <asm/vx-insn.h>
0018 
0019 /* Vector register range containing CRC-32 constants */
0020 #define CONST_R1R2      %v9
0021 #define CONST_R3R4      %v10
0022 #define CONST_R5        %v11
0023 #define CONST_R6        %v12
0024 #define CONST_RU_POLY       %v13
0025 #define CONST_CRC_POLY      %v14
0026 
0027 .data
0028 .align 8
0029 
0030 /*
0031  * The CRC-32 constant block contains reduction constants to fold and
0032  * process particular chunks of the input data stream in parallel.
0033  *
0034  * For the CRC-32 variants, the constants are precomputed according to
0035  * these definitions:
0036  *
0037  *  R1 = x4*128+64 mod P(x)
0038  *  R2 = x4*128    mod P(x)
0039  *  R3 = x128+64   mod P(x)
0040  *  R4 = x128      mod P(x)
0041  *  R5 = x96       mod P(x)
0042  *  R6 = x64       mod P(x)
0043  *
0044  *  Barret reduction constant, u, is defined as floor(x**64 / P(x)).
0045  *
0046  *  where P(x) is the polynomial in the normal domain and the P'(x) is the
0047  *  polynomial in the reversed (bitreflected) domain.
0048  *
0049  * Note that the constant definitions below are extended in order to compute
0050  * intermediate results with a single VECTOR GALOIS FIELD MULTIPLY instruction.
0051  * The righmost doubleword can be 0 to prevent contribution to the result or
0052  * can be multiplied by 1 to perform an XOR without the need for a separate
0053  * VECTOR EXCLUSIVE OR instruction.
0054  *
0055  * CRC-32 (IEEE 802.3 Ethernet, ...) polynomials:
0056  *
0057  *  P(x)  = 0x04C11DB7
0058  *  P'(x) = 0xEDB88320
0059  */
0060 
0061 .Lconstants_CRC_32_BE:
0062     .quad       0x08833794c, 0x0e6228b11    # R1, R2
0063     .quad       0x0c5b9cd4c, 0x0e8a45605    # R3, R4
0064     .quad       0x0f200aa66, 1 << 32        # R5, x32
0065     .quad       0x0490d678d, 1          # R6, 1
0066     .quad       0x104d101df, 0          # u
0067     .quad       0x104C11DB7, 0          # P(x)
0068 
0069 .previous
0070 
0071     GEN_BR_THUNK %r14
0072 
0073 .text
0074 /*
0075  * The CRC-32 function(s) use these calling conventions:
0076  *
0077  * Parameters:
0078  *
0079  *  %r2:    Initial CRC value, typically ~0; and final CRC (return) value.
0080  *  %r3:    Input buffer pointer, performance might be improved if the
0081  *      buffer is on a doubleword boundary.
0082  *  %r4:    Length of the buffer, must be 64 bytes or greater.
0083  *
0084  * Register usage:
0085  *
0086  *  %r5:    CRC-32 constant pool base pointer.
0087  *  V0: Initial CRC value and intermediate constants and results.
0088  *  V1..V4: Data for CRC computation.
0089  *  V5..V8: Next data chunks that are fetched from the input buffer.
0090  *
0091  *  V9..V14: CRC-32 constants.
0092  */
0093 ENTRY(crc32_be_vgfm_16)
0094     /* Load CRC-32 constants */
0095     larl    %r5,.Lconstants_CRC_32_BE
0096     VLM CONST_R1R2,CONST_CRC_POLY,0,%r5
0097 
0098     /* Load the initial CRC value into the leftmost word of V0. */
0099     VZERO   %v0
0100     VLVGF   %v0,%r2,0
0101 
0102     /* Load a 64-byte data chunk and XOR with CRC */
0103     VLM %v1,%v4,0,%r3       /* 64-bytes into V1..V4 */
0104     VX  %v1,%v0,%v1     /* V1 ^= CRC */
0105     aghi    %r3,64          /* BUF = BUF + 64 */
0106     aghi    %r4,-64         /* LEN = LEN - 64 */
0107 
0108     /* Check remaining buffer size and jump to proper folding method */
0109     cghi    %r4,64
0110     jl  .Lless_than_64bytes
0111 
0112 .Lfold_64bytes_loop:
0113     /* Load the next 64-byte data chunk into V5 to V8 */
0114     VLM %v5,%v8,0,%r3
0115 
0116     /*
0117      * Perform a GF(2) multiplication of the doublewords in V1 with
0118      * the reduction constants in V0.  The intermediate result is
0119      * then folded (accumulated) with the next data chunk in V5 and
0120      * stored in V1.  Repeat this step for the register contents
0121      * in V2, V3, and V4 respectively.
0122      */
0123     VGFMAG  %v1,CONST_R1R2,%v1,%v5
0124     VGFMAG  %v2,CONST_R1R2,%v2,%v6
0125     VGFMAG  %v3,CONST_R1R2,%v3,%v7
0126     VGFMAG  %v4,CONST_R1R2,%v4,%v8
0127 
0128     /* Adjust buffer pointer and length for next loop */
0129     aghi    %r3,64          /* BUF = BUF + 64 */
0130     aghi    %r4,-64         /* LEN = LEN - 64 */
0131 
0132     cghi    %r4,64
0133     jnl .Lfold_64bytes_loop
0134 
0135 .Lless_than_64bytes:
0136     /* Fold V1 to V4 into a single 128-bit value in V1 */
0137     VGFMAG  %v1,CONST_R3R4,%v1,%v2
0138     VGFMAG  %v1,CONST_R3R4,%v1,%v3
0139     VGFMAG  %v1,CONST_R3R4,%v1,%v4
0140 
0141     /* Check whether to continue with 64-bit folding */
0142     cghi    %r4,16
0143     jl  .Lfinal_fold
0144 
0145 .Lfold_16bytes_loop:
0146 
0147     VL  %v2,0,,%r3      /* Load next data chunk */
0148     VGFMAG  %v1,CONST_R3R4,%v1,%v2  /* Fold next data chunk */
0149 
0150     /* Adjust buffer pointer and size for folding next data chunk */
0151     aghi    %r3,16
0152     aghi    %r4,-16
0153 
0154     /* Process remaining data chunks */
0155     cghi    %r4,16
0156     jnl .Lfold_16bytes_loop
0157 
0158 .Lfinal_fold:
0159     /*
0160      * The R5 constant is used to fold a 128-bit value into an 96-bit value
0161      * that is XORed with the next 96-bit input data chunk.  To use a single
0162      * VGFMG instruction, multiply the rightmost 64-bit with x^32 (1<<32) to
0163      * form an intermediate 96-bit value (with appended zeros) which is then
0164      * XORed with the intermediate reduction result.
0165      */
0166     VGFMG   %v1,CONST_R5,%v1
0167 
0168     /*
0169      * Further reduce the remaining 96-bit value to a 64-bit value using a
0170      * single VGFMG, the rightmost doubleword is multiplied with 0x1. The
0171      * intermediate result is then XORed with the product of the leftmost
0172      * doubleword with R6.  The result is a 64-bit value and is subject to
0173      * the Barret reduction.
0174      */
0175     VGFMG   %v1,CONST_R6,%v1
0176 
0177     /*
0178      * The input values to the Barret reduction are the degree-63 polynomial
0179      * in V1 (R(x)), degree-32 generator polynomial, and the reduction
0180      * constant u.  The Barret reduction result is the CRC value of R(x) mod
0181      * P(x).
0182      *
0183      * The Barret reduction algorithm is defined as:
0184      *
0185      *    1. T1(x) = floor( R(x) / x^32 ) GF2MUL u
0186      *    2. T2(x) = floor( T1(x) / x^32 ) GF2MUL P(x)
0187      *    3. C(x)  = R(x) XOR T2(x) mod x^32
0188      *
0189      * Note: To compensate the division by x^32, use the vector unpack
0190      * instruction to move the leftmost word into the leftmost doubleword
0191      * of the vector register.  The rightmost doubleword is multiplied
0192      * with zero to not contribute to the intermediate results.
0193      */
0194 
0195     /* T1(x) = floor( R(x) / x^32 ) GF2MUL u */
0196     VUPLLF  %v2,%v1
0197     VGFMG   %v2,CONST_RU_POLY,%v2
0198 
0199     /*
0200      * Compute the GF(2) product of the CRC polynomial in VO with T1(x) in
0201      * V2 and XOR the intermediate result, T2(x),  with the value in V1.
0202      * The final result is in the rightmost word of V2.
0203      */
0204     VUPLLF  %v2,%v2
0205     VGFMAG  %v2,CONST_CRC_POLY,%v2,%v1
0206 
0207 .Ldone:
0208     VLGVF   %r2,%v2,3
0209     BR_EX   %r14
0210 ENDPROC(crc32_be_vgfm_16)
0211 
0212 .previous