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 180085 : is_aligned(void *ptr, size_t alignment)
16 : {
17 180085 : uintptr_t p = (uintptr_t)ptr;
18 :
19 360170 : return p == SPDK_ALIGN_FLOOR(p, alignment);
20 180085 : }
21 :
22 : static bool
23 115096 : buffers_aligned(void *dest, void **sources, uint32_t n, size_t alignment)
24 : {
25 115096 : uint32_t i;
26 :
27 180085 : for (i = 0; i < n; i++) {
28 161163 : if (!is_aligned(sources[i], alignment)) {
29 96174 : return false;
30 : }
31 64989 : }
32 :
33 18922 : return is_aligned(dest, alignment);
34 115096 : }
35 :
36 : static void
37 48729 : xor_gen_unaligned(void *dest, void **sources, uint32_t n, uint32_t len)
38 : {
39 48729 : uint32_t i, j;
40 :
41 329540196 : for (i = 0; i < len; i++) {
42 329491467 : uint8_t b = 0;
43 :
44 1398443588 : for (j = 0; j < n; j++) {
45 1068952121 : b ^= ((uint8_t *)sources[j])[i];
46 1068952121 : }
47 329491467 : ((uint8_t *)dest)[i] = b;
48 329491467 : }
49 48729 : }
50 :
51 : static void
52 52637 : xor_gen_basic(void *dest, void **sources, uint32_t n, uint32_t len)
53 : {
54 52637 : uint32_t shift;
55 52637 : uint32_t len_div, len_rem;
56 52637 : uint32_t i, j;
57 :
58 52637 : if (!buffers_aligned(dest, sources, n, sizeof(uint64_t))) {
59 43865 : xor_gen_unaligned(dest, sources, n, len);
60 43865 : return;
61 : }
62 :
63 8772 : shift = spdk_u32log2(sizeof(uint64_t));
64 8772 : len_div = len >> shift;
65 8772 : len_rem = len_div << shift;
66 :
67 4459899 : for (i = 0; i < len_div; i++) {
68 4451127 : uint64_t w = 0;
69 :
70 21494643 : for (j = 0; j < n; j++) {
71 17043516 : w ^= ((uint64_t *)sources[j])[i];
72 17043516 : }
73 4451127 : ((uint64_t *)dest)[i] = w;
74 4451127 : }
75 :
76 8772 : if (len_rem < len) {
77 4864 : void *sources2[SPDK_XOR_MAX_SRC];
78 :
79 21346 : for (j = 0; j < n; j++) {
80 16482 : sources2[j] = (uint8_t *)sources[j] + len_rem;
81 16482 : }
82 :
83 4864 : xor_gen_unaligned((uint8_t *)dest + len_rem, sources2, n, len - len_rem);
84 4864 : }
85 52637 : }
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 62459 : do_xor_gen(void *dest, void **sources, uint32_t n, uint32_t len)
94 : {
95 62459 : if (buffers_aligned(dest, sources, n, SPDK_XOR_BUF_ALIGN)) {
96 9822 : void *buffers[SPDK_XOR_MAX_SRC + 1];
97 :
98 9822 : if (n >= INT_MAX) {
99 0 : return -EINVAL;
100 : }
101 :
102 9822 : memcpy(buffers, sources, n * sizeof(buffers[0]));
103 9822 : buffers[n] = dest;
104 :
105 9822 : if (xor_gen(n + 1, len, buffers)) {
106 0 : return -EINVAL;
107 : }
108 9822 : } else {
109 52637 : xor_gen_basic(dest, sources, n, len);
110 : }
111 :
112 62459 : return 0;
113 62459 : }
114 :
115 : #else
116 :
117 : #define SPDK_XOR_BUF_ALIGN sizeof(uint64_t)
118 :
119 : static inline int
120 : do_xor_gen(void *dest, void **sources, uint32_t n, uint32_t len)
121 : {
122 : xor_gen_basic(dest, sources, n, len);
123 : return 0;
124 : }
125 :
126 : #endif
127 :
128 : int
129 62459 : spdk_xor_gen(void *dest, void **sources, uint32_t n, uint32_t len)
130 : {
131 62459 : if (n < 2 || n > SPDK_XOR_MAX_SRC) {
132 0 : return -EINVAL;
133 : }
134 :
135 62459 : return do_xor_gen(dest, sources, n, len);
136 62459 : }
137 :
138 : size_t
139 0 : spdk_xor_get_optimal_alignment(void)
140 : {
141 0 : 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");
|