2018-04-17 09:23:17 +00:00
|
|
|
/* SPDX-License-Identifier: BSD-3-Clause
|
|
|
|
* Copyright(c) 2018 HUAWEI TECHNOLOGIES CO., LTD.
|
|
|
|
*/
|
2018-04-17 09:23:20 +00:00
|
|
|
#include <stdbool.h>
|
|
|
|
#include <unistd.h>
|
|
|
|
|
|
|
|
#include <rte_common.h>
|
crypto/virtio: support basic PMD ops
This patch implements the basic operations of virtio crypto PMD, which
includes start, stop, close, information getting, queue setup and
release of the device.
The virtio crypto device has two types of queues, data queue and
control queue. It has one data queue at least and has one and only one
control queue. For example, if a virtio crypto device has N queues,
then [0, N-2] is the data queue index, N-1 is the control
queue index.
Signed-off-by: Jay Zhou <jianjay.zhou@huawei.com>
Reviewed-by: Fan Zhang <roy.fan.zhang@intel.com>
2018-04-17 09:23:19 +00:00
|
|
|
#include <rte_errno.h>
|
2018-04-17 09:23:17 +00:00
|
|
|
#include <rte_pci.h>
|
|
|
|
#include <rte_bus_pci.h>
|
2018-04-17 09:23:18 +00:00
|
|
|
#include <rte_cryptodev.h>
|
2018-04-17 09:23:17 +00:00
|
|
|
#include <rte_cryptodev_pmd.h>
|
2018-04-17 09:23:18 +00:00
|
|
|
#include <rte_eal.h>
|
2018-04-17 09:23:17 +00:00
|
|
|
|
|
|
|
#include "virtio_cryptodev.h"
|
2018-04-17 09:23:18 +00:00
|
|
|
#include "virtqueue.h"
|
2018-04-17 09:23:20 +00:00
|
|
|
#include "virtio_crypto_algs.h"
|
2018-04-17 09:23:23 +00:00
|
|
|
#include "virtio_crypto_capabilities.h"
|
2018-04-17 09:23:18 +00:00
|
|
|
|
crypto/virtio: support basic PMD ops
This patch implements the basic operations of virtio crypto PMD, which
includes start, stop, close, information getting, queue setup and
release of the device.
The virtio crypto device has two types of queues, data queue and
control queue. It has one data queue at least and has one and only one
control queue. For example, if a virtio crypto device has N queues,
then [0, N-2] is the data queue index, N-1 is the control
queue index.
Signed-off-by: Jay Zhou <jianjay.zhou@huawei.com>
Reviewed-by: Fan Zhang <roy.fan.zhang@intel.com>
2018-04-17 09:23:19 +00:00
|
|
|
static int virtio_crypto_dev_configure(struct rte_cryptodev *dev,
|
|
|
|
struct rte_cryptodev_config *config);
|
|
|
|
static int virtio_crypto_dev_start(struct rte_cryptodev *dev);
|
|
|
|
static void virtio_crypto_dev_stop(struct rte_cryptodev *dev);
|
|
|
|
static int virtio_crypto_dev_close(struct rte_cryptodev *dev);
|
|
|
|
static void virtio_crypto_dev_info_get(struct rte_cryptodev *dev,
|
|
|
|
struct rte_cryptodev_info *dev_info);
|
2018-04-17 09:23:22 +00:00
|
|
|
static void virtio_crypto_dev_stats_get(struct rte_cryptodev *dev,
|
|
|
|
struct rte_cryptodev_stats *stats);
|
|
|
|
static void virtio_crypto_dev_stats_reset(struct rte_cryptodev *dev);
|
crypto/virtio: support basic PMD ops
This patch implements the basic operations of virtio crypto PMD, which
includes start, stop, close, information getting, queue setup and
release of the device.
The virtio crypto device has two types of queues, data queue and
control queue. It has one data queue at least and has one and only one
control queue. For example, if a virtio crypto device has N queues,
then [0, N-2] is the data queue index, N-1 is the control
queue index.
Signed-off-by: Jay Zhou <jianjay.zhou@huawei.com>
Reviewed-by: Fan Zhang <roy.fan.zhang@intel.com>
2018-04-17 09:23:19 +00:00
|
|
|
static int virtio_crypto_qp_setup(struct rte_cryptodev *dev,
|
|
|
|
uint16_t queue_pair_id,
|
|
|
|
const struct rte_cryptodev_qp_conf *qp_conf,
|
2019-01-10 14:50:11 +00:00
|
|
|
int socket_id);
|
crypto/virtio: support basic PMD ops
This patch implements the basic operations of virtio crypto PMD, which
includes start, stop, close, information getting, queue setup and
release of the device.
The virtio crypto device has two types of queues, data queue and
control queue. It has one data queue at least and has one and only one
control queue. For example, if a virtio crypto device has N queues,
then [0, N-2] is the data queue index, N-1 is the control
queue index.
Signed-off-by: Jay Zhou <jianjay.zhou@huawei.com>
Reviewed-by: Fan Zhang <roy.fan.zhang@intel.com>
2018-04-17 09:23:19 +00:00
|
|
|
static int virtio_crypto_qp_release(struct rte_cryptodev *dev,
|
|
|
|
uint16_t queue_pair_id);
|
|
|
|
static void virtio_crypto_dev_free_mbufs(struct rte_cryptodev *dev);
|
2018-04-17 09:23:20 +00:00
|
|
|
static unsigned int virtio_crypto_sym_get_session_private_size(
|
|
|
|
struct rte_cryptodev *dev);
|
|
|
|
static void virtio_crypto_sym_clear_session(struct rte_cryptodev *dev,
|
|
|
|
struct rte_cryptodev_sym_session *sess);
|
|
|
|
static int virtio_crypto_sym_configure_session(struct rte_cryptodev *dev,
|
|
|
|
struct rte_crypto_sym_xform *xform,
|
|
|
|
struct rte_cryptodev_sym_session *session,
|
|
|
|
struct rte_mempool *mp);
|
crypto/virtio: support basic PMD ops
This patch implements the basic operations of virtio crypto PMD, which
includes start, stop, close, information getting, queue setup and
release of the device.
The virtio crypto device has two types of queues, data queue and
control queue. It has one data queue at least and has one and only one
control queue. For example, if a virtio crypto device has N queues,
then [0, N-2] is the data queue index, N-1 is the control
queue index.
Signed-off-by: Jay Zhou <jianjay.zhou@huawei.com>
Reviewed-by: Fan Zhang <roy.fan.zhang@intel.com>
2018-04-17 09:23:19 +00:00
|
|
|
|
2018-04-17 09:23:18 +00:00
|
|
|
/*
|
|
|
|
* The set of PCI devices this driver supports
|
|
|
|
*/
|
|
|
|
static const struct rte_pci_id pci_id_virtio_crypto_map[] = {
|
|
|
|
{ RTE_PCI_DEVICE(VIRTIO_CRYPTO_PCI_VENDORID,
|
|
|
|
VIRTIO_CRYPTO_PCI_DEVICEID) },
|
|
|
|
{ .vendor_id = 0, /* sentinel */ },
|
|
|
|
};
|
2018-04-17 09:23:17 +00:00
|
|
|
|
2018-04-17 09:23:23 +00:00
|
|
|
static const struct rte_cryptodev_capabilities virtio_capabilities[] = {
|
|
|
|
VIRTIO_SYM_CAPABILITIES,
|
|
|
|
RTE_CRYPTODEV_END_OF_CAPABILITIES_LIST()
|
|
|
|
};
|
|
|
|
|
2018-04-17 09:23:17 +00:00
|
|
|
uint8_t cryptodev_virtio_driver_id;
|
|
|
|
|
2018-04-17 09:23:20 +00:00
|
|
|
#define NUM_ENTRY_SYM_CREATE_SESSION 4
|
|
|
|
|
|
|
|
static int
|
|
|
|
virtio_crypto_send_command(struct virtqueue *vq,
|
|
|
|
struct virtio_crypto_op_ctrl_req *ctrl, uint8_t *cipher_key,
|
|
|
|
uint8_t *auth_key, struct virtio_crypto_session *session)
|
|
|
|
{
|
|
|
|
uint8_t idx = 0;
|
|
|
|
uint8_t needed = 1;
|
|
|
|
uint32_t head = 0;
|
|
|
|
uint32_t len_cipher_key = 0;
|
|
|
|
uint32_t len_auth_key = 0;
|
|
|
|
uint32_t len_ctrl_req = sizeof(struct virtio_crypto_op_ctrl_req);
|
|
|
|
uint32_t len_session_input = sizeof(struct virtio_crypto_session_input);
|
|
|
|
uint32_t len_total = 0;
|
|
|
|
uint32_t input_offset = 0;
|
|
|
|
void *virt_addr_started = NULL;
|
|
|
|
phys_addr_t phys_addr_started;
|
|
|
|
struct vring_desc *desc;
|
|
|
|
uint32_t desc_offset;
|
|
|
|
struct virtio_crypto_session_input *input;
|
|
|
|
int ret;
|
|
|
|
|
|
|
|
PMD_INIT_FUNC_TRACE();
|
|
|
|
|
|
|
|
if (session == NULL) {
|
|
|
|
VIRTIO_CRYPTO_SESSION_LOG_ERR("session is NULL.");
|
|
|
|
return -EINVAL;
|
|
|
|
}
|
|
|
|
/* cipher only is supported, it is available if auth_key is NULL */
|
|
|
|
if (!cipher_key) {
|
|
|
|
VIRTIO_CRYPTO_SESSION_LOG_ERR("cipher key is NULL.");
|
|
|
|
return -EINVAL;
|
|
|
|
}
|
|
|
|
|
|
|
|
head = vq->vq_desc_head_idx;
|
|
|
|
VIRTIO_CRYPTO_INIT_LOG_DBG("vq->vq_desc_head_idx = %d, vq = %p",
|
|
|
|
head, vq);
|
|
|
|
|
|
|
|
if (vq->vq_free_cnt < needed) {
|
|
|
|
VIRTIO_CRYPTO_SESSION_LOG_ERR("Not enough entry");
|
|
|
|
return -ENOSPC;
|
|
|
|
}
|
|
|
|
|
|
|
|
/* calculate the length of cipher key */
|
|
|
|
if (cipher_key) {
|
|
|
|
switch (ctrl->u.sym_create_session.op_type) {
|
|
|
|
case VIRTIO_CRYPTO_SYM_OP_CIPHER:
|
|
|
|
len_cipher_key
|
|
|
|
= ctrl->u.sym_create_session.u.cipher
|
|
|
|
.para.keylen;
|
|
|
|
break;
|
|
|
|
case VIRTIO_CRYPTO_SYM_OP_ALGORITHM_CHAINING:
|
|
|
|
len_cipher_key
|
|
|
|
= ctrl->u.sym_create_session.u.chain
|
|
|
|
.para.cipher_param.keylen;
|
|
|
|
break;
|
|
|
|
default:
|
|
|
|
VIRTIO_CRYPTO_SESSION_LOG_ERR("invalid op type");
|
|
|
|
return -EINVAL;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
/* calculate the length of auth key */
|
|
|
|
if (auth_key) {
|
|
|
|
len_auth_key =
|
|
|
|
ctrl->u.sym_create_session.u.chain.para.u.mac_param
|
|
|
|
.auth_key_len;
|
|
|
|
}
|
|
|
|
|
|
|
|
/*
|
|
|
|
* malloc memory to store indirect vring_desc entries, including
|
|
|
|
* ctrl request, cipher key, auth key, session input and desc vring
|
|
|
|
*/
|
|
|
|
desc_offset = len_ctrl_req + len_cipher_key + len_auth_key
|
|
|
|
+ len_session_input;
|
|
|
|
virt_addr_started = rte_malloc(NULL,
|
|
|
|
desc_offset + NUM_ENTRY_SYM_CREATE_SESSION
|
|
|
|
* sizeof(struct vring_desc), RTE_CACHE_LINE_SIZE);
|
|
|
|
if (virt_addr_started == NULL) {
|
|
|
|
VIRTIO_CRYPTO_SESSION_LOG_ERR("not enough heap memory");
|
|
|
|
return -ENOSPC;
|
|
|
|
}
|
|
|
|
phys_addr_started = rte_malloc_virt2iova(virt_addr_started);
|
|
|
|
|
|
|
|
/* address to store indirect vring desc entries */
|
|
|
|
desc = (struct vring_desc *)
|
|
|
|
((uint8_t *)virt_addr_started + desc_offset);
|
|
|
|
|
|
|
|
/* ctrl req part */
|
|
|
|
memcpy(virt_addr_started, ctrl, len_ctrl_req);
|
|
|
|
desc[idx].addr = phys_addr_started;
|
|
|
|
desc[idx].len = len_ctrl_req;
|
|
|
|
desc[idx].flags = VRING_DESC_F_NEXT;
|
|
|
|
desc[idx].next = idx + 1;
|
|
|
|
idx++;
|
|
|
|
len_total += len_ctrl_req;
|
|
|
|
input_offset += len_ctrl_req;
|
|
|
|
|
|
|
|
/* cipher key part */
|
|
|
|
if (len_cipher_key > 0) {
|
|
|
|
memcpy((uint8_t *)virt_addr_started + len_total,
|
|
|
|
cipher_key, len_cipher_key);
|
|
|
|
|
|
|
|
desc[idx].addr = phys_addr_started + len_total;
|
|
|
|
desc[idx].len = len_cipher_key;
|
|
|
|
desc[idx].flags = VRING_DESC_F_NEXT;
|
|
|
|
desc[idx].next = idx + 1;
|
|
|
|
idx++;
|
|
|
|
len_total += len_cipher_key;
|
|
|
|
input_offset += len_cipher_key;
|
|
|
|
}
|
|
|
|
|
|
|
|
/* auth key part */
|
|
|
|
if (len_auth_key > 0) {
|
|
|
|
memcpy((uint8_t *)virt_addr_started + len_total,
|
|
|
|
auth_key, len_auth_key);
|
|
|
|
|
|
|
|
desc[idx].addr = phys_addr_started + len_total;
|
|
|
|
desc[idx].len = len_auth_key;
|
|
|
|
desc[idx].flags = VRING_DESC_F_NEXT;
|
|
|
|
desc[idx].next = idx + 1;
|
|
|
|
idx++;
|
|
|
|
len_total += len_auth_key;
|
|
|
|
input_offset += len_auth_key;
|
|
|
|
}
|
|
|
|
|
|
|
|
/* input part */
|
|
|
|
input = (struct virtio_crypto_session_input *)
|
|
|
|
((uint8_t *)virt_addr_started + input_offset);
|
|
|
|
input->status = VIRTIO_CRYPTO_ERR;
|
|
|
|
input->session_id = ~0ULL;
|
|
|
|
desc[idx].addr = phys_addr_started + len_total;
|
|
|
|
desc[idx].len = len_session_input;
|
|
|
|
desc[idx].flags = VRING_DESC_F_WRITE;
|
|
|
|
idx++;
|
|
|
|
|
|
|
|
/* use a single desc entry */
|
|
|
|
vq->vq_ring.desc[head].addr = phys_addr_started + desc_offset;
|
|
|
|
vq->vq_ring.desc[head].len = idx * sizeof(struct vring_desc);
|
|
|
|
vq->vq_ring.desc[head].flags = VRING_DESC_F_INDIRECT;
|
|
|
|
vq->vq_free_cnt--;
|
|
|
|
|
|
|
|
vq->vq_desc_head_idx = vq->vq_ring.desc[head].next;
|
|
|
|
|
|
|
|
vq_update_avail_ring(vq, head);
|
|
|
|
vq_update_avail_idx(vq);
|
|
|
|
|
|
|
|
VIRTIO_CRYPTO_INIT_LOG_DBG("vq->vq_queue_index = %d",
|
|
|
|
vq->vq_queue_index);
|
|
|
|
|
|
|
|
virtqueue_notify(vq);
|
|
|
|
|
|
|
|
rte_rmb();
|
|
|
|
while (vq->vq_used_cons_idx == vq->vq_ring.used->idx) {
|
|
|
|
rte_rmb();
|
|
|
|
usleep(100);
|
|
|
|
}
|
|
|
|
|
|
|
|
while (vq->vq_used_cons_idx != vq->vq_ring.used->idx) {
|
|
|
|
uint32_t idx, desc_idx, used_idx;
|
|
|
|
struct vring_used_elem *uep;
|
|
|
|
|
|
|
|
used_idx = (uint32_t)(vq->vq_used_cons_idx
|
|
|
|
& (vq->vq_nentries - 1));
|
|
|
|
uep = &vq->vq_ring.used->ring[used_idx];
|
|
|
|
idx = (uint32_t) uep->id;
|
|
|
|
desc_idx = idx;
|
|
|
|
|
|
|
|
while (vq->vq_ring.desc[desc_idx].flags & VRING_DESC_F_NEXT) {
|
|
|
|
desc_idx = vq->vq_ring.desc[desc_idx].next;
|
|
|
|
vq->vq_free_cnt++;
|
|
|
|
}
|
|
|
|
|
|
|
|
vq->vq_ring.desc[desc_idx].next = vq->vq_desc_head_idx;
|
|
|
|
vq->vq_desc_head_idx = idx;
|
|
|
|
|
|
|
|
vq->vq_used_cons_idx++;
|
|
|
|
vq->vq_free_cnt++;
|
|
|
|
}
|
|
|
|
|
|
|
|
VIRTIO_CRYPTO_INIT_LOG_DBG("vq->vq_free_cnt=%d\n"
|
|
|
|
"vq->vq_desc_head_idx=%d",
|
|
|
|
vq->vq_free_cnt, vq->vq_desc_head_idx);
|
|
|
|
|
|
|
|
/* get the result */
|
|
|
|
if (input->status != VIRTIO_CRYPTO_OK) {
|
|
|
|
VIRTIO_CRYPTO_SESSION_LOG_ERR("Something wrong on backend! "
|
|
|
|
"status=%u, session_id=%" PRIu64 "",
|
|
|
|
input->status, input->session_id);
|
|
|
|
rte_free(virt_addr_started);
|
|
|
|
ret = -1;
|
|
|
|
} else {
|
|
|
|
session->session_id = input->session_id;
|
|
|
|
|
|
|
|
VIRTIO_CRYPTO_SESSION_LOG_INFO("Create session successfully, "
|
|
|
|
"session_id=%" PRIu64 "", input->session_id);
|
|
|
|
rte_free(virt_addr_started);
|
|
|
|
ret = 0;
|
|
|
|
}
|
|
|
|
|
|
|
|
return ret;
|
|
|
|
}
|
|
|
|
|
crypto/virtio: support basic PMD ops
This patch implements the basic operations of virtio crypto PMD, which
includes start, stop, close, information getting, queue setup and
release of the device.
The virtio crypto device has two types of queues, data queue and
control queue. It has one data queue at least and has one and only one
control queue. For example, if a virtio crypto device has N queues,
then [0, N-2] is the data queue index, N-1 is the control
queue index.
Signed-off-by: Jay Zhou <jianjay.zhou@huawei.com>
Reviewed-by: Fan Zhang <roy.fan.zhang@intel.com>
2018-04-17 09:23:19 +00:00
|
|
|
void
|
|
|
|
virtio_crypto_queue_release(struct virtqueue *vq)
|
|
|
|
{
|
|
|
|
struct virtio_crypto_hw *hw;
|
|
|
|
|
|
|
|
PMD_INIT_FUNC_TRACE();
|
|
|
|
|
|
|
|
if (vq) {
|
|
|
|
hw = vq->hw;
|
|
|
|
/* Select and deactivate the queue */
|
|
|
|
VTPCI_OPS(hw)->del_queue(hw, vq);
|
|
|
|
|
|
|
|
rte_memzone_free(vq->mz);
|
|
|
|
rte_mempool_free(vq->mpool);
|
|
|
|
rte_free(vq);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
#define MPOOL_MAX_NAME_SZ 32
|
|
|
|
|
|
|
|
int
|
|
|
|
virtio_crypto_queue_setup(struct rte_cryptodev *dev,
|
|
|
|
int queue_type,
|
|
|
|
uint16_t vtpci_queue_idx,
|
|
|
|
uint16_t nb_desc,
|
|
|
|
int socket_id,
|
|
|
|
struct virtqueue **pvq)
|
|
|
|
{
|
|
|
|
char vq_name[VIRTQUEUE_MAX_NAME_SZ];
|
|
|
|
char mpool_name[MPOOL_MAX_NAME_SZ];
|
|
|
|
const struct rte_memzone *mz;
|
|
|
|
unsigned int vq_size, size;
|
|
|
|
struct virtio_crypto_hw *hw = dev->data->dev_private;
|
|
|
|
struct virtqueue *vq = NULL;
|
|
|
|
uint32_t i = 0;
|
|
|
|
uint32_t j;
|
|
|
|
|
|
|
|
PMD_INIT_FUNC_TRACE();
|
|
|
|
|
|
|
|
VIRTIO_CRYPTO_INIT_LOG_DBG("setting up queue: %u", vtpci_queue_idx);
|
|
|
|
|
|
|
|
/*
|
|
|
|
* Read the virtqueue size from the Queue Size field
|
|
|
|
* Always power of 2 and if 0 virtqueue does not exist
|
|
|
|
*/
|
|
|
|
vq_size = VTPCI_OPS(hw)->get_queue_num(hw, vtpci_queue_idx);
|
|
|
|
if (vq_size == 0) {
|
|
|
|
VIRTIO_CRYPTO_INIT_LOG_ERR("virtqueue does not exist");
|
|
|
|
return -EINVAL;
|
|
|
|
}
|
|
|
|
VIRTIO_CRYPTO_INIT_LOG_DBG("vq_size: %u", vq_size);
|
|
|
|
|
|
|
|
if (!rte_is_power_of_2(vq_size)) {
|
|
|
|
VIRTIO_CRYPTO_INIT_LOG_ERR("virtqueue size is not powerof 2");
|
|
|
|
return -EINVAL;
|
|
|
|
}
|
|
|
|
|
|
|
|
if (queue_type == VTCRYPTO_DATAQ) {
|
|
|
|
snprintf(vq_name, sizeof(vq_name), "dev%d_dataqueue%d",
|
|
|
|
dev->data->dev_id, vtpci_queue_idx);
|
|
|
|
snprintf(mpool_name, sizeof(mpool_name),
|
|
|
|
"dev%d_dataqueue%d_mpool",
|
|
|
|
dev->data->dev_id, vtpci_queue_idx);
|
|
|
|
} else if (queue_type == VTCRYPTO_CTRLQ) {
|
|
|
|
snprintf(vq_name, sizeof(vq_name), "dev%d_controlqueue",
|
|
|
|
dev->data->dev_id);
|
|
|
|
snprintf(mpool_name, sizeof(mpool_name),
|
|
|
|
"dev%d_controlqueue_mpool",
|
|
|
|
dev->data->dev_id);
|
|
|
|
}
|
|
|
|
size = RTE_ALIGN_CEIL(sizeof(*vq) +
|
|
|
|
vq_size * sizeof(struct vq_desc_extra),
|
|
|
|
RTE_CACHE_LINE_SIZE);
|
|
|
|
vq = rte_zmalloc_socket(vq_name, size, RTE_CACHE_LINE_SIZE,
|
|
|
|
socket_id);
|
|
|
|
if (vq == NULL) {
|
|
|
|
VIRTIO_CRYPTO_INIT_LOG_ERR("Can not allocate virtqueue");
|
|
|
|
return -ENOMEM;
|
|
|
|
}
|
|
|
|
|
|
|
|
if (queue_type == VTCRYPTO_DATAQ) {
|
|
|
|
/* pre-allocate a mempool and use it in the data plane to
|
|
|
|
* improve performance
|
|
|
|
*/
|
|
|
|
vq->mpool = rte_mempool_lookup(mpool_name);
|
|
|
|
if (vq->mpool == NULL)
|
|
|
|
vq->mpool = rte_mempool_create(mpool_name,
|
|
|
|
vq_size,
|
|
|
|
sizeof(struct virtio_crypto_op_cookie),
|
|
|
|
RTE_CACHE_LINE_SIZE, 0,
|
|
|
|
NULL, NULL, NULL, NULL, socket_id,
|
|
|
|
0);
|
|
|
|
if (!vq->mpool) {
|
|
|
|
VIRTIO_CRYPTO_DRV_LOG_ERR("Virtio Crypto PMD "
|
|
|
|
"Cannot create mempool");
|
|
|
|
goto mpool_create_err;
|
|
|
|
}
|
|
|
|
for (i = 0; i < vq_size; i++) {
|
|
|
|
vq->vq_descx[i].cookie =
|
|
|
|
rte_zmalloc("crypto PMD op cookie pointer",
|
|
|
|
sizeof(struct virtio_crypto_op_cookie),
|
|
|
|
RTE_CACHE_LINE_SIZE);
|
|
|
|
if (vq->vq_descx[i].cookie == NULL) {
|
|
|
|
VIRTIO_CRYPTO_DRV_LOG_ERR("Failed to "
|
|
|
|
"alloc mem for cookie");
|
|
|
|
goto cookie_alloc_err;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
vq->hw = hw;
|
|
|
|
vq->dev_id = dev->data->dev_id;
|
|
|
|
vq->vq_queue_index = vtpci_queue_idx;
|
|
|
|
vq->vq_nentries = vq_size;
|
|
|
|
|
|
|
|
/*
|
|
|
|
* Using part of the vring entries is permitted, but the maximum
|
|
|
|
* is vq_size
|
|
|
|
*/
|
|
|
|
if (nb_desc == 0 || nb_desc > vq_size)
|
|
|
|
nb_desc = vq_size;
|
|
|
|
vq->vq_free_cnt = nb_desc;
|
|
|
|
|
|
|
|
/*
|
|
|
|
* Reserve a memzone for vring elements
|
|
|
|
*/
|
|
|
|
size = vring_size(vq_size, VIRTIO_PCI_VRING_ALIGN);
|
|
|
|
vq->vq_ring_size = RTE_ALIGN_CEIL(size, VIRTIO_PCI_VRING_ALIGN);
|
|
|
|
VIRTIO_CRYPTO_INIT_LOG_DBG("%s vring_size: %d, rounded_vring_size: %d",
|
|
|
|
(queue_type == VTCRYPTO_DATAQ) ? "dataq" : "ctrlq",
|
|
|
|
size, vq->vq_ring_size);
|
|
|
|
|
|
|
|
mz = rte_memzone_reserve_aligned(vq_name, vq->vq_ring_size,
|
|
|
|
socket_id, 0, VIRTIO_PCI_VRING_ALIGN);
|
|
|
|
if (mz == NULL) {
|
|
|
|
if (rte_errno == EEXIST)
|
|
|
|
mz = rte_memzone_lookup(vq_name);
|
|
|
|
if (mz == NULL) {
|
|
|
|
VIRTIO_CRYPTO_INIT_LOG_ERR("not enough memory");
|
|
|
|
goto mz_reserve_err;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
/*
|
|
|
|
* Virtio PCI device VIRTIO_PCI_QUEUE_PF register is 32bit,
|
|
|
|
* and only accepts 32 bit page frame number.
|
|
|
|
* Check if the allocated physical memory exceeds 16TB.
|
|
|
|
*/
|
2020-09-14 14:36:31 +00:00
|
|
|
if ((mz->iova + vq->vq_ring_size - 1)
|
crypto/virtio: support basic PMD ops
This patch implements the basic operations of virtio crypto PMD, which
includes start, stop, close, information getting, queue setup and
release of the device.
The virtio crypto device has two types of queues, data queue and
control queue. It has one data queue at least and has one and only one
control queue. For example, if a virtio crypto device has N queues,
then [0, N-2] is the data queue index, N-1 is the control
queue index.
Signed-off-by: Jay Zhou <jianjay.zhou@huawei.com>
Reviewed-by: Fan Zhang <roy.fan.zhang@intel.com>
2018-04-17 09:23:19 +00:00
|
|
|
>> (VIRTIO_PCI_QUEUE_ADDR_SHIFT + 32)) {
|
|
|
|
VIRTIO_CRYPTO_INIT_LOG_ERR("vring address shouldn't be "
|
|
|
|
"above 16TB!");
|
|
|
|
goto vring_addr_err;
|
|
|
|
}
|
|
|
|
|
|
|
|
memset(mz->addr, 0, sizeof(mz->len));
|
|
|
|
vq->mz = mz;
|
2020-09-14 14:36:31 +00:00
|
|
|
vq->vq_ring_mem = mz->iova;
|
crypto/virtio: support basic PMD ops
This patch implements the basic operations of virtio crypto PMD, which
includes start, stop, close, information getting, queue setup and
release of the device.
The virtio crypto device has two types of queues, data queue and
control queue. It has one data queue at least and has one and only one
control queue. For example, if a virtio crypto device has N queues,
then [0, N-2] is the data queue index, N-1 is the control
queue index.
Signed-off-by: Jay Zhou <jianjay.zhou@huawei.com>
Reviewed-by: Fan Zhang <roy.fan.zhang@intel.com>
2018-04-17 09:23:19 +00:00
|
|
|
vq->vq_ring_virt_mem = mz->addr;
|
|
|
|
VIRTIO_CRYPTO_INIT_LOG_DBG("vq->vq_ring_mem(physical): 0x%"PRIx64,
|
2020-09-14 14:36:31 +00:00
|
|
|
(uint64_t)mz->iova);
|
crypto/virtio: support basic PMD ops
This patch implements the basic operations of virtio crypto PMD, which
includes start, stop, close, information getting, queue setup and
release of the device.
The virtio crypto device has two types of queues, data queue and
control queue. It has one data queue at least and has one and only one
control queue. For example, if a virtio crypto device has N queues,
then [0, N-2] is the data queue index, N-1 is the control
queue index.
Signed-off-by: Jay Zhou <jianjay.zhou@huawei.com>
Reviewed-by: Fan Zhang <roy.fan.zhang@intel.com>
2018-04-17 09:23:19 +00:00
|
|
|
VIRTIO_CRYPTO_INIT_LOG_DBG("vq->vq_ring_virt_mem: 0x%"PRIx64,
|
|
|
|
(uint64_t)(uintptr_t)mz->addr);
|
|
|
|
|
|
|
|
*pvq = vq;
|
|
|
|
|
|
|
|
return 0;
|
|
|
|
|
|
|
|
vring_addr_err:
|
|
|
|
rte_memzone_free(mz);
|
|
|
|
mz_reserve_err:
|
|
|
|
cookie_alloc_err:
|
|
|
|
rte_mempool_free(vq->mpool);
|
|
|
|
if (i != 0) {
|
|
|
|
for (j = 0; j < i; j++)
|
|
|
|
rte_free(vq->vq_descx[j].cookie);
|
|
|
|
}
|
|
|
|
mpool_create_err:
|
|
|
|
rte_free(vq);
|
|
|
|
return -ENOMEM;
|
|
|
|
}
|
|
|
|
|
|
|
|
static int
|
|
|
|
virtio_crypto_ctrlq_setup(struct rte_cryptodev *dev, uint16_t queue_idx)
|
|
|
|
{
|
|
|
|
int ret;
|
|
|
|
struct virtqueue *vq;
|
|
|
|
struct virtio_crypto_hw *hw = dev->data->dev_private;
|
|
|
|
|
|
|
|
/* if virtio device has started, do not touch the virtqueues */
|
|
|
|
if (dev->data->dev_started)
|
|
|
|
return 0;
|
|
|
|
|
|
|
|
PMD_INIT_FUNC_TRACE();
|
|
|
|
|
|
|
|
ret = virtio_crypto_queue_setup(dev, VTCRYPTO_CTRLQ, queue_idx,
|
|
|
|
0, SOCKET_ID_ANY, &vq);
|
|
|
|
if (ret < 0) {
|
|
|
|
VIRTIO_CRYPTO_INIT_LOG_ERR("control vq initialization failed");
|
|
|
|
return ret;
|
|
|
|
}
|
|
|
|
|
|
|
|
hw->cvq = vq;
|
|
|
|
|
|
|
|
return 0;
|
|
|
|
}
|
|
|
|
|
|
|
|
static void
|
|
|
|
virtio_crypto_free_queues(struct rte_cryptodev *dev)
|
|
|
|
{
|
|
|
|
unsigned int i;
|
|
|
|
struct virtio_crypto_hw *hw = dev->data->dev_private;
|
|
|
|
|
|
|
|
PMD_INIT_FUNC_TRACE();
|
|
|
|
|
|
|
|
/* control queue release */
|
|
|
|
virtio_crypto_queue_release(hw->cvq);
|
|
|
|
|
|
|
|
/* data queue release */
|
|
|
|
for (i = 0; i < hw->max_dataqueues; i++)
|
|
|
|
virtio_crypto_queue_release(dev->data->queue_pairs[i]);
|
|
|
|
}
|
|
|
|
|
|
|
|
static int
|
|
|
|
virtio_crypto_dev_close(struct rte_cryptodev *dev __rte_unused)
|
|
|
|
{
|
|
|
|
return 0;
|
|
|
|
}
|
|
|
|
|
2018-04-17 09:23:18 +00:00
|
|
|
/*
|
|
|
|
* dev_ops for virtio, bare necessities for basic operation
|
|
|
|
*/
|
|
|
|
static struct rte_cryptodev_ops virtio_crypto_dev_ops = {
|
|
|
|
/* Device related operations */
|
crypto/virtio: support basic PMD ops
This patch implements the basic operations of virtio crypto PMD, which
includes start, stop, close, information getting, queue setup and
release of the device.
The virtio crypto device has two types of queues, data queue and
control queue. It has one data queue at least and has one and only one
control queue. For example, if a virtio crypto device has N queues,
then [0, N-2] is the data queue index, N-1 is the control
queue index.
Signed-off-by: Jay Zhou <jianjay.zhou@huawei.com>
Reviewed-by: Fan Zhang <roy.fan.zhang@intel.com>
2018-04-17 09:23:19 +00:00
|
|
|
.dev_configure = virtio_crypto_dev_configure,
|
|
|
|
.dev_start = virtio_crypto_dev_start,
|
|
|
|
.dev_stop = virtio_crypto_dev_stop,
|
|
|
|
.dev_close = virtio_crypto_dev_close,
|
|
|
|
.dev_infos_get = virtio_crypto_dev_info_get,
|
2018-04-17 09:23:18 +00:00
|
|
|
|
2018-04-17 09:23:22 +00:00
|
|
|
.stats_get = virtio_crypto_dev_stats_get,
|
|
|
|
.stats_reset = virtio_crypto_dev_stats_reset,
|
2018-04-17 09:23:18 +00:00
|
|
|
|
crypto/virtio: support basic PMD ops
This patch implements the basic operations of virtio crypto PMD, which
includes start, stop, close, information getting, queue setup and
release of the device.
The virtio crypto device has two types of queues, data queue and
control queue. It has one data queue at least and has one and only one
control queue. For example, if a virtio crypto device has N queues,
then [0, N-2] is the data queue index, N-1 is the control
queue index.
Signed-off-by: Jay Zhou <jianjay.zhou@huawei.com>
Reviewed-by: Fan Zhang <roy.fan.zhang@intel.com>
2018-04-17 09:23:19 +00:00
|
|
|
.queue_pair_setup = virtio_crypto_qp_setup,
|
|
|
|
.queue_pair_release = virtio_crypto_qp_release,
|
2018-04-17 09:23:18 +00:00
|
|
|
|
|
|
|
/* Crypto related operations */
|
2018-07-05 02:08:04 +00:00
|
|
|
.sym_session_get_size = virtio_crypto_sym_get_session_private_size,
|
|
|
|
.sym_session_configure = virtio_crypto_sym_configure_session,
|
|
|
|
.sym_session_clear = virtio_crypto_sym_clear_session
|
2018-04-17 09:23:18 +00:00
|
|
|
};
|
|
|
|
|
2018-04-17 09:23:22 +00:00
|
|
|
static void
|
|
|
|
virtio_crypto_update_stats(struct rte_cryptodev *dev,
|
|
|
|
struct rte_cryptodev_stats *stats)
|
|
|
|
{
|
|
|
|
unsigned int i;
|
|
|
|
struct virtio_crypto_hw *hw = dev->data->dev_private;
|
|
|
|
|
|
|
|
PMD_INIT_FUNC_TRACE();
|
|
|
|
|
|
|
|
if (stats == NULL) {
|
|
|
|
VIRTIO_CRYPTO_DRV_LOG_ERR("invalid pointer");
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
|
|
|
|
for (i = 0; i < hw->max_dataqueues; i++) {
|
|
|
|
const struct virtqueue *data_queue
|
|
|
|
= dev->data->queue_pairs[i];
|
|
|
|
if (data_queue == NULL)
|
|
|
|
continue;
|
|
|
|
|
|
|
|
stats->enqueued_count += data_queue->packets_sent_total;
|
|
|
|
stats->enqueue_err_count += data_queue->packets_sent_failed;
|
|
|
|
|
|
|
|
stats->dequeued_count += data_queue->packets_received_total;
|
|
|
|
stats->dequeue_err_count
|
|
|
|
+= data_queue->packets_received_failed;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
static void
|
|
|
|
virtio_crypto_dev_stats_get(struct rte_cryptodev *dev,
|
|
|
|
struct rte_cryptodev_stats *stats)
|
|
|
|
{
|
|
|
|
PMD_INIT_FUNC_TRACE();
|
|
|
|
|
|
|
|
virtio_crypto_update_stats(dev, stats);
|
|
|
|
}
|
|
|
|
|
|
|
|
static void
|
|
|
|
virtio_crypto_dev_stats_reset(struct rte_cryptodev *dev)
|
|
|
|
{
|
|
|
|
unsigned int i;
|
|
|
|
struct virtio_crypto_hw *hw = dev->data->dev_private;
|
|
|
|
|
|
|
|
PMD_INIT_FUNC_TRACE();
|
|
|
|
|
|
|
|
for (i = 0; i < hw->max_dataqueues; i++) {
|
|
|
|
struct virtqueue *data_queue = dev->data->queue_pairs[i];
|
|
|
|
if (data_queue == NULL)
|
|
|
|
continue;
|
|
|
|
|
|
|
|
data_queue->packets_sent_total = 0;
|
|
|
|
data_queue->packets_sent_failed = 0;
|
|
|
|
|
|
|
|
data_queue->packets_received_total = 0;
|
|
|
|
data_queue->packets_received_failed = 0;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
crypto/virtio: support basic PMD ops
This patch implements the basic operations of virtio crypto PMD, which
includes start, stop, close, information getting, queue setup and
release of the device.
The virtio crypto device has two types of queues, data queue and
control queue. It has one data queue at least and has one and only one
control queue. For example, if a virtio crypto device has N queues,
then [0, N-2] is the data queue index, N-1 is the control
queue index.
Signed-off-by: Jay Zhou <jianjay.zhou@huawei.com>
Reviewed-by: Fan Zhang <roy.fan.zhang@intel.com>
2018-04-17 09:23:19 +00:00
|
|
|
static int
|
|
|
|
virtio_crypto_qp_setup(struct rte_cryptodev *dev, uint16_t queue_pair_id,
|
|
|
|
const struct rte_cryptodev_qp_conf *qp_conf,
|
2019-01-10 14:50:11 +00:00
|
|
|
int socket_id)
|
crypto/virtio: support basic PMD ops
This patch implements the basic operations of virtio crypto PMD, which
includes start, stop, close, information getting, queue setup and
release of the device.
The virtio crypto device has two types of queues, data queue and
control queue. It has one data queue at least and has one and only one
control queue. For example, if a virtio crypto device has N queues,
then [0, N-2] is the data queue index, N-1 is the control
queue index.
Signed-off-by: Jay Zhou <jianjay.zhou@huawei.com>
Reviewed-by: Fan Zhang <roy.fan.zhang@intel.com>
2018-04-17 09:23:19 +00:00
|
|
|
{
|
|
|
|
int ret;
|
|
|
|
struct virtqueue *vq;
|
|
|
|
|
|
|
|
PMD_INIT_FUNC_TRACE();
|
|
|
|
|
|
|
|
/* if virtio dev is started, do not touch the virtqueues */
|
|
|
|
if (dev->data->dev_started)
|
|
|
|
return 0;
|
|
|
|
|
|
|
|
ret = virtio_crypto_queue_setup(dev, VTCRYPTO_DATAQ, queue_pair_id,
|
|
|
|
qp_conf->nb_descriptors, socket_id, &vq);
|
|
|
|
if (ret < 0) {
|
|
|
|
VIRTIO_CRYPTO_INIT_LOG_ERR(
|
|
|
|
"virtio crypto data queue initialization failed\n");
|
|
|
|
return ret;
|
|
|
|
}
|
|
|
|
|
|
|
|
dev->data->queue_pairs[queue_pair_id] = vq;
|
|
|
|
|
|
|
|
return 0;
|
|
|
|
}
|
|
|
|
|
|
|
|
static int
|
|
|
|
virtio_crypto_qp_release(struct rte_cryptodev *dev, uint16_t queue_pair_id)
|
|
|
|
{
|
|
|
|
struct virtqueue *vq
|
|
|
|
= (struct virtqueue *)dev->data->queue_pairs[queue_pair_id];
|
|
|
|
|
|
|
|
PMD_INIT_FUNC_TRACE();
|
|
|
|
|
|
|
|
if (vq == NULL) {
|
|
|
|
VIRTIO_CRYPTO_DRV_LOG_DBG("vq already freed");
|
|
|
|
return 0;
|
|
|
|
}
|
|
|
|
|
|
|
|
virtio_crypto_queue_release(vq);
|
|
|
|
return 0;
|
|
|
|
}
|
|
|
|
|
2018-04-17 09:23:18 +00:00
|
|
|
static int
|
|
|
|
virtio_negotiate_features(struct virtio_crypto_hw *hw, uint64_t req_features)
|
|
|
|
{
|
|
|
|
uint64_t host_features;
|
|
|
|
|
|
|
|
PMD_INIT_FUNC_TRACE();
|
|
|
|
|
|
|
|
/* Prepare guest_features: feature that driver wants to support */
|
|
|
|
VIRTIO_CRYPTO_INIT_LOG_DBG("guest_features before negotiate = %" PRIx64,
|
|
|
|
req_features);
|
|
|
|
|
|
|
|
/* Read device(host) feature bits */
|
|
|
|
host_features = VTPCI_OPS(hw)->get_features(hw);
|
|
|
|
VIRTIO_CRYPTO_INIT_LOG_DBG("host_features before negotiate = %" PRIx64,
|
|
|
|
host_features);
|
|
|
|
|
|
|
|
/*
|
|
|
|
* Negotiate features: Subset of device feature bits are written back
|
|
|
|
* guest feature bits.
|
|
|
|
*/
|
|
|
|
hw->guest_features = req_features;
|
|
|
|
hw->guest_features = vtpci_cryptodev_negotiate_features(hw,
|
|
|
|
host_features);
|
|
|
|
VIRTIO_CRYPTO_INIT_LOG_DBG("features after negotiate = %" PRIx64,
|
|
|
|
hw->guest_features);
|
|
|
|
|
|
|
|
if (hw->modern) {
|
|
|
|
if (!vtpci_with_feature(hw, VIRTIO_F_VERSION_1)) {
|
|
|
|
VIRTIO_CRYPTO_INIT_LOG_ERR(
|
|
|
|
"VIRTIO_F_VERSION_1 features is not enabled.");
|
|
|
|
return -1;
|
|
|
|
}
|
|
|
|
vtpci_cryptodev_set_status(hw,
|
|
|
|
VIRTIO_CONFIG_STATUS_FEATURES_OK);
|
|
|
|
if (!(vtpci_cryptodev_get_status(hw) &
|
|
|
|
VIRTIO_CONFIG_STATUS_FEATURES_OK)) {
|
|
|
|
VIRTIO_CRYPTO_INIT_LOG_ERR("failed to set FEATURES_OK "
|
|
|
|
"status!");
|
|
|
|
return -1;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
hw->req_guest_features = req_features;
|
|
|
|
|
|
|
|
return 0;
|
|
|
|
}
|
|
|
|
|
|
|
|
/* reset device and renegotiate features if needed */
|
|
|
|
static int
|
|
|
|
virtio_crypto_init_device(struct rte_cryptodev *cryptodev,
|
|
|
|
uint64_t req_features)
|
|
|
|
{
|
|
|
|
struct virtio_crypto_hw *hw = cryptodev->data->dev_private;
|
|
|
|
struct virtio_crypto_config local_config;
|
|
|
|
struct virtio_crypto_config *config = &local_config;
|
|
|
|
|
|
|
|
PMD_INIT_FUNC_TRACE();
|
|
|
|
|
|
|
|
/* Reset the device although not necessary at startup */
|
|
|
|
vtpci_cryptodev_reset(hw);
|
|
|
|
|
|
|
|
/* Tell the host we've noticed this device. */
|
|
|
|
vtpci_cryptodev_set_status(hw, VIRTIO_CONFIG_STATUS_ACK);
|
|
|
|
|
|
|
|
/* Tell the host we've known how to drive the device. */
|
|
|
|
vtpci_cryptodev_set_status(hw, VIRTIO_CONFIG_STATUS_DRIVER);
|
|
|
|
if (virtio_negotiate_features(hw, req_features) < 0)
|
|
|
|
return -1;
|
|
|
|
|
|
|
|
/* Get status of the device */
|
|
|
|
vtpci_read_cryptodev_config(hw,
|
|
|
|
offsetof(struct virtio_crypto_config, status),
|
|
|
|
&config->status, sizeof(config->status));
|
|
|
|
if (config->status != VIRTIO_CRYPTO_S_HW_READY) {
|
|
|
|
VIRTIO_CRYPTO_DRV_LOG_ERR("accelerator hardware is "
|
|
|
|
"not ready");
|
|
|
|
return -1;
|
|
|
|
}
|
|
|
|
|
|
|
|
/* Get number of data queues */
|
|
|
|
vtpci_read_cryptodev_config(hw,
|
|
|
|
offsetof(struct virtio_crypto_config, max_dataqueues),
|
|
|
|
&config->max_dataqueues,
|
|
|
|
sizeof(config->max_dataqueues));
|
|
|
|
hw->max_dataqueues = config->max_dataqueues;
|
|
|
|
|
|
|
|
VIRTIO_CRYPTO_INIT_LOG_DBG("hw->max_dataqueues=%d",
|
|
|
|
hw->max_dataqueues);
|
|
|
|
|
|
|
|
return 0;
|
|
|
|
}
|
|
|
|
|
|
|
|
/*
|
|
|
|
* This function is based on probe() function
|
|
|
|
* It returns 0 on success.
|
|
|
|
*/
|
|
|
|
static int
|
|
|
|
crypto_virtio_create(const char *name, struct rte_pci_device *pci_dev,
|
|
|
|
struct rte_cryptodev_pmd_init_params *init_params)
|
|
|
|
{
|
|
|
|
struct rte_cryptodev *cryptodev;
|
|
|
|
struct virtio_crypto_hw *hw;
|
|
|
|
|
|
|
|
PMD_INIT_FUNC_TRACE();
|
|
|
|
|
|
|
|
cryptodev = rte_cryptodev_pmd_create(name, &pci_dev->device,
|
|
|
|
init_params);
|
|
|
|
if (cryptodev == NULL)
|
|
|
|
return -ENODEV;
|
|
|
|
|
|
|
|
cryptodev->driver_id = cryptodev_virtio_driver_id;
|
|
|
|
cryptodev->dev_ops = &virtio_crypto_dev_ops;
|
|
|
|
|
|
|
|
cryptodev->enqueue_burst = virtio_crypto_pkt_tx_burst;
|
|
|
|
cryptodev->dequeue_burst = virtio_crypto_pkt_rx_burst;
|
|
|
|
|
|
|
|
cryptodev->feature_flags = RTE_CRYPTODEV_FF_SYMMETRIC_CRYPTO |
|
2020-05-15 09:31:27 +00:00
|
|
|
RTE_CRYPTODEV_FF_SYM_OPERATION_CHAINING |
|
|
|
|
RTE_CRYPTODEV_FF_OOP_LB_IN_LB_OUT;
|
2018-04-17 09:23:18 +00:00
|
|
|
|
|
|
|
hw = cryptodev->data->dev_private;
|
|
|
|
hw->dev_id = cryptodev->data->dev_id;
|
2018-04-17 09:23:23 +00:00
|
|
|
hw->virtio_dev_capabilities = virtio_capabilities;
|
2018-04-17 09:23:18 +00:00
|
|
|
|
|
|
|
VIRTIO_CRYPTO_INIT_LOG_DBG("dev %d vendorID=0x%x deviceID=0x%x",
|
|
|
|
cryptodev->data->dev_id, pci_dev->id.vendor_id,
|
|
|
|
pci_dev->id.device_id);
|
|
|
|
|
|
|
|
/* pci device init */
|
|
|
|
if (vtpci_cryptodev_init(pci_dev, hw))
|
|
|
|
return -1;
|
|
|
|
|
|
|
|
if (virtio_crypto_init_device(cryptodev,
|
|
|
|
VIRTIO_CRYPTO_PMD_GUEST_FEATURES) < 0)
|
|
|
|
return -1;
|
|
|
|
|
|
|
|
return 0;
|
|
|
|
}
|
|
|
|
|
crypto/virtio: support basic PMD ops
This patch implements the basic operations of virtio crypto PMD, which
includes start, stop, close, information getting, queue setup and
release of the device.
The virtio crypto device has two types of queues, data queue and
control queue. It has one data queue at least and has one and only one
control queue. For example, if a virtio crypto device has N queues,
then [0, N-2] is the data queue index, N-1 is the control
queue index.
Signed-off-by: Jay Zhou <jianjay.zhou@huawei.com>
Reviewed-by: Fan Zhang <roy.fan.zhang@intel.com>
2018-04-17 09:23:19 +00:00
|
|
|
static int
|
|
|
|
virtio_crypto_dev_uninit(struct rte_cryptodev *cryptodev)
|
|
|
|
{
|
|
|
|
struct virtio_crypto_hw *hw = cryptodev->data->dev_private;
|
|
|
|
|
|
|
|
PMD_INIT_FUNC_TRACE();
|
|
|
|
|
|
|
|
if (rte_eal_process_type() == RTE_PROC_SECONDARY)
|
|
|
|
return -EPERM;
|
|
|
|
|
|
|
|
if (cryptodev->data->dev_started) {
|
|
|
|
virtio_crypto_dev_stop(cryptodev);
|
|
|
|
virtio_crypto_dev_close(cryptodev);
|
|
|
|
}
|
|
|
|
|
|
|
|
cryptodev->dev_ops = NULL;
|
|
|
|
cryptodev->enqueue_burst = NULL;
|
|
|
|
cryptodev->dequeue_burst = NULL;
|
|
|
|
|
|
|
|
/* release control queue */
|
|
|
|
virtio_crypto_queue_release(hw->cvq);
|
|
|
|
|
|
|
|
rte_free(cryptodev->data);
|
|
|
|
cryptodev->data = NULL;
|
|
|
|
|
|
|
|
VIRTIO_CRYPTO_DRV_LOG_INFO("dev_uninit completed");
|
|
|
|
|
|
|
|
return 0;
|
|
|
|
}
|
|
|
|
|
|
|
|
static int
|
|
|
|
virtio_crypto_dev_configure(struct rte_cryptodev *cryptodev,
|
|
|
|
struct rte_cryptodev_config *config __rte_unused)
|
|
|
|
{
|
|
|
|
struct virtio_crypto_hw *hw = cryptodev->data->dev_private;
|
|
|
|
|
|
|
|
PMD_INIT_FUNC_TRACE();
|
|
|
|
|
|
|
|
if (virtio_crypto_init_device(cryptodev,
|
|
|
|
VIRTIO_CRYPTO_PMD_GUEST_FEATURES) < 0)
|
|
|
|
return -1;
|
|
|
|
|
|
|
|
/* setup control queue
|
|
|
|
* [0, 1, ... ,(config->max_dataqueues - 1)] are data queues
|
|
|
|
* config->max_dataqueues is the control queue
|
|
|
|
*/
|
|
|
|
if (virtio_crypto_ctrlq_setup(cryptodev, hw->max_dataqueues) < 0) {
|
|
|
|
VIRTIO_CRYPTO_INIT_LOG_ERR("control queue setup error");
|
|
|
|
return -1;
|
|
|
|
}
|
|
|
|
virtio_crypto_ctrlq_start(cryptodev);
|
|
|
|
|
|
|
|
return 0;
|
|
|
|
}
|
|
|
|
|
|
|
|
static void
|
|
|
|
virtio_crypto_dev_stop(struct rte_cryptodev *dev)
|
|
|
|
{
|
|
|
|
struct virtio_crypto_hw *hw = dev->data->dev_private;
|
|
|
|
|
|
|
|
PMD_INIT_FUNC_TRACE();
|
|
|
|
VIRTIO_CRYPTO_DRV_LOG_DBG("virtio_dev_stop");
|
|
|
|
|
|
|
|
vtpci_cryptodev_reset(hw);
|
|
|
|
|
|
|
|
virtio_crypto_dev_free_mbufs(dev);
|
|
|
|
virtio_crypto_free_queues(dev);
|
|
|
|
|
|
|
|
dev->data->dev_started = 0;
|
|
|
|
}
|
|
|
|
|
|
|
|
static int
|
|
|
|
virtio_crypto_dev_start(struct rte_cryptodev *dev)
|
|
|
|
{
|
|
|
|
struct virtio_crypto_hw *hw = dev->data->dev_private;
|
|
|
|
|
|
|
|
if (dev->data->dev_started)
|
|
|
|
return 0;
|
|
|
|
|
|
|
|
/* Do final configuration before queue engine starts */
|
|
|
|
virtio_crypto_dataq_start(dev);
|
|
|
|
vtpci_cryptodev_reinit_complete(hw);
|
|
|
|
|
|
|
|
dev->data->dev_started = 1;
|
|
|
|
|
|
|
|
return 0;
|
|
|
|
}
|
|
|
|
|
|
|
|
static void
|
|
|
|
virtio_crypto_dev_free_mbufs(struct rte_cryptodev *dev)
|
|
|
|
{
|
|
|
|
uint32_t i;
|
|
|
|
struct virtio_crypto_hw *hw = dev->data->dev_private;
|
|
|
|
|
|
|
|
for (i = 0; i < hw->max_dataqueues; i++) {
|
|
|
|
VIRTIO_CRYPTO_INIT_LOG_DBG("Before freeing dataq[%d] used "
|
|
|
|
"and unused buf", i);
|
|
|
|
VIRTQUEUE_DUMP((struct virtqueue *)
|
|
|
|
dev->data->queue_pairs[i]);
|
|
|
|
|
|
|
|
VIRTIO_CRYPTO_INIT_LOG_DBG("queue_pairs[%d]=%p",
|
|
|
|
i, dev->data->queue_pairs[i]);
|
|
|
|
|
|
|
|
virtqueue_detatch_unused(dev->data->queue_pairs[i]);
|
|
|
|
|
|
|
|
VIRTIO_CRYPTO_INIT_LOG_DBG("After freeing dataq[%d] used and "
|
|
|
|
"unused buf", i);
|
|
|
|
VIRTQUEUE_DUMP(
|
|
|
|
(struct virtqueue *)dev->data->queue_pairs[i]);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2018-04-17 09:23:20 +00:00
|
|
|
static unsigned int
|
|
|
|
virtio_crypto_sym_get_session_private_size(
|
|
|
|
struct rte_cryptodev *dev __rte_unused)
|
|
|
|
{
|
|
|
|
PMD_INIT_FUNC_TRACE();
|
|
|
|
|
|
|
|
return RTE_ALIGN_CEIL(sizeof(struct virtio_crypto_session), 16);
|
|
|
|
}
|
|
|
|
|
|
|
|
static int
|
|
|
|
virtio_crypto_check_sym_session_paras(
|
|
|
|
struct rte_cryptodev *dev)
|
|
|
|
{
|
|
|
|
struct virtio_crypto_hw *hw;
|
|
|
|
|
|
|
|
PMD_INIT_FUNC_TRACE();
|
|
|
|
|
|
|
|
if (unlikely(dev == NULL)) {
|
|
|
|
VIRTIO_CRYPTO_SESSION_LOG_ERR("dev is NULL");
|
|
|
|
return -1;
|
|
|
|
}
|
|
|
|
if (unlikely(dev->data == NULL)) {
|
|
|
|
VIRTIO_CRYPTO_SESSION_LOG_ERR("dev->data is NULL");
|
|
|
|
return -1;
|
|
|
|
}
|
|
|
|
hw = dev->data->dev_private;
|
|
|
|
if (unlikely(hw == NULL)) {
|
|
|
|
VIRTIO_CRYPTO_SESSION_LOG_ERR("hw is NULL");
|
|
|
|
return -1;
|
|
|
|
}
|
|
|
|
if (unlikely(hw->cvq == NULL)) {
|
|
|
|
VIRTIO_CRYPTO_SESSION_LOG_ERR("vq is NULL");
|
|
|
|
return -1;
|
|
|
|
}
|
|
|
|
|
|
|
|
return 0;
|
|
|
|
}
|
|
|
|
|
|
|
|
static int
|
|
|
|
virtio_crypto_check_sym_clear_session_paras(
|
|
|
|
struct rte_cryptodev *dev,
|
|
|
|
struct rte_cryptodev_sym_session *sess)
|
|
|
|
{
|
|
|
|
PMD_INIT_FUNC_TRACE();
|
|
|
|
|
|
|
|
if (sess == NULL) {
|
|
|
|
VIRTIO_CRYPTO_SESSION_LOG_ERR("sym_session is NULL");
|
|
|
|
return -1;
|
|
|
|
}
|
|
|
|
|
|
|
|
return virtio_crypto_check_sym_session_paras(dev);
|
|
|
|
}
|
|
|
|
|
|
|
|
#define NUM_ENTRY_SYM_CLEAR_SESSION 2
|
|
|
|
|
|
|
|
static void
|
|
|
|
virtio_crypto_sym_clear_session(
|
|
|
|
struct rte_cryptodev *dev,
|
|
|
|
struct rte_cryptodev_sym_session *sess)
|
|
|
|
{
|
|
|
|
struct virtio_crypto_hw *hw;
|
|
|
|
struct virtqueue *vq;
|
|
|
|
struct virtio_crypto_session *session;
|
|
|
|
struct virtio_crypto_op_ctrl_req *ctrl;
|
|
|
|
struct vring_desc *desc;
|
|
|
|
uint8_t *status;
|
|
|
|
uint8_t needed = 1;
|
|
|
|
uint32_t head;
|
|
|
|
uint8_t *malloc_virt_addr;
|
|
|
|
uint64_t malloc_phys_addr;
|
|
|
|
uint8_t len_inhdr = sizeof(struct virtio_crypto_inhdr);
|
|
|
|
uint32_t len_op_ctrl_req = sizeof(struct virtio_crypto_op_ctrl_req);
|
|
|
|
uint32_t desc_offset = len_op_ctrl_req + len_inhdr;
|
|
|
|
|
|
|
|
PMD_INIT_FUNC_TRACE();
|
|
|
|
|
|
|
|
if (virtio_crypto_check_sym_clear_session_paras(dev, sess) < 0)
|
|
|
|
return;
|
|
|
|
|
|
|
|
hw = dev->data->dev_private;
|
|
|
|
vq = hw->cvq;
|
2018-07-05 02:08:04 +00:00
|
|
|
session = (struct virtio_crypto_session *)get_sym_session_private_data(
|
2018-04-17 09:23:20 +00:00
|
|
|
sess, cryptodev_virtio_driver_id);
|
|
|
|
if (session == NULL) {
|
|
|
|
VIRTIO_CRYPTO_SESSION_LOG_ERR("Invalid session parameter");
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
|
|
|
|
VIRTIO_CRYPTO_SESSION_LOG_INFO("vq->vq_desc_head_idx = %d, "
|
|
|
|
"vq = %p", vq->vq_desc_head_idx, vq);
|
|
|
|
|
|
|
|
if (vq->vq_free_cnt < needed) {
|
|
|
|
VIRTIO_CRYPTO_SESSION_LOG_ERR(
|
|
|
|
"vq->vq_free_cnt = %d is less than %d, "
|
|
|
|
"not enough", vq->vq_free_cnt, needed);
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
|
|
|
|
/*
|
|
|
|
* malloc memory to store information of ctrl request op,
|
|
|
|
* returned status and desc vring
|
|
|
|
*/
|
|
|
|
malloc_virt_addr = rte_malloc(NULL, len_op_ctrl_req + len_inhdr
|
|
|
|
+ NUM_ENTRY_SYM_CLEAR_SESSION
|
|
|
|
* sizeof(struct vring_desc), RTE_CACHE_LINE_SIZE);
|
|
|
|
if (malloc_virt_addr == NULL) {
|
|
|
|
VIRTIO_CRYPTO_SESSION_LOG_ERR("not enough heap room");
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
malloc_phys_addr = rte_malloc_virt2iova(malloc_virt_addr);
|
|
|
|
|
|
|
|
/* assign ctrl request op part */
|
|
|
|
ctrl = (struct virtio_crypto_op_ctrl_req *)malloc_virt_addr;
|
|
|
|
ctrl->header.opcode = VIRTIO_CRYPTO_CIPHER_DESTROY_SESSION;
|
|
|
|
/* default data virtqueue is 0 */
|
|
|
|
ctrl->header.queue_id = 0;
|
|
|
|
ctrl->u.destroy_session.session_id = session->session_id;
|
|
|
|
|
|
|
|
/* status part */
|
|
|
|
status = &(((struct virtio_crypto_inhdr *)
|
|
|
|
((uint8_t *)malloc_virt_addr + len_op_ctrl_req))->status);
|
|
|
|
*status = VIRTIO_CRYPTO_ERR;
|
|
|
|
|
|
|
|
/* indirect desc vring part */
|
|
|
|
desc = (struct vring_desc *)((uint8_t *)malloc_virt_addr
|
|
|
|
+ desc_offset);
|
|
|
|
|
|
|
|
/* ctrl request part */
|
|
|
|
desc[0].addr = malloc_phys_addr;
|
|
|
|
desc[0].len = len_op_ctrl_req;
|
|
|
|
desc[0].flags = VRING_DESC_F_NEXT;
|
|
|
|
desc[0].next = 1;
|
|
|
|
|
|
|
|
/* status part */
|
|
|
|
desc[1].addr = malloc_phys_addr + len_op_ctrl_req;
|
|
|
|
desc[1].len = len_inhdr;
|
|
|
|
desc[1].flags = VRING_DESC_F_WRITE;
|
|
|
|
|
|
|
|
/* use only a single desc entry */
|
|
|
|
head = vq->vq_desc_head_idx;
|
|
|
|
vq->vq_ring.desc[head].flags = VRING_DESC_F_INDIRECT;
|
|
|
|
vq->vq_ring.desc[head].addr = malloc_phys_addr + desc_offset;
|
|
|
|
vq->vq_ring.desc[head].len
|
|
|
|
= NUM_ENTRY_SYM_CLEAR_SESSION
|
|
|
|
* sizeof(struct vring_desc);
|
|
|
|
vq->vq_free_cnt -= needed;
|
|
|
|
|
|
|
|
vq->vq_desc_head_idx = vq->vq_ring.desc[head].next;
|
|
|
|
|
|
|
|
vq_update_avail_ring(vq, head);
|
|
|
|
vq_update_avail_idx(vq);
|
|
|
|
|
|
|
|
VIRTIO_CRYPTO_INIT_LOG_DBG("vq->vq_queue_index = %d",
|
|
|
|
vq->vq_queue_index);
|
|
|
|
|
|
|
|
virtqueue_notify(vq);
|
|
|
|
|
|
|
|
rte_rmb();
|
|
|
|
while (vq->vq_used_cons_idx == vq->vq_ring.used->idx) {
|
|
|
|
rte_rmb();
|
|
|
|
usleep(100);
|
|
|
|
}
|
|
|
|
|
|
|
|
while (vq->vq_used_cons_idx != vq->vq_ring.used->idx) {
|
|
|
|
uint32_t idx, desc_idx, used_idx;
|
|
|
|
struct vring_used_elem *uep;
|
|
|
|
|
|
|
|
used_idx = (uint32_t)(vq->vq_used_cons_idx
|
|
|
|
& (vq->vq_nentries - 1));
|
|
|
|
uep = &vq->vq_ring.used->ring[used_idx];
|
|
|
|
idx = (uint32_t) uep->id;
|
|
|
|
desc_idx = idx;
|
|
|
|
while (vq->vq_ring.desc[desc_idx].flags
|
|
|
|
& VRING_DESC_F_NEXT) {
|
|
|
|
desc_idx = vq->vq_ring.desc[desc_idx].next;
|
|
|
|
vq->vq_free_cnt++;
|
|
|
|
}
|
|
|
|
|
|
|
|
vq->vq_ring.desc[desc_idx].next = vq->vq_desc_head_idx;
|
|
|
|
vq->vq_desc_head_idx = idx;
|
|
|
|
vq->vq_used_cons_idx++;
|
|
|
|
vq->vq_free_cnt++;
|
|
|
|
}
|
|
|
|
|
|
|
|
if (*status != VIRTIO_CRYPTO_OK) {
|
|
|
|
VIRTIO_CRYPTO_SESSION_LOG_ERR("Close session failed "
|
|
|
|
"status=%"PRIu32", session_id=%"PRIu64"",
|
|
|
|
*status, session->session_id);
|
|
|
|
rte_free(malloc_virt_addr);
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
|
|
|
|
VIRTIO_CRYPTO_INIT_LOG_DBG("vq->vq_free_cnt=%d\n"
|
|
|
|
"vq->vq_desc_head_idx=%d",
|
|
|
|
vq->vq_free_cnt, vq->vq_desc_head_idx);
|
|
|
|
|
|
|
|
VIRTIO_CRYPTO_SESSION_LOG_INFO("Close session %"PRIu64" successfully ",
|
|
|
|
session->session_id);
|
|
|
|
|
2018-07-19 09:05:56 +00:00
|
|
|
memset(session, 0, sizeof(struct virtio_crypto_session));
|
|
|
|
struct rte_mempool *sess_mp = rte_mempool_from_obj(session);
|
|
|
|
set_sym_session_private_data(sess, cryptodev_virtio_driver_id, NULL);
|
|
|
|
rte_mempool_put(sess_mp, session);
|
2018-04-17 09:23:20 +00:00
|
|
|
rte_free(malloc_virt_addr);
|
|
|
|
}
|
|
|
|
|
|
|
|
static struct rte_crypto_cipher_xform *
|
|
|
|
virtio_crypto_get_cipher_xform(struct rte_crypto_sym_xform *xform)
|
|
|
|
{
|
|
|
|
do {
|
|
|
|
if (xform->type == RTE_CRYPTO_SYM_XFORM_CIPHER)
|
|
|
|
return &xform->cipher;
|
|
|
|
|
|
|
|
xform = xform->next;
|
|
|
|
} while (xform);
|
|
|
|
|
|
|
|
return NULL;
|
|
|
|
}
|
|
|
|
|
|
|
|
static struct rte_crypto_auth_xform *
|
|
|
|
virtio_crypto_get_auth_xform(struct rte_crypto_sym_xform *xform)
|
|
|
|
{
|
|
|
|
do {
|
|
|
|
if (xform->type == RTE_CRYPTO_SYM_XFORM_AUTH)
|
|
|
|
return &xform->auth;
|
|
|
|
|
|
|
|
xform = xform->next;
|
|
|
|
} while (xform);
|
|
|
|
|
|
|
|
return NULL;
|
|
|
|
}
|
|
|
|
|
|
|
|
/** Get xform chain order */
|
|
|
|
static int
|
|
|
|
virtio_crypto_get_chain_order(struct rte_crypto_sym_xform *xform)
|
|
|
|
{
|
|
|
|
if (xform == NULL)
|
|
|
|
return -1;
|
|
|
|
|
|
|
|
/* Cipher Only */
|
|
|
|
if (xform->type == RTE_CRYPTO_SYM_XFORM_CIPHER &&
|
|
|
|
xform->next == NULL)
|
|
|
|
return VIRTIO_CRYPTO_CMD_CIPHER;
|
|
|
|
|
|
|
|
/* Authentication Only */
|
|
|
|
if (xform->type == RTE_CRYPTO_SYM_XFORM_AUTH &&
|
|
|
|
xform->next == NULL)
|
|
|
|
return VIRTIO_CRYPTO_CMD_AUTH;
|
|
|
|
|
|
|
|
/* Authenticate then Cipher */
|
|
|
|
if (xform->type == RTE_CRYPTO_SYM_XFORM_AUTH &&
|
|
|
|
xform->next->type == RTE_CRYPTO_SYM_XFORM_CIPHER)
|
|
|
|
return VIRTIO_CRYPTO_CMD_HASH_CIPHER;
|
|
|
|
|
|
|
|
/* Cipher then Authenticate */
|
|
|
|
if (xform->type == RTE_CRYPTO_SYM_XFORM_CIPHER &&
|
|
|
|
xform->next->type == RTE_CRYPTO_SYM_XFORM_AUTH)
|
|
|
|
return VIRTIO_CRYPTO_CMD_CIPHER_HASH;
|
|
|
|
|
|
|
|
return -1;
|
|
|
|
}
|
|
|
|
|
|
|
|
static int
|
|
|
|
virtio_crypto_sym_pad_cipher_param(
|
|
|
|
struct virtio_crypto_cipher_session_para *para,
|
|
|
|
struct rte_crypto_cipher_xform *cipher_xform)
|
|
|
|
{
|
|
|
|
switch (cipher_xform->algo) {
|
2018-04-17 09:23:23 +00:00
|
|
|
case RTE_CRYPTO_CIPHER_AES_CBC:
|
|
|
|
para->algo = VIRTIO_CRYPTO_CIPHER_AES_CBC;
|
|
|
|
break;
|
2018-04-17 09:23:20 +00:00
|
|
|
default:
|
|
|
|
VIRTIO_CRYPTO_SESSION_LOG_ERR("Crypto: Unsupported "
|
|
|
|
"Cipher alg %u", cipher_xform->algo);
|
|
|
|
return -1;
|
|
|
|
}
|
|
|
|
|
|
|
|
para->keylen = cipher_xform->key.length;
|
|
|
|
switch (cipher_xform->op) {
|
|
|
|
case RTE_CRYPTO_CIPHER_OP_ENCRYPT:
|
|
|
|
para->op = VIRTIO_CRYPTO_OP_ENCRYPT;
|
|
|
|
break;
|
|
|
|
case RTE_CRYPTO_CIPHER_OP_DECRYPT:
|
|
|
|
para->op = VIRTIO_CRYPTO_OP_DECRYPT;
|
|
|
|
break;
|
|
|
|
default:
|
|
|
|
VIRTIO_CRYPTO_SESSION_LOG_ERR("Unsupported cipher operation "
|
|
|
|
"parameter");
|
|
|
|
return -1;
|
|
|
|
}
|
|
|
|
|
|
|
|
return 0;
|
|
|
|
}
|
|
|
|
|
|
|
|
static int
|
|
|
|
virtio_crypto_sym_pad_auth_param(
|
|
|
|
struct virtio_crypto_op_ctrl_req *ctrl,
|
|
|
|
struct rte_crypto_auth_xform *auth_xform)
|
|
|
|
{
|
|
|
|
uint32_t *algo;
|
|
|
|
struct virtio_crypto_alg_chain_session_para *para =
|
|
|
|
&(ctrl->u.sym_create_session.u.chain.para);
|
|
|
|
|
|
|
|
switch (ctrl->u.sym_create_session.u.chain.para.hash_mode) {
|
|
|
|
case VIRTIO_CRYPTO_SYM_HASH_MODE_PLAIN:
|
|
|
|
algo = &(para->u.hash_param.algo);
|
|
|
|
break;
|
|
|
|
case VIRTIO_CRYPTO_SYM_HASH_MODE_AUTH:
|
|
|
|
algo = &(para->u.mac_param.algo);
|
|
|
|
break;
|
|
|
|
default:
|
|
|
|
VIRTIO_CRYPTO_SESSION_LOG_ERR("Unsupported hash mode %u "
|
|
|
|
"specified",
|
|
|
|
ctrl->u.sym_create_session.u.chain.para.hash_mode);
|
|
|
|
return -1;
|
|
|
|
}
|
|
|
|
|
|
|
|
switch (auth_xform->algo) {
|
2018-04-17 09:23:24 +00:00
|
|
|
case RTE_CRYPTO_AUTH_SHA1_HMAC:
|
|
|
|
*algo = VIRTIO_CRYPTO_MAC_HMAC_SHA1;
|
|
|
|
break;
|
2018-04-17 09:23:20 +00:00
|
|
|
default:
|
|
|
|
VIRTIO_CRYPTO_SESSION_LOG_ERR(
|
|
|
|
"Crypto: Undefined Hash algo %u specified",
|
|
|
|
auth_xform->algo);
|
|
|
|
return -1;
|
|
|
|
}
|
|
|
|
|
|
|
|
return 0;
|
|
|
|
}
|
|
|
|
|
|
|
|
static int
|
|
|
|
virtio_crypto_sym_pad_op_ctrl_req(
|
|
|
|
struct virtio_crypto_op_ctrl_req *ctrl,
|
|
|
|
struct rte_crypto_sym_xform *xform, bool is_chainned,
|
2019-06-24 13:35:22 +00:00
|
|
|
uint8_t *cipher_key_data, uint8_t *auth_key_data,
|
2018-04-17 09:23:20 +00:00
|
|
|
struct virtio_crypto_session *session)
|
|
|
|
{
|
|
|
|
int ret;
|
|
|
|
struct rte_crypto_auth_xform *auth_xform = NULL;
|
|
|
|
struct rte_crypto_cipher_xform *cipher_xform = NULL;
|
|
|
|
|
|
|
|
/* Get cipher xform from crypto xform chain */
|
|
|
|
cipher_xform = virtio_crypto_get_cipher_xform(xform);
|
|
|
|
if (cipher_xform) {
|
2019-06-24 13:35:22 +00:00
|
|
|
if (cipher_xform->key.length > VIRTIO_CRYPTO_MAX_KEY_SIZE) {
|
|
|
|
VIRTIO_CRYPTO_SESSION_LOG_ERR(
|
|
|
|
"cipher key size cannot be longer than %u",
|
|
|
|
VIRTIO_CRYPTO_MAX_KEY_SIZE);
|
|
|
|
return -1;
|
|
|
|
}
|
2018-06-26 02:10:48 +00:00
|
|
|
if (cipher_xform->iv.length > VIRTIO_CRYPTO_MAX_IV_SIZE) {
|
|
|
|
VIRTIO_CRYPTO_SESSION_LOG_ERR(
|
|
|
|
"cipher IV size cannot be longer than %u",
|
|
|
|
VIRTIO_CRYPTO_MAX_IV_SIZE);
|
|
|
|
return -1;
|
|
|
|
}
|
2018-04-17 09:23:20 +00:00
|
|
|
if (is_chainned)
|
|
|
|
ret = virtio_crypto_sym_pad_cipher_param(
|
|
|
|
&ctrl->u.sym_create_session.u.chain.para
|
|
|
|
.cipher_param, cipher_xform);
|
|
|
|
else
|
|
|
|
ret = virtio_crypto_sym_pad_cipher_param(
|
|
|
|
&ctrl->u.sym_create_session.u.cipher.para,
|
|
|
|
cipher_xform);
|
|
|
|
|
|
|
|
if (ret < 0) {
|
|
|
|
VIRTIO_CRYPTO_SESSION_LOG_ERR(
|
|
|
|
"pad cipher parameter failed");
|
|
|
|
return -1;
|
|
|
|
}
|
|
|
|
|
2019-06-24 13:35:22 +00:00
|
|
|
memcpy(cipher_key_data, cipher_xform->key.data,
|
|
|
|
cipher_xform->key.length);
|
2018-04-17 09:23:20 +00:00
|
|
|
|
|
|
|
session->iv.offset = cipher_xform->iv.offset;
|
|
|
|
session->iv.length = cipher_xform->iv.length;
|
|
|
|
}
|
|
|
|
|
|
|
|
/* Get auth xform from crypto xform chain */
|
|
|
|
auth_xform = virtio_crypto_get_auth_xform(xform);
|
|
|
|
if (auth_xform) {
|
|
|
|
/* FIXME: support VIRTIO_CRYPTO_SYM_HASH_MODE_NESTED */
|
|
|
|
struct virtio_crypto_alg_chain_session_para *para =
|
|
|
|
&(ctrl->u.sym_create_session.u.chain.para);
|
|
|
|
if (auth_xform->key.length) {
|
2019-06-24 13:35:22 +00:00
|
|
|
if (auth_xform->key.length >
|
|
|
|
VIRTIO_CRYPTO_MAX_KEY_SIZE) {
|
|
|
|
VIRTIO_CRYPTO_SESSION_LOG_ERR(
|
|
|
|
"auth key size cannot be longer than %u",
|
|
|
|
VIRTIO_CRYPTO_MAX_KEY_SIZE);
|
|
|
|
return -1;
|
|
|
|
}
|
2018-04-17 09:23:20 +00:00
|
|
|
para->hash_mode = VIRTIO_CRYPTO_SYM_HASH_MODE_AUTH;
|
|
|
|
para->u.mac_param.auth_key_len =
|
|
|
|
(uint32_t)auth_xform->key.length;
|
|
|
|
para->u.mac_param.hash_result_len =
|
|
|
|
auth_xform->digest_length;
|
2019-06-24 13:35:22 +00:00
|
|
|
memcpy(auth_key_data, auth_xform->key.data,
|
|
|
|
auth_xform->key.length);
|
2018-04-17 09:23:20 +00:00
|
|
|
} else {
|
|
|
|
para->hash_mode = VIRTIO_CRYPTO_SYM_HASH_MODE_PLAIN;
|
|
|
|
para->u.hash_param.hash_result_len =
|
|
|
|
auth_xform->digest_length;
|
|
|
|
}
|
|
|
|
|
|
|
|
ret = virtio_crypto_sym_pad_auth_param(ctrl, auth_xform);
|
|
|
|
if (ret < 0) {
|
|
|
|
VIRTIO_CRYPTO_SESSION_LOG_ERR("pad auth parameter "
|
|
|
|
"failed");
|
|
|
|
return -1;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
return 0;
|
|
|
|
}
|
|
|
|
|
|
|
|
static int
|
|
|
|
virtio_crypto_check_sym_configure_session_paras(
|
|
|
|
struct rte_cryptodev *dev,
|
|
|
|
struct rte_crypto_sym_xform *xform,
|
|
|
|
struct rte_cryptodev_sym_session *sym_sess,
|
|
|
|
struct rte_mempool *mempool)
|
|
|
|
{
|
|
|
|
if (unlikely(xform == NULL) || unlikely(sym_sess == NULL) ||
|
|
|
|
unlikely(mempool == NULL)) {
|
|
|
|
VIRTIO_CRYPTO_SESSION_LOG_ERR("NULL pointer");
|
|
|
|
return -1;
|
|
|
|
}
|
|
|
|
|
|
|
|
if (virtio_crypto_check_sym_session_paras(dev) < 0)
|
|
|
|
return -1;
|
|
|
|
|
|
|
|
return 0;
|
|
|
|
}
|
|
|
|
|
|
|
|
static int
|
|
|
|
virtio_crypto_sym_configure_session(
|
|
|
|
struct rte_cryptodev *dev,
|
|
|
|
struct rte_crypto_sym_xform *xform,
|
|
|
|
struct rte_cryptodev_sym_session *sess,
|
|
|
|
struct rte_mempool *mempool)
|
|
|
|
{
|
|
|
|
int ret;
|
|
|
|
struct virtio_crypto_session crypto_sess;
|
|
|
|
void *session_private = &crypto_sess;
|
|
|
|
struct virtio_crypto_session *session;
|
|
|
|
struct virtio_crypto_op_ctrl_req *ctrl_req;
|
|
|
|
enum virtio_crypto_cmd_id cmd_id;
|
2019-06-24 13:35:22 +00:00
|
|
|
uint8_t cipher_key_data[VIRTIO_CRYPTO_MAX_KEY_SIZE] = {0};
|
|
|
|
uint8_t auth_key_data[VIRTIO_CRYPTO_MAX_KEY_SIZE] = {0};
|
2018-04-17 09:23:20 +00:00
|
|
|
struct virtio_crypto_hw *hw;
|
|
|
|
struct virtqueue *control_vq;
|
|
|
|
|
|
|
|
PMD_INIT_FUNC_TRACE();
|
|
|
|
|
|
|
|
ret = virtio_crypto_check_sym_configure_session_paras(dev, xform,
|
|
|
|
sess, mempool);
|
|
|
|
if (ret < 0) {
|
|
|
|
VIRTIO_CRYPTO_SESSION_LOG_ERR("Invalid parameters");
|
|
|
|
return ret;
|
|
|
|
}
|
|
|
|
|
|
|
|
if (rte_mempool_get(mempool, &session_private)) {
|
|
|
|
VIRTIO_CRYPTO_SESSION_LOG_ERR(
|
|
|
|
"Couldn't get object from session mempool");
|
|
|
|
return -ENOMEM;
|
|
|
|
}
|
|
|
|
|
|
|
|
session = (struct virtio_crypto_session *)session_private;
|
|
|
|
memset(session, 0, sizeof(struct virtio_crypto_session));
|
|
|
|
ctrl_req = &session->ctrl;
|
|
|
|
ctrl_req->header.opcode = VIRTIO_CRYPTO_CIPHER_CREATE_SESSION;
|
|
|
|
/* FIXME: support multiqueue */
|
|
|
|
ctrl_req->header.queue_id = 0;
|
|
|
|
|
|
|
|
hw = dev->data->dev_private;
|
|
|
|
control_vq = hw->cvq;
|
|
|
|
|
|
|
|
cmd_id = virtio_crypto_get_chain_order(xform);
|
|
|
|
if (cmd_id == VIRTIO_CRYPTO_CMD_CIPHER_HASH)
|
|
|
|
ctrl_req->u.sym_create_session.u.chain.para.alg_chain_order
|
|
|
|
= VIRTIO_CRYPTO_SYM_ALG_CHAIN_ORDER_CIPHER_THEN_HASH;
|
|
|
|
if (cmd_id == VIRTIO_CRYPTO_CMD_HASH_CIPHER)
|
|
|
|
ctrl_req->u.sym_create_session.u.chain.para.alg_chain_order
|
|
|
|
= VIRTIO_CRYPTO_SYM_ALG_CHAIN_ORDER_HASH_THEN_CIPHER;
|
|
|
|
|
|
|
|
switch (cmd_id) {
|
|
|
|
case VIRTIO_CRYPTO_CMD_CIPHER_HASH:
|
|
|
|
case VIRTIO_CRYPTO_CMD_HASH_CIPHER:
|
|
|
|
ctrl_req->u.sym_create_session.op_type
|
|
|
|
= VIRTIO_CRYPTO_SYM_OP_ALGORITHM_CHAINING;
|
|
|
|
|
|
|
|
ret = virtio_crypto_sym_pad_op_ctrl_req(ctrl_req,
|
2019-06-24 13:35:22 +00:00
|
|
|
xform, true, cipher_key_data, auth_key_data, session);
|
2018-04-17 09:23:20 +00:00
|
|
|
if (ret < 0) {
|
|
|
|
VIRTIO_CRYPTO_SESSION_LOG_ERR(
|
|
|
|
"padding sym op ctrl req failed");
|
|
|
|
goto error_out;
|
|
|
|
}
|
|
|
|
ret = virtio_crypto_send_command(control_vq, ctrl_req,
|
|
|
|
cipher_key_data, auth_key_data, session);
|
|
|
|
if (ret < 0) {
|
|
|
|
VIRTIO_CRYPTO_SESSION_LOG_ERR(
|
|
|
|
"create session failed: %d", ret);
|
|
|
|
goto error_out;
|
|
|
|
}
|
|
|
|
break;
|
|
|
|
case VIRTIO_CRYPTO_CMD_CIPHER:
|
|
|
|
ctrl_req->u.sym_create_session.op_type
|
|
|
|
= VIRTIO_CRYPTO_SYM_OP_CIPHER;
|
|
|
|
ret = virtio_crypto_sym_pad_op_ctrl_req(ctrl_req, xform,
|
2019-06-24 13:35:22 +00:00
|
|
|
false, cipher_key_data, auth_key_data, session);
|
2018-04-17 09:23:20 +00:00
|
|
|
if (ret < 0) {
|
|
|
|
VIRTIO_CRYPTO_SESSION_LOG_ERR(
|
|
|
|
"padding sym op ctrl req failed");
|
|
|
|
goto error_out;
|
|
|
|
}
|
|
|
|
ret = virtio_crypto_send_command(control_vq, ctrl_req,
|
|
|
|
cipher_key_data, NULL, session);
|
|
|
|
if (ret < 0) {
|
|
|
|
VIRTIO_CRYPTO_SESSION_LOG_ERR(
|
|
|
|
"create session failed: %d", ret);
|
|
|
|
goto error_out;
|
|
|
|
}
|
|
|
|
break;
|
|
|
|
default:
|
|
|
|
VIRTIO_CRYPTO_SESSION_LOG_ERR(
|
|
|
|
"Unsupported operation chain order parameter");
|
|
|
|
goto error_out;
|
|
|
|
}
|
|
|
|
|
2018-07-05 02:08:04 +00:00
|
|
|
set_sym_session_private_data(sess, dev->driver_id,
|
2018-04-17 09:23:20 +00:00
|
|
|
session_private);
|
|
|
|
|
|
|
|
return 0;
|
|
|
|
|
|
|
|
error_out:
|
|
|
|
return -1;
|
|
|
|
}
|
|
|
|
|
crypto/virtio: support basic PMD ops
This patch implements the basic operations of virtio crypto PMD, which
includes start, stop, close, information getting, queue setup and
release of the device.
The virtio crypto device has two types of queues, data queue and
control queue. It has one data queue at least and has one and only one
control queue. For example, if a virtio crypto device has N queues,
then [0, N-2] is the data queue index, N-1 is the control
queue index.
Signed-off-by: Jay Zhou <jianjay.zhou@huawei.com>
Reviewed-by: Fan Zhang <roy.fan.zhang@intel.com>
2018-04-17 09:23:19 +00:00
|
|
|
static void
|
|
|
|
virtio_crypto_dev_info_get(struct rte_cryptodev *dev,
|
|
|
|
struct rte_cryptodev_info *info)
|
|
|
|
{
|
|
|
|
struct virtio_crypto_hw *hw = dev->data->dev_private;
|
|
|
|
|
|
|
|
PMD_INIT_FUNC_TRACE();
|
|
|
|
|
|
|
|
if (info != NULL) {
|
|
|
|
info->driver_id = cryptodev_virtio_driver_id;
|
|
|
|
info->feature_flags = dev->feature_flags;
|
|
|
|
info->max_nb_queue_pairs = hw->max_dataqueues;
|
2018-07-05 02:07:58 +00:00
|
|
|
/* No limit of number of sessions */
|
|
|
|
info->sym.max_nb_sessions = 0;
|
2018-04-17 09:23:23 +00:00
|
|
|
info->capabilities = hw->virtio_dev_capabilities;
|
crypto/virtio: support basic PMD ops
This patch implements the basic operations of virtio crypto PMD, which
includes start, stop, close, information getting, queue setup and
release of the device.
The virtio crypto device has two types of queues, data queue and
control queue. It has one data queue at least and has one and only one
control queue. For example, if a virtio crypto device has N queues,
then [0, N-2] is the data queue index, N-1 is the control
queue index.
Signed-off-by: Jay Zhou <jianjay.zhou@huawei.com>
Reviewed-by: Fan Zhang <roy.fan.zhang@intel.com>
2018-04-17 09:23:19 +00:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2018-04-17 09:23:17 +00:00
|
|
|
static int
|
|
|
|
crypto_virtio_pci_probe(
|
|
|
|
struct rte_pci_driver *pci_drv __rte_unused,
|
2018-04-17 09:23:18 +00:00
|
|
|
struct rte_pci_device *pci_dev)
|
2018-04-17 09:23:17 +00:00
|
|
|
{
|
2018-04-17 09:23:18 +00:00
|
|
|
struct rte_cryptodev_pmd_init_params init_params = {
|
|
|
|
.name = "",
|
2019-09-04 13:21:51 +00:00
|
|
|
.socket_id = pci_dev->device.numa_node,
|
2018-07-05 02:07:58 +00:00
|
|
|
.private_data_size = sizeof(struct virtio_crypto_hw)
|
2018-04-17 09:23:18 +00:00
|
|
|
};
|
|
|
|
char name[RTE_CRYPTODEV_NAME_MAX_LEN];
|
|
|
|
|
|
|
|
VIRTIO_CRYPTO_DRV_LOG_DBG("Found Crypto device at %02x:%02x.%x",
|
|
|
|
pci_dev->addr.bus,
|
|
|
|
pci_dev->addr.devid,
|
|
|
|
pci_dev->addr.function);
|
|
|
|
|
|
|
|
rte_pci_device_name(&pci_dev->addr, name, sizeof(name));
|
|
|
|
|
|
|
|
return crypto_virtio_create(name, pci_dev, &init_params);
|
2018-04-17 09:23:17 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
static int
|
|
|
|
crypto_virtio_pci_remove(
|
|
|
|
struct rte_pci_device *pci_dev __rte_unused)
|
|
|
|
{
|
2018-04-17 09:23:18 +00:00
|
|
|
struct rte_cryptodev *cryptodev;
|
|
|
|
char cryptodev_name[RTE_CRYPTODEV_NAME_MAX_LEN];
|
|
|
|
|
|
|
|
if (pci_dev == NULL)
|
|
|
|
return -EINVAL;
|
|
|
|
|
|
|
|
rte_pci_device_name(&pci_dev->addr, cryptodev_name,
|
|
|
|
sizeof(cryptodev_name));
|
|
|
|
|
|
|
|
cryptodev = rte_cryptodev_pmd_get_named_dev(cryptodev_name);
|
|
|
|
if (cryptodev == NULL)
|
|
|
|
return -ENODEV;
|
|
|
|
|
crypto/virtio: support basic PMD ops
This patch implements the basic operations of virtio crypto PMD, which
includes start, stop, close, information getting, queue setup and
release of the device.
The virtio crypto device has two types of queues, data queue and
control queue. It has one data queue at least and has one and only one
control queue. For example, if a virtio crypto device has N queues,
then [0, N-2] is the data queue index, N-1 is the control
queue index.
Signed-off-by: Jay Zhou <jianjay.zhou@huawei.com>
Reviewed-by: Fan Zhang <roy.fan.zhang@intel.com>
2018-04-17 09:23:19 +00:00
|
|
|
return virtio_crypto_dev_uninit(cryptodev);
|
2018-04-17 09:23:17 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
static struct rte_pci_driver rte_virtio_crypto_driver = {
|
2018-04-17 09:23:18 +00:00
|
|
|
.id_table = pci_id_virtio_crypto_map,
|
|
|
|
.drv_flags = 0,
|
2018-04-17 09:23:17 +00:00
|
|
|
.probe = crypto_virtio_pci_probe,
|
|
|
|
.remove = crypto_virtio_pci_remove
|
|
|
|
};
|
|
|
|
|
|
|
|
static struct cryptodev_driver virtio_crypto_drv;
|
|
|
|
|
|
|
|
RTE_PMD_REGISTER_PCI(CRYPTODEV_NAME_VIRTIO_PMD, rte_virtio_crypto_driver);
|
|
|
|
RTE_PMD_REGISTER_CRYPTO_DRIVER(virtio_crypto_drv,
|
|
|
|
rte_virtio_crypto_driver.driver,
|
|
|
|
cryptodev_virtio_driver_id);
|
2020-07-01 12:33:35 +00:00
|
|
|
RTE_LOG_REGISTER(virtio_crypto_logtype_init, pmd.crypto.virtio.init, NOTICE);
|
|
|
|
RTE_LOG_REGISTER(virtio_crypto_logtype_session, pmd.crypto.virtio.session,
|
|
|
|
NOTICE);
|
|
|
|
RTE_LOG_REGISTER(virtio_crypto_logtype_rx, pmd.crypto.virtio.rx, NOTICE);
|
|
|
|
RTE_LOG_REGISTER(virtio_crypto_logtype_tx, pmd.crypto.virtio.tx, NOTICE);
|
|
|
|
RTE_LOG_REGISTER(virtio_crypto_logtype_driver, pmd.crypto.virtio.driver,
|
|
|
|
NOTICE);
|