Branch data Line data Source code
1 : : /* SPDX-License-Identifier: BSD-3-Clause
2 : : * Copyright(c) 2018 HUAWEI TECHNOLOGIES CO., LTD.
3 : : */
4 : : #include <cryptodev_pmd.h>
5 : :
6 : : #include "virtqueue.h"
7 : : #include "virtio_ring.h"
8 : : #include "virtio_cryptodev.h"
9 : : #include "virtio_crypto_algs.h"
10 : :
11 : : static void
12 : 0 : vq_ring_free_chain(struct virtqueue *vq, uint16_t desc_idx)
13 : : {
14 : : struct vring_desc *dp, *dp_tail;
15 : : struct vq_desc_extra *dxp;
16 : : uint16_t desc_idx_last = desc_idx;
17 : :
18 : 0 : dp = &vq->vq_split.ring.desc[desc_idx];
19 : 0 : dxp = &vq->vq_descx[desc_idx];
20 : 0 : vq->vq_free_cnt = (uint16_t)(vq->vq_free_cnt + dxp->ndescs);
21 [ # # ]: 0 : if ((dp->flags & VRING_DESC_F_INDIRECT) == 0) {
22 [ # # ]: 0 : while (dp->flags & VRING_DESC_F_NEXT) {
23 : 0 : desc_idx_last = dp->next;
24 : 0 : dp = &vq->vq_split.ring.desc[dp->next];
25 : : }
26 : : }
27 : 0 : dxp->ndescs = 0;
28 : :
29 : : /*
30 : : * We must append the existing free chain, if any, to the end of
31 : : * newly freed chain. If the virtqueue was completely used, then
32 : : * head would be VQ_RING_DESC_CHAIN_END (ASSERTed above).
33 : : */
34 [ # # ]: 0 : if (vq->vq_desc_tail_idx == VQ_RING_DESC_CHAIN_END) {
35 : 0 : vq->vq_desc_head_idx = desc_idx;
36 : : } else {
37 : 0 : dp_tail = &vq->vq_split.ring.desc[vq->vq_desc_tail_idx];
38 : 0 : dp_tail->next = desc_idx;
39 : : }
40 : :
41 : 0 : vq->vq_desc_tail_idx = desc_idx_last;
42 : 0 : dp->next = VQ_RING_DESC_CHAIN_END;
43 : 0 : }
44 : :
45 : : static uint16_t
46 : 0 : virtqueue_dequeue_burst_rx(struct virtqueue *vq,
47 : : struct rte_crypto_op **rx_pkts, uint16_t num)
48 : : {
49 : : struct vring_used_elem *uep;
50 : : struct rte_crypto_op *cop;
51 : : uint16_t used_idx, desc_idx;
52 : : uint16_t i;
53 : : struct virtio_crypto_inhdr *inhdr;
54 : : struct virtio_crypto_op_cookie *op_cookie;
55 : :
56 : : /* Caller does the check */
57 [ # # ]: 0 : for (i = 0; i < num ; i++) {
58 : 0 : used_idx = (uint16_t)(vq->vq_used_cons_idx
59 : 0 : & (vq->vq_nentries - 1));
60 : 0 : uep = &vq->vq_split.ring.used->ring[used_idx];
61 : 0 : desc_idx = (uint16_t)uep->id;
62 : 0 : cop = (struct rte_crypto_op *)
63 : 0 : vq->vq_descx[desc_idx].crypto_op;
64 [ # # ]: 0 : if (unlikely(cop == NULL)) {
65 : 0 : VIRTIO_CRYPTO_RX_LOG_DBG("vring descriptor with no "
66 : : "mbuf cookie at %u",
67 : : vq->vq_used_cons_idx);
68 : 0 : break;
69 : : }
70 : :
71 : 0 : op_cookie = (struct virtio_crypto_op_cookie *)
72 : : vq->vq_descx[desc_idx].cookie;
73 : : inhdr = &(op_cookie->inhdr);
74 [ # # # # : 0 : switch (inhdr->status) {
# # ]
75 : 0 : case VIRTIO_CRYPTO_OK:
76 : 0 : cop->status = RTE_CRYPTO_OP_STATUS_SUCCESS;
77 : 0 : break;
78 : 0 : case VIRTIO_CRYPTO_ERR:
79 : 0 : cop->status = RTE_CRYPTO_OP_STATUS_ERROR;
80 : 0 : vq->packets_received_failed++;
81 : 0 : break;
82 : 0 : case VIRTIO_CRYPTO_BADMSG:
83 : 0 : cop->status = RTE_CRYPTO_OP_STATUS_INVALID_ARGS;
84 : 0 : vq->packets_received_failed++;
85 : 0 : break;
86 : 0 : case VIRTIO_CRYPTO_NOTSUPP:
87 : 0 : cop->status = RTE_CRYPTO_OP_STATUS_INVALID_ARGS;
88 : 0 : vq->packets_received_failed++;
89 : 0 : break;
90 : 0 : case VIRTIO_CRYPTO_INVSESS:
91 : 0 : cop->status = RTE_CRYPTO_OP_STATUS_INVALID_SESSION;
92 : 0 : vq->packets_received_failed++;
93 : 0 : break;
94 : : default:
95 : : break;
96 : : }
97 : :
98 : 0 : vq->packets_received_total++;
99 : :
100 : 0 : rx_pkts[i] = cop;
101 [ # # ]: 0 : rte_mempool_put(vq->mpool, op_cookie);
102 : :
103 : 0 : vq->vq_used_cons_idx++;
104 : 0 : vq_ring_free_chain(vq, desc_idx);
105 : 0 : vq->vq_descx[desc_idx].crypto_op = NULL;
106 : : }
107 : :
108 : 0 : return i;
109 : : }
110 : :
111 : : static uint16_t
112 : 0 : virtqueue_dequeue_burst_rx_packed(struct virtqueue *vq,
113 : : struct rte_crypto_op **rx_pkts, uint16_t num)
114 : : {
115 : : struct rte_crypto_op *cop;
116 : : uint16_t used_idx;
117 : : uint16_t i;
118 : : struct virtio_crypto_inhdr *inhdr;
119 : : struct virtio_crypto_op_cookie *op_cookie;
120 : : struct vring_packed_desc *desc;
121 : :
122 : 0 : desc = vq->vq_packed.ring.desc;
123 : :
124 : : /* Caller does the check */
125 [ # # ]: 0 : for (i = 0; i < num ; i++) {
126 : 0 : used_idx = vq->vq_used_cons_idx;
127 [ # # ]: 0 : if (!desc_is_used(&desc[used_idx], vq))
128 : : break;
129 : :
130 : 0 : cop = (struct rte_crypto_op *)
131 : 0 : vq->vq_descx[used_idx].crypto_op;
132 [ # # ]: 0 : if (unlikely(cop == NULL)) {
133 : 0 : VIRTIO_CRYPTO_RX_LOG_DBG("vring descriptor with no "
134 : : "mbuf cookie at %u",
135 : : vq->vq_used_cons_idx);
136 : 0 : break;
137 : : }
138 : :
139 : 0 : op_cookie = (struct virtio_crypto_op_cookie *)
140 : : vq->vq_descx[used_idx].cookie;
141 : : inhdr = &(op_cookie->inhdr);
142 [ # # # # : 0 : switch (inhdr->status) {
# # ]
143 : 0 : case VIRTIO_CRYPTO_OK:
144 : 0 : cop->status = RTE_CRYPTO_OP_STATUS_SUCCESS;
145 : 0 : break;
146 : 0 : case VIRTIO_CRYPTO_ERR:
147 : 0 : cop->status = RTE_CRYPTO_OP_STATUS_ERROR;
148 : 0 : vq->packets_received_failed++;
149 : 0 : break;
150 : 0 : case VIRTIO_CRYPTO_BADMSG:
151 : 0 : cop->status = RTE_CRYPTO_OP_STATUS_INVALID_ARGS;
152 : 0 : vq->packets_received_failed++;
153 : 0 : break;
154 : 0 : case VIRTIO_CRYPTO_NOTSUPP:
155 : 0 : cop->status = RTE_CRYPTO_OP_STATUS_INVALID_ARGS;
156 : 0 : vq->packets_received_failed++;
157 : 0 : break;
158 : 0 : case VIRTIO_CRYPTO_INVSESS:
159 : 0 : cop->status = RTE_CRYPTO_OP_STATUS_INVALID_SESSION;
160 : 0 : vq->packets_received_failed++;
161 : 0 : break;
162 : : default:
163 : : break;
164 : : }
165 : :
166 : 0 : vq->packets_received_total++;
167 : :
168 [ # # ]: 0 : if (cop->asym->rsa.op_type == RTE_CRYPTO_ASYM_OP_SIGN)
169 : 0 : memcpy(cop->asym->rsa.sign.data, op_cookie->sign,
170 : : cop->asym->rsa.sign.length);
171 [ # # ]: 0 : else if (cop->asym->rsa.op_type == RTE_CRYPTO_ASYM_OP_VERIFY)
172 : 0 : memcpy(cop->asym->rsa.message.data, op_cookie->message,
173 : : cop->asym->rsa.message.length);
174 [ # # ]: 0 : else if (cop->asym->rsa.op_type == RTE_CRYPTO_ASYM_OP_ENCRYPT)
175 : 0 : memcpy(cop->asym->rsa.cipher.data, op_cookie->cipher,
176 : : cop->asym->rsa.cipher.length);
177 [ # # ]: 0 : else if (cop->asym->rsa.op_type == RTE_CRYPTO_ASYM_OP_DECRYPT)
178 : 0 : memcpy(cop->asym->rsa.message.data, op_cookie->message,
179 : : cop->asym->rsa.message.length);
180 : :
181 : 0 : rx_pkts[i] = cop;
182 [ # # ]: 0 : rte_mempool_put(vq->mpool, op_cookie);
183 : :
184 : 0 : vq->vq_free_cnt += 4;
185 : 0 : vq->vq_used_cons_idx += 4;
186 : 0 : vq->vq_descx[used_idx].crypto_op = NULL;
187 [ # # ]: 0 : if (vq->vq_used_cons_idx >= vq->vq_nentries) {
188 : 0 : vq->vq_used_cons_idx -= vq->vq_nentries;
189 : 0 : vq->vq_packed.used_wrap_counter ^= 1;
190 : : }
191 : : }
192 : :
193 : 0 : return i;
194 : : }
195 : :
196 : : static inline int
197 : 0 : virtqueue_crypto_sym_pkt_header_arrange(
198 : : struct rte_crypto_op *cop,
199 : : struct virtio_crypto_op_data_req *data,
200 : : struct virtio_crypto_session *session)
201 : : {
202 : : struct rte_crypto_sym_op *sym_op = cop->sym;
203 : : struct virtio_crypto_op_data_req *req_data = data;
204 : : struct virtio_crypto_op_ctrl_req *ctrl = &session->ctrl.hdr;
205 : : struct virtio_crypto_sym_create_session_req *sym_sess_req =
206 : : &ctrl->u.sym_create_session;
207 : : struct virtio_crypto_alg_chain_session_para *chain_para =
208 : : &sym_sess_req->u.chain.para;
209 : : struct virtio_crypto_cipher_session_para *cipher_para;
210 : :
211 : 0 : req_data->header.session_id = session->session_id;
212 : :
213 [ # # # ]: 0 : switch (sym_sess_req->op_type) {
214 : 0 : case VIRTIO_CRYPTO_SYM_OP_CIPHER:
215 : 0 : req_data->u.sym_req.op_type = VIRTIO_CRYPTO_SYM_OP_CIPHER;
216 : :
217 : : cipher_para = &sym_sess_req->u.cipher.para;
218 [ # # ]: 0 : if (cipher_para->op == VIRTIO_CRYPTO_OP_ENCRYPT)
219 : 0 : req_data->header.opcode = VIRTIO_CRYPTO_CIPHER_ENCRYPT;
220 : : else
221 : 0 : req_data->header.opcode = VIRTIO_CRYPTO_CIPHER_DECRYPT;
222 : :
223 : : req_data->u.sym_req.u.cipher.para.iv_len
224 : 0 : = session->iv.length;
225 : :
226 : 0 : req_data->u.sym_req.u.cipher.para.src_data_len =
227 : 0 : (sym_op->cipher.data.length +
228 : 0 : sym_op->cipher.data.offset);
229 : 0 : req_data->u.sym_req.u.cipher.para.dst_data_len =
230 : : req_data->u.sym_req.u.cipher.para.src_data_len;
231 : 0 : break;
232 : 0 : case VIRTIO_CRYPTO_SYM_OP_ALGORITHM_CHAINING:
233 : 0 : req_data->u.sym_req.op_type =
234 : : VIRTIO_CRYPTO_SYM_OP_ALGORITHM_CHAINING;
235 : :
236 : : cipher_para = &chain_para->cipher_param;
237 [ # # ]: 0 : if (cipher_para->op == VIRTIO_CRYPTO_OP_ENCRYPT)
238 : 0 : req_data->header.opcode = VIRTIO_CRYPTO_CIPHER_ENCRYPT;
239 : : else
240 : 0 : req_data->header.opcode = VIRTIO_CRYPTO_CIPHER_DECRYPT;
241 : :
242 : 0 : req_data->u.sym_req.u.chain.para.iv_len = session->iv.length;
243 : : req_data->u.sym_req.u.chain.para.aad_len = session->aad.length;
244 : :
245 : 0 : req_data->u.sym_req.u.chain.para.src_data_len =
246 : 0 : RTE_MAX((sym_op->cipher.data.length +
247 : : sym_op->cipher.data.offset),
248 : : (sym_op->auth.data.length +
249 : : sym_op->auth.data.offset));
250 : 0 : req_data->u.sym_req.u.chain.para.dst_data_len =
251 : : req_data->u.sym_req.u.chain.para.src_data_len;
252 : 0 : req_data->u.sym_req.u.chain.para.cipher_start_src_offset =
253 : : sym_op->cipher.data.offset;
254 : 0 : req_data->u.sym_req.u.chain.para.len_to_cipher =
255 : : sym_op->cipher.data.length;
256 : 0 : req_data->u.sym_req.u.chain.para.hash_start_src_offset =
257 : : sym_op->auth.data.offset;
258 : 0 : req_data->u.sym_req.u.chain.para.len_to_hash =
259 : : sym_op->auth.data.length;
260 : 0 : req_data->u.sym_req.u.chain.para.aad_len =
261 : 0 : chain_para->aad_len;
262 : :
263 [ # # ]: 0 : if (chain_para->hash_mode == VIRTIO_CRYPTO_SYM_HASH_MODE_PLAIN)
264 : 0 : req_data->u.sym_req.u.chain.para.hash_result_len =
265 : 0 : chain_para->u.hash_param.hash_result_len;
266 [ # # ]: 0 : if (chain_para->hash_mode ==
267 : : VIRTIO_CRYPTO_SYM_HASH_MODE_AUTH)
268 : 0 : req_data->u.sym_req.u.chain.para.hash_result_len =
269 : 0 : chain_para->u.mac_param.hash_result_len;
270 : : break;
271 : : default:
272 : : return -1;
273 : : }
274 : :
275 : : return 0;
276 : : }
277 : :
278 : : static inline int
279 : 0 : virtqueue_crypto_sym_enqueue_xmit_split(
280 : : struct virtqueue *txvq,
281 : : struct rte_crypto_op *cop)
282 : : {
283 : : uint16_t idx = 0;
284 : : uint16_t num_entry;
285 : : uint16_t needed = 1;
286 : : uint16_t head_idx;
287 : : struct vq_desc_extra *dxp;
288 : : struct vring_desc *start_dp;
289 : : struct vring_desc *desc;
290 : : uint64_t indirect_op_data_req_phys_addr;
291 : : uint16_t req_data_len = sizeof(struct virtio_crypto_op_data_req);
292 : : uint32_t indirect_vring_addr_offset = req_data_len +
293 : : sizeof(struct virtio_crypto_inhdr);
294 : : uint32_t indirect_iv_addr_offset =
295 : : offsetof(struct virtio_crypto_op_cookie, iv);
296 : : struct rte_crypto_sym_op *sym_op = cop->sym;
297 : 0 : struct virtio_crypto_session *session =
298 : 0 : CRYPTODEV_GET_SYM_SESS_PRIV(cop->sym->session);
299 : : struct virtio_crypto_op_data_req *op_data_req;
300 : : uint32_t hash_result_len = 0;
301 : : struct virtio_crypto_op_cookie *crypto_op_cookie;
302 : : struct virtio_crypto_alg_chain_session_para *para;
303 : : uint32_t src_len;
304 : :
305 [ # # ]: 0 : if (unlikely(sym_op->m_src->nb_segs != 1))
306 : : return -EMSGSIZE;
307 [ # # ]: 0 : if (unlikely(txvq->vq_free_cnt == 0))
308 : : return -ENOSPC;
309 : : if (unlikely(txvq->vq_free_cnt < needed))
310 : : return -EMSGSIZE;
311 : 0 : head_idx = txvq->vq_desc_head_idx;
312 [ # # ]: 0 : if (unlikely(head_idx >= txvq->vq_nentries))
313 : : return -EFAULT;
314 : : if (unlikely(session == NULL))
315 : : return -EFAULT;
316 : :
317 : 0 : dxp = &txvq->vq_descx[head_idx];
318 : :
319 [ # # # # ]: 0 : if (rte_mempool_get(txvq->mpool, &dxp->cookie)) {
320 : 0 : VIRTIO_CRYPTO_TX_LOG_ERR("can not get cookie");
321 : 0 : return -EFAULT;
322 : : }
323 : 0 : crypto_op_cookie = dxp->cookie;
324 : : indirect_op_data_req_phys_addr =
325 : : rte_mempool_virt2iova(crypto_op_cookie);
326 : : op_data_req = (struct virtio_crypto_op_data_req *)crypto_op_cookie;
327 : :
328 [ # # ]: 0 : if (virtqueue_crypto_sym_pkt_header_arrange(cop, op_data_req, session))
329 : : return -EFAULT;
330 : :
331 : : /* status is initialized to VIRTIO_CRYPTO_ERR */
332 : : ((struct virtio_crypto_inhdr *)
333 : 0 : ((uint8_t *)op_data_req + req_data_len))->status =
334 : : VIRTIO_CRYPTO_ERR;
335 : :
336 : : /* point to indirect vring entry */
337 : 0 : desc = (struct vring_desc *)
338 : : ((uint8_t *)op_data_req + indirect_vring_addr_offset);
339 [ # # ]: 0 : for (idx = 0; idx < (NUM_ENTRY_VIRTIO_CRYPTO_OP - 1); idx++)
340 : 0 : desc[idx].next = idx + 1;
341 : 0 : desc[NUM_ENTRY_VIRTIO_CRYPTO_OP - 1].next = VQ_RING_DESC_CHAIN_END;
342 : :
343 : : idx = 0;
344 : :
345 : : /* indirect vring: first part, virtio_crypto_op_data_req */
346 : 0 : desc[idx].addr = indirect_op_data_req_phys_addr;
347 : 0 : desc[idx].len = req_data_len;
348 : 0 : desc[idx++].flags = VRING_DESC_F_NEXT;
349 : :
350 : : /* indirect vring: iv of cipher */
351 [ # # ]: 0 : if (session->iv.length) {
352 [ # # ]: 0 : if (cop->phys_addr)
353 : 0 : desc[idx].addr = cop->phys_addr + session->iv.offset;
354 : : else {
355 [ # # ]: 0 : if (session->iv.length > VIRTIO_CRYPTO_MAX_IV_SIZE)
356 : : return -ENOMEM;
357 : :
358 : 0 : rte_memcpy(crypto_op_cookie->iv,
359 [ # # ]: 0 : rte_crypto_op_ctod_offset(cop,
360 : : uint8_t *, session->iv.offset),
361 : : session->iv.length);
362 : 0 : desc[idx].addr = indirect_op_data_req_phys_addr +
363 : : indirect_iv_addr_offset;
364 : : }
365 : :
366 : 0 : desc[idx].len = session->iv.length;
367 : 0 : desc[idx++].flags = VRING_DESC_F_NEXT;
368 : : }
369 : :
370 : : /* indirect vring: additional auth data */
371 [ # # ]: 0 : if (session->aad.length) {
372 : 0 : desc[idx].addr = session->aad.phys_addr;
373 : 0 : desc[idx].len = session->aad.length;
374 : 0 : desc[idx++].flags = VRING_DESC_F_NEXT;
375 : : }
376 : :
377 : 0 : src_len = RTE_MAX((sym_op->cipher.data.offset +
378 : : sym_op->cipher.data.length),
379 : : (sym_op->auth.data.length +
380 : : sym_op->auth.data.offset));
381 : : /* indirect vring: src data */
382 [ # # ]: 0 : desc[idx].addr = rte_pktmbuf_iova_offset(sym_op->m_src, 0);
383 : 0 : desc[idx].len = src_len;
384 : 0 : desc[idx++].flags = VRING_DESC_F_NEXT;
385 : :
386 : : /* indirect vring: dst data */
387 [ # # ]: 0 : if (sym_op->m_dst) {
388 : 0 : desc[idx].addr = rte_pktmbuf_iova_offset(sym_op->m_dst, 0);
389 : 0 : desc[idx].len = src_len;
390 : : } else {
391 : 0 : desc[idx].addr = rte_pktmbuf_iova_offset(sym_op->m_src, 0);
392 : 0 : desc[idx].len = src_len;
393 : : }
394 : 0 : desc[idx++].flags = VRING_DESC_F_WRITE | VRING_DESC_F_NEXT;
395 : :
396 : : /* indirect vring: digest result */
397 : : para = &(session->ctrl.hdr.u.sym_create_session.u.chain.para);
398 [ # # ]: 0 : if (para->hash_mode == VIRTIO_CRYPTO_SYM_HASH_MODE_PLAIN)
399 : 0 : hash_result_len = para->u.hash_param.hash_result_len;
400 [ # # ]: 0 : if (para->hash_mode == VIRTIO_CRYPTO_SYM_HASH_MODE_AUTH)
401 : 0 : hash_result_len = para->u.mac_param.hash_result_len;
402 [ # # ]: 0 : if (hash_result_len > 0) {
403 : 0 : desc[idx].addr = sym_op->auth.digest.phys_addr;
404 : 0 : desc[idx].len = hash_result_len;
405 : 0 : desc[idx++].flags = VRING_DESC_F_WRITE | VRING_DESC_F_NEXT;
406 : : }
407 : :
408 : : /* indirect vring: last part, status returned */
409 : 0 : desc[idx].addr = indirect_op_data_req_phys_addr + req_data_len;
410 : 0 : desc[idx].len = sizeof(struct virtio_crypto_inhdr);
411 : 0 : desc[idx++].flags = VRING_DESC_F_WRITE;
412 : :
413 : : num_entry = idx;
414 : :
415 : : /* save the infos to use when receiving packets */
416 : 0 : dxp->crypto_op = (void *)cop;
417 : 0 : dxp->ndescs = needed;
418 : :
419 : : /* use a single buffer */
420 : 0 : start_dp = txvq->vq_split.ring.desc;
421 : 0 : start_dp[head_idx].addr = indirect_op_data_req_phys_addr +
422 : : indirect_vring_addr_offset;
423 : 0 : start_dp[head_idx].len = num_entry * sizeof(struct vring_desc);
424 : 0 : start_dp[head_idx].flags = VRING_DESC_F_INDIRECT;
425 : :
426 : 0 : idx = start_dp[head_idx].next;
427 : 0 : txvq->vq_desc_head_idx = idx;
428 [ # # ]: 0 : if (txvq->vq_desc_head_idx == VQ_RING_DESC_CHAIN_END)
429 : 0 : txvq->vq_desc_tail_idx = idx;
430 [ # # ]: 0 : txvq->vq_free_cnt = (uint16_t)(txvq->vq_free_cnt - needed);
431 : : vq_update_avail_ring(txvq, head_idx);
432 : :
433 : 0 : return 0;
434 : : }
435 : :
436 : : static inline int
437 : 0 : virtqueue_crypto_sym_enqueue_xmit_packed(
438 : : struct virtqueue *txvq,
439 : : struct rte_crypto_op *cop)
440 : : {
441 : : uint16_t idx = 0;
442 : : uint16_t needed = 1;
443 : : uint16_t head_idx;
444 : : struct vq_desc_extra *dxp;
445 : : struct vring_packed_desc *start_dp;
446 : : struct vring_packed_desc *desc;
447 : : uint64_t op_data_req_phys_addr;
448 : : uint16_t req_data_len = sizeof(struct virtio_crypto_op_data_req);
449 : : uint32_t iv_addr_offset =
450 : : offsetof(struct virtio_crypto_op_cookie, iv);
451 : : struct rte_crypto_sym_op *sym_op = cop->sym;
452 : 0 : struct virtio_crypto_session *session =
453 : 0 : CRYPTODEV_GET_SYM_SESS_PRIV(cop->sym->session);
454 : : struct virtio_crypto_op_data_req *op_data_req;
455 : : uint32_t hash_result_len = 0;
456 : : struct virtio_crypto_op_cookie *crypto_op_cookie;
457 : : struct virtio_crypto_alg_chain_session_para *para;
458 : : uint16_t flags = VRING_DESC_F_NEXT;
459 : :
460 [ # # ]: 0 : if (unlikely(sym_op->m_src->nb_segs != 1))
461 : : return -EMSGSIZE;
462 [ # # ]: 0 : if (unlikely(txvq->vq_free_cnt == 0))
463 : : return -ENOSPC;
464 : : if (unlikely(txvq->vq_free_cnt < needed))
465 : : return -EMSGSIZE;
466 : 0 : head_idx = txvq->vq_desc_head_idx;
467 [ # # ]: 0 : if (unlikely(head_idx >= txvq->vq_nentries))
468 : : return -EFAULT;
469 : : if (unlikely(session == NULL))
470 : : return -EFAULT;
471 : :
472 : 0 : dxp = &txvq->vq_descx[head_idx];
473 : :
474 [ # # # # ]: 0 : if (rte_mempool_get(txvq->mpool, &dxp->cookie)) {
475 : 0 : VIRTIO_CRYPTO_TX_LOG_ERR("can not get cookie");
476 : 0 : return -EFAULT;
477 : : }
478 : 0 : crypto_op_cookie = dxp->cookie;
479 : : op_data_req_phys_addr = rte_mempool_virt2iova(crypto_op_cookie);
480 : : op_data_req = (struct virtio_crypto_op_data_req *)crypto_op_cookie;
481 : :
482 [ # # ]: 0 : if (virtqueue_crypto_sym_pkt_header_arrange(cop, op_data_req, session))
483 : : return -EFAULT;
484 : :
485 : : /* status is initialized to VIRTIO_CRYPTO_ERR */
486 : : ((struct virtio_crypto_inhdr *)
487 : 0 : ((uint8_t *)op_data_req + req_data_len))->status =
488 : : VIRTIO_CRYPTO_ERR;
489 : :
490 : 0 : desc = &txvq->vq_packed.ring.desc[txvq->vq_desc_head_idx];
491 : : needed = 4;
492 : 0 : flags |= txvq->vq_packed.cached_flags;
493 : :
494 : : start_dp = desc;
495 : : idx = 0;
496 : :
497 : : /* packed vring: first part, virtio_crypto_op_data_req */
498 : 0 : desc[idx].addr = op_data_req_phys_addr;
499 : 0 : desc[idx].len = req_data_len;
500 : 0 : desc[idx++].flags = flags;
501 : :
502 : : /* packed vring: iv of cipher */
503 [ # # ]: 0 : if (session->iv.length) {
504 [ # # ]: 0 : if (cop->phys_addr)
505 : 0 : desc[idx].addr = cop->phys_addr + session->iv.offset;
506 : : else {
507 [ # # ]: 0 : if (session->iv.length > VIRTIO_CRYPTO_MAX_IV_SIZE)
508 : : return -ENOMEM;
509 : :
510 : 0 : rte_memcpy(crypto_op_cookie->iv,
511 [ # # ]: 0 : rte_crypto_op_ctod_offset(cop,
512 : : uint8_t *, session->iv.offset),
513 : : session->iv.length);
514 : 0 : desc[idx].addr = op_data_req_phys_addr + iv_addr_offset;
515 : : }
516 : :
517 : 0 : desc[idx].len = session->iv.length;
518 : 0 : desc[idx++].flags = flags;
519 : : }
520 : :
521 : : /* packed vring: additional auth data */
522 [ # # ]: 0 : if (session->aad.length) {
523 : 0 : desc[idx].addr = session->aad.phys_addr;
524 : 0 : desc[idx].len = session->aad.length;
525 : 0 : desc[idx++].flags = flags;
526 : : }
527 : :
528 : : /* packed vring: src data */
529 [ # # ]: 0 : desc[idx].addr = rte_pktmbuf_iova_offset(sym_op->m_src, 0);
530 : 0 : desc[idx].len = (sym_op->cipher.data.offset
531 : 0 : + sym_op->cipher.data.length);
532 : 0 : desc[idx++].flags = flags;
533 : :
534 : : /* packed vring: dst data */
535 [ # # ]: 0 : if (sym_op->m_dst) {
536 : 0 : desc[idx].addr = rte_pktmbuf_iova_offset(sym_op->m_dst, 0);
537 : 0 : desc[idx].len = (sym_op->cipher.data.offset
538 : : + sym_op->cipher.data.length);
539 : : } else {
540 : 0 : desc[idx].addr = rte_pktmbuf_iova_offset(sym_op->m_src, 0);
541 : 0 : desc[idx].len = (sym_op->cipher.data.offset
542 : : + sym_op->cipher.data.length);
543 : : }
544 : 0 : desc[idx++].flags = VRING_DESC_F_WRITE | VRING_DESC_F_NEXT;
545 : :
546 : : /* packed vring: digest result */
547 : : para = &(session->ctrl.hdr.u.sym_create_session.u.chain.para);
548 [ # # ]: 0 : if (para->hash_mode == VIRTIO_CRYPTO_SYM_HASH_MODE_PLAIN)
549 : 0 : hash_result_len = para->u.hash_param.hash_result_len;
550 [ # # ]: 0 : if (para->hash_mode == VIRTIO_CRYPTO_SYM_HASH_MODE_AUTH)
551 : 0 : hash_result_len = para->u.mac_param.hash_result_len;
552 [ # # ]: 0 : if (hash_result_len > 0) {
553 : 0 : desc[idx].addr = sym_op->auth.digest.phys_addr;
554 : 0 : desc[idx].len = hash_result_len;
555 : 0 : desc[idx++].flags = VRING_DESC_F_WRITE | VRING_DESC_F_NEXT;
556 : : }
557 : :
558 : : /* packed vring: last part, status returned */
559 : 0 : desc[idx].addr = op_data_req_phys_addr + req_data_len;
560 : 0 : desc[idx].len = sizeof(struct virtio_crypto_inhdr);
561 : 0 : desc[idx++].flags = flags | VRING_DESC_F_WRITE;
562 : :
563 : : /* save the infos to use when receiving packets */
564 : 0 : dxp->crypto_op = (void *)cop;
565 : 0 : dxp->ndescs = needed;
566 : :
567 : 0 : txvq->vq_desc_head_idx += idx & (txvq->vq_nentries - 1);
568 [ # # ]: 0 : if (txvq->vq_desc_head_idx == VQ_RING_DESC_CHAIN_END)
569 : 0 : txvq->vq_desc_tail_idx = idx;
570 : 0 : txvq->vq_free_cnt = (uint16_t)(txvq->vq_free_cnt - needed);
571 : 0 : virtqueue_store_flags_packed(&start_dp[0],
572 : 0 : start_dp[0].flags | flags,
573 [ # # ]: 0 : txvq->hw->weak_barriers);
574 [ # # ]: 0 : virtio_wmb(txvq->hw->weak_barriers);
575 : :
576 : : return 0;
577 : : }
578 : :
579 : : static inline int
580 : 0 : virtqueue_crypto_sym_enqueue_xmit(
581 : : struct virtqueue *txvq,
582 : : struct rte_crypto_op *cop)
583 : : {
584 [ # # ]: 0 : if (vtpci_with_packed_queue(txvq->hw))
585 : 0 : return virtqueue_crypto_sym_enqueue_xmit_packed(txvq, cop);
586 : : else
587 : 0 : return virtqueue_crypto_sym_enqueue_xmit_split(txvq, cop);
588 : : }
589 : :
590 : : static inline int
591 : 0 : virtqueue_crypto_asym_pkt_header_arrange(
592 : : struct rte_crypto_op *cop,
593 : : struct virtio_crypto_op_data_req *data,
594 : : struct virtio_crypto_session *session)
595 : : {
596 : : struct virtio_crypto_op_ctrl_req *ctrl = &session->ctrl.hdr;
597 : : struct virtio_crypto_op_data_req *req_data = data;
598 : : struct rte_crypto_asym_op *asym_op = cop->asym;
599 : :
600 : 0 : req_data->header.session_id = session->session_id;
601 : :
602 [ # # ]: 0 : switch (ctrl->header.algo) {
603 : 0 : case VIRTIO_CRYPTO_AKCIPHER_RSA:
604 : 0 : req_data->header.algo = ctrl->header.algo;
605 [ # # ]: 0 : if (asym_op->rsa.op_type == RTE_CRYPTO_ASYM_OP_SIGN) {
606 : 0 : req_data->header.opcode = VIRTIO_CRYPTO_AKCIPHER_SIGN;
607 : : req_data->u.akcipher_req.para.src_data_len
608 : 0 : = asym_op->rsa.message.length;
609 : : req_data->u.akcipher_req.para.dst_data_len
610 : 0 : = asym_op->rsa.sign.length;
611 [ # # ]: 0 : } else if (asym_op->rsa.op_type == RTE_CRYPTO_ASYM_OP_VERIFY) {
612 : 0 : req_data->header.opcode = VIRTIO_CRYPTO_AKCIPHER_VERIFY;
613 : : req_data->u.akcipher_req.para.src_data_len
614 : 0 : = asym_op->rsa.sign.length;
615 : : req_data->u.akcipher_req.para.dst_data_len
616 : 0 : = asym_op->rsa.message.length;
617 [ # # ]: 0 : } else if (asym_op->rsa.op_type == RTE_CRYPTO_ASYM_OP_ENCRYPT) {
618 : 0 : req_data->header.opcode = VIRTIO_CRYPTO_AKCIPHER_ENCRYPT;
619 : : req_data->u.akcipher_req.para.src_data_len
620 : 0 : = asym_op->rsa.message.length;
621 : : req_data->u.akcipher_req.para.dst_data_len
622 : 0 : = asym_op->rsa.cipher.length;
623 [ # # ]: 0 : } else if (asym_op->rsa.op_type == RTE_CRYPTO_ASYM_OP_DECRYPT) {
624 : 0 : req_data->header.opcode = VIRTIO_CRYPTO_AKCIPHER_DECRYPT;
625 : : req_data->u.akcipher_req.para.src_data_len
626 : 0 : = asym_op->rsa.cipher.length;
627 : : req_data->u.akcipher_req.para.dst_data_len
628 : 0 : = asym_op->rsa.message.length;
629 : : } else {
630 : : return -EINVAL;
631 : : }
632 : :
633 : : break;
634 : 0 : default:
635 : 0 : req_data->header.algo = VIRTIO_CRYPTO_NO_AKCIPHER;
636 : : }
637 : :
638 : : return 0;
639 : : }
640 : :
641 : : static inline int
642 : 0 : virtqueue_crypto_asym_enqueue_xmit_split(
643 : : struct virtqueue *txvq,
644 : : struct rte_crypto_op *cop)
645 : : {
646 : : uint16_t req_data_len = sizeof(struct virtio_crypto_op_data_req);
647 : : uint32_t indirect_vring_addr_offset = req_data_len +
648 : : sizeof(struct virtio_crypto_inhdr);
649 : 0 : struct virtio_crypto_session *session =
650 : 0 : CRYPTODEV_GET_ASYM_SESS_PRIV(cop->asym->session);
651 : : struct virtio_crypto_op_cookie *crypto_op_cookie;
652 : : struct rte_crypto_asym_op *asym_op = cop->asym;
653 : : struct virtio_crypto_op_data_req *op_data_req;
654 : : uint64_t indirect_op_data_req_phys_addr;
655 : : struct vring_used_elem *uep;
656 : : struct vring_desc *start_dp;
657 : : struct vq_desc_extra *dxp;
658 : : struct vring_desc *desc;
659 : : uint16_t needed = 1;
660 : : uint16_t num_entry;
661 : : uint16_t head_idx;
662 : : uint16_t idx = 0;
663 : :
664 [ # # ]: 0 : if (unlikely(txvq->vq_free_cnt == 0))
665 : : return -ENOSPC;
666 : : if (unlikely(txvq->vq_free_cnt < needed))
667 : : return -EMSGSIZE;
668 : 0 : head_idx = txvq->vq_desc_head_idx;
669 [ # # ]: 0 : if (unlikely(head_idx >= txvq->vq_nentries))
670 : : return -EFAULT;
671 : :
672 : 0 : dxp = &txvq->vq_descx[head_idx];
673 : :
674 [ # # # # ]: 0 : if (rte_mempool_get(txvq->mpool, &dxp->cookie)) {
675 : 0 : VIRTIO_CRYPTO_TX_LOG_ERR("can not get cookie");
676 : 0 : return -EFAULT;
677 : : }
678 : 0 : crypto_op_cookie = dxp->cookie;
679 : : indirect_op_data_req_phys_addr =
680 : : rte_mempool_virt2iova(crypto_op_cookie);
681 : : op_data_req = (struct virtio_crypto_op_data_req *)crypto_op_cookie;
682 [ # # ]: 0 : if (virtqueue_crypto_asym_pkt_header_arrange(cop, op_data_req, session))
683 : : return -EFAULT;
684 : :
685 : : /* status is initialized to VIRTIO_CRYPTO_ERR */
686 : : ((struct virtio_crypto_inhdr *)
687 : 0 : ((uint8_t *)op_data_req + req_data_len))->status =
688 : : VIRTIO_CRYPTO_ERR;
689 : :
690 : : /* point to indirect vring entry */
691 : : desc = (struct vring_desc *)
692 : : ((uint8_t *)op_data_req + indirect_vring_addr_offset);
693 [ # # ]: 0 : for (idx = 0; idx < (NUM_ENTRY_VIRTIO_CRYPTO_OP - 1); idx++)
694 : 0 : desc[idx].next = idx + 1;
695 : 0 : desc[NUM_ENTRY_VIRTIO_CRYPTO_OP - 1].next = VQ_RING_DESC_CHAIN_END;
696 : :
697 : : idx = 0;
698 : :
699 : : /* indirect vring: first part, virtio_crypto_op_data_req */
700 : 0 : desc[idx].addr = indirect_op_data_req_phys_addr;
701 : 0 : desc[idx].len = req_data_len;
702 : 0 : desc[idx++].flags = VRING_DESC_F_NEXT;
703 : :
704 [ # # ]: 0 : if (asym_op->rsa.op_type == RTE_CRYPTO_ASYM_OP_SIGN) {
705 : : /* indirect vring: src data */
706 : 0 : desc[idx].addr = rte_mem_virt2iova(asym_op->rsa.message.data);
707 : 0 : desc[idx].len = asym_op->rsa.message.length;
708 : 0 : desc[idx++].flags = VRING_DESC_F_NEXT;
709 : :
710 : : /* indirect vring: dst data */
711 : 0 : desc[idx].addr = rte_mem_virt2iova(asym_op->rsa.sign.data);
712 : 0 : desc[idx].len = asym_op->rsa.sign.length;
713 : 0 : desc[idx++].flags = VRING_DESC_F_NEXT | VRING_DESC_F_WRITE;
714 [ # # ]: 0 : } else if (asym_op->rsa.op_type == RTE_CRYPTO_ASYM_OP_VERIFY) {
715 : : /* indirect vring: src data */
716 : 0 : desc[idx].addr = rte_mem_virt2iova(asym_op->rsa.sign.data);
717 : 0 : desc[idx].len = asym_op->rsa.sign.length;
718 : 0 : desc[idx++].flags = VRING_DESC_F_NEXT;
719 : :
720 : : /* indirect vring: dst data */
721 : 0 : desc[idx].addr = rte_mem_virt2iova(asym_op->rsa.message.data);
722 : 0 : desc[idx].len = asym_op->rsa.message.length;
723 : 0 : desc[idx++].flags = VRING_DESC_F_NEXT;
724 [ # # ]: 0 : } else if (asym_op->rsa.op_type == RTE_CRYPTO_ASYM_OP_ENCRYPT) {
725 : : /* indirect vring: src data */
726 : 0 : desc[idx].addr = rte_mem_virt2iova(asym_op->rsa.message.data);
727 : 0 : desc[idx].len = asym_op->rsa.message.length;
728 : 0 : desc[idx++].flags = VRING_DESC_F_NEXT;
729 : :
730 : : /* indirect vring: dst data */
731 : 0 : desc[idx].addr = rte_mem_virt2iova(asym_op->rsa.cipher.data);
732 : 0 : desc[idx].len = asym_op->rsa.cipher.length;
733 : 0 : desc[idx++].flags = VRING_DESC_F_NEXT | VRING_DESC_F_WRITE;
734 [ # # ]: 0 : } else if (asym_op->rsa.op_type == RTE_CRYPTO_ASYM_OP_DECRYPT) {
735 : : /* indirect vring: src data */
736 : 0 : desc[idx].addr = rte_mem_virt2iova(asym_op->rsa.cipher.data);
737 : 0 : desc[idx].len = asym_op->rsa.cipher.length;
738 : 0 : desc[idx++].flags = VRING_DESC_F_NEXT;
739 : :
740 : : /* indirect vring: dst data */
741 : 0 : desc[idx].addr = rte_mem_virt2iova(asym_op->rsa.message.data);
742 : 0 : desc[idx].len = asym_op->rsa.message.length;
743 : 0 : desc[idx++].flags = VRING_DESC_F_NEXT | VRING_DESC_F_WRITE;
744 : : } else {
745 : 0 : VIRTIO_CRYPTO_TX_LOG_ERR("Invalid asym op");
746 : 0 : return -EINVAL;
747 : : }
748 : :
749 : : /* indirect vring: last part, status returned */
750 : 0 : desc[idx].addr = indirect_op_data_req_phys_addr + req_data_len;
751 : 0 : desc[idx].len = sizeof(struct virtio_crypto_inhdr);
752 : 0 : desc[idx++].flags = VRING_DESC_F_WRITE;
753 : :
754 : : num_entry = idx;
755 : :
756 : : /* save the infos to use when receiving packets */
757 : 0 : dxp->crypto_op = (void *)cop;
758 : 0 : dxp->ndescs = needed;
759 : :
760 : : /* use a single buffer */
761 : 0 : start_dp = txvq->vq_split.ring.desc;
762 : 0 : start_dp[head_idx].addr = indirect_op_data_req_phys_addr +
763 : : indirect_vring_addr_offset;
764 : 0 : start_dp[head_idx].len = num_entry * sizeof(struct vring_desc);
765 : 0 : start_dp[head_idx].flags = VRING_DESC_F_INDIRECT;
766 : :
767 : 0 : idx = start_dp[head_idx].next;
768 : 0 : txvq->vq_desc_head_idx = idx;
769 [ # # ]: 0 : if (txvq->vq_desc_head_idx == VQ_RING_DESC_CHAIN_END)
770 : 0 : txvq->vq_desc_tail_idx = idx;
771 : 0 : txvq->vq_free_cnt = (uint16_t)(txvq->vq_free_cnt - needed);
772 : :
773 : 0 : uep = &txvq->vq_split.ring.used->ring[head_idx];
774 [ # # ]: 0 : uep->id = head_idx;
775 : : vq_update_avail_ring(txvq, head_idx);
776 : :
777 : 0 : return 0;
778 : : }
779 : :
780 : : static inline int
781 : 0 : virtqueue_crypto_asym_enqueue_xmit_packed(
782 : : struct virtqueue *txvq,
783 : : struct rte_crypto_op *cop)
784 : : {
785 : : uint16_t idx = 0;
786 : : uint16_t num_entry;
787 : : uint16_t needed = 1;
788 : : uint16_t head_idx;
789 : : struct vq_desc_extra *dxp;
790 : : struct vring_packed_desc *start_dp;
791 : : struct vring_packed_desc *desc;
792 : : uint64_t op_data_req_phys_addr;
793 : : uint16_t req_data_len = sizeof(struct virtio_crypto_op_data_req);
794 : : struct rte_crypto_asym_op *asym_op = cop->asym;
795 : 0 : struct virtio_crypto_session *session =
796 : 0 : CRYPTODEV_GET_ASYM_SESS_PRIV(cop->asym->session);
797 : : struct virtio_crypto_op_data_req *op_data_req;
798 : : struct virtio_crypto_op_cookie *crypto_op_cookie;
799 : : uint16_t flags = VRING_DESC_F_NEXT;
800 : :
801 [ # # ]: 0 : if (unlikely(txvq->vq_free_cnt == 0))
802 : : return -ENOSPC;
803 : : if (unlikely(txvq->vq_free_cnt < needed))
804 : : return -EMSGSIZE;
805 : 0 : head_idx = txvq->vq_desc_head_idx;
806 [ # # ]: 0 : if (unlikely(head_idx >= txvq->vq_nentries))
807 : : return -EFAULT;
808 : :
809 : 0 : dxp = &txvq->vq_descx[head_idx];
810 : :
811 [ # # # # ]: 0 : if (rte_mempool_get(txvq->mpool, &dxp->cookie)) {
812 : 0 : VIRTIO_CRYPTO_TX_LOG_ERR("can not get cookie");
813 : 0 : return -EFAULT;
814 : : }
815 : 0 : crypto_op_cookie = dxp->cookie;
816 : : op_data_req_phys_addr = rte_mempool_virt2iova(crypto_op_cookie);
817 : : op_data_req = (struct virtio_crypto_op_data_req *)crypto_op_cookie;
818 [ # # ]: 0 : if (virtqueue_crypto_asym_pkt_header_arrange(cop, op_data_req, session))
819 : : return -EFAULT;
820 : :
821 : : /* status is initialized to VIRTIO_CRYPTO_ERR */
822 : : ((struct virtio_crypto_inhdr *)
823 : 0 : ((uint8_t *)op_data_req + req_data_len))->status =
824 : : VIRTIO_CRYPTO_ERR;
825 : :
826 : 0 : desc = &txvq->vq_packed.ring.desc[txvq->vq_desc_head_idx];
827 : : needed = 4;
828 : 0 : flags |= txvq->vq_packed.cached_flags;
829 : :
830 : : start_dp = desc;
831 : : idx = 0;
832 : :
833 : : /* packed vring: first part, virtio_crypto_op_data_req */
834 : 0 : desc[idx].addr = op_data_req_phys_addr;
835 : 0 : desc[idx].len = sizeof(struct virtio_crypto_op_data_req);
836 : 0 : desc[idx++].flags = flags;
837 : :
838 [ # # ]: 0 : if (asym_op->rsa.op_type == RTE_CRYPTO_ASYM_OP_SIGN) {
839 : : /* packed vring: src data */
840 [ # # ]: 0 : if (asym_op->rsa.message.length > VIRTIO_CRYPTO_MAX_MSG_SIZE)
841 : : return -ENOMEM;
842 [ # # ]: 0 : memcpy(crypto_op_cookie->message, asym_op->rsa.message.data,
843 : : asym_op->rsa.message.length);
844 : 0 : desc[idx].addr = op_data_req_phys_addr +
845 : : offsetof(struct virtio_crypto_op_cookie, message);
846 : 0 : desc[idx].len = asym_op->rsa.message.length;
847 : 0 : desc[idx++].flags = flags;
848 : :
849 : : /* packed vring: dst data */
850 [ # # ]: 0 : if (asym_op->rsa.sign.length > VIRTIO_CRYPTO_MAX_SIGN_SIZE)
851 : : return -ENOMEM;
852 : 0 : desc[idx].addr = op_data_req_phys_addr +
853 : : offsetof(struct virtio_crypto_op_cookie, sign);
854 : 0 : desc[idx].len = asym_op->rsa.sign.length;
855 : 0 : desc[idx++].flags = flags | VRING_DESC_F_WRITE;
856 [ # # ]: 0 : } else if (asym_op->rsa.op_type == RTE_CRYPTO_ASYM_OP_VERIFY) {
857 : : /* packed vring: src data */
858 [ # # ]: 0 : if (asym_op->rsa.sign.length > VIRTIO_CRYPTO_MAX_SIGN_SIZE)
859 : : return -ENOMEM;
860 [ # # ]: 0 : memcpy(crypto_op_cookie->sign, asym_op->rsa.sign.data,
861 : : asym_op->rsa.sign.length);
862 : 0 : desc[idx].addr = op_data_req_phys_addr +
863 : : offsetof(struct virtio_crypto_op_cookie, sign);
864 : 0 : desc[idx].len = asym_op->rsa.sign.length;
865 : 0 : desc[idx++].flags = flags;
866 : :
867 : : /* packed vring: dst data */
868 [ # # ]: 0 : if (asym_op->rsa.message.length > VIRTIO_CRYPTO_MAX_MSG_SIZE)
869 : : return -ENOMEM;
870 : 0 : desc[idx].addr = op_data_req_phys_addr +
871 : : offsetof(struct virtio_crypto_op_cookie, message);
872 : 0 : desc[idx].len = asym_op->rsa.message.length;
873 : 0 : desc[idx++].flags = flags;
874 [ # # ]: 0 : } else if (asym_op->rsa.op_type == RTE_CRYPTO_ASYM_OP_ENCRYPT) {
875 : : /* packed vring: src data */
876 [ # # ]: 0 : if (asym_op->rsa.message.length > VIRTIO_CRYPTO_MAX_MSG_SIZE)
877 : : return -ENOMEM;
878 [ # # ]: 0 : memcpy(crypto_op_cookie->message, asym_op->rsa.message.data,
879 : : asym_op->rsa.message.length);
880 : 0 : desc[idx].addr = op_data_req_phys_addr +
881 : : offsetof(struct virtio_crypto_op_cookie, message);
882 : 0 : desc[idx].len = asym_op->rsa.message.length;
883 : 0 : desc[idx++].flags = flags;
884 : :
885 : : /* packed vring: dst data */
886 [ # # ]: 0 : if (asym_op->rsa.cipher.length > VIRTIO_CRYPTO_MAX_CIPHER_SIZE)
887 : : return -ENOMEM;
888 : 0 : desc[idx].addr = op_data_req_phys_addr +
889 : : offsetof(struct virtio_crypto_op_cookie, cipher);
890 : 0 : desc[idx].len = asym_op->rsa.cipher.length;
891 : 0 : desc[idx++].flags = flags | VRING_DESC_F_WRITE;
892 [ # # ]: 0 : } else if (asym_op->rsa.op_type == RTE_CRYPTO_ASYM_OP_DECRYPT) {
893 : : /* packed vring: src data */
894 [ # # ]: 0 : if (asym_op->rsa.cipher.length > VIRTIO_CRYPTO_MAX_CIPHER_SIZE)
895 : : return -ENOMEM;
896 [ # # ]: 0 : memcpy(crypto_op_cookie->cipher, asym_op->rsa.cipher.data,
897 : : asym_op->rsa.cipher.length);
898 : 0 : desc[idx].addr = op_data_req_phys_addr +
899 : : offsetof(struct virtio_crypto_op_cookie, cipher);
900 : 0 : desc[idx].len = asym_op->rsa.cipher.length;
901 : 0 : desc[idx++].flags = flags;
902 : :
903 : : /* packed vring: dst data */
904 [ # # ]: 0 : if (asym_op->rsa.message.length > VIRTIO_CRYPTO_MAX_MSG_SIZE)
905 : : return -ENOMEM;
906 : 0 : desc[idx].addr = op_data_req_phys_addr +
907 : : offsetof(struct virtio_crypto_op_cookie, message);
908 : 0 : desc[idx].len = asym_op->rsa.message.length;
909 : 0 : desc[idx++].flags = flags | VRING_DESC_F_WRITE;
910 : : } else {
911 : 0 : VIRTIO_CRYPTO_TX_LOG_ERR("Invalid asym op");
912 : 0 : return -EINVAL;
913 : : }
914 : :
915 : : /* packed vring: last part, status returned */
916 : 0 : desc[idx].addr = op_data_req_phys_addr + req_data_len;
917 : 0 : desc[idx].len = sizeof(struct virtio_crypto_inhdr);
918 : 0 : desc[idx++].flags = txvq->vq_packed.cached_flags | VRING_DESC_F_WRITE;
919 : :
920 : : num_entry = idx;
921 : 0 : txvq->vq_avail_idx += num_entry;
922 [ # # ]: 0 : if (txvq->vq_avail_idx >= txvq->vq_nentries) {
923 : 0 : txvq->vq_avail_idx -= txvq->vq_nentries;
924 : 0 : txvq->vq_packed.cached_flags ^= VRING_PACKED_DESC_F_AVAIL_USED;
925 : : }
926 : :
927 : : /* save the infos to use when receiving packets */
928 : 0 : dxp->crypto_op = (void *)cop;
929 : 0 : dxp->ndescs = needed;
930 : :
931 : 0 : txvq->vq_desc_head_idx = (txvq->vq_desc_head_idx + idx) & (txvq->vq_nentries - 1);
932 [ # # ]: 0 : if (txvq->vq_desc_head_idx == VQ_RING_DESC_CHAIN_END)
933 : 0 : txvq->vq_desc_tail_idx = idx;
934 : 0 : txvq->vq_free_cnt = (uint16_t)(txvq->vq_free_cnt - needed);
935 : 0 : virtqueue_store_flags_packed(&start_dp[0],
936 : 0 : start_dp[0].flags | flags,
937 [ # # ]: 0 : txvq->hw->weak_barriers);
938 [ # # ]: 0 : virtio_wmb(txvq->hw->weak_barriers);
939 : : return 0;
940 : : }
941 : :
942 : : static inline int
943 : 0 : virtqueue_crypto_asym_enqueue_xmit(
944 : : struct virtqueue *txvq,
945 : : struct rte_crypto_op *cop)
946 : : {
947 [ # # ]: 0 : if (vtpci_with_packed_queue(txvq->hw))
948 : 0 : return virtqueue_crypto_asym_enqueue_xmit_packed(txvq, cop);
949 : : else
950 : 0 : return virtqueue_crypto_asym_enqueue_xmit_split(txvq, cop);
951 : : }
952 : :
953 : : static int
954 : 0 : virtio_crypto_vring_start(struct virtqueue *vq)
955 : : {
956 : 0 : struct virtio_crypto_hw *hw = vq->hw;
957 : 0 : uint8_t *ring_mem = vq->vq_ring_virt_mem;
958 : :
959 : 0 : PMD_INIT_FUNC_TRACE();
960 : :
961 [ # # ]: 0 : if (ring_mem == NULL) {
962 : 0 : VIRTIO_CRYPTO_INIT_LOG_ERR("virtqueue ring memory is NULL");
963 : 0 : return -EINVAL;
964 : : }
965 : :
966 : : /*
967 : : * Set guest physical address of the virtqueue
968 : : * in VIRTIO_PCI_QUEUE_PFN config register of device
969 : : * to share with the backend
970 : : */
971 [ # # ]: 0 : if (VTPCI_OPS(hw)->setup_queue(hw, vq) < 0) {
972 : 0 : VIRTIO_CRYPTO_INIT_LOG_ERR("setup_queue failed");
973 : 0 : return -EINVAL;
974 : : }
975 : :
976 : : return 0;
977 : : }
978 : :
979 : : void
980 : 0 : virtio_crypto_ctrlq_start(struct rte_cryptodev *dev)
981 : : {
982 : 0 : struct virtio_crypto_hw *hw = dev->data->dev_private;
983 : :
984 [ # # ]: 0 : if (hw->cvq) {
985 : : rte_spinlock_init(&hw->cvq->lock);
986 : 0 : virtio_crypto_vring_start(virtcrypto_cq_to_vq(hw->cvq));
987 [ # # ]: 0 : VIRTQUEUE_DUMP(virtcrypto_cq_to_vq(hw->cvq));
988 : : }
989 : 0 : }
990 : :
991 : : void
992 : 0 : virtio_crypto_dataq_start(struct rte_cryptodev *dev)
993 : : {
994 : : /*
995 : : * Start data vrings
996 : : * - Setup vring structure for data queues
997 : : */
998 : : uint16_t i;
999 : :
1000 : 0 : PMD_INIT_FUNC_TRACE();
1001 : :
1002 : : /* Start data vring. */
1003 [ # # ]: 0 : for (i = 0; i < dev->data->nb_queue_pairs; i++) {
1004 : 0 : virtio_crypto_vring_start(dev->data->queue_pairs[i]);
1005 [ # # ]: 0 : VIRTQUEUE_DUMP((struct virtqueue *)dev->data->queue_pairs[i]);
1006 : : }
1007 : 0 : }
1008 : :
1009 : : /* vring size of data queue is 1024 */
1010 : : #define VIRTIO_MBUF_BURST_SZ 1024
1011 : :
1012 : : uint16_t
1013 : 0 : virtio_crypto_pkt_rx_burst(void *tx_queue, struct rte_crypto_op **rx_pkts,
1014 : : uint16_t nb_pkts)
1015 : : {
1016 : : struct virtqueue *txvq = tx_queue;
1017 : : uint16_t nb_used, num, nb_rx;
1018 : :
1019 : : virtio_rmb(0);
1020 : :
1021 [ # # ]: 0 : num = (uint16_t)(likely(nb_pkts <= VIRTIO_MBUF_BURST_SZ)
1022 : : ? nb_pkts : VIRTIO_MBUF_BURST_SZ);
1023 [ # # ]: 0 : if (num == 0)
1024 : : return 0;
1025 : :
1026 [ # # ]: 0 : if (likely(vtpci_with_packed_queue(txvq->hw))) {
1027 : 0 : nb_rx = virtqueue_dequeue_burst_rx_packed(txvq, rx_pkts, num);
1028 : : } else {
1029 : 0 : nb_used = VIRTQUEUE_NUSED(txvq);
1030 [ # # ]: 0 : num = (uint16_t)(likely(num <= nb_used) ? num : nb_used);
1031 : 0 : nb_rx = virtqueue_dequeue_burst_rx(txvq, rx_pkts, num);
1032 : : }
1033 : :
1034 : 0 : VIRTIO_CRYPTO_RX_LOG_DBG("used:%d dequeue:%d", nb_rx, num);
1035 : :
1036 : 0 : return nb_rx;
1037 : : }
1038 : :
1039 : : uint16_t
1040 : 0 : virtio_crypto_pkt_tx_burst(void *tx_queue, struct rte_crypto_op **tx_pkts,
1041 : : uint16_t nb_pkts)
1042 : : {
1043 : : struct virtqueue *txvq;
1044 : : uint16_t nb_tx;
1045 : : int error;
1046 : :
1047 [ # # ]: 0 : if (unlikely(nb_pkts < 1))
1048 : : return nb_pkts;
1049 [ # # ]: 0 : if (unlikely(tx_queue == NULL)) {
1050 : 0 : VIRTIO_CRYPTO_TX_LOG_ERR("tx_queue is NULL");
1051 : 0 : return 0;
1052 : : }
1053 : : txvq = tx_queue;
1054 : :
1055 : 0 : VIRTIO_CRYPTO_TX_LOG_DBG("%d packets to xmit", nb_pkts);
1056 : :
1057 [ # # ]: 0 : for (nb_tx = 0; nb_tx < nb_pkts; nb_tx++) {
1058 [ # # ]: 0 : if (tx_pkts[nb_tx]->type == RTE_CRYPTO_OP_TYPE_SYMMETRIC) {
1059 : 0 : struct rte_mbuf *txm = tx_pkts[nb_tx]->sym->m_src;
1060 : : /* nb_segs is always 1 at virtio crypto situation */
1061 : 0 : int need = txm->nb_segs - txvq->vq_free_cnt;
1062 : :
1063 : : /*
1064 : : * Positive value indicates it hasn't enough space in vring
1065 : : * descriptors
1066 : : */
1067 [ # # ]: 0 : if (unlikely(need > 0)) {
1068 : : /*
1069 : : * try it again because the receive process may be
1070 : : * free some space
1071 : : */
1072 : : need = txm->nb_segs - txvq->vq_free_cnt;
1073 : : if (unlikely(need > 0)) {
1074 : 0 : VIRTIO_CRYPTO_TX_LOG_DBG("No free tx "
1075 : : "descriptors to transmit");
1076 : 0 : break;
1077 : : }
1078 : : }
1079 : :
1080 : : /* Enqueue Packet buffers */
1081 : 0 : error = virtqueue_crypto_sym_enqueue_xmit(txvq, tx_pkts[nb_tx]);
1082 [ # # ]: 0 : } else if (tx_pkts[nb_tx]->type == RTE_CRYPTO_OP_TYPE_ASYMMETRIC) {
1083 : : /* Enqueue Packet buffers */
1084 : 0 : error = virtqueue_crypto_asym_enqueue_xmit(txvq, tx_pkts[nb_tx]);
1085 : : } else {
1086 : 0 : VIRTIO_CRYPTO_TX_LOG_ERR("invalid crypto op type %u",
1087 : : tx_pkts[nb_tx]->type);
1088 : 0 : txvq->packets_sent_failed++;
1089 : 0 : continue;
1090 : : }
1091 : :
1092 [ # # ]: 0 : if (unlikely(error)) {
1093 [ # # ]: 0 : if (error == ENOSPC)
1094 : 0 : VIRTIO_CRYPTO_TX_LOG_ERR(
1095 : : "virtqueue_enqueue Free count = 0");
1096 [ # # ]: 0 : else if (error == EMSGSIZE)
1097 : 0 : VIRTIO_CRYPTO_TX_LOG_ERR(
1098 : : "virtqueue_enqueue Free count < 1");
1099 : : else
1100 : 0 : VIRTIO_CRYPTO_TX_LOG_ERR(
1101 : : "virtqueue_enqueue error: %d", error);
1102 : 0 : txvq->packets_sent_failed++;
1103 : 0 : break;
1104 : : }
1105 : :
1106 : 0 : txvq->packets_sent_total++;
1107 : : }
1108 : :
1109 [ # # ]: 0 : if (likely(nb_tx)) {
1110 [ # # ]: 0 : if (vtpci_with_packed_queue(txvq->hw)) {
1111 : : virtqueue_notify(txvq);
1112 : 0 : VIRTIO_CRYPTO_TX_LOG_DBG("Notified backend after xmit");
1113 : 0 : return nb_tx;
1114 : : }
1115 : :
1116 : : vq_update_avail_idx(txvq);
1117 : :
1118 [ # # ]: 0 : if (unlikely(virtqueue_kick_prepare(txvq))) {
1119 : : virtqueue_notify(txvq);
1120 : 0 : VIRTIO_CRYPTO_TX_LOG_DBG("Notified backend after xmit");
1121 : : }
1122 : : }
1123 : :
1124 : : return nb_tx;
1125 : : }
|