Branch data Line data Source code
1 : : /* SPDX-License-Identifier: BSD-3-Clause
2 : : * Copyright (C) 2022 Intel Corporation.
3 : : * All rights reserved.
4 : : */
5 : :
6 : : #include "spdk/xor.h"
7 : : #include "spdk/config.h"
8 : : #include "spdk/assert.h"
9 : : #include "spdk/util.h"
10 : :
11 : : /* maximum number of source buffers */
12 : : #define SPDK_XOR_MAX_SRC 256
13 : :
14 : : static inline bool
15 : 215138467 : is_aligned(void *ptr, size_t alignment)
16 : : {
17 : 215138467 : uintptr_t p = (uintptr_t)ptr;
18 : :
19 : 215138467 : return p == SPDK_ALIGN_FLOOR(p, alignment);
20 : : }
21 : :
22 : : static bool
23 : 61904384 : buffers_aligned(void *dest, void **sources, uint32_t n, size_t alignment)
24 : : {
25 : : uint32_t i;
26 : :
27 [ + + ]: 215138467 : for (i = 0; i < n; i++) {
28 [ + + ]: 153296570 : if (!is_aligned(sources[i], alignment)) {
29 : 62487 : return false;
30 : : }
31 : : }
32 : :
33 : 61841897 : return is_aligned(dest, alignment);
34 : : }
35 : :
36 : : static void
37 : 31741 : xor_gen_unaligned(void *dest, void **sources, uint32_t n, uint32_t len)
38 : : {
39 : : uint32_t i, j;
40 : :
41 [ + + ]: 216617368 : for (i = 0; i < len; i++) {
42 : 216585363 : uint8_t b = 0;
43 : :
44 [ + + ]: 918874904 : for (j = 0; j < n; j++) {
45 : 702289541 : b ^= ((uint8_t *)sources[j])[i];
46 : : }
47 : 216585363 : ((uint8_t *)dest)[i] = b;
48 : : }
49 : 31741 : }
50 : :
51 : : static void
52 : 289500 : xor_gen_basic(void *dest, void **sources, uint32_t n, uint32_t len)
53 : : {
54 : : uint32_t shift;
55 : : uint32_t len_div, len_rem;
56 : : uint32_t i, j;
57 : :
58 [ + + ]: 289500 : if (!buffers_aligned(dest, sources, n, sizeof(uint64_t))) {
59 : 28416 : xor_gen_unaligned(dest, sources, n, len);
60 : 28416 : return;
61 : : }
62 : :
63 : 261084 : shift = spdk_u32log2(sizeof(uint64_t));
64 [ - + ]: 261084 : len_div = len >> shift;
65 [ - + ]: 261084 : len_rem = len_div << shift;
66 : :
67 [ + + ]: 134190629 : for (i = 0; i < len_div; i++) {
68 : 133929551 : uint64_t w = 0;
69 : :
70 [ + + ]: 460905348 : for (j = 0; j < n; j++) {
71 : 326975817 : w ^= ((uint64_t *)sources[j])[i];
72 : : }
73 : 133929551 : ((uint64_t *)dest)[i] = w;
74 : : }
75 : :
76 [ + + ]: 261084 : if (len_rem < len) {
77 : 3325 : void *sources2[SPDK_XOR_MAX_SRC];
78 : :
79 [ + + ]: 14620 : for (j = 0; j < n; j++) {
80 : 11295 : sources2[j] = (uint8_t *)sources[j] + len_rem;
81 : : }
82 : :
83 : 3325 : xor_gen_unaligned((uint8_t *)dest + len_rem, sources2, n, len - len_rem);
84 : : }
85 : : }
86 : :
87 : : #ifdef SPDK_CONFIG_ISAL
88 : : #include "isa-l/include/raid.h"
89 : :
90 : : #define SPDK_XOR_BUF_ALIGN 32
91 : :
92 : : static int
93 : 61614882 : do_xor_gen(void *dest, void **sources, uint32_t n, uint32_t len)
94 : : {
95 [ + + ]: 61614882 : if (buffers_aligned(dest, sources, n, SPDK_XOR_BUF_ALIGN)) {
96 : 21455241 : void *buffers[SPDK_XOR_MAX_SRC + 1];
97 : :
98 [ - + ]: 61580809 : if (n >= INT_MAX) {
99 : 0 : return -EINVAL;
100 : : }
101 : :
102 [ - + - + ]: 61580809 : memcpy(buffers, sources, n * sizeof(buffers[0]));
103 : 61580809 : buffers[n] = dest;
104 : :
105 [ - + ]: 61580809 : if (xor_gen(n + 1, len, buffers)) {
106 : 0 : return -EINVAL;
107 : : }
108 : : } else {
109 : 34071 : xor_gen_basic(dest, sources, n, len);
110 : : }
111 : :
112 : 61614882 : return 0;
113 : : }
114 : :
115 : : #else
116 : :
117 : : #define SPDK_XOR_BUF_ALIGN sizeof(uint64_t)
118 : :
119 : : static inline int
120 : 255429 : do_xor_gen(void *dest, void **sources, uint32_t n, uint32_t len)
121 : : {
122 : 255429 : xor_gen_basic(dest, sources, n, len);
123 : 255429 : return 0;
124 : : }
125 : :
126 : : #endif
127 : :
128 : : int
129 : 61870311 : spdk_xor_gen(void *dest, void **sources, uint32_t n, uint32_t len)
130 : : {
131 [ + - - + ]: 61870311 : if (n < 2 || n > SPDK_XOR_MAX_SRC) {
132 : 0 : return -EINVAL;
133 : : }
134 : :
135 : 61870311 : return do_xor_gen(dest, sources, n, len);
136 : : }
137 : :
138 : : size_t
139 : 32 : spdk_xor_get_optimal_alignment(void)
140 : : {
141 : 32 : return SPDK_XOR_BUF_ALIGN;
142 : : }
143 : :
144 : : SPDK_STATIC_ASSERT(SPDK_XOR_BUF_ALIGN > 0 && !(SPDK_XOR_BUF_ALIGN & (SPDK_XOR_BUF_ALIGN - 1)),
145 : : "Must be power of 2");
|