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 : 199016130 : is_aligned(void *ptr, size_t alignment)
16 : : {
17 : 199016130 : uintptr_t p = (uintptr_t)ptr;
18 : :
19 : 199016130 : return p == SPDK_ALIGN_FLOOR(p, alignment);
20 : : }
21 : :
22 : : static bool
23 : 57357503 : buffers_aligned(void *dest, void **sources, uint32_t n, size_t alignment)
24 : : {
25 : : uint32_t i;
26 : :
27 [ + + ]: 199016130 : for (i = 0; i < n; i++) {
28 [ + + ]: 141908935 : if (!is_aligned(sources[i], alignment)) {
29 : 250309 : return false;
30 : : }
31 : : }
32 : :
33 : 57107195 : return is_aligned(dest, alignment);
34 : : }
35 : :
36 : : static void
37 : 128229 : xor_gen_unaligned(void *dest, void **sources, uint32_t n, uint32_t len)
38 : : {
39 : : uint32_t i, j;
40 : :
41 [ + + ]: 866433433 : for (i = 0; i < len; i++) {
42 : 866304940 : uint8_t b = 0;
43 : :
44 [ + + ]: 3675190160 : for (j = 0; j < n; j++) {
45 : 2808885220 : b ^= ((uint8_t *)sources[j])[i];
46 : : }
47 : 866304940 : ((uint8_t *)dest)[i] = b;
48 : : }
49 : 128229 : }
50 : :
51 : : static void
52 : 465216 : 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 [ + + ]: 465216 : if (!buffers_aligned(dest, sources, n, sizeof(uint64_t))) {
59 : 113654 : xor_gen_unaligned(dest, sources, n, len);
60 : 113654 : return;
61 : : }
62 : :
63 : 351562 : shift = spdk_u32log2(sizeof(uint64_t));
64 [ - + ]: 351562 : len_div = len >> shift;
65 [ - + ]: 351562 : len_rem = len_div << shift;
66 : :
67 [ + + ]: 180770342 : for (i = 0; i < len_div; i++) {
68 : 180418777 : uint64_t w = 0;
69 : :
70 [ + + ]: 636391396 : for (j = 0; j < n; j++) {
71 : 455972639 : w ^= ((uint64_t *)sources[j])[i];
72 : : }
73 : 180418777 : ((uint64_t *)dest)[i] = w;
74 : : }
75 : :
76 [ + + ]: 351562 : if (len_rem < len) {
77 : 9973 : void *sources2[SPDK_XOR_MAX_SRC];
78 : :
79 [ + + ]: 64029 : for (j = 0; j < n; j++) {
80 : 49454 : sources2[j] = (uint8_t *)sources[j] + len_rem;
81 : : }
82 : :
83 : 14575 : 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 : 56892286 : do_xor_gen(void *dest, void **sources, uint32_t n, uint32_t len)
94 : : {
95 [ + + ]: 56892286 : if (buffers_aligned(dest, sources, n, SPDK_XOR_BUF_ALIGN)) {
96 : 25159709 : void *buffers[SPDK_XOR_MAX_SRC + 1];
97 : :
98 [ - + ]: 56753154 : if (n >= INT_MAX) {
99 : 0 : return -EINVAL;
100 : : }
101 : :
102 [ - + - + ]: 56753154 : memcpy(buffers, sources, n * sizeof(buffers[0]));
103 : 56753154 : buffers[n] = dest;
104 : :
105 [ - + ]: 56753154 : if (xor_gen(n + 1, len, buffers)) {
106 : 0 : return -EINVAL;
107 : : }
108 : : } else {
109 : 139131 : xor_gen_basic(dest, sources, n, len);
110 : : }
111 : :
112 : 56892286 : return 0;
113 : : }
114 : :
115 : : #else
116 : :
117 : : #define SPDK_XOR_BUF_ALIGN sizeof(uint64_t)
118 : :
119 : : static inline int
120 : 326085 : do_xor_gen(void *dest, void **sources, uint32_t n, uint32_t len)
121 : : {
122 : 326085 : xor_gen_basic(dest, sources, n, len);
123 : 326085 : return 0;
124 : : }
125 : :
126 : : #endif
127 : :
128 : : int
129 : 57218371 : spdk_xor_gen(void *dest, void **sources, uint32_t n, uint32_t len)
130 : : {
131 [ + - - + ]: 57218371 : if (n < 2 || n > SPDK_XOR_MAX_SRC) {
132 : 0 : return -EINVAL;
133 : : }
134 : :
135 : 57218371 : return do_xor_gen(dest, sources, n, len);
136 : : }
137 : :
138 : : size_t
139 : 48 : spdk_xor_get_optimal_alignment(void)
140 : : {
141 : 48 : 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");
|