1 /* SPDX-License-Identifier: BSD-3-Clause
2 * Copyright(C) 2019 Marvell International Ltd.
5 #include <rte_crypto.h>
6 #include <rte_cryptodev.h>
7 #include <rte_cycles.h>
10 #include "nitrox_sym_reqmgr.h"
11 #include "nitrox_logs.h"
13 #define MAX_SGBUF_CNT 16
14 #define MAX_SGCOMP_CNT 5
16 #define MIN_UDD_LEN 16
17 /* PKT_IN_HDR + SLC_STORE_INFO */
19 /* Base destination port for the solicited requests */
20 #define SOLICIT_BASE_DPORT 256
21 #define PENDING_SIG 0xFFFFFFFFFFFFFFFFUL
34 #if RTE_BYTE_ORDER == RTE_BIG_ENDIAN
35 uint64_t raz_48_63 : 16;
40 uint64_t raz_30_31 : 2;
42 uint64_t raz_16_23 : 8;
46 uint64_t raz_16_23 : 8;
48 uint64_t raz_30_31 : 2;
53 uint64_t raz_48_63 : 16;
61 #if RTE_BYTE_ORDER == RTE_BIG_ENDIAN
68 uint64_t destport : 9;
70 uint64_t raz_19_23 : 5;
80 uint64_t raz_19_23 : 5;
82 uint64_t destport : 9;
94 union slc_store_info {
97 #if RTE_BYTE_ORDER == RTE_BIG_ENDIAN
98 uint64_t raz_39_63 : 25;
100 uint64_t raz_0_31 : 32;
102 uint64_t raz_0_31 : 32;
104 uint64_t raz_39_63 : 25;
110 struct nps_pkt_instr {
112 union pkt_instr_hdr ih;
114 union slc_store_info slc;
123 struct nitrox_sglist {
131 struct nitrox_sgcomp {
136 struct nitrox_sgtable {
137 uint8_t map_bufs_cnt;
139 uint16_t total_bytes;
141 struct nitrox_sglist sglist[MAX_SGBUF_CNT];
142 struct nitrox_sgcomp sgcomp[MAX_SGCOMP_CNT];
151 struct nitrox_softreq {
152 struct nitrox_crypto_ctx *ctx;
153 struct rte_crypto_op *op;
155 struct nps_pkt_instr instr;
156 struct resp_hdr resp;
157 struct nitrox_sgtable in;
158 struct nitrox_sgtable out;
167 softreq_init(struct nitrox_softreq *sr, rte_iova_t iova)
169 memset(sr, 0, sizeof(*sr));
174 * 64-Byte Instruction Format
176 * ----------------------
178 * ----------------------
179 * | PKT_IN_INSTR_HDR | 8 bytes
180 * ----------------------
181 * | PKT_IN_HDR | 16 bytes
182 * ----------------------
183 * | SLC_INFO | 16 bytes
184 * ----------------------
185 * | Front data | 16 bytes
186 * ----------------------
189 create_se_instr(struct nitrox_softreq *sr, uint8_t qno)
191 struct nitrox_crypto_ctx *ctx = sr->ctx;
192 rte_iova_t ctx_handle;
194 /* fill the packet instruction */
196 sr->instr.dptr0 = rte_cpu_to_be_64(sr->dptr);
199 sr->instr.ih.value = 0;
200 sr->instr.ih.s.g = 1;
201 sr->instr.ih.s.gsz = sr->in.map_bufs_cnt;
202 sr->instr.ih.s.ssz = sr->out.map_bufs_cnt;
203 sr->instr.ih.s.fsz = FDATA_SIZE + sizeof(struct gphdr);
204 sr->instr.ih.s.tlen = sr->instr.ih.s.fsz + sr->in.total_bytes;
205 sr->instr.ih.value = rte_cpu_to_be_64(sr->instr.ih.value);
208 sr->instr.irh.value[0] = 0;
209 sr->instr.irh.s.uddl = MIN_UDD_LEN;
210 /* context length in 64-bit words */
211 sr->instr.irh.s.ctxl = RTE_ALIGN_MUL_CEIL(sizeof(ctx->fctx), 8) / 8;
212 /* offset from solicit base port 256 */
213 sr->instr.irh.s.destport = SOLICIT_BASE_DPORT + qno;
214 /* Invalid context cache */
215 sr->instr.irh.s.ctxc = 0x3;
216 sr->instr.irh.s.arg = ctx->req_op;
217 sr->instr.irh.s.opcode = ctx->opcode;
218 sr->instr.irh.value[0] = rte_cpu_to_be_64(sr->instr.irh.value[0]);
221 ctx_handle = ctx->iova + offsetof(struct nitrox_crypto_ctx, fctx);
222 sr->instr.irh.s.ctxp = rte_cpu_to_be_64(ctx_handle);
225 sr->instr.slc.value[0] = 0;
226 sr->instr.slc.s.ssz = sr->out.map_bufs_cnt;
227 sr->instr.slc.value[0] = rte_cpu_to_be_64(sr->instr.slc.value[0]);
230 sr->instr.slc.s.rptr = rte_cpu_to_be_64(sr->rptr);
232 * No conversion for front data,
233 * It goes into payload
234 * put GP Header in front data
236 memcpy(&sr->instr.fdata[0], &sr->gph, sizeof(sr->instr.fdata[0]));
237 sr->instr.fdata[1] = 0;
241 softreq_copy_iv(struct nitrox_softreq *sr, uint8_t salt_size)
243 uint16_t offset = sr->ctx->iv.offset + salt_size;
245 sr->iv.virt = rte_crypto_op_ctod_offset(sr->op, uint8_t *, offset);
246 sr->iv.iova = rte_crypto_op_ctophys_offset(sr->op, offset);
247 sr->iv.len = sr->ctx->iv.length - salt_size;
251 extract_cipher_auth_digest(struct nitrox_softreq *sr,
252 struct nitrox_sglist *digest)
254 struct rte_crypto_op *op = sr->op;
255 struct rte_mbuf *mdst = op->sym->m_dst ? op->sym->m_dst :
258 if (sr->ctx->req_op == NITROX_OP_DECRYPT &&
259 unlikely(!op->sym->auth.digest.data))
262 digest->len = sr->ctx->digest_length;
263 if (op->sym->auth.digest.data) {
264 digest->iova = op->sym->auth.digest.phys_addr;
265 digest->virt = op->sym->auth.digest.data;
269 if (unlikely(rte_pktmbuf_data_len(mdst) < op->sym->auth.data.offset +
270 op->sym->auth.data.length + digest->len))
273 digest->iova = rte_pktmbuf_iova_offset(mdst,
274 op->sym->auth.data.offset +
275 op->sym->auth.data.length);
276 digest->virt = rte_pktmbuf_mtod_offset(mdst, uint8_t *,
277 op->sym->auth.data.offset +
278 op->sym->auth.data.length);
283 fill_sglist(struct nitrox_sgtable *sgtbl, uint16_t len, rte_iova_t iova,
286 struct nitrox_sglist *sglist = sgtbl->sglist;
287 uint8_t cnt = sgtbl->map_bufs_cnt;
292 sglist[cnt].len = len;
293 sglist[cnt].iova = iova;
294 sglist[cnt].virt = virt;
295 sgtbl->total_bytes += len;
297 sgtbl->map_bufs_cnt = cnt;
301 create_sglist_from_mbuf(struct nitrox_sgtable *sgtbl, struct rte_mbuf *mbuf,
302 uint32_t off, int datalen)
304 struct nitrox_sglist *sglist = sgtbl->sglist;
305 uint8_t cnt = sgtbl->map_bufs_cnt;
309 if (unlikely(datalen <= 0))
312 for (m = mbuf; m && off > rte_pktmbuf_data_len(m); m = m->next)
313 off -= rte_pktmbuf_data_len(m);
318 mlen = rte_pktmbuf_data_len(m) - off;
321 sglist[cnt].len = mlen;
322 sglist[cnt].iova = rte_pktmbuf_iova_offset(m, off);
323 sglist[cnt].virt = rte_pktmbuf_mtod_offset(m, uint8_t *, off);
324 sgtbl->total_bytes += mlen;
327 for (m = m->next; m && datalen; m = m->next) {
328 mlen = rte_pktmbuf_data_len(m) < datalen ?
329 rte_pktmbuf_data_len(m) : datalen;
330 sglist[cnt].len = mlen;
331 sglist[cnt].iova = rte_pktmbuf_iova(m);
332 sglist[cnt].virt = rte_pktmbuf_mtod(m, uint8_t *);
333 sgtbl->total_bytes += mlen;
338 RTE_VERIFY(cnt <= MAX_SGBUF_CNT);
339 sgtbl->map_bufs_cnt = cnt;
344 create_cipher_auth_sglist(struct nitrox_softreq *sr,
345 struct nitrox_sgtable *sgtbl, struct rte_mbuf *mbuf)
347 struct rte_crypto_op *op = sr->op;
351 fill_sglist(sgtbl, sr->iv.len, sr->iv.iova, sr->iv.virt);
352 auth_only_len = op->sym->auth.data.length - op->sym->cipher.data.length;
353 if (unlikely(auth_only_len < 0))
357 op->sym->cipher.data.offset + op->sym->cipher.data.length !=
358 op->sym->auth.data.offset + op->sym->auth.data.length)) {
359 NITROX_LOG(ERR, "Auth only data after cipher data not supported\n");
363 err = create_sglist_from_mbuf(sgtbl, mbuf, op->sym->auth.data.offset,
368 err = create_sglist_from_mbuf(sgtbl, mbuf, op->sym->cipher.data.offset,
369 op->sym->cipher.data.length);
377 create_combined_sglist(struct nitrox_softreq *sr, struct nitrox_sgtable *sgtbl,
378 struct rte_mbuf *mbuf)
380 struct rte_crypto_op *op = sr->op;
382 fill_sglist(sgtbl, sr->iv.len, sr->iv.iova, sr->iv.virt);
383 fill_sglist(sgtbl, sr->ctx->aad_length, op->sym->aead.aad.phys_addr,
384 op->sym->aead.aad.data);
385 return create_sglist_from_mbuf(sgtbl, mbuf, op->sym->cipher.data.offset,
386 op->sym->cipher.data.length);
390 create_aead_sglist(struct nitrox_softreq *sr, struct nitrox_sgtable *sgtbl,
391 struct rte_mbuf *mbuf)
395 switch (sr->ctx->nitrox_chain) {
396 case NITROX_CHAIN_CIPHER_AUTH:
397 case NITROX_CHAIN_AUTH_CIPHER:
398 err = create_cipher_auth_sglist(sr, sgtbl, mbuf);
400 case NITROX_CHAIN_COMBINED:
401 err = create_combined_sglist(sr, sgtbl, mbuf);
412 create_sgcomp(struct nitrox_sgtable *sgtbl)
415 struct nitrox_sgcomp *sgcomp = sgtbl->sgcomp;
416 struct nitrox_sglist *sglist = sgtbl->sglist;
418 nr_sgcomp = RTE_ALIGN_MUL_CEIL(sgtbl->map_bufs_cnt, 4) / 4;
419 sgtbl->nr_sgcomp = nr_sgcomp;
420 for (i = 0; i < nr_sgcomp; i++, sgcomp++) {
421 for (j = 0; j < 4; j++, sglist++) {
422 sgcomp->len[j] = rte_cpu_to_be_16(sglist->len);
423 sgcomp->iova[j] = rte_cpu_to_be_64(sglist->iova);
429 create_aead_inbuf(struct nitrox_softreq *sr, struct nitrox_sglist *digest)
432 struct nitrox_crypto_ctx *ctx = sr->ctx;
434 err = create_aead_sglist(sr, &sr->in, sr->op->sym->m_src);
438 if (ctx->req_op == NITROX_OP_DECRYPT)
439 fill_sglist(&sr->in, digest->len, digest->iova, digest->virt);
441 create_sgcomp(&sr->in);
442 sr->dptr = sr->iova + offsetof(struct nitrox_softreq, in.sgcomp);
447 create_aead_oop_outbuf(struct nitrox_softreq *sr, struct nitrox_sglist *digest)
450 struct nitrox_crypto_ctx *ctx = sr->ctx;
452 err = create_aead_sglist(sr, &sr->out, sr->op->sym->m_dst);
456 if (ctx->req_op == NITROX_OP_ENCRYPT)
457 fill_sglist(&sr->out, digest->len, digest->iova, digest->virt);
463 create_aead_inplace_outbuf(struct nitrox_softreq *sr,
464 struct nitrox_sglist *digest)
467 struct nitrox_crypto_ctx *ctx = sr->ctx;
469 cnt = sr->out.map_bufs_cnt;
470 for (i = 0; i < sr->in.map_bufs_cnt; i++, cnt++) {
471 sr->out.sglist[cnt].len = sr->in.sglist[i].len;
472 sr->out.sglist[cnt].iova = sr->in.sglist[i].iova;
473 sr->out.sglist[cnt].virt = sr->in.sglist[i].virt;
476 sr->out.map_bufs_cnt = cnt;
477 if (ctx->req_op == NITROX_OP_ENCRYPT) {
478 fill_sglist(&sr->out, digest->len, digest->iova,
480 } else if (ctx->req_op == NITROX_OP_DECRYPT) {
481 sr->out.map_bufs_cnt--;
486 create_aead_outbuf(struct nitrox_softreq *sr, struct nitrox_sglist *digest)
488 struct rte_crypto_op *op = sr->op;
491 sr->resp.orh = PENDING_SIG;
492 sr->out.sglist[cnt].len = sizeof(sr->resp.orh);
493 sr->out.sglist[cnt].iova = sr->iova + offsetof(struct nitrox_softreq,
495 sr->out.sglist[cnt].virt = &sr->resp.orh;
497 sr->out.map_bufs_cnt = cnt;
498 if (op->sym->m_dst) {
501 err = create_aead_oop_outbuf(sr, digest);
505 create_aead_inplace_outbuf(sr, digest);
508 cnt = sr->out.map_bufs_cnt;
509 sr->resp.completion = PENDING_SIG;
510 sr->out.sglist[cnt].len = sizeof(sr->resp.completion);
511 sr->out.sglist[cnt].iova = sr->iova + offsetof(struct nitrox_softreq,
513 sr->out.sglist[cnt].virt = &sr->resp.completion;
515 RTE_VERIFY(cnt <= MAX_SGBUF_CNT);
516 sr->out.map_bufs_cnt = cnt;
518 create_sgcomp(&sr->out);
519 sr->rptr = sr->iova + offsetof(struct nitrox_softreq, out.sgcomp);
524 create_aead_gph(uint32_t cryptlen, uint16_t ivlen, uint32_t authlen,
530 #if RTE_BYTE_ORDER == RTE_BIG_ENDIAN
531 uint16_t iv_offset : 8;
532 uint16_t auth_offset : 8;
534 uint16_t auth_offset : 8;
535 uint16_t iv_offset : 8;
541 gph->param0 = rte_cpu_to_be_16(cryptlen);
542 gph->param1 = rte_cpu_to_be_16(authlen);
544 auth_only_len = authlen - cryptlen;
545 gph->param2 = rte_cpu_to_be_16(ivlen + auth_only_len);
547 param3.iv_offset = 0;
548 param3.auth_offset = ivlen;
549 gph->param3 = rte_cpu_to_be_16(param3.value);
553 process_cipher_auth_data(struct nitrox_softreq *sr)
555 struct rte_crypto_op *op = sr->op;
557 struct nitrox_sglist digest;
559 softreq_copy_iv(sr, 0);
560 err = extract_cipher_auth_digest(sr, &digest);
564 err = create_aead_inbuf(sr, &digest);
568 err = create_aead_outbuf(sr, &digest);
572 create_aead_gph(op->sym->cipher.data.length, sr->iv.len,
573 op->sym->auth.data.length, &sr->gph);
578 softreq_copy_salt(struct nitrox_softreq *sr)
580 struct nitrox_crypto_ctx *ctx = sr->ctx;
583 if (unlikely(ctx->iv.length < AES_GCM_SALT_SIZE)) {
584 NITROX_LOG(ERR, "Invalid IV length %d\n", ctx->iv.length);
588 addr = rte_crypto_op_ctod_offset(sr->op, uint8_t *, ctx->iv.offset);
589 if (!memcmp(ctx->salt, addr, AES_GCM_SALT_SIZE))
592 memcpy(ctx->salt, addr, AES_GCM_SALT_SIZE);
593 memcpy(ctx->fctx.crypto.iv, addr, AES_GCM_SALT_SIZE);
598 extract_combined_digest(struct nitrox_softreq *sr, struct nitrox_sglist *digest)
600 struct rte_crypto_op *op = sr->op;
601 struct rte_mbuf *mdst = op->sym->m_dst ? op->sym->m_dst :
604 digest->len = sr->ctx->digest_length;
605 if (op->sym->aead.digest.data) {
606 digest->iova = op->sym->aead.digest.phys_addr;
607 digest->virt = op->sym->aead.digest.data;
612 if (unlikely(rte_pktmbuf_data_len(mdst) < op->sym->aead.data.offset +
613 op->sym->aead.data.length + digest->len))
616 digest->iova = rte_pktmbuf_iova_offset(mdst,
617 op->sym->aead.data.offset +
618 op->sym->aead.data.length);
619 digest->virt = rte_pktmbuf_mtod_offset(mdst, uint8_t *,
620 op->sym->aead.data.offset +
621 op->sym->aead.data.length);
627 process_combined_data(struct nitrox_softreq *sr)
630 struct nitrox_sglist digest;
631 struct rte_crypto_op *op = sr->op;
633 err = softreq_copy_salt(sr);
637 softreq_copy_iv(sr, AES_GCM_SALT_SIZE);
638 err = extract_combined_digest(sr, &digest);
642 err = create_aead_inbuf(sr, &digest);
646 err = create_aead_outbuf(sr, &digest);
650 create_aead_gph(op->sym->aead.data.length, sr->iv.len,
651 op->sym->aead.data.length + sr->ctx->aad_length,
658 process_softreq(struct nitrox_softreq *sr)
660 struct nitrox_crypto_ctx *ctx = sr->ctx;
663 switch (ctx->nitrox_chain) {
664 case NITROX_CHAIN_CIPHER_AUTH:
665 case NITROX_CHAIN_AUTH_CIPHER:
666 err = process_cipher_auth_data(sr);
668 case NITROX_CHAIN_COMBINED:
669 err = process_combined_data(sr);
680 nitrox_process_se_req(uint16_t qno, struct rte_crypto_op *op,
681 struct nitrox_crypto_ctx *ctx,
682 struct nitrox_softreq *sr)
686 softreq_init(sr, sr->iova);
689 err = process_softreq(sr);
693 create_se_instr(sr, qno);
694 sr->timeout = rte_get_timer_cycles() + CMD_TIMEOUT * rte_get_timer_hz();
699 nitrox_check_se_req(struct nitrox_softreq *sr, struct rte_crypto_op **op)
705 cc = *(volatile uint64_t *)(&sr->resp.completion);
706 orh = *(volatile uint64_t *)(&sr->resp.orh);
707 if (cc != PENDING_SIG)
709 else if ((orh != PENDING_SIG) && (orh & 0xff))
711 else if (rte_get_timer_cycles() >= sr->timeout)
717 NITROX_LOG(ERR, "Request err 0x%x, orh 0x%"PRIx64"\n", err,
725 nitrox_sym_instr_addr(struct nitrox_softreq *sr)
731 req_pool_obj_init(__rte_unused struct rte_mempool *mp,
732 __rte_unused void *opaque, void *obj,
733 __rte_unused unsigned int obj_idx)
735 softreq_init(obj, rte_mempool_virt2iova(obj));
739 nitrox_sym_req_pool_create(struct rte_cryptodev *cdev, uint32_t nobjs,
740 uint16_t qp_id, int socket_id)
742 char softreq_pool_name[RTE_RING_NAMESIZE];
743 struct rte_mempool *mp;
745 snprintf(softreq_pool_name, RTE_RING_NAMESIZE, "%s_sr_%d",
746 cdev->data->name, qp_id);
747 mp = rte_mempool_create(softreq_pool_name,
748 RTE_ALIGN_MUL_CEIL(nobjs, 64),
749 sizeof(struct nitrox_softreq),
750 64, 0, NULL, NULL, req_pool_obj_init, NULL,
753 NITROX_LOG(ERR, "Failed to create req pool, qid %d, err %d\n",
760 nitrox_sym_req_pool_free(struct rte_mempool *mp)
762 rte_mempool_free(mp);