Branch data Line data Source code
1 : : /* SPDX-License-Identifier: BSD-3-Clause 2 : : * Copyright (C) 2017 Intel Corporation. 3 : : * All rights reserved. 4 : : */ 5 : : 6 : : #include "util_internal.h" 7 : : #include "crc_internal.h" 8 : : #include "spdk/crc32.h" 9 : : 10 : : #ifdef SPDK_HAVE_ISAL 11 : : 12 : : uint32_t 13 : 195649392 : spdk_crc32c_update(const void *buf, size_t len, uint32_t crc) 14 : : { 15 : 195649392 : return crc32_iscsi((unsigned char *)buf, len, crc); 16 : : } 17 : : 18 : : #elif defined(SPDK_HAVE_SSE4_2) 19 : : 20 : : uint32_t 21 : 1933230 : spdk_crc32c_update(const void *buf, size_t len, uint32_t crc) 22 : : { 23 : : size_t count_pre, count_post, count_mid; 24 : : const uint64_t *dword_buf; 25 : : uint64_t crc_tmp64; 26 : : 27 : : /* process the head and tail bytes seperately to make the buf address 28 : : * passed to _mm_crc32_u64 is 8 byte aligned. This can avoid unaligned loads. 29 : : */ 30 [ + + ]: 1933230 : count_pre = ((uint64_t)buf & 7) == 0 ? 0 : 8 - ((uint64_t)buf & 7); 31 : 1933230 : count_post = (uint64_t)((uintptr_t)buf + len) & 7; 32 : 1933230 : count_mid = (len - count_pre - count_post) / 8; 33 : : 34 [ + + ]: 1933535 : while (count_pre--) { 35 : 305 : crc = _mm_crc32_u8(crc, *(const uint8_t *)buf); 36 : 305 : buf = (uint8_t *)buf + 1; 37 : : } 38 : : 39 : : /* _mm_crc32_u64() needs a 64-bit intermediate value */ 40 : 1933230 : crc_tmp64 = crc; 41 : 1933230 : dword_buf = (const uint64_t *)buf; 42 : : 43 [ + + ]: 991450994 : while (count_mid--) { 44 : 989517764 : crc_tmp64 = _mm_crc32_u64(crc_tmp64, *dword_buf); 45 : 989517764 : dword_buf++; 46 : : } 47 : : 48 : 1933230 : buf = dword_buf; 49 : 1933230 : crc = (uint32_t)crc_tmp64; 50 [ + + ]: 2011193 : while (count_post--) { 51 : 77963 : crc = _mm_crc32_u8(crc, *(const uint8_t *)buf); 52 : 77963 : buf = (uint8_t *)buf + 1; 53 : : } 54 : : 55 : 1933230 : return crc; 56 : : } 57 : : 58 : : #elif defined(SPDK_HAVE_ARM_CRC) 59 : : 60 : : uint32_t 61 : : spdk_crc32c_update(const void *buf, size_t len, uint32_t crc) 62 : : { 63 : : size_t count_pre, count_post, count_mid; 64 : : const uint64_t *dword_buf; 65 : : 66 : : /* process the head and tail bytes seperately to make the buf address 67 : : * passed to crc32_cd is 8 byte aligned. This can avoid unaligned loads. 68 : : */ 69 : : count_pre = ((uint64_t)buf & 7) == 0 ? 0 : 8 - ((uint64_t)buf & 7); 70 : : count_post = (uint64_t)(buf + len) & 7; 71 : : count_mid = (len - count_pre - count_post) / 8; 72 : : 73 : : while (count_pre--) { 74 : : crc = __crc32cb(crc, *(const uint8_t *)buf); 75 : : buf++; 76 : : } 77 : : 78 : : dword_buf = (const uint64_t *)buf; 79 : : while (count_mid--) { 80 : : crc = __crc32cd(crc, *dword_buf); 81 : : dword_buf++; 82 : : } 83 : : 84 : : buf = dword_buf; 85 : : while (count_post--) { 86 : : crc = __crc32cb(crc, *(const uint8_t *)buf); 87 : : buf++; 88 : : } 89 : : 90 : : return crc; 91 : : } 92 : : 93 : : #else /* Neither SSE 4.2 nor ARM CRC32 instructions available */ 94 : : 95 : : static struct spdk_crc32_table g_crc32c_table; 96 : : 97 : : __attribute__((constructor)) static void 98 : : crc32c_init(void) 99 : : { 100 : : crc32_table_init(&g_crc32c_table, SPDK_CRC32C_POLYNOMIAL_REFLECT); 101 : : } 102 : : 103 : : uint32_t 104 : : spdk_crc32c_update(const void *buf, size_t len, uint32_t crc) 105 : : { 106 : : return crc32_update(&g_crc32c_table, buf, len, crc); 107 : : } 108 : : 109 : : #endif 110 : : 111 : : uint32_t 112 : 134258080 : spdk_crc32c_iov_update(struct iovec *iov, int iovcnt, uint32_t crc32c) 113 : : { 114 : : int i; 115 : : 116 [ - + ]: 134258080 : if (iov == NULL) { 117 : 0 : return crc32c; 118 : : } 119 : : 120 [ + + ]: 324064695 : for (i = 0; i < iovcnt; i++) { 121 [ - + ]: 189806625 : assert(iov[i].iov_base != NULL); 122 [ - + ]: 189806625 : assert(iov[i].iov_len != 0); 123 : 189806625 : crc32c = spdk_crc32c_update(iov[i].iov_base, iov[i].iov_len, crc32c); 124 : : } 125 : : 126 : 134258080 : return crc32c; 127 : : } 128 : : 129 : : uint32_t 130 : 9676 : spdk_crc32c_nvme(const void *buf, size_t len, uint32_t crc) 131 : : { 132 : 9676 : return ~(spdk_crc32c_update(buf, len, ~crc)); 133 : : }