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