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 num_entry;
483 : : uint16_t needed = 1;
484 : : uint16_t head_idx;
485 : : struct vq_desc_extra *dxp;
486 : : struct vring_packed_desc *start_dp;
487 : : struct vring_packed_desc *desc;
488 : : uint64_t op_data_req_phys_addr;
489 : : uint16_t req_data_len = sizeof(struct virtio_crypto_op_data_req);
490 : : uint32_t iv_addr_offset =
491 : : offsetof(struct virtio_crypto_op_cookie, iv);
492 : : struct rte_crypto_sym_op *sym_op = cop->sym;
493 : 0 : struct virtio_crypto_session *session =
494 : 0 : CRYPTODEV_GET_SYM_SESS_PRIV(cop->sym->session);
495 : : struct virtio_crypto_op_data_req *op_data_req;
496 : : uint32_t hash_result_len = 0;
497 : : struct virtio_crypto_op_cookie *crypto_op_cookie;
498 : : struct virtio_crypto_alg_chain_session_para *para;
499 : : uint16_t flags = VRING_DESC_F_NEXT;
500 : :
501 [ # # ]: 0 : if (unlikely(sym_op->m_src->nb_segs != 1))
502 : : return -EMSGSIZE;
503 [ # # ]: 0 : if (unlikely(txvq->vq_free_cnt == 0))
504 : : return -ENOSPC;
505 : : if (unlikely(txvq->vq_free_cnt < needed))
506 : : return -EMSGSIZE;
507 : 0 : head_idx = txvq->vq_desc_head_idx;
508 [ # # ]: 0 : if (unlikely(head_idx >= txvq->vq_nentries))
509 : : return -EFAULT;
510 : : if (unlikely(session == NULL))
511 : : return -EFAULT;
512 : :
513 : 0 : dxp = &txvq->vq_descx[head_idx];
514 : :
515 [ # # # # ]: 0 : if (rte_mempool_get(txvq->mpool, &dxp->cookie)) {
516 : 0 : VIRTIO_CRYPTO_TX_LOG_ERR("can not get cookie");
517 : 0 : return -EFAULT;
518 : : }
519 : 0 : crypto_op_cookie = dxp->cookie;
520 : : op_data_req_phys_addr = rte_mempool_virt2iova(crypto_op_cookie);
521 : : op_data_req = (struct virtio_crypto_op_data_req *)crypto_op_cookie;
522 : :
523 [ # # ]: 0 : if (virtqueue_crypto_sym_pkt_header_arrange(cop, op_data_req, session))
524 : : return -EFAULT;
525 : :
526 : : /* status is initialized to VIRTIO_CRYPTO_ERR */
527 : : ((struct virtio_crypto_inhdr *)
528 : 0 : ((uint8_t *)op_data_req + req_data_len))->status =
529 : : VIRTIO_CRYPTO_ERR;
530 : :
531 : 0 : desc = &txvq->vq_packed.ring.desc[txvq->vq_desc_head_idx];
532 : : needed = 4;
533 : 0 : flags |= txvq->vq_packed.cached_flags;
534 : :
535 : : start_dp = desc;
536 : : idx = 0;
537 : :
538 : : /* packed vring: first part, virtio_crypto_op_data_req */
539 : 0 : desc[idx].addr = op_data_req_phys_addr;
540 : 0 : desc[idx].len = req_data_len;
541 : 0 : desc[idx++].flags = flags;
542 : :
543 : : /* packed vring: iv of cipher */
544 [ # # ]: 0 : if (session->iv.length) {
545 [ # # ]: 0 : if (cop->phys_addr)
546 : 0 : desc[idx].addr = cop->phys_addr + session->iv.offset;
547 : : else {
548 [ # # ]: 0 : if (session->iv.length > VIRTIO_CRYPTO_MAX_IV_SIZE)
549 : : return -ENOMEM;
550 : :
551 : 0 : rte_memcpy(crypto_op_cookie->iv,
552 [ # # ]: 0 : rte_crypto_op_ctod_offset(cop,
553 : : uint8_t *, session->iv.offset),
554 : : session->iv.length);
555 : 0 : desc[idx].addr = op_data_req_phys_addr + iv_addr_offset;
556 : : }
557 : :
558 : 0 : desc[idx].len = session->iv.length;
559 : 0 : desc[idx++].flags = flags;
560 : : }
561 : :
562 : : /* packed vring: additional auth data */
563 [ # # ]: 0 : if (session->aad.length) {
564 : 0 : desc[idx].addr = session->aad.phys_addr;
565 : 0 : desc[idx].len = session->aad.length;
566 : 0 : desc[idx++].flags = flags;
567 : : }
568 : :
569 : : /* packed vring: src data */
570 [ # # ]: 0 : desc[idx].addr = rte_pktmbuf_iova_offset(sym_op->m_src, 0);
571 : 0 : desc[idx].len = (sym_op->cipher.data.offset
572 : 0 : + sym_op->cipher.data.length);
573 : 0 : desc[idx++].flags = flags;
574 : :
575 : : /* packed vring: dst data */
576 [ # # ]: 0 : if (sym_op->m_dst) {
577 : 0 : desc[idx].addr = rte_pktmbuf_iova_offset(sym_op->m_dst, 0);
578 : 0 : desc[idx].len = (sym_op->cipher.data.offset
579 : : + sym_op->cipher.data.length);
580 : : } else {
581 : 0 : desc[idx].addr = rte_pktmbuf_iova_offset(sym_op->m_src, 0);
582 : 0 : desc[idx].len = (sym_op->cipher.data.offset
583 : : + sym_op->cipher.data.length);
584 : : }
585 : 0 : desc[idx++].flags = VRING_DESC_F_WRITE | VRING_DESC_F_NEXT;
586 : :
587 : : /* packed vring: digest result */
588 : : para = &(session->ctrl.hdr.u.sym_create_session.u.chain.para);
589 [ # # ]: 0 : if (para->hash_mode == VIRTIO_CRYPTO_SYM_HASH_MODE_PLAIN)
590 : 0 : hash_result_len = para->u.hash_param.hash_result_len;
591 [ # # ]: 0 : if (para->hash_mode == VIRTIO_CRYPTO_SYM_HASH_MODE_AUTH)
592 : 0 : hash_result_len = para->u.mac_param.hash_result_len;
593 [ # # ]: 0 : if (hash_result_len > 0) {
594 : 0 : desc[idx].addr = sym_op->auth.digest.phys_addr;
595 : 0 : desc[idx].len = hash_result_len;
596 : 0 : desc[idx++].flags = VRING_DESC_F_WRITE | VRING_DESC_F_NEXT;
597 : : }
598 : :
599 : : /* packed vring: last part, status returned */
600 : 0 : desc[idx].addr = op_data_req_phys_addr + req_data_len;
601 : 0 : desc[idx].len = sizeof(struct virtio_crypto_inhdr);
602 : 0 : desc[idx++].flags = txvq->vq_packed.cached_flags | VRING_DESC_F_WRITE;
603 : :
604 : : num_entry = idx;
605 : 0 : txvq->vq_avail_idx += num_entry;
606 [ # # ]: 0 : if (txvq->vq_avail_idx >= txvq->vq_nentries) {
607 : 0 : txvq->vq_avail_idx -= txvq->vq_nentries;
608 : 0 : txvq->vq_packed.cached_flags ^= VRING_PACKED_DESC_F_AVAIL_USED;
609 : : }
610 : :
611 : : /* save the infos to use when receiving packets */
612 : 0 : dxp->crypto_op = (void *)cop;
613 : 0 : dxp->ndescs = needed;
614 : :
615 : 0 : txvq->vq_desc_head_idx = (txvq->vq_desc_head_idx + idx) & (txvq->vq_nentries - 1);
616 [ # # ]: 0 : if (txvq->vq_desc_head_idx == VQ_RING_DESC_CHAIN_END)
617 : 0 : txvq->vq_desc_tail_idx = idx;
618 : 0 : txvq->vq_free_cnt = (uint16_t)(txvq->vq_free_cnt - needed);
619 : 0 : virtqueue_store_flags_packed(&start_dp[0],
620 : 0 : start_dp[0].flags | flags,
621 [ # # ]: 0 : txvq->hw->weak_barriers);
622 [ # # ]: 0 : virtio_wmb(txvq->hw->weak_barriers);
623 : :
624 : : return 0;
625 : : }
626 : :
627 : : static inline int
628 : 0 : virtqueue_crypto_sym_enqueue_xmit(
629 : : struct virtqueue *txvq,
630 : : struct rte_crypto_op *cop)
631 : : {
632 [ # # ]: 0 : if (vtpci_with_packed_queue(txvq->hw))
633 : 0 : return virtqueue_crypto_sym_enqueue_xmit_packed(txvq, cop);
634 : : else
635 : 0 : return virtqueue_crypto_sym_enqueue_xmit_split(txvq, cop);
636 : : }
637 : :
638 : : static inline int
639 : 0 : virtqueue_crypto_asym_pkt_header_arrange(
640 : : struct rte_crypto_op *cop,
641 : : struct virtio_crypto_op_data_req *data,
642 : : struct virtio_crypto_session *session)
643 : : {
644 : : struct virtio_crypto_op_ctrl_req *ctrl = &session->ctrl.hdr;
645 : : struct virtio_crypto_op_data_req *req_data = data;
646 : : struct rte_crypto_asym_op *asym_op = cop->asym;
647 : :
648 : 0 : req_data->header.session_id = session->session_id;
649 : :
650 [ # # ]: 0 : switch (ctrl->header.algo) {
651 : 0 : case VIRTIO_CRYPTO_AKCIPHER_RSA:
652 : 0 : req_data->header.algo = ctrl->header.algo;
653 [ # # ]: 0 : if (asym_op->rsa.op_type == RTE_CRYPTO_ASYM_OP_SIGN) {
654 : 0 : req_data->header.opcode = VIRTIO_CRYPTO_AKCIPHER_SIGN;
655 : : req_data->u.akcipher_req.para.src_data_len
656 : 0 : = asym_op->rsa.message.length;
657 : : req_data->u.akcipher_req.para.dst_data_len
658 : 0 : = asym_op->rsa.sign.length;
659 [ # # ]: 0 : } else if (asym_op->rsa.op_type == RTE_CRYPTO_ASYM_OP_VERIFY) {
660 : 0 : req_data->header.opcode = VIRTIO_CRYPTO_AKCIPHER_VERIFY;
661 : : req_data->u.akcipher_req.para.src_data_len
662 : 0 : = asym_op->rsa.sign.length;
663 : : req_data->u.akcipher_req.para.dst_data_len
664 : 0 : = asym_op->rsa.message.length;
665 [ # # ]: 0 : } else if (asym_op->rsa.op_type == RTE_CRYPTO_ASYM_OP_ENCRYPT) {
666 : 0 : req_data->header.opcode = VIRTIO_CRYPTO_AKCIPHER_ENCRYPT;
667 : : req_data->u.akcipher_req.para.src_data_len
668 : 0 : = asym_op->rsa.message.length;
669 : : req_data->u.akcipher_req.para.dst_data_len
670 : 0 : = asym_op->rsa.cipher.length;
671 [ # # ]: 0 : } else if (asym_op->rsa.op_type == RTE_CRYPTO_ASYM_OP_DECRYPT) {
672 : 0 : req_data->header.opcode = VIRTIO_CRYPTO_AKCIPHER_DECRYPT;
673 : : req_data->u.akcipher_req.para.src_data_len
674 : 0 : = asym_op->rsa.cipher.length;
675 : : req_data->u.akcipher_req.para.dst_data_len
676 : 0 : = asym_op->rsa.message.length;
677 : : } else {
678 : : return -EINVAL;
679 : : }
680 : :
681 : : break;
682 : 0 : default:
683 : 0 : req_data->header.algo = VIRTIO_CRYPTO_NO_AKCIPHER;
684 : : }
685 : :
686 : : return 0;
687 : : }
688 : :
689 : : static inline int
690 : 0 : virtqueue_crypto_asym_enqueue_xmit_split(
691 : : struct virtqueue *txvq,
692 : : struct rte_crypto_op *cop)
693 : : {
694 : : uint16_t req_data_len = sizeof(struct virtio_crypto_op_data_req);
695 : : uint32_t indirect_vring_addr_offset = req_data_len +
696 : : sizeof(struct virtio_crypto_inhdr);
697 : 0 : struct virtio_crypto_session *session =
698 : 0 : CRYPTODEV_GET_ASYM_SESS_PRIV(cop->asym->session);
699 : : struct virtio_crypto_op_cookie *crypto_op_cookie;
700 : : struct rte_crypto_asym_op *asym_op = cop->asym;
701 : : struct virtio_crypto_op_data_req *op_data_req;
702 : : uint64_t indirect_op_data_req_phys_addr;
703 : : struct vring_used_elem *uep;
704 : : struct vring_desc *start_dp;
705 : : struct vq_desc_extra *dxp;
706 : : struct vring_desc *desc;
707 : : uint16_t needed = 1;
708 : : uint16_t num_entry;
709 : : uint16_t head_idx;
710 : : uint16_t idx = 0;
711 : :
712 [ # # ]: 0 : if (unlikely(txvq->vq_free_cnt == 0))
713 : : return -ENOSPC;
714 : : if (unlikely(txvq->vq_free_cnt < needed))
715 : : return -EMSGSIZE;
716 : 0 : head_idx = txvq->vq_desc_head_idx;
717 [ # # ]: 0 : if (unlikely(head_idx >= txvq->vq_nentries))
718 : : return -EFAULT;
719 : :
720 : 0 : dxp = &txvq->vq_descx[head_idx];
721 : :
722 [ # # # # ]: 0 : if (rte_mempool_get(txvq->mpool, &dxp->cookie)) {
723 : 0 : VIRTIO_CRYPTO_TX_LOG_ERR("can not get cookie");
724 : 0 : return -EFAULT;
725 : : }
726 : 0 : crypto_op_cookie = dxp->cookie;
727 : : indirect_op_data_req_phys_addr =
728 : : rte_mempool_virt2iova(crypto_op_cookie);
729 : : op_data_req = (struct virtio_crypto_op_data_req *)crypto_op_cookie;
730 [ # # ]: 0 : if (virtqueue_crypto_asym_pkt_header_arrange(cop, op_data_req, session))
731 : : return -EFAULT;
732 : :
733 : : /* status is initialized to VIRTIO_CRYPTO_ERR */
734 : : ((struct virtio_crypto_inhdr *)
735 : 0 : ((uint8_t *)op_data_req + req_data_len))->status =
736 : : VIRTIO_CRYPTO_ERR;
737 : :
738 : : /* point to indirect vring entry */
739 : : desc = (struct vring_desc *)
740 : : ((uint8_t *)op_data_req + indirect_vring_addr_offset);
741 [ # # ]: 0 : for (idx = 0; idx < (NUM_ENTRY_VIRTIO_CRYPTO_OP - 1); idx++)
742 : 0 : desc[idx].next = idx + 1;
743 : 0 : desc[NUM_ENTRY_VIRTIO_CRYPTO_OP - 1].next = VQ_RING_DESC_CHAIN_END;
744 : :
745 : : idx = 0;
746 : :
747 : : /* indirect vring: first part, virtio_crypto_op_data_req */
748 : 0 : desc[idx].addr = indirect_op_data_req_phys_addr;
749 : 0 : desc[idx].len = req_data_len;
750 : 0 : desc[idx++].flags = VRING_DESC_F_NEXT;
751 : :
752 [ # # ]: 0 : if (asym_op->rsa.op_type == RTE_CRYPTO_ASYM_OP_SIGN) {
753 : : /* indirect vring: src data */
754 : 0 : desc[idx].addr = rte_mem_virt2iova(asym_op->rsa.message.data);
755 : 0 : desc[idx].len = asym_op->rsa.message.length;
756 : 0 : desc[idx++].flags = VRING_DESC_F_NEXT;
757 : :
758 : : /* indirect vring: dst data */
759 : 0 : desc[idx].addr = rte_mem_virt2iova(asym_op->rsa.sign.data);
760 : 0 : desc[idx].len = asym_op->rsa.sign.length;
761 : 0 : desc[idx++].flags = VRING_DESC_F_NEXT | VRING_DESC_F_WRITE;
762 [ # # ]: 0 : } else if (asym_op->rsa.op_type == RTE_CRYPTO_ASYM_OP_VERIFY) {
763 : : /* indirect vring: src data */
764 : 0 : desc[idx].addr = rte_mem_virt2iova(asym_op->rsa.sign.data);
765 : 0 : desc[idx].len = asym_op->rsa.sign.length;
766 : 0 : desc[idx++].flags = VRING_DESC_F_NEXT;
767 : :
768 : : /* indirect vring: dst data */
769 : 0 : desc[idx].addr = rte_mem_virt2iova(asym_op->rsa.message.data);
770 : 0 : desc[idx].len = asym_op->rsa.message.length;
771 : 0 : desc[idx++].flags = VRING_DESC_F_NEXT;
772 [ # # ]: 0 : } else if (asym_op->rsa.op_type == RTE_CRYPTO_ASYM_OP_ENCRYPT) {
773 : : /* indirect vring: src data */
774 : 0 : desc[idx].addr = rte_mem_virt2iova(asym_op->rsa.message.data);
775 : 0 : desc[idx].len = asym_op->rsa.message.length;
776 : 0 : desc[idx++].flags = VRING_DESC_F_NEXT;
777 : :
778 : : /* indirect vring: dst data */
779 : 0 : desc[idx].addr = rte_mem_virt2iova(asym_op->rsa.cipher.data);
780 : 0 : desc[idx].len = asym_op->rsa.cipher.length;
781 : 0 : desc[idx++].flags = VRING_DESC_F_NEXT | VRING_DESC_F_WRITE;
782 [ # # ]: 0 : } else if (asym_op->rsa.op_type == RTE_CRYPTO_ASYM_OP_DECRYPT) {
783 : : /* indirect vring: src data */
784 : 0 : desc[idx].addr = rte_mem_virt2iova(asym_op->rsa.cipher.data);
785 : 0 : desc[idx].len = asym_op->rsa.cipher.length;
786 : 0 : desc[idx++].flags = VRING_DESC_F_NEXT;
787 : :
788 : : /* indirect vring: dst data */
789 : 0 : desc[idx].addr = rte_mem_virt2iova(asym_op->rsa.message.data);
790 : 0 : desc[idx].len = asym_op->rsa.message.length;
791 : 0 : desc[idx++].flags = VRING_DESC_F_NEXT | VRING_DESC_F_WRITE;
792 : : } else {
793 : 0 : VIRTIO_CRYPTO_TX_LOG_ERR("Invalid asym op");
794 : 0 : return -EINVAL;
795 : : }
796 : :
797 : : /* indirect vring: last part, status returned */
798 : 0 : desc[idx].addr = indirect_op_data_req_phys_addr + req_data_len;
799 : 0 : desc[idx].len = sizeof(struct virtio_crypto_inhdr);
800 : 0 : desc[idx++].flags = VRING_DESC_F_WRITE;
801 : :
802 : : num_entry = idx;
803 : :
804 : : /* save the infos to use when receiving packets */
805 : 0 : dxp->crypto_op = (void *)cop;
806 : 0 : dxp->ndescs = needed;
807 : :
808 : : /* use a single buffer */
809 : 0 : start_dp = txvq->vq_split.ring.desc;
810 : 0 : start_dp[head_idx].addr = indirect_op_data_req_phys_addr +
811 : : indirect_vring_addr_offset;
812 : 0 : start_dp[head_idx].len = num_entry * sizeof(struct vring_desc);
813 : 0 : start_dp[head_idx].flags = VRING_DESC_F_INDIRECT;
814 : :
815 : 0 : idx = start_dp[head_idx].next;
816 : 0 : txvq->vq_desc_head_idx = idx;
817 [ # # ]: 0 : if (txvq->vq_desc_head_idx == VQ_RING_DESC_CHAIN_END)
818 : 0 : txvq->vq_desc_tail_idx = idx;
819 : 0 : txvq->vq_free_cnt = (uint16_t)(txvq->vq_free_cnt - needed);
820 : :
821 : 0 : uep = &txvq->vq_split.ring.used->ring[head_idx];
822 [ # # ]: 0 : uep->id = head_idx;
823 : : vq_update_avail_ring(txvq, head_idx);
824 : :
825 : 0 : return 0;
826 : : }
827 : :
828 : : static inline int
829 : 0 : virtqueue_crypto_asym_enqueue_xmit_packed(
830 : : struct virtqueue *txvq,
831 : : struct rte_crypto_op *cop)
832 : : {
833 : : uint16_t idx = 0;
834 : : uint16_t num_entry;
835 : : uint16_t needed = 1;
836 : : uint16_t head_idx;
837 : : struct vq_desc_extra *dxp;
838 : : struct vring_packed_desc *start_dp;
839 : : struct vring_packed_desc *desc;
840 : : uint64_t op_data_req_phys_addr;
841 : : uint16_t req_data_len = sizeof(struct virtio_crypto_op_data_req);
842 : : struct rte_crypto_asym_op *asym_op = cop->asym;
843 : 0 : struct virtio_crypto_session *session =
844 : 0 : CRYPTODEV_GET_ASYM_SESS_PRIV(cop->asym->session);
845 : : struct virtio_crypto_op_data_req *op_data_req;
846 : : struct virtio_crypto_op_cookie *crypto_op_cookie;
847 : : uint16_t flags = VRING_DESC_F_NEXT;
848 : :
849 [ # # ]: 0 : if (unlikely(txvq->vq_free_cnt == 0))
850 : : return -ENOSPC;
851 : : if (unlikely(txvq->vq_free_cnt < needed))
852 : : return -EMSGSIZE;
853 : 0 : head_idx = txvq->vq_desc_head_idx;
854 [ # # ]: 0 : if (unlikely(head_idx >= txvq->vq_nentries))
855 : : return -EFAULT;
856 : :
857 : 0 : dxp = &txvq->vq_descx[head_idx];
858 : :
859 [ # # # # ]: 0 : if (rte_mempool_get(txvq->mpool, &dxp->cookie)) {
860 : 0 : VIRTIO_CRYPTO_TX_LOG_ERR("can not get cookie");
861 : 0 : return -EFAULT;
862 : : }
863 : 0 : crypto_op_cookie = dxp->cookie;
864 : : op_data_req_phys_addr = rte_mempool_virt2iova(crypto_op_cookie);
865 : : op_data_req = (struct virtio_crypto_op_data_req *)crypto_op_cookie;
866 [ # # ]: 0 : if (virtqueue_crypto_asym_pkt_header_arrange(cop, op_data_req, session))
867 : : return -EFAULT;
868 : :
869 : : /* status is initialized to VIRTIO_CRYPTO_ERR */
870 : : ((struct virtio_crypto_inhdr *)
871 : 0 : ((uint8_t *)op_data_req + req_data_len))->status =
872 : : VIRTIO_CRYPTO_ERR;
873 : :
874 : 0 : desc = &txvq->vq_packed.ring.desc[txvq->vq_desc_head_idx];
875 : : needed = 4;
876 : 0 : flags |= txvq->vq_packed.cached_flags;
877 : :
878 : : start_dp = desc;
879 : : idx = 0;
880 : :
881 : : /* packed vring: first part, virtio_crypto_op_data_req */
882 : 0 : desc[idx].addr = op_data_req_phys_addr;
883 : 0 : desc[idx].len = sizeof(struct virtio_crypto_op_data_req);
884 : 0 : desc[idx++].flags = flags;
885 : :
886 [ # # ]: 0 : if (asym_op->rsa.op_type == RTE_CRYPTO_ASYM_OP_SIGN) {
887 : : /* packed vring: src data */
888 [ # # ]: 0 : if (asym_op->rsa.message.length > VIRTIO_CRYPTO_MAX_MSG_SIZE)
889 : : return -ENOMEM;
890 [ # # ]: 0 : memcpy(crypto_op_cookie->message, asym_op->rsa.message.data,
891 : : asym_op->rsa.message.length);
892 : 0 : desc[idx].addr = op_data_req_phys_addr +
893 : : offsetof(struct virtio_crypto_op_cookie, message);
894 : 0 : desc[idx].len = asym_op->rsa.message.length;
895 : 0 : desc[idx++].flags = flags;
896 : :
897 : : /* packed vring: dst data */
898 [ # # ]: 0 : if (asym_op->rsa.sign.length > VIRTIO_CRYPTO_MAX_SIGN_SIZE)
899 : : return -ENOMEM;
900 : 0 : desc[idx].addr = op_data_req_phys_addr +
901 : : offsetof(struct virtio_crypto_op_cookie, sign);
902 : 0 : desc[idx].len = asym_op->rsa.sign.length;
903 : 0 : desc[idx++].flags = flags | VRING_DESC_F_WRITE;
904 [ # # ]: 0 : } else if (asym_op->rsa.op_type == RTE_CRYPTO_ASYM_OP_VERIFY) {
905 : : /* packed vring: src data */
906 [ # # ]: 0 : if (asym_op->rsa.sign.length > VIRTIO_CRYPTO_MAX_SIGN_SIZE)
907 : : return -ENOMEM;
908 [ # # ]: 0 : memcpy(crypto_op_cookie->sign, asym_op->rsa.sign.data,
909 : : asym_op->rsa.sign.length);
910 : 0 : desc[idx].addr = op_data_req_phys_addr +
911 : : offsetof(struct virtio_crypto_op_cookie, sign);
912 : 0 : desc[idx].len = asym_op->rsa.sign.length;
913 : 0 : desc[idx++].flags = flags;
914 : :
915 : : /* packed vring: dst data */
916 [ # # ]: 0 : if (asym_op->rsa.message.length > VIRTIO_CRYPTO_MAX_MSG_SIZE)
917 : : return -ENOMEM;
918 : 0 : desc[idx].addr = op_data_req_phys_addr +
919 : : offsetof(struct virtio_crypto_op_cookie, message);
920 : 0 : desc[idx].len = asym_op->rsa.message.length;
921 : 0 : desc[idx++].flags = flags;
922 [ # # ]: 0 : } else if (asym_op->rsa.op_type == RTE_CRYPTO_ASYM_OP_ENCRYPT) {
923 : : /* packed vring: src data */
924 [ # # ]: 0 : if (asym_op->rsa.message.length > VIRTIO_CRYPTO_MAX_MSG_SIZE)
925 : : return -ENOMEM;
926 [ # # ]: 0 : memcpy(crypto_op_cookie->message, asym_op->rsa.message.data,
927 : : asym_op->rsa.message.length);
928 : 0 : desc[idx].addr = op_data_req_phys_addr +
929 : : offsetof(struct virtio_crypto_op_cookie, message);
930 : 0 : desc[idx].len = asym_op->rsa.message.length;
931 : 0 : desc[idx++].flags = flags;
932 : :
933 : : /* packed vring: dst data */
934 [ # # ]: 0 : if (asym_op->rsa.cipher.length > VIRTIO_CRYPTO_MAX_CIPHER_SIZE)
935 : : return -ENOMEM;
936 : 0 : desc[idx].addr = op_data_req_phys_addr +
937 : : offsetof(struct virtio_crypto_op_cookie, cipher);
938 : 0 : desc[idx].len = asym_op->rsa.cipher.length;
939 : 0 : desc[idx++].flags = flags | VRING_DESC_F_WRITE;
940 [ # # ]: 0 : } else if (asym_op->rsa.op_type == RTE_CRYPTO_ASYM_OP_DECRYPT) {
941 : : /* packed vring: src data */
942 [ # # ]: 0 : if (asym_op->rsa.cipher.length > VIRTIO_CRYPTO_MAX_CIPHER_SIZE)
943 : : return -ENOMEM;
944 [ # # ]: 0 : memcpy(crypto_op_cookie->cipher, asym_op->rsa.cipher.data,
945 : : asym_op->rsa.cipher.length);
946 : 0 : desc[idx].addr = op_data_req_phys_addr +
947 : : offsetof(struct virtio_crypto_op_cookie, cipher);
948 : 0 : desc[idx].len = asym_op->rsa.cipher.length;
949 : 0 : desc[idx++].flags = flags;
950 : :
951 : : /* packed vring: dst data */
952 [ # # ]: 0 : if (asym_op->rsa.message.length > VIRTIO_CRYPTO_MAX_MSG_SIZE)
953 : : return -ENOMEM;
954 : 0 : desc[idx].addr = op_data_req_phys_addr +
955 : : offsetof(struct virtio_crypto_op_cookie, message);
956 : 0 : desc[idx].len = asym_op->rsa.message.length;
957 : 0 : desc[idx++].flags = flags | VRING_DESC_F_WRITE;
958 : : } else {
959 : 0 : VIRTIO_CRYPTO_TX_LOG_ERR("Invalid asym op");
960 : 0 : return -EINVAL;
961 : : }
962 : :
963 : : /* packed vring: last part, status returned */
964 : 0 : desc[idx].addr = op_data_req_phys_addr + req_data_len;
965 : 0 : desc[idx].len = sizeof(struct virtio_crypto_inhdr);
966 : 0 : desc[idx++].flags = txvq->vq_packed.cached_flags | VRING_DESC_F_WRITE;
967 : :
968 : : num_entry = idx;
969 : 0 : txvq->vq_avail_idx += num_entry;
970 [ # # ]: 0 : if (txvq->vq_avail_idx >= txvq->vq_nentries) {
971 : 0 : txvq->vq_avail_idx -= txvq->vq_nentries;
972 : 0 : txvq->vq_packed.cached_flags ^= VRING_PACKED_DESC_F_AVAIL_USED;
973 : : }
974 : :
975 : : /* save the infos to use when receiving packets */
976 : 0 : dxp->crypto_op = (void *)cop;
977 : 0 : dxp->ndescs = needed;
978 : :
979 : 0 : txvq->vq_desc_head_idx = (txvq->vq_desc_head_idx + idx) & (txvq->vq_nentries - 1);
980 [ # # ]: 0 : if (txvq->vq_desc_head_idx == VQ_RING_DESC_CHAIN_END)
981 : 0 : txvq->vq_desc_tail_idx = idx;
982 : 0 : txvq->vq_free_cnt = (uint16_t)(txvq->vq_free_cnt - needed);
983 : 0 : virtqueue_store_flags_packed(&start_dp[0],
984 : 0 : start_dp[0].flags | flags,
985 [ # # ]: 0 : txvq->hw->weak_barriers);
986 [ # # ]: 0 : virtio_wmb(txvq->hw->weak_barriers);
987 : : return 0;
988 : : }
989 : :
990 : : static inline int
991 : 0 : virtqueue_crypto_asym_enqueue_xmit(
992 : : struct virtqueue *txvq,
993 : : struct rte_crypto_op *cop)
994 : : {
995 [ # # ]: 0 : if (vtpci_with_packed_queue(txvq->hw))
996 : 0 : return virtqueue_crypto_asym_enqueue_xmit_packed(txvq, cop);
997 : : else
998 : 0 : return virtqueue_crypto_asym_enqueue_xmit_split(txvq, cop);
999 : : }
1000 : :
1001 : : static int
1002 : 0 : virtio_crypto_vring_start(struct virtqueue *vq)
1003 : : {
1004 : 0 : struct virtio_crypto_hw *hw = vq->hw;
1005 : 0 : uint8_t *ring_mem = vq->vq_ring_virt_mem;
1006 : :
1007 : 0 : PMD_INIT_FUNC_TRACE();
1008 : :
1009 [ # # ]: 0 : if (ring_mem == NULL) {
1010 : 0 : VIRTIO_CRYPTO_INIT_LOG_ERR("virtqueue ring memory is NULL");
1011 : 0 : return -EINVAL;
1012 : : }
1013 : :
1014 : : /*
1015 : : * Set guest physical address of the virtqueue
1016 : : * in VIRTIO_PCI_QUEUE_PFN config register of device
1017 : : * to share with the backend
1018 : : */
1019 [ # # ]: 0 : if (VTPCI_OPS(hw)->setup_queue(hw, vq) < 0) {
1020 : 0 : VIRTIO_CRYPTO_INIT_LOG_ERR("setup_queue failed");
1021 : 0 : return -EINVAL;
1022 : : }
1023 : :
1024 : : return 0;
1025 : : }
1026 : :
1027 : : void
1028 : 0 : virtio_crypto_ctrlq_start(struct rte_cryptodev *dev)
1029 : : {
1030 : 0 : struct virtio_crypto_hw *hw = dev->data->dev_private;
1031 : :
1032 [ # # ]: 0 : if (hw->cvq) {
1033 : : rte_spinlock_init(&hw->cvq->lock);
1034 : 0 : virtio_crypto_vring_start(virtcrypto_cq_to_vq(hw->cvq));
1035 [ # # ]: 0 : VIRTQUEUE_DUMP(virtcrypto_cq_to_vq(hw->cvq));
1036 : : }
1037 : 0 : }
1038 : :
1039 : : void
1040 : 0 : virtio_crypto_dataq_start(struct rte_cryptodev *dev)
1041 : : {
1042 : : /*
1043 : : * Start data vrings
1044 : : * - Setup vring structure for data queues
1045 : : */
1046 : : uint16_t i;
1047 : :
1048 : 0 : PMD_INIT_FUNC_TRACE();
1049 : :
1050 : : /* Start data vring. */
1051 [ # # ]: 0 : for (i = 0; i < dev->data->nb_queue_pairs; i++) {
1052 : 0 : virtio_crypto_vring_start(dev->data->queue_pairs[i]);
1053 [ # # ]: 0 : VIRTQUEUE_DUMP((struct virtqueue *)dev->data->queue_pairs[i]);
1054 : : }
1055 : 0 : }
1056 : :
1057 : : /* vring size of data queue is 1024 */
1058 : : #define VIRTIO_MBUF_BURST_SZ 1024
1059 : :
1060 : : uint16_t
1061 : 0 : virtio_crypto_pkt_rx_burst(void *tx_queue, struct rte_crypto_op **rx_pkts,
1062 : : uint16_t nb_pkts)
1063 : : {
1064 : : struct virtqueue *txvq = tx_queue;
1065 : : uint16_t nb_used, num, nb_rx;
1066 : :
1067 : : virtio_rmb(0);
1068 : :
1069 [ # # ]: 0 : num = (uint16_t)(likely(nb_pkts <= VIRTIO_MBUF_BURST_SZ)
1070 : : ? nb_pkts : VIRTIO_MBUF_BURST_SZ);
1071 [ # # ]: 0 : if (num == 0)
1072 : : return 0;
1073 : :
1074 [ # # ]: 0 : if (likely(vtpci_with_packed_queue(txvq->hw))) {
1075 : 0 : nb_rx = virtqueue_dequeue_burst_rx_packed(txvq, rx_pkts, num);
1076 : : } else {
1077 : 0 : nb_used = VIRTQUEUE_NUSED(txvq);
1078 [ # # ]: 0 : num = (uint16_t)(likely(num <= nb_used) ? num : nb_used);
1079 : 0 : nb_rx = virtqueue_dequeue_burst_rx(txvq, rx_pkts, num);
1080 : : }
1081 : :
1082 : 0 : VIRTIO_CRYPTO_RX_LOG_DBG("used:%d dequeue:%d", nb_rx, num);
1083 : :
1084 : 0 : return nb_rx;
1085 : : }
1086 : :
1087 : : uint16_t
1088 : 0 : virtio_crypto_pkt_tx_burst(void *tx_queue, struct rte_crypto_op **tx_pkts,
1089 : : uint16_t nb_pkts)
1090 : : {
1091 : : struct virtqueue *txvq;
1092 : : uint16_t nb_tx;
1093 : : int error;
1094 : :
1095 [ # # ]: 0 : if (unlikely(nb_pkts < 1))
1096 : : return nb_pkts;
1097 [ # # ]: 0 : if (unlikely(tx_queue == NULL)) {
1098 : 0 : VIRTIO_CRYPTO_TX_LOG_ERR("tx_queue is NULL");
1099 : 0 : return 0;
1100 : : }
1101 : : txvq = tx_queue;
1102 : :
1103 : 0 : VIRTIO_CRYPTO_TX_LOG_DBG("%d packets to xmit", nb_pkts);
1104 : :
1105 [ # # ]: 0 : for (nb_tx = 0; nb_tx < nb_pkts; nb_tx++) {
1106 [ # # ]: 0 : if (tx_pkts[nb_tx]->type == RTE_CRYPTO_OP_TYPE_SYMMETRIC) {
1107 : 0 : struct rte_mbuf *txm = tx_pkts[nb_tx]->sym->m_src;
1108 : : /* nb_segs is always 1 at virtio crypto situation */
1109 : 0 : int need = txm->nb_segs - txvq->vq_free_cnt;
1110 : :
1111 : : /*
1112 : : * Positive value indicates it hasn't enough space in vring
1113 : : * descriptors
1114 : : */
1115 [ # # ]: 0 : if (unlikely(need > 0)) {
1116 : : /*
1117 : : * try it again because the receive process may be
1118 : : * free some space
1119 : : */
1120 : : need = txm->nb_segs - txvq->vq_free_cnt;
1121 : : if (unlikely(need > 0)) {
1122 : 0 : VIRTIO_CRYPTO_TX_LOG_DBG("No free tx "
1123 : : "descriptors to transmit");
1124 : 0 : break;
1125 : : }
1126 : : }
1127 : :
1128 : : /* Enqueue Packet buffers */
1129 : 0 : error = virtqueue_crypto_sym_enqueue_xmit(txvq, tx_pkts[nb_tx]);
1130 [ # # ]: 0 : } else if (tx_pkts[nb_tx]->type == RTE_CRYPTO_OP_TYPE_ASYMMETRIC) {
1131 : : /* Enqueue Packet buffers */
1132 : 0 : error = virtqueue_crypto_asym_enqueue_xmit(txvq, tx_pkts[nb_tx]);
1133 : : } else {
1134 : 0 : VIRTIO_CRYPTO_TX_LOG_ERR("invalid crypto op type %u",
1135 : : tx_pkts[nb_tx]->type);
1136 : 0 : txvq->packets_sent_failed++;
1137 : 0 : continue;
1138 : : }
1139 : :
1140 [ # # ]: 0 : if (unlikely(error)) {
1141 [ # # ]: 0 : if (error == ENOSPC)
1142 : 0 : VIRTIO_CRYPTO_TX_LOG_ERR(
1143 : : "virtqueue_enqueue Free count = 0");
1144 [ # # ]: 0 : else if (error == EMSGSIZE)
1145 : 0 : VIRTIO_CRYPTO_TX_LOG_ERR(
1146 : : "virtqueue_enqueue Free count < 1");
1147 : : else
1148 : 0 : VIRTIO_CRYPTO_TX_LOG_ERR(
1149 : : "virtqueue_enqueue error: %d", error);
1150 : 0 : txvq->packets_sent_failed++;
1151 : 0 : break;
1152 : : }
1153 : :
1154 : 0 : txvq->packets_sent_total++;
1155 : : }
1156 : :
1157 [ # # ]: 0 : if (likely(nb_tx)) {
1158 [ # # ]: 0 : if (vtpci_with_packed_queue(txvq->hw)) {
1159 : : virtqueue_notify(txvq);
1160 : 0 : VIRTIO_CRYPTO_TX_LOG_DBG("Notified backend after xmit");
1161 : 0 : return nb_tx;
1162 : : }
1163 : :
1164 : : vq_update_avail_idx(txvq);
1165 : :
1166 [ # # ]: 0 : if (unlikely(virtqueue_kick_prepare(txvq))) {
1167 : : virtqueue_notify(txvq);
1168 : 0 : VIRTIO_CRYPTO_TX_LOG_DBG("Notified backend after xmit");
1169 : : }
1170 : : }
1171 : :
1172 : : return nb_tx;
1173 : : }
|