3 #define CRC32C3X8(ITR) \
4 crc1 = __crc32cd(crc1, *((const uint64_t *)data + 42*1 + (ITR)));\
5 crc2 = __crc32cd(crc2, *((const uint64_t *)data + 42*2 + (ITR)));\
6 crc0 = __crc32cd(crc0, *((const uint64_t *)data + 42*0 + (ITR)));
8 #define CRC32C7X3X8(ITR) do {\
10 CRC32C3X8((ITR)*7+1) \
11 CRC32C3X8((ITR)*7+2) \
12 CRC32C3X8((ITR)*7+3) \
13 CRC32C3X8((ITR)*7+4) \
14 CRC32C3X8((ITR)*7+5) \
15 CRC32C3X8((ITR)*7+6) \
19 #define HWCAP_CRC32 (1 << 7)
20 #endif /* HWCAP_CRC32 */
22 bool crc32c_arm64_available = false;
24 #ifdef ARCH_HAVE_ARM64_CRC_CRYPTO
30 static bool crc32c_probed;
33 * Function to calculate reflected crc with PMULL Instruction
34 * crc done "by 3" for fixed input block size of 1024 bytes
36 uint32_t crc32c_arm64(unsigned char const *data, unsigned long length)
38 signed long len = length;
40 uint32_t crc0, crc1, crc2;
42 /* Load two consts: K1 and K2 */
43 const poly64_t k1 = 0xe417f38a, k2 = 0x8f158014;
46 while ((len -= 1024) >= 0) {
47 /* Do first 8 bytes here for better pipelining */
48 crc0 = __crc32cd(crc, *(const uint64_t *)data);
51 data += sizeof(uint64_t);
53 /* Process block inline
54 Process crc0 last to avoid dependency with above */
62 data += 42*3*sizeof(uint64_t);
64 /* Merge crc0 and crc1 into crc2
66 crc0 multiply by K1 */
68 t1 = (uint64_t)vmull_p64(crc1, k2);
69 t0 = (uint64_t)vmull_p64(crc0, k1);
70 crc = __crc32cd(crc2, *(const uint64_t *)data);
71 crc1 = __crc32cd(0, t1);
73 crc0 = __crc32cd(0, t0);
76 data += sizeof(uint64_t);
82 while ((len -= sizeof(uint64_t)) >= 0) {
83 crc = __crc32cd(crc, *(const uint64_t *)data);
84 data += sizeof(uint64_t);
87 /* The following is more efficient than the straight loop */
88 if (len & sizeof(uint32_t)) {
89 crc = __crc32cw(crc, *(const uint32_t *)data);
90 data += sizeof(uint32_t);
92 if (len & sizeof(uint16_t)) {
93 crc = __crc32ch(crc, *(const uint16_t *)data);
94 data += sizeof(uint16_t);
96 if (len & sizeof(uint8_t)) {
97 crc = __crc32cb(crc, *(const uint8_t *)data);
103 void crc32c_arm64_probe(void)
107 if (!crc32c_probed) {
108 hwcap = getauxval(AT_HWCAP);
109 crc32c_arm64_available = (hwcap & HWCAP_CRC32) != 0;
110 crc32c_probed = true;
114 #endif /* ARCH_HAVE_ARM64_CRC_CRYPTO */