Branch data Line data Source code
1 : : /* SPDX-License-Identifier: BSD-3-Clause
2 : : * Copyright (C) 2022 Intel Corporation.
3 : : * Copyright (c) 2022, 2023 NVIDIA CORPORATION & AFFILIATES
4 : : * All rights reserved.
5 : : */
6 : :
7 : : #include "spdk/stdinc.h"
8 : :
9 : : #include "spdk/accel_module.h"
10 : : #include "accel_internal.h"
11 : :
12 : : #include "spdk/env.h"
13 : : #include "spdk/likely.h"
14 : : #include "spdk/log.h"
15 : : #include "spdk/thread.h"
16 : : #include "spdk/json.h"
17 : : #include "spdk/crc32.h"
18 : : #include "spdk/util.h"
19 : : #include "spdk/xor.h"
20 : : #include "spdk/dif.h"
21 : :
22 : : #ifdef SPDK_CONFIG_ISAL
23 : : #include "../isa-l/include/igzip_lib.h"
24 : : #ifdef SPDK_CONFIG_ISAL_CRYPTO
25 : : #include "../isa-l-crypto/include/aes_xts.h"
26 : : #endif
27 : : #endif
28 : :
29 : : /* Per the AES-XTS spec, the size of data unit cannot be bigger than 2^20 blocks, 128b each block */
30 : : #define ACCEL_AES_XTS_MAX_BLOCK_SIZE (1 << 24)
31 : :
32 : : struct sw_accel_io_channel {
33 : : /* for ISAL */
34 : : #ifdef SPDK_CONFIG_ISAL
35 : : struct isal_zstream stream;
36 : : struct inflate_state state;
37 : : #endif
38 : : struct spdk_poller *completion_poller;
39 : : STAILQ_HEAD(, spdk_accel_task) tasks_to_complete;
40 : : };
41 : :
42 : : typedef void (*sw_accel_crypto_op)(uint8_t *k2, uint8_t *k1, uint8_t *tweak, uint64_t lba_size,
43 : : const uint8_t *src, uint8_t *dst);
44 : :
45 : : struct sw_accel_crypto_key_data {
46 : : sw_accel_crypto_op encrypt;
47 : : sw_accel_crypto_op decrypt;
48 : : };
49 : :
50 : : static struct spdk_accel_module_if g_sw_module;
51 : :
52 : : static void sw_accel_crypto_key_deinit(struct spdk_accel_crypto_key *_key);
53 : : static int sw_accel_crypto_key_init(struct spdk_accel_crypto_key *key);
54 : : static bool sw_accel_crypto_supports_tweak_mode(enum spdk_accel_crypto_tweak_mode tweak_mode);
55 : : static bool sw_accel_crypto_supports_cipher(enum spdk_accel_cipher cipher, size_t key_size);
56 : :
57 : : /* Post SW completions to a list and complete in a poller as we don't want to
58 : : * complete them on the caller's stack as they'll likely submit another. */
59 : : inline static void
60 : 369244275 : _add_to_comp_list(struct sw_accel_io_channel *sw_ch, struct spdk_accel_task *accel_task, int status)
61 : : {
62 [ + - + - ]: 369244275 : accel_task->status = status;
63 [ + - + - : 369244275 : STAILQ_INSERT_TAIL(&sw_ch->tasks_to_complete, accel_task, link);
+ - + - +
- + - + -
+ - + - +
- + - +
- ]
64 : 369244275 : }
65 : :
66 : : static bool
67 : 39319 : sw_accel_supports_opcode(enum spdk_accel_opcode opc)
68 : : {
69 [ + + ]: 39319 : switch (opc) {
70 : 37918 : case SPDK_ACCEL_OPC_COPY:
71 : : case SPDK_ACCEL_OPC_FILL:
72 : : case SPDK_ACCEL_OPC_DUALCAST:
73 : : case SPDK_ACCEL_OPC_COMPARE:
74 : : case SPDK_ACCEL_OPC_CRC32C:
75 : : case SPDK_ACCEL_OPC_COPY_CRC32C:
76 : : case SPDK_ACCEL_OPC_COMPRESS:
77 : : case SPDK_ACCEL_OPC_DECOMPRESS:
78 : : case SPDK_ACCEL_OPC_ENCRYPT:
79 : : case SPDK_ACCEL_OPC_DECRYPT:
80 : : case SPDK_ACCEL_OPC_XOR:
81 : : case SPDK_ACCEL_OPC_DIF_VERIFY:
82 : : case SPDK_ACCEL_OPC_DIF_GENERATE:
83 : : case SPDK_ACCEL_OPC_DIF_GENERATE_COPY:
84 : 39319 : return true;
85 : 0 : default:
86 : 0 : return false;
87 : : }
88 : 1401 : }
89 : :
90 : : static int
91 : 22954886 : _sw_accel_dualcast_iovs(struct iovec *dst_iovs, uint32_t dst_iovcnt,
92 : : struct iovec *dst2_iovs, uint32_t dst2_iovcnt,
93 : : struct iovec *src_iovs, uint32_t src_iovcnt)
94 : : {
95 [ + - - + : 22954886 : if (spdk_unlikely(dst_iovcnt != 1 || dst2_iovcnt != 1 || src_iovcnt != 1)) {
+ + - + ]
96 : 0 : return -EINVAL;
97 : : }
98 : :
99 [ + - + + : 22954886 : if (spdk_unlikely(dst_iovs[0].iov_len != src_iovs[0].iov_len ||
+ - + - +
- + - - +
+ - + - +
- + - + -
+ - + - ]
100 : : dst_iovs[0].iov_len != dst2_iovs[0].iov_len)) {
101 : 0 : return -EINVAL;
102 : : }
103 : :
104 [ + + + + : 22954886 : memcpy(dst_iovs[0].iov_base, src_iovs[0].iov_base, dst_iovs[0].iov_len);
+ - + - +
- + - + -
+ - + - +
- + - ]
105 [ + + + + : 22954886 : memcpy(dst2_iovs[0].iov_base, src_iovs[0].iov_base, dst_iovs[0].iov_len);
+ - + - +
- + - + -
+ - + - +
- + - ]
106 : :
107 : 22954886 : return 0;
108 : 1262145 : }
109 : :
110 : : static void
111 : 133327142 : _sw_accel_copy_iovs(struct iovec *dst_iovs, uint32_t dst_iovcnt,
112 : : struct iovec *src_iovs, uint32_t src_iovcnt)
113 : : {
114 : 59347449 : struct spdk_ioviter iter;
115 : 59347449 : void *src, *dst;
116 : 8 : size_t len;
117 : :
118 [ + + ]: 139377640 : for (len = spdk_ioviter_first(&iter, src_iovs, src_iovcnt,
119 : 2728769 : dst_iovs, dst_iovcnt, &src, &dst);
120 [ + + ]: 300972351 : len != 0;
121 : 167645209 : len = spdk_ioviter_next(&iter, &src, &dst)) {
122 [ - + - + ]: 167645209 : memcpy(dst, src, len);
123 : 3321729 : }
124 : 133327142 : }
125 : :
126 : : static int
127 : 33263942 : _sw_accel_compare(struct iovec *src_iovs, uint32_t src_iovcnt,
128 : : struct iovec *src2_iovs, uint32_t src2_iovcnt)
129 : : {
130 [ + + - + ]: 33263942 : if (spdk_unlikely(src_iovcnt != 1 || src2_iovcnt != 1)) {
131 : 0 : return -EINVAL;
132 : : }
133 : :
134 [ + + + - : 33263942 : if (spdk_unlikely(src_iovs[0].iov_len != src2_iovs[0].iov_len)) {
+ - + - +
- + - +
- ]
135 : 0 : return -EINVAL;
136 : : }
137 : :
138 [ + + + + : 33263942 : return memcmp(src_iovs[0].iov_base, src2_iovs[0].iov_base, src_iovs[0].iov_len);
+ - + - +
- + - + -
+ - + - +
- + - ]
139 : 1660449 : }
140 : :
141 : : static int
142 : 44976934 : _sw_accel_fill(struct iovec *iovs, uint32_t iovcnt, uint8_t fill)
143 : : {
144 : 25 : void *dst;
145 : 25 : size_t nbytes;
146 : :
147 [ - + ]: 44976934 : if (spdk_unlikely(iovcnt != 1)) {
148 : 0 : return -EINVAL;
149 : : }
150 : :
151 [ + - + - : 44976934 : dst = iovs[0].iov_base;
+ - ]
152 [ + - + - : 44976934 : nbytes = iovs[0].iov_len;
+ - ]
153 : :
154 [ + + ]: 44976934 : memset(dst, fill, nbytes);
155 : :
156 : 44976934 : return 0;
157 : 1962713 : }
158 : :
159 : : static void
160 : 78560926 : _sw_accel_crc32cv(uint32_t *crc_dst, struct iovec *iov, uint32_t iovcnt, uint32_t seed)
161 : : {
162 [ + - ]: 78560926 : *crc_dst = spdk_crc32c_iov_update(iov, iovcnt, ~seed);
163 : 78560926 : }
164 : :
165 : : static int
166 : 2976318 : _sw_accel_compress(struct sw_accel_io_channel *sw_ch, struct spdk_accel_task *accel_task)
167 : : {
168 : : #ifdef SPDK_CONFIG_ISAL
169 [ + - + - : 2976318 : size_t last_seglen = accel_task->s.iovs[accel_task->s.iovcnt - 1].iov_len;
+ - + - +
- + - + -
+ - + - +
- + - ]
170 [ + - + - : 2976318 : struct iovec *siov = accel_task->s.iovs;
+ - + - ]
171 [ + - + - : 2976318 : struct iovec *diov = accel_task->d.iovs;
+ - + - ]
172 : 2 : size_t remaining;
173 : 2976318 : uint32_t i, s = 0, d = 0;
174 : 2976318 : int rc = 0;
175 : :
176 : 2976318 : remaining = 0;
177 [ + + + - : 5952636 : for (i = 0; i < accel_task->s.iovcnt; ++i) {
+ - + - +
+ ]
178 [ + - + - : 2976318 : remaining += accel_task->s.iovs[i].iov_len;
+ - + - +
- + - +
- ]
179 : 134504 : }
180 : :
181 [ + - ]: 2976318 : isal_deflate_reset(&sw_ch->stream);
182 [ + - + - : 2976318 : sw_ch->stream.end_of_stream = 0;
+ - ]
183 [ + - + - : 2976318 : sw_ch->stream.next_out = diov[d].iov_base;
+ - + - +
- + - ]
184 [ + - + - : 2976318 : sw_ch->stream.avail_out = diov[d].iov_len;
+ - + - +
- + - ]
185 [ + - + - : 2976318 : sw_ch->stream.next_in = siov[s].iov_base;
+ - + - +
- + - ]
186 [ + - + - : 2976318 : sw_ch->stream.avail_in = siov[s].iov_len;
+ - + - +
- + - ]
187 : :
188 : 134504 : do {
189 : : /* if isal has exhausted the current dst iovec, move to the next
190 : : * one if there is one */
191 [ + + + - : 2976318 : if (sw_ch->stream.avail_out == 0) {
+ - + - ]
192 [ # # # # : 0 : if (++d < accel_task->d.iovcnt) {
# # # # #
# ]
193 [ # # # # : 0 : sw_ch->stream.next_out = diov[d].iov_base;
# # # # #
# # # ]
194 [ # # # # : 0 : sw_ch->stream.avail_out = diov[d].iov_len;
# # # # #
# # # ]
195 [ # # # # : 0 : assert(sw_ch->stream.avail_out > 0);
# # # # #
# ]
196 : 0 : } else {
197 : : /* we have no avail_out but also no more iovecs left so this is
198 : : * the case where either the output buffer was a perfect fit
199 : : * or not enough was provided. Check the ISAL state to determine
200 : : * which. */
201 [ # # # # : 0 : if (sw_ch->stream.internal_state.state != ZSTATE_END) {
# # # # #
# ]
202 : 0 : SPDK_ERRLOG("Not enough destination buffer provided.\n");
203 : 0 : rc = -ENOMEM;
204 : 0 : }
205 : 0 : break;
206 : : }
207 : 0 : }
208 : :
209 : : /* if isal has exhausted the current src iovec, move to the next
210 : : * one if there is one */
211 [ + + + - : 2976318 : if (sw_ch->stream.avail_in == 0 && ((s + 1) < accel_task->s.iovcnt)) {
+ - - + #
# # # # #
# # # # ]
212 : 0 : s++;
213 [ # # # # : 0 : sw_ch->stream.next_in = siov[s].iov_base;
# # # # #
# # # ]
214 [ # # # # : 0 : sw_ch->stream.avail_in = siov[s].iov_len;
# # # # #
# # # ]
215 [ # # # # : 0 : assert(sw_ch->stream.avail_in > 0);
# # # # #
# ]
216 : 0 : }
217 : :
218 [ + - ]: 2976318 : if (remaining <= last_seglen) {
219 : : /* Need to set end of stream on last block */
220 [ + - + - : 2976318 : sw_ch->stream.end_of_stream = 1;
+ - ]
221 : 134504 : }
222 : :
223 [ + - ]: 2976318 : rc = isal_deflate(&sw_ch->stream);
224 [ - + ]: 2976318 : if (rc) {
225 : 0 : SPDK_ERRLOG("isal_deflate returned error %d.\n", rc);
226 : 0 : }
227 : :
228 [ + + ]: 2976318 : if (remaining > 0) {
229 [ + + + - : 2976318 : assert(siov[s].iov_len > sw_ch->stream.avail_in);
+ - + - +
- + - - +
# # ]
230 [ + - + - : 2976318 : remaining -= (siov[s].iov_len - sw_ch->stream.avail_in);
+ - + - +
- + - ]
231 : 134504 : }
232 : :
233 [ - + + + : 2976318 : } while (remaining > 0 || sw_ch->stream.avail_out == 0);
+ - + - -
+ ]
234 [ + + + - : 2976318 : assert(sw_ch->stream.avail_in == 0);
+ - + - #
# ]
235 : :
236 : : /* Get our total output size */
237 [ + - + - : 2976318 : if (accel_task->output_size != NULL) {
+ - - + ]
238 [ + + + - : 2976318 : assert(sw_ch->stream.total_out > 0);
+ - + - #
# ]
239 [ + - + - : 2976318 : *accel_task->output_size = sw_ch->stream.total_out;
+ - + - +
- + - +
- ]
240 : 134504 : }
241 : :
242 : 2976320 : return rc;
243 : : #else
244 : : SPDK_ERRLOG("ISAL option is required to use software compression.\n");
245 : : return -EINVAL;
246 : : #endif
247 : 2 : }
248 : :
249 : : static int
250 : 19673651 : _sw_accel_decompress(struct sw_accel_io_channel *sw_ch, struct spdk_accel_task *accel_task)
251 : : {
252 : : #ifdef SPDK_CONFIG_ISAL
253 [ + - + - : 19673651 : struct iovec *siov = accel_task->s.iovs;
+ - + - ]
254 [ + - + - : 19673651 : struct iovec *diov = accel_task->d.iovs;
+ - + - ]
255 : 19673651 : uint32_t s = 0, d = 0;
256 : 19673651 : int rc = 0;
257 : :
258 [ + - ]: 19673651 : isal_inflate_reset(&sw_ch->state);
259 [ + - + - : 19673651 : sw_ch->state.next_out = diov[d].iov_base;
+ - + - +
- + - ]
260 [ + - + - : 19673651 : sw_ch->state.avail_out = diov[d].iov_len;
+ - + - +
- + - ]
261 [ + - + - : 19673651 : sw_ch->state.next_in = siov[s].iov_base;
+ - + - +
- + - ]
262 [ + - + - : 19673651 : sw_ch->state.avail_in = siov[s].iov_len;
+ - + - +
- + - ]
263 : :
264 : 1054930 : do {
265 : : /* if isal has exhausted the current dst iovec, move to the next
266 : : * one if there is one */
267 [ + + + - : 19685182 : if (sw_ch->state.avail_out == 0 && ((d + 1) < accel_task->d.iovcnt)) {
+ - - + #
# # # # #
# # # # ]
268 : 0 : d++;
269 [ # # # # : 0 : sw_ch->state.next_out = diov[d].iov_base;
# # # # #
# # # ]
270 [ # # # # : 0 : sw_ch->state.avail_out = diov[d].iov_len;
# # # # #
# # # ]
271 [ # # # # : 0 : assert(sw_ch->state.avail_out > 0);
# # # # #
# ]
272 : 0 : }
273 : :
274 : : /* if isal has exhausted the current src iovec, move to the next
275 : : * one if there is one */
276 [ + + + - : 19685182 : if (sw_ch->state.avail_in == 0 && ((s + 1) < accel_task->s.iovcnt)) {
+ - - + #
# # # # #
# # # # ]
277 : 0 : s++;
278 [ # # # # : 0 : sw_ch->state.next_in = siov[s].iov_base;
# # # # #
# # # ]
279 [ # # # # : 0 : sw_ch->state.avail_in = siov[s].iov_len;
# # # # #
# # # ]
280 [ # # # # : 0 : assert(sw_ch->state.avail_in > 0);
# # # # #
# ]
281 : 0 : }
282 : :
283 [ + - ]: 19685182 : rc = isal_inflate(&sw_ch->state);
284 [ + + ]: 19685182 : if (rc) {
285 : 0 : SPDK_ERRLOG("isal_inflate returned error %d.\n", rc);
286 : 0 : }
287 : :
288 [ + + + - : 19685182 : } while (sw_ch->state.block_state < ISAL_BLOCK_FINISH);
+ - + + ]
289 [ + + + - : 19673651 : assert(sw_ch->state.avail_in == 0);
+ - + - #
# ]
290 : :
291 : : /* Get our total output size */
292 [ + + + - : 19673651 : if (accel_task->output_size != NULL) {
+ - + - ]
293 [ - + # # : 1056478 : assert(sw_ch->state.total_out > 0);
# # # # #
# ]
294 [ # # # # : 1056478 : *accel_task->output_size = sw_ch->state.total_out;
# # # # #
# # # #
# ]
295 : 0 : }
296 : :
297 : 19673658 : return rc;
298 : : #else
299 : : SPDK_ERRLOG("ISAL option is required to use software decompression.\n");
300 : : return -EINVAL;
301 : : #endif
302 : 7 : }
303 : :
304 : : static int
305 : 3614992 : _sw_accel_crypto_operation(struct spdk_accel_task *accel_task, struct spdk_accel_crypto_key *key,
306 : : sw_accel_crypto_op op)
307 : : {
308 : : #ifdef SPDK_CONFIG_ISAL_CRYPTO
309 : 25 : uint64_t iv[2];
310 : 5 : size_t remaining_len, dst_len;
311 : 3614992 : uint64_t src_offset = 0, dst_offset = 0;
312 : 3614992 : uint32_t src_iovpos = 0, dst_iovpos = 0, src_iovcnt, dst_iovcnt;
313 : 3614992 : uint32_t i, block_size, crypto_len, crypto_accum_len = 0;
314 : 5 : struct iovec *src_iov, *dst_iov;
315 : 5 : uint8_t *src, *dst;
316 : :
317 : : /* iv is 128 bits, since we are using logical block address (64 bits) as iv, fill first 8 bytes with zeroes */
318 [ + - + - ]: 3614992 : iv[0] = 0;
319 [ + - + - : 3614992 : iv[1] = accel_task->iv;
+ - + - +
- ]
320 [ + - + - : 3614992 : src_iov = accel_task->s.iovs;
+ - + - ]
321 [ + - + - : 3614992 : src_iovcnt = accel_task->s.iovcnt;
+ - + - ]
322 [ + - + - : 3614992 : if (accel_task->d.iovcnt) {
+ - + - +
- ]
323 [ + - + - : 3614992 : dst_iov = accel_task->d.iovs;
+ - + - ]
324 [ + - + - : 3614992 : dst_iovcnt = accel_task->d.iovcnt;
+ - + - ]
325 : 5 : } else {
326 : : /* inplace operation */
327 [ # # # # : 0 : dst_iov = accel_task->s.iovs;
# # # # ]
328 [ # # # # : 0 : dst_iovcnt = accel_task->s.iovcnt;
# # # # ]
329 : : }
330 [ + - + - : 3614992 : block_size = accel_task->block_size;
+ - ]
331 : :
332 [ + - + - : 3614992 : if (!src_iovcnt || !dst_iovcnt || !block_size || !op) {
+ - - + ]
333 : 0 : SPDK_ERRLOG("src_iovcnt %d, dst_iovcnt %d, block_size %d, op %p\n", src_iovcnt, dst_iovcnt,
334 : : block_size, op);
335 : 0 : return -EINVAL;
336 : : }
337 : :
338 : 3614992 : remaining_len = 0;
339 [ + + ]: 7230089 : for (i = 0; i < src_iovcnt; i++) {
340 [ + - + - : 3615097 : remaining_len += src_iov[i].iov_len;
+ - ]
341 : 5 : }
342 : 3614992 : dst_len = 0;
343 [ + + ]: 7230112 : for (i = 0; i < dst_iovcnt; i++) {
344 [ + - + - : 3615120 : dst_len += dst_iov[i].iov_len;
+ - ]
345 : 5 : }
346 : :
347 [ + + - + ]: 3614992 : if (spdk_unlikely(remaining_len != dst_len || !remaining_len)) {
348 : 0 : return -ERANGE;
349 : : }
350 [ - + - + : 3614992 : if (spdk_unlikely(remaining_len % accel_task->block_size != 0)) {
- + - + -
+ ]
351 : 0 : return -EINVAL;
352 : : }
353 : :
354 [ + + ]: 16604062 : while (remaining_len) {
355 [ + - + - : 16604062 : crypto_len = spdk_min(block_size - crypto_accum_len, src_iov->iov_len - src_offset);
- + + - +
- ]
356 [ + - + - : 16604062 : crypto_len = spdk_min(crypto_len, dst_iov->iov_len - dst_offset);
- + + - +
- ]
357 [ + - + - : 16604062 : src = (uint8_t *)src_iov->iov_base + src_offset;
+ - ]
358 [ + - + - : 16604062 : dst = (uint8_t *)dst_iov->iov_base + dst_offset;
+ - ]
359 : :
360 [ + - # # : 16604062 : op((uint8_t *)key->key2, (uint8_t *)key->key, (uint8_t *)iv, crypto_len, src, dst);
+ - + - +
- + - ]
361 : :
362 : 16604062 : src_offset += crypto_len;
363 : 16604062 : dst_offset += crypto_len;
364 : 16604062 : crypto_accum_len += crypto_len;
365 : 16604062 : remaining_len -= crypto_len;
366 : :
367 [ + + ]: 16604062 : if (crypto_accum_len == block_size) {
368 : : /* we can process part of logical block. Once the whole block is processed, increment iv */
369 : 16604062 : crypto_accum_len = 0;
370 [ + - + - ]: 16604062 : iv[1]++;
371 : 5 : }
372 [ + + + - : 16604062 : if (src_offset == src_iov->iov_len) {
- + ]
373 [ + - ]: 3615097 : src_iov++;
374 : 3615097 : src_iovpos++;
375 : 3615097 : src_offset = 0;
376 : 5 : }
377 [ + + ]: 16604062 : if (src_iovpos == src_iovcnt) {
378 : 3614992 : break;
379 : : }
380 [ + + # # : 12989070 : if (dst_offset == dst_iov->iov_len) {
# # ]
381 [ # # ]: 128 : dst_iov++;
382 : 128 : dst_iovpos++;
383 : 128 : dst_offset = 0;
384 : 0 : }
385 [ - + ]: 12989070 : if (dst_iovpos == dst_iovcnt) {
386 : 0 : break;
387 : : }
388 : : }
389 : :
390 [ - + ]: 3614992 : if (remaining_len) {
391 : 0 : SPDK_ERRLOG("remaining len %zu\n", remaining_len);
392 : 0 : return -EINVAL;
393 : : }
394 : :
395 : 3614992 : return 0;
396 : : #else
397 : : return -ENOTSUP;
398 : : #endif
399 : 5 : }
400 : :
401 : : static int
402 : 2214332 : _sw_accel_encrypt(struct sw_accel_io_channel *sw_ch, struct spdk_accel_task *accel_task)
403 : : {
404 : 3 : struct spdk_accel_crypto_key *key;
405 : 3 : struct sw_accel_crypto_key_data *key_data;
406 : :
407 [ + - + - : 2214332 : key = accel_task->crypto_key;
+ - ]
408 [ + - + + : 2214332 : if (spdk_unlikely(key->module_if != &g_sw_module || !key->priv)) {
- + + - +
- - + ]
409 : 0 : return -EINVAL;
410 : : }
411 [ + + + - : 2214332 : if (spdk_unlikely(accel_task->block_size > ACCEL_AES_XTS_MAX_BLOCK_SIZE)) {
+ - - + +
- + - ]
412 [ # # # # : 0 : SPDK_WARNLOG("Max block size for AES_XTS is limited to %u, current size %u\n",
# # # # #
# ]
413 : : ACCEL_AES_XTS_MAX_BLOCK_SIZE, accel_task->block_size);
414 : 0 : return -ERANGE;
415 : : }
416 [ + - + - ]: 2214332 : key_data = key->priv;
417 [ + - + - ]: 2214332 : return _sw_accel_crypto_operation(accel_task, key, key_data->encrypt);
418 : 3 : }
419 : :
420 : : static int
421 : 1400660 : _sw_accel_decrypt(struct sw_accel_io_channel *sw_ch, struct spdk_accel_task *accel_task)
422 : : {
423 : 2 : struct spdk_accel_crypto_key *key;
424 : 2 : struct sw_accel_crypto_key_data *key_data;
425 : :
426 [ + - + - : 1400660 : key = accel_task->crypto_key;
+ - ]
427 [ + - + + : 1400660 : if (spdk_unlikely(key->module_if != &g_sw_module || !key->priv)) {
- + + - +
- - + ]
428 : 0 : return -EINVAL;
429 : : }
430 [ + + + - : 1400660 : if (spdk_unlikely(accel_task->block_size > ACCEL_AES_XTS_MAX_BLOCK_SIZE)) {
+ - - + +
- + - ]
431 [ # # # # : 0 : SPDK_WARNLOG("Max block size for AES_XTS is limited to %u, current size %u\n",
# # # # #
# ]
432 : : ACCEL_AES_XTS_MAX_BLOCK_SIZE, accel_task->block_size);
433 : 0 : return -ERANGE;
434 : : }
435 [ + - + - ]: 1400660 : key_data = key->priv;
436 [ + - + - ]: 1400660 : return _sw_accel_crypto_operation(accel_task, key, key_data->decrypt);
437 : 2 : }
438 : :
439 : : static int
440 : 37466300 : _sw_accel_xor(struct sw_accel_io_channel *sw_ch, struct spdk_accel_task *accel_task)
441 : : {
442 [ + - + - : 50975422 : return spdk_xor_gen(accel_task->d.iovs[0].iov_base,
+ - + - +
- + - +
- ]
443 [ + - + - : 2701153 : accel_task->nsrcs.srcs,
+ - + - ]
444 [ + - + - : 2701153 : accel_task->nsrcs.cnt,
+ - + - ]
445 [ + - + - : 37466300 : accel_task->d.iovs[0].iov_len);
+ - + - +
- + - +
- ]
446 : : }
447 : :
448 : : static int
449 : 6111900 : _sw_accel_dif_verify(struct sw_accel_io_channel *sw_ch, struct spdk_accel_task *accel_task)
450 : : {
451 [ + - + - : 12223800 : return spdk_dif_verify(accel_task->s.iovs,
+ - + - ]
452 [ + - + - : 6111900 : accel_task->s.iovcnt,
+ - + - ]
453 [ + - + - : 496748 : accel_task->dif.num_blocks,
+ - + - ]
454 [ + - + - : 496748 : accel_task->dif.ctx,
+ - + - ]
455 [ + - + - : 496748 : accel_task->dif.err);
+ - + - ]
456 : : }
457 : :
458 : : static int
459 : 7762688 : _sw_accel_dif_generate(struct sw_accel_io_channel *sw_ch, struct spdk_accel_task *accel_task)
460 : : {
461 [ + - + - : 15525376 : return spdk_dif_generate(accel_task->s.iovs,
+ - + - ]
462 [ + - + - : 7762688 : accel_task->s.iovcnt,
+ - + - ]
463 [ + - + - : 567776 : accel_task->dif.num_blocks,
+ - + - ]
464 [ + - + - : 567776 : accel_task->dif.ctx);
+ - + - ]
465 : : }
466 : :
467 : : static int
468 : 5971912 : _sw_accel_dif_generate_copy(struct sw_accel_io_channel *sw_ch, struct spdk_accel_task *accel_task)
469 : : {
470 [ + - + - : 15574040 : return spdk_dif_generate_copy(accel_task->s.iovs,
+ - + - ]
471 [ + - + - : 5971912 : accel_task->s.iovcnt,
+ - + - ]
472 [ + - + - : 449704 : accel_task->d.iovs,
+ - + - ]
473 [ + - + - : 5971912 : accel_task->d.iovcnt,
+ - + - ]
474 [ + - + - : 449704 : accel_task->dif.num_blocks,
+ - + - ]
475 [ + - + - : 449704 : accel_task->dif.ctx);
+ - + - ]
476 : : }
477 : :
478 : : static int
479 : 369241267 : sw_accel_submit_tasks(struct spdk_io_channel *ch, struct spdk_accel_task *accel_task)
480 : : {
481 : 369241267 : struct sw_accel_io_channel *sw_ch = spdk_io_channel_get_ctx(ch);
482 : 58 : struct spdk_accel_task *tmp;
483 : 369241267 : int rc = 0;
484 : :
485 : 15969018 : do {
486 [ + + + + : 369251520 : switch (accel_task->op_code) {
+ + + + +
+ + + + +
+ + + +
+ ]
487 : 104615840 : case SPDK_ACCEL_OPC_COPY:
488 [ + - + - : 107169120 : _sw_accel_copy_iovs(accel_task->d.iovs, accel_task->d.iovcnt,
+ - + - +
- + - + -
+ - ]
489 [ + - + - : 1276640 : accel_task->s.iovs, accel_task->s.iovcnt);
+ - + - +
- + - + -
+ - ]
490 : 105892480 : break;
491 : 43014221 : case SPDK_ACCEL_OPC_FILL:
492 [ + - + - : 46939647 : rc = _sw_accel_fill(accel_task->d.iovs, accel_task->d.iovcnt,
+ - + - +
- + - + -
+ - ]
493 [ + - + - : 44976934 : accel_task->fill_pattern);
+ - ]
494 : 44976934 : break;
495 : 21692741 : case SPDK_ACCEL_OPC_DUALCAST:
496 [ + - + - : 24217031 : rc = _sw_accel_dualcast_iovs(accel_task->d.iovs, accel_task->d.iovcnt,
+ - + - +
- + - + -
+ - ]
497 [ + - + - : 1262145 : accel_task->d2.iovs, accel_task->d2.iovcnt,
+ - + - +
- + - + -
+ - ]
498 [ + - + - : 1262145 : accel_task->s.iovs, accel_task->s.iovcnt);
+ - + - +
- + - + -
+ - ]
499 : 22954886 : break;
500 : 31603493 : case SPDK_ACCEL_OPC_COMPARE:
501 [ + - + - : 34924391 : rc = _sw_accel_compare(accel_task->s.iovs, accel_task->s.iovcnt,
+ - + - +
- + - + -
+ - ]
502 [ + - + - : 1660449 : accel_task->s2.iovs, accel_task->s2.iovcnt);
+ - + - +
- + - + -
+ - ]
503 : 33263942 : break;
504 : 48190480 : case SPDK_ACCEL_OPC_CRC32C:
505 [ + - + - : 51126264 : _sw_accel_crc32cv(accel_task->crc_dst, accel_task->s.iovs, accel_task->s.iovcnt, accel_task->seed);
+ - + - +
- + - + -
+ - + - +
- + - + -
+ - + - ]
506 : 51126264 : break;
507 : 25982533 : case SPDK_ACCEL_OPC_COPY_CRC32C:
508 [ + - + - : 28886791 : _sw_accel_copy_iovs(accel_task->d.iovs, accel_task->d.iovcnt,
+ - + - +
- + - + -
+ - ]
509 [ + - + - : 1452129 : accel_task->s.iovs, accel_task->s.iovcnt);
+ - + - +
- + - + -
+ - ]
510 [ + - + - : 28886791 : _sw_accel_crc32cv(accel_task->crc_dst, accel_task->s.iovs,
+ - + - +
- + - +
- ]
511 [ + - + - : 1452129 : accel_task->s.iovcnt, accel_task->seed);
+ - + - +
- + - +
- ]
512 : 27434662 : break;
513 : 2841814 : case SPDK_ACCEL_OPC_COMPRESS:
514 : 2976318 : rc = _sw_accel_compress(sw_ch, accel_task);
515 : 2976318 : break;
516 : 18618721 : case SPDK_ACCEL_OPC_DECOMPRESS:
517 : 19677736 : rc = _sw_accel_decompress(sw_ch, accel_task);
518 : 19677736 : break;
519 : 34765147 : case SPDK_ACCEL_OPC_XOR:
520 : 37466300 : rc = _sw_accel_xor(sw_ch, accel_task);
521 : 37466300 : break;
522 : 2214329 : case SPDK_ACCEL_OPC_ENCRYPT:
523 : 2214332 : rc = _sw_accel_encrypt(sw_ch, accel_task);
524 : 2214332 : break;
525 : 1400658 : case SPDK_ACCEL_OPC_DECRYPT:
526 : 1400660 : rc = _sw_accel_decrypt(sw_ch, accel_task);
527 : 1400660 : break;
528 : 5615152 : case SPDK_ACCEL_OPC_DIF_VERIFY:
529 : 6111900 : rc = _sw_accel_dif_verify(sw_ch, accel_task);
530 : 6111900 : break;
531 : 7194912 : case SPDK_ACCEL_OPC_DIF_GENERATE:
532 : 7762688 : rc = _sw_accel_dif_generate(sw_ch, accel_task);
533 : 7762688 : break;
534 : 5522208 : case SPDK_ACCEL_OPC_DIF_GENERATE_COPY:
535 : 5971912 : rc = _sw_accel_dif_generate_copy(sw_ch, accel_task);
536 : 5971912 : break;
537 : 0 : default:
538 [ # # ]: 0 : assert(false);
539 : : break;
540 : : }
541 : :
542 [ + - + - : 369231014 : tmp = STAILQ_NEXT(accel_task, link);
+ - ]
543 : :
544 : 369231014 : _add_to_comp_list(sw_ch, accel_task, rc);
545 : :
546 : 369231014 : accel_task = tmp;
547 [ + + ]: 369231014 : } while (accel_task);
548 : :
549 : 369220761 : return 0;
550 : 58 : }
551 : :
552 : : static int
553 : 3291247650 : accel_comp_poll(void *arg)
554 : : {
555 : 3291247650 : struct sw_accel_io_channel *sw_ch = arg;
556 : 1406240305 : STAILQ_HEAD(, spdk_accel_task) tasks_to_complete;
557 : 163 : struct spdk_accel_task *accel_task;
558 : :
559 [ + + + - : 3291247650 : if (STAILQ_EMPTY(&sw_ch->tasks_to_complete)) {
+ - + + ]
560 : 3262774364 : return SPDK_POLLER_IDLE;
561 : : }
562 : :
563 [ + - ]: 28473286 : STAILQ_INIT(&tasks_to_complete);
564 [ + + + - : 28473286 : STAILQ_SWAP(&tasks_to_complete, &sw_ch->tasks_to_complete, spdk_accel_task);
+ - + - +
- + - + -
+ - + - +
- + - + -
+ - + - -
+ # # + -
+ - + - +
+ + - + -
+ - + - +
- ]
565 : :
566 [ + + ]: 397710316 : while ((accel_task = STAILQ_FIRST(&tasks_to_complete))) {
567 [ + + + - : 369237042 : STAILQ_REMOVE_HEAD(&tasks_to_complete, link);
+ - + + +
- ]
568 [ + - + - ]: 369237042 : spdk_accel_task_complete(accel_task, accel_task->status);
569 : : }
570 : :
571 : 28473274 : return SPDK_POLLER_BUSY;
572 : 17152348 : }
573 : :
574 : : static int
575 : 9947 : sw_accel_create_cb(void *io_device, void *ctx_buf)
576 : : {
577 : 9947 : struct sw_accel_io_channel *sw_ch = ctx_buf;
578 : :
579 [ + - + - : 9947 : STAILQ_INIT(&sw_ch->tasks_to_complete);
+ - + - +
- + - + -
+ - ]
580 [ + - + - ]: 9947 : sw_ch->completion_poller = SPDK_POLLER_REGISTER(accel_comp_poll, sw_ch, 0);
581 : :
582 : : #ifdef SPDK_CONFIG_ISAL
583 [ + - ]: 9947 : isal_deflate_init(&sw_ch->stream);
584 [ + - + - : 9947 : sw_ch->stream.flush = NO_FLUSH;
+ - ]
585 [ + - + - : 9947 : sw_ch->stream.level = 1;
+ - ]
586 [ + - + - : 9947 : sw_ch->stream.level_buf = calloc(1, ISAL_DEF_LVL1_DEFAULT);
+ - ]
587 [ + + + - : 9947 : if (sw_ch->stream.level_buf == NULL) {
+ - + - ]
588 : 0 : SPDK_ERRLOG("Could not allocate isal internal buffer\n");
589 : 0 : return -ENOMEM;
590 : : }
591 [ + - + - : 9947 : sw_ch->stream.level_buf_size = ISAL_DEF_LVL1_DEFAULT;
+ - ]
592 [ + - ]: 9947 : isal_inflate_init(&sw_ch->state);
593 : : #endif
594 : :
595 : 9947 : return 0;
596 : 167 : }
597 : :
598 : : static void
599 : 9947 : sw_accel_destroy_cb(void *io_device, void *ctx_buf)
600 : : {
601 : 9947 : struct sw_accel_io_channel *sw_ch = ctx_buf;
602 : :
603 : : #ifdef SPDK_CONFIG_ISAL
604 [ + - + - : 9947 : free(sw_ch->stream.level_buf);
+ - ]
605 : : #endif
606 : :
607 [ + - ]: 9947 : spdk_poller_unregister(&sw_ch->completion_poller);
608 : 9947 : }
609 : :
610 : : static struct spdk_io_channel *
611 : 138807 : sw_accel_get_io_channel(void)
612 : : {
613 : 138807 : return spdk_get_io_channel(&g_sw_module);
614 : : }
615 : :
616 : : static size_t
617 : 5614 : sw_accel_module_get_ctx_size(void)
618 : : {
619 : 5614 : return sizeof(struct spdk_accel_task);
620 : : }
621 : :
622 : : static int
623 : 2807 : sw_accel_module_init(void)
624 : : {
625 : 2807 : spdk_io_device_register(&g_sw_module, sw_accel_create_cb, sw_accel_destroy_cb,
626 : : sizeof(struct sw_accel_io_channel), "sw_accel_module");
627 : :
628 : 2807 : return 0;
629 : : }
630 : :
631 : : static void
632 : 2807 : sw_accel_module_fini(void *ctxt)
633 : : {
634 : 2807 : spdk_io_device_unregister(&g_sw_module, NULL);
635 : 2807 : spdk_accel_module_finish();
636 : 2807 : }
637 : :
638 : : static int
639 : 42 : sw_accel_create_aes_xts(struct spdk_accel_crypto_key *key)
640 : : {
641 : : #ifdef SPDK_CONFIG_ISAL_CRYPTO
642 : 1 : struct sw_accel_crypto_key_data *key_data;
643 : :
644 : 42 : key_data = calloc(1, sizeof(*key_data));
645 [ + + ]: 42 : if (!key_data) {
646 : 0 : return -ENOMEM;
647 : : }
648 : :
649 [ + - + - : 42 : switch (key->key_size) {
- + - ]
650 : 41 : case SPDK_ACCEL_AES_XTS_128_KEY_SIZE:
651 [ + - + - ]: 42 : key_data->encrypt = XTS_AES_128_enc;
652 [ + - + - ]: 42 : key_data->decrypt = XTS_AES_128_dec;
653 : 42 : break;
654 : 0 : case SPDK_ACCEL_AES_XTS_256_KEY_SIZE:
655 [ # # # # ]: 0 : key_data->encrypt = XTS_AES_256_enc;
656 [ # # # # ]: 0 : key_data->decrypt = XTS_AES_256_dec;
657 : 0 : break;
658 : 0 : default:
659 [ # # ]: 0 : assert(0);
660 : : free(key_data);
661 : : return -EINVAL;
662 : : }
663 : :
664 [ + - + - ]: 42 : key->priv = key_data;
665 : :
666 : 42 : return 0;
667 : : #else
668 : : return -ENOTSUP;
669 : : #endif
670 : 1 : }
671 : :
672 : : static int
673 : 42 : sw_accel_crypto_key_init(struct spdk_accel_crypto_key *key)
674 : : {
675 : 42 : return sw_accel_create_aes_xts(key);
676 : : }
677 : :
678 : : static void
679 : 42 : sw_accel_crypto_key_deinit(struct spdk_accel_crypto_key *key)
680 : : {
681 [ + - + - : 42 : if (!key || key->module_if != &g_sw_module || !key->priv) {
+ + + - +
- + - +
- ]
682 : 0 : return;
683 : : }
684 : :
685 [ + - + - ]: 42 : free(key->priv);
686 : 1 : }
687 : :
688 : : static bool
689 : 42 : sw_accel_crypto_supports_tweak_mode(enum spdk_accel_crypto_tweak_mode tweak_mode)
690 : : {
691 : 42 : return tweak_mode == SPDK_ACCEL_CRYPTO_TWEAK_MODE_SIMPLE_LBA;
692 : : }
693 : :
694 : : static bool
695 : 42 : sw_accel_crypto_supports_cipher(enum spdk_accel_cipher cipher, size_t key_size)
696 : : {
697 [ + - ]: 42 : switch (cipher) {
698 : 41 : case SPDK_ACCEL_CIPHER_AES_XTS:
699 [ + + - - ]: 42 : return key_size == SPDK_ACCEL_AES_XTS_128_KEY_SIZE || key_size == SPDK_ACCEL_AES_XTS_256_KEY_SIZE;
700 : 0 : default:
701 : 0 : return false;
702 : : }
703 : 1 : }
704 : :
705 : : static int
706 : 216 : sw_accel_get_operation_info(enum spdk_accel_opcode opcode,
707 : : const struct spdk_accel_operation_exec_ctx *ctx,
708 : : struct spdk_accel_opcode_info *info)
709 : : {
710 [ # # # # ]: 216 : info->required_alignment = 0;
711 : :
712 : 216 : return 0;
713 : : }
714 : :
715 : : static struct spdk_accel_module_if g_sw_module = {
716 : : .module_init = sw_accel_module_init,
717 : : .module_fini = sw_accel_module_fini,
718 : : .write_config_json = NULL,
719 : : .get_ctx_size = sw_accel_module_get_ctx_size,
720 : : .name = "software",
721 : : .priority = SPDK_ACCEL_SW_PRIORITY,
722 : : .supports_opcode = sw_accel_supports_opcode,
723 : : .get_io_channel = sw_accel_get_io_channel,
724 : : .submit_tasks = sw_accel_submit_tasks,
725 : : .crypto_key_init = sw_accel_crypto_key_init,
726 : : .crypto_key_deinit = sw_accel_crypto_key_deinit,
727 : : .crypto_supports_tweak_mode = sw_accel_crypto_supports_tweak_mode,
728 : : .crypto_supports_cipher = sw_accel_crypto_supports_cipher,
729 : : .get_operation_info = sw_accel_get_operation_info,
730 : : };
731 : :
732 : 2949 : SPDK_ACCEL_MODULE_REGISTER(sw, &g_sw_module)
|