From 2715595877bb5a7ae7372711886be173e155ad1e Mon Sep 17 00:00:00 2001 From: Kailiang Zhou Date: Wed, 8 Jun 2022 13:56:22 +0300 Subject: [PATCH 1/2] vhost/vdpa: Add config get/set msg handler For virito-blk device, vhost must support config msg. So, add support for vhost framework Signed-off-by: Kailiang Zhou --- lib/vhost/vdpa_driver.h | 3 +++ lib/vhost/vhost_user.c | 50 ++++++++++++++++++++++++++++++++++++----- lib/vhost/vhost_user.h | 16 +++++++++++++ 3 files changed, 63 insertions(+), 6 deletions(-) diff --git a/lib/vhost/vdpa_driver.h b/lib/vhost/vdpa_driver.h index 88138be34a9..2accabbbde8 100644 --- a/lib/vhost/vdpa_driver.h +++ b/lib/vhost/vdpa_driver.h @@ -72,6 +72,9 @@ struct rte_vdpa_dev_ops { /** Reset statistics of the queue */ int (*reset_stats)(struct rte_vdpa_device *dev, int qid); + /** Get the device specific config */ + int (*get_dev_config)(int vid, uint8_t *payload, uint32_t len); + /** Reserved for future extension */ void *reserved[2]; }; diff --git a/lib/vhost/vhost_user.c b/lib/vhost/vhost_user.c index 1d390677fa4..d4c7ae1e821 100644 --- a/lib/vhost/vhost_user.c +++ b/lib/vhost/vhost_user.c @@ -80,6 +80,8 @@ static const char *vhost_message_str[VHOST_USER_MAX] = { [VHOST_USER_NET_SET_MTU] = "VHOST_USER_NET_SET_MTU", [VHOST_USER_SET_SLAVE_REQ_FD] = "VHOST_USER_SET_SLAVE_REQ_FD", [VHOST_USER_IOTLB_MSG] = "VHOST_USER_IOTLB_MSG", + [VHOST_USER_GET_CONFIG] = "VHOST_USER_GET_CONFIG", + [VHOST_USER_SET_CONFIG] = "VHOST_USER_SET_CONFIG", [VHOST_USER_CRYPTO_CREATE_SESS] = "VHOST_USER_CRYPTO_CREATE_SESS", [VHOST_USER_CRYPTO_CLOSE_SESS] = "VHOST_USER_CRYPTO_CLOSE_SESS", [VHOST_USER_POSTCOPY_ADVISE] = "VHOST_USER_POSTCOPY_ADVISE", @@ -342,6 +344,27 @@ vhost_user_get_features(struct virtio_net **pdev, return RTE_VHOST_MSG_RESULT_REPLY; } +static int +vhost_user_get_config(struct virtio_net **pdev, + struct vhu_msg_context *ctx, + int main_fd __rte_unused) +{ + struct virtio_net *dev = *pdev; + struct rte_vdpa_device *vdpa_dev; + + if (validate_msg_fds(dev, ctx, 0) != 0) + return RTE_VHOST_MSG_RESULT_ERR; + + vdpa_dev = dev->vdpa_dev; + + if (vdpa_dev) + vdpa_dev->ops->get_dev_config(dev->vid, + ctx->msg.payload.cfg.region, + ctx->msg.payload.cfg.size); + + return RTE_VHOST_MSG_RESULT_REPLY; +} + /* * The queue number that we support are requested. */ @@ -1505,6 +1528,17 @@ virtio_is_ready(struct virtio_net *dev) if (!dev->nr_vring) return 0; + /* If supported, we rely on device status */ + if (dev->protocol_features & (1ULL << VHOST_USER_PROTOCOL_F_STATUS)) { + if (dev->status & VIRTIO_DEVICE_STATUS_DRIVER_OK) { + dev->flags |= VIRTIO_DEV_READY; + if (!(dev->flags & VIRTIO_DEV_RUNNING)) + VHOST_LOG_CONFIG(INFO, "(%s) virtio is now ready for processing.\n", dev->ifname); + return 1; + } else + return 0; + } + if (dev->flags & VIRTIO_DEV_BUILTIN_VIRTIO_NET) { nr_vring = VIRTIO_BUILTIN_NUM_VQS_TO_BE_READY; @@ -1519,11 +1553,6 @@ virtio_is_ready(struct virtio_net *dev) return 0; } - /* If supported, ensure the frontend is really done with config */ - if (dev->protocol_features & (1ULL << VHOST_USER_PROTOCOL_F_STATUS)) - if (!(dev->status & VIRTIO_DEVICE_STATUS_DRIVER_OK)) - return 0; - dev->flags |= VIRTIO_DEV_READY; if (!(dev->flags & VIRTIO_DEV_RUNNING)) @@ -2131,6 +2160,11 @@ vhost_user_get_vring_base(struct virtio_net **pdev, /* We have to stop the queue (virtio) if it is running. */ vhost_destroy_device_notify(dev); + /* Device is not running after get vring base, we should unmask driver_ok. + * If no, function virtio_is_ready will judge device is ready again and + * config device. So, should unmask driver_ok. + */ + dev->status &= ~VIRTIO_DEVICE_STATUS_DRIVER_OK; dev->flags &= ~VIRTIO_DEV_READY; dev->flags &= ~VIRTIO_DEV_VDPA_CONFIGURED; @@ -2782,6 +2816,8 @@ static vhost_message_handler_t vhost_message_handlers[VHOST_USER_MAX] = { [VHOST_USER_NET_SET_MTU] = vhost_user_net_set_mtu, [VHOST_USER_SET_SLAVE_REQ_FD] = vhost_user_set_req_fd, [VHOST_USER_IOTLB_MSG] = vhost_user_iotlb_msg, + [VHOST_USER_GET_CONFIG] = vhost_user_get_config, + [VHOST_USER_SET_CONFIG] = NULL, [VHOST_USER_POSTCOPY_ADVISE] = vhost_user_set_postcopy_advise, [VHOST_USER_POSTCOPY_LISTEN] = vhost_user_set_postcopy_listen, [VHOST_USER_POSTCOPY_END] = vhost_user_postcopy_end, @@ -3311,7 +3347,9 @@ int rte_vhost_host_notifier_ctrl(int vid, uint16_t qid, bool enable) return -ENODEV; if (!(dev->features & (1ULL << VIRTIO_F_VERSION_1)) || - !(dev->features & (1ULL << VHOST_USER_F_PROTOCOL_FEATURES)) || +/* !(dev->features & (1ULL << VHOST_USER_F_PROTOCOL_FEATURES)) || + * Blk device will not negotiate protocal feature, but still can use notify + */ !(dev->protocol_features & (1ULL << VHOST_USER_PROTOCOL_F_SLAVE_REQ)) || !(dev->protocol_features & diff --git a/lib/vhost/vhost_user.h b/lib/vhost/vhost_user.h index c946cc2ef48..e6745c7a81c 100644 --- a/lib/vhost/vhost_user.h +++ b/lib/vhost/vhost_user.h @@ -24,6 +24,7 @@ (1ULL << VHOST_USER_PROTOCOL_F_SLAVE_SEND_FD) | \ (1ULL << VHOST_USER_PROTOCOL_F_HOST_NOTIFIER) | \ (1ULL << VHOST_USER_PROTOCOL_F_PAGEFAULT) | \ + (1ULL << VHOST_USER_PROTOCOL_F_CONFIG) | \ (1ULL << VHOST_USER_PROTOCOL_F_STATUS)) typedef enum VhostUserRequest { @@ -50,6 +51,8 @@ typedef enum VhostUserRequest { VHOST_USER_NET_SET_MTU = 20, VHOST_USER_SET_SLAVE_REQ_FD = 21, VHOST_USER_IOTLB_MSG = 22, + VHOST_USER_GET_CONFIG = 24, + VHOST_USER_SET_CONFIG = 25, VHOST_USER_CRYPTO_CREATE_SESS = 26, VHOST_USER_CRYPTO_CLOSE_SESS = 27, VHOST_USER_POSTCOPY_ADVISE = 28, @@ -125,6 +128,18 @@ typedef struct VhostUserInflight { uint16_t queue_size; } VhostUserInflight; +#ifndef VHOST_USER_MAX_CONFIG_SIZE +#define VHOST_USER_MAX_CONFIG_SIZE 256 +#endif + +/* Get/set config msg payload */ +struct vhost_user_config { + uint32_t offset; + uint32_t size; + uint32_t flags; + uint8_t region[VHOST_USER_MAX_CONFIG_SIZE]; +}; + typedef struct VhostUserMsg { union { uint32_t master; /* a VhostUserRequest value */ @@ -148,6 +163,7 @@ typedef struct VhostUserMsg { VhostUserCryptoSessionParam crypto_session; VhostUserVringArea area; VhostUserInflight inflight; + struct vhost_user_config cfg; } payload; /* Nothing should be added after the payload */ } __rte_packed VhostUserMsg; From 94cc1f9c51d673240a3fda6d812eca47634602db Mon Sep 17 00:00:00 2001 From: Kailiang Zhou Date: Wed, 8 Jun 2022 14:16:08 +0300 Subject: [PATCH 2/2] vdpa/virtio: Add support for virtio-blk for vdpa driver Enable config_get/set feature for virtio-blk Seprate vhost feature get for blk and net device Signed-off-by: Kailiang Zhou --- drivers/common/virtio/meson.build | 2 + drivers/common/virtio/virtio.h | 2 + drivers/common/virtio/virtio_blk.h | 141 +++++++++++++++++++++++++ drivers/common/virtio/virtio_pci.c | 34 +----- drivers/common/virtio/virtio_pci.h | 1 + drivers/common/virtio/virtio_pci_blk.c | 35 ++++++ drivers/common/virtio/virtio_pci_net.c | 42 ++++++++ drivers/vdpa/virtio/meson.build | 4 +- drivers/vdpa/virtio/virtio_vdpa.c | 83 ++++++--------- drivers/vdpa/virtio/virtio_vdpa.h | 50 +++++++++ drivers/vdpa/virtio/virtio_vdpa_blk.c | 27 +++++ drivers/vdpa/virtio/virtio_vdpa_net.c | 24 +++++ examples/vdpa/main.c | 20 +++- 13 files changed, 379 insertions(+), 86 deletions(-) create mode 100644 drivers/common/virtio/virtio_blk.h create mode 100644 drivers/common/virtio/virtio_pci_blk.c create mode 100644 drivers/common/virtio/virtio_pci_net.c create mode 100644 drivers/vdpa/virtio/virtio_vdpa.h create mode 100644 drivers/vdpa/virtio/virtio_vdpa_blk.c create mode 100644 drivers/vdpa/virtio/virtio_vdpa_net.c diff --git a/drivers/common/virtio/meson.build b/drivers/common/virtio/meson.build index 8781a4091f4..259381a85cf 100644 --- a/drivers/common/virtio/meson.build +++ b/drivers/common/virtio/meson.build @@ -5,5 +5,7 @@ deps += ['pci', 'bus_pci', 'ethdev'] sources += files( 'virtio.c', 'virtio_pci.c', + 'virtio_pci_net.c', + 'virtio_pci_blk.c', ) diff --git a/drivers/common/virtio/virtio.h b/drivers/common/virtio/virtio.h index d537efe4b98..a196774c8bf 100644 --- a/drivers/common/virtio/virtio.h +++ b/drivers/common/virtio/virtio.h @@ -5,6 +5,7 @@ #ifndef _VIRTIO_H_ #define _VIRTIO_H_ #include "virtio_net.h" +#include "virtio_blk.h" /* * Do we get callbacks when the ring is completely used, @@ -107,6 +108,7 @@ struct virtio_hw { uint8_t weak_barriers; uint8_t intr_lsc; uint16_t max_queue_pairs; + uint16_t num_queues_blk; struct virtnet_ctl *cvq; struct rte_pci_device *pci_dev; const struct virtio_ops *virtio_ops; diff --git a/drivers/common/virtio/virtio_blk.h b/drivers/common/virtio/virtio_blk.h new file mode 100644 index 00000000000..c177d4f516d --- /dev/null +++ b/drivers/common/virtio/virtio_blk.h @@ -0,0 +1,141 @@ +/* SPDX-License-Identifier: BSD-3-Clause + * Copyright (c) 2022 NVIDIA Corporation & Affiliates + */ + +#ifndef _VIRTIO_BLK_H +#define _VIRTIO_BLK_H + +/* Feature bits */ +#define VIRTIO_BLK_F_SIZE_MAX 1 /* Indicates maximum segment size */ +#define VIRTIO_BLK_F_SEG_MAX 2 /* Indicates maximum # of segments */ +#define VIRTIO_BLK_F_GEOMETRY 4 /* Legacy geometry available */ +#define VIRTIO_BLK_F_RO 5 /* Disk is read-only */ +#define VIRTIO_BLK_F_BLK_SIZE 6 /* Block size of disk is available */ +#define VIRTIO_BLK_F_TOPOLOGY 10 /* Topology information is available */ +#define VIRTIO_BLK_F_MQ 12 /* support more than one vq */ +#define VIRTIO_BLK_F_DISCARD 13 /* DISCARD is supported */ +#define VIRTIO_BLK_F_WRITE_ZEROES 14 /* WRITE ZEROES is supported */ + +/* Legacy feature bits */ +#ifndef VIRTIO_BLK_NO_LEGACY +#define VIRTIO_BLK_F_BARRIER 0 /* Does host support barriers? */ +#define VIRTIO_BLK_F_SCSI 7 /* Supports scsi command passthru */ +#define VIRTIO_BLK_F_FLUSH 9 /* Flush command supported */ +#define VIRTIO_BLK_F_CONFIG_WCE 11 /* Writeback mode available in config */ +/* Old (deprecated) name for VIRTIO_BLK_F_FLUSH. */ +#define VIRTIO_BLK_F_WCE VIRTIO_BLK_F_FLUSH +#endif /* !VIRTIO_BLK_NO_LEGACY */ + +#define VIRTIO_BLK_ID_BYTES 20 /* ID string length */ + +struct virtio_blk_config { + /* The capacity (in 512-byte sectors). */ + uint64_t capacity; + /* The maximum segment size (if VIRTIO_BLK_F_SIZE_MAX) */ + uint32_t size_max; + /* The maximum number of segments (if VIRTIO_BLK_F_SEG_MAX) */ + uint32_t seg_max; + /* geometry of the device (if VIRTIO_BLK_F_GEOMETRY) */ + struct virtio_blk_geometry { + uint16_t cylinders; + uint8_t heads; + uint8_t sectors; + } geometry; + + /* block size of device (if VIRTIO_BLK_F_BLK_SIZE) */ + uint32_t blk_size; + + /* the next 4 entries are guarded by VIRTIO_BLK_F_TOPOLOGY */ + /* exponent for physical block per logical block. */ + uint8_t physical_block_exp; + /* alignment offset in logical blocks. */ + uint8_t alignment_offset; + /* minimum I/O size without performance penalty in logical blocks. */ + uint16_t min_io_size; + /* optimal sustained I/O size in logical blocks. */ + uint32_t opt_io_size; + + /* writeback mode (if VIRTIO_BLK_F_CONFIG_WCE) */ + uint8_t wce; + uint8_t unused; + + /* number of vqs, only available when VIRTIO_BLK_F_MQ is set */ + uint16_t num_queues; + + /* the next 3 entries are guarded by VIRTIO_BLK_F_DISCARD */ + /* + * The maximum discard sectors (in 512-byte sectors) for + * one segment. + */ + uint32_t max_discard_sectors; + /* + * The maximum number of discard segments in a + * discard command. + */ + uint32_t max_discard_seg; + /* Discard commands must be aligned to this number of sectors. */ + uint32_t discard_sector_alignment; + + /* the next 3 entries are guarded by VIRTIO_BLK_F_WRITE_ZEROES */ + /* + * The maximum number of write zeroes sectors (in 512-byte sectors) in + * one segment. + */ + uint32_t max_write_zeroes_sectors; + /* + * The maximum number of segments in a write zeroes + * command. + */ + uint32_t max_write_zeroes_seg; + /* + * Set if a VIRTIO_BLK_T_WRITE_ZEROES request may result in the + * deallocation of one or more of the sectors. + */ + uint8_t write_zeroes_may_unmap; + + uint8_t unused1[3]; +} __attribute__((packed)); + +/* + * Command types + * + * Usage is a bit tricky as some bits are used as flags and some are not. + * + * Rules: + * VIRTIO_BLK_T_OUT may be combined with VIRTIO_BLK_T_SCSI_CMD or + * VIRTIO_BLK_T_BARRIER. VIRTIO_BLK_T_FLUSH is a command of its own + * and may not be combined with any of the other flags. + */ + +/* These two define direction. */ +#define VIRTIO_BLK_T_IN 0 +#define VIRTIO_BLK_T_OUT 1 + +#ifndef VIRTIO_BLK_NO_LEGACY +/* This bit says it's a scsi command, not an actual read or write. */ +#define VIRTIO_BLK_T_SCSI_CMD 2 +#endif /* VIRTIO_BLK_NO_LEGACY */ + +/* Cache flush command */ +#define VIRTIO_BLK_T_FLUSH 4 + +/* Get device ID command */ +#define VIRTIO_BLK_T_GET_ID 8 + +/* Discard command */ +#define VIRTIO_BLK_T_DISCARD 11 + +/* Write zeroes command */ +#define VIRTIO_BLK_T_WRITE_ZEROES 13 + +#ifndef VIRTIO_BLK_NO_LEGACY +/* Barrier before this op. */ +#define VIRTIO_BLK_T_BARRIER 0x80000000 +#endif /* !VIRTIO_BLK_NO_LEGACY */ + +/* And this is the final byte of the write scatter-gather list. */ +#define VIRTIO_BLK_S_OK 0 +#define VIRTIO_BLK_S_IOERR 1 +#define VIRTIO_BLK_S_UNSUPP 2 +#endif /* _LINUX_VIRTIO_BLK_H */ + diff --git a/drivers/common/virtio/virtio_pci.c b/drivers/common/virtio/virtio_pci.c index e9ff016afa0..068ebe5b9e8 100644 --- a/drivers/common/virtio/virtio_pci.c +++ b/drivers/common/virtio/virtio_pci.c @@ -12,6 +12,7 @@ #include "virtio_pci.h" #include "virtio_logs.h" #include "virtqueue.h" +#include "virtio_blk.h" /* * Following macros are derived from linux/pci_regs.h, however, @@ -442,32 +443,6 @@ modern_get_queue_size(struct virtio_hw *hw, uint16_t queue_id) return rte_read16(&dev->common_cfg->queue_size); } -static uint16_t -modern_net_get_queue_num(struct virtio_hw *hw) -{ - uint16_t nr_vq; - - if (virtio_with_feature(hw, VIRTIO_NET_F_MQ) || - virtio_with_feature(hw, VIRTIO_NET_F_RSS)) { - VIRTIO_OPS(hw)->read_dev_cfg(hw, - offsetof(struct virtio_net_config, max_virtqueue_pairs), - &hw->max_queue_pairs, - sizeof(hw->max_queue_pairs)); - } else { - PMD_INIT_LOG(DEBUG, - "Neither VIRTIO_NET_F_MQ nor VIRTIO_NET_F_RSS are supported"); - hw->max_queue_pairs = 1; - } - - nr_vq = hw->max_queue_pairs * 2; - if (virtio_with_feature(hw, VIRTIO_NET_F_CTRL_VQ)) - nr_vq += 1; - - PMD_INIT_LOG(DEBUG, "Virtio net nr_vq is %d", nr_vq); - return nr_vq; - -} - static uint16_t modern_get_queue_num(struct virtio_hw *hw) { @@ -596,9 +571,8 @@ static const struct virtio_ops virtio_dev_pci_modern_ops = { .dev_close = modern_dev_close, }; -const struct virtio_dev_specific_ops virtio_net_dev_pci_modern_ops = { - .get_queue_num = modern_net_get_queue_num, -}; +extern const struct virtio_dev_specific_ops virtio_net_dev_pci_modern_ops; +extern const struct virtio_dev_specific_ops virtio_blk_dev_pci_modern_ops; static void * get_cfg_addr(struct rte_pci_device *dev, struct virtio_pci_cap *cap) @@ -777,6 +751,8 @@ virtio_pci_dev_init(struct rte_pci_device *pci_dev, struct virtio_pci_dev *dev) VIRTIO_OPS(hw) = &virtio_dev_pci_modern_ops; if (pci_dev->id.device_id == VIRTIO_PCI_MODERN_DEVICEID_NET) hw->virtio_dev_sp_ops = &virtio_net_dev_pci_modern_ops; + else if (pci_dev->id.device_id == VIRTIO_PCI_MODERN_DEVICEID_BLK) + hw->virtio_dev_sp_ops = &virtio_blk_dev_pci_modern_ops; else { rte_pci_unmap_device(pci_dev); PMD_INIT_LOG(ERR, "device id 0x%x not supported", pci_dev->id.device_id); diff --git a/drivers/common/virtio/virtio_pci.h b/drivers/common/virtio/virtio_pci.h index 7593e2e2cf5..4d2d23bc939 100644 --- a/drivers/common/virtio/virtio_pci.h +++ b/drivers/common/virtio/virtio_pci.h @@ -21,6 +21,7 @@ struct virtnet_ctl; #define VIRTIO_PCI_VENDORID 0x1AF4 #define VIRTIO_PCI_LEGACY_DEVICEID_NET 0x1000 #define VIRTIO_PCI_MODERN_DEVICEID_NET 0x1041 +#define VIRTIO_PCI_MODERN_DEVICEID_BLK 0x1042 /* VirtIO ABI version, this must match exactly. */ #define VIRTIO_PCI_ABI_VERSION 0 diff --git a/drivers/common/virtio/virtio_pci_blk.c b/drivers/common/virtio/virtio_pci_blk.c new file mode 100644 index 00000000000..05b31915fec --- /dev/null +++ b/drivers/common/virtio/virtio_pci_blk.c @@ -0,0 +1,35 @@ +/* SPDX-License-Identifier: BSD-3-Clause + * Copyright (c) 2022 NVIDIA Corporation & Affiliates + */ +#ifdef RTE_EXEC_ENV_LINUX + #include + #include +#endif + +#include +#include + +#include "virtio_pci.h" +#include "virtio_logs.h" +#include "virtqueue.h" +#include "virtio_blk.h" + +static uint16_t +modern_blk_get_queue_num(struct virtio_hw *hw) +{ + if (virtio_with_feature(hw, VIRTIO_BLK_F_MQ)) { + VIRTIO_OPS(hw)->read_dev_cfg(hw, + offsetof(struct virtio_blk_config, num_queues), + &hw->num_queues_blk, + sizeof(hw->num_queues_blk)); + } else { + hw->num_queues_blk = 1; + } + PMD_INIT_LOG(DEBUG, "Virtio blk nr_vq is %d", hw->num_queues_blk); + + return hw->num_queues_blk; +} + +const struct virtio_dev_specific_ops virtio_blk_dev_pci_modern_ops = { + .get_queue_num = modern_blk_get_queue_num, +}; diff --git a/drivers/common/virtio/virtio_pci_net.c b/drivers/common/virtio/virtio_pci_net.c new file mode 100644 index 00000000000..090860fa6da --- /dev/null +++ b/drivers/common/virtio/virtio_pci_net.c @@ -0,0 +1,42 @@ +/* SPDX-License-Identifier: BSD-3-Clause + * Copyright (c) 2022 NVIDIA Corporation & Affiliates + */ +#ifdef RTE_EXEC_ENV_LINUX + #include + #include +#endif + +#include +#include + +#include "virtio_pci.h" +#include "virtio_logs.h" +#include "virtqueue.h" + +static uint16_t +modern_net_get_queue_num(struct virtio_hw *hw) +{ + uint16_t nr_vq; + + if (virtio_with_feature(hw, VIRTIO_NET_F_MQ) || + virtio_with_feature(hw, VIRTIO_NET_F_RSS)) { + VIRTIO_OPS(hw)->read_dev_cfg(hw, + offsetof(struct virtio_net_config, max_virtqueue_pairs), + &hw->max_queue_pairs, + sizeof(hw->max_queue_pairs)); + } else { + PMD_INIT_LOG(DEBUG, + "Neither VIRTIO_NET_F_MQ nor VIRTIO_NET_F_RSS are supported"); + hw->max_queue_pairs = 1; + } + + nr_vq = hw->max_queue_pairs * 2; + + PMD_INIT_LOG(DEBUG, "Virtio net nr_vq is %d", nr_vq); + return nr_vq; + +} + +const struct virtio_dev_specific_ops virtio_net_dev_pci_modern_ops = { + .get_queue_num = modern_net_get_queue_num, +}; diff --git a/drivers/vdpa/virtio/meson.build b/drivers/vdpa/virtio/meson.build index 11fec9894e7..f218d3c3786 100644 --- a/drivers/vdpa/virtio/meson.build +++ b/drivers/vdpa/virtio/meson.build @@ -1,5 +1,5 @@ #SPDX-License-Identifier: BSD-3-Clause #Copyright (c) 2022 NVIDIA Corporation & Affiliates -deps += 'common_virtio' -sources = files('virtio_vdpa.c') +deps += ['common_virtio'] +sources = files('virtio_vdpa.c','virtio_vdpa_net.c','virtio_vdpa_blk.c') diff --git a/drivers/vdpa/virtio/virtio_vdpa.c b/drivers/vdpa/virtio/virtio_vdpa.c index 63d77698238..feebf0c00f3 100644 --- a/drivers/vdpa/virtio/virtio_vdpa.c +++ b/drivers/vdpa/virtio/virtio_vdpa.c @@ -11,63 +11,19 @@ #include #include - -enum { - VIRTIO_VDPA_NOTIFIER_STATE_DISABLED, - VIRTIO_VDPA_NOTIFIER_STATE_ENABLED, - VIRTIO_VDPA_NOTIFIER_STATE_ERR -}; - -struct virtio_vdpa_vring_info { - uint64_t desc; - uint64_t avail; - uint64_t used; - uint16_t size; - uint16_t index; - uint8_t notifier_state; - bool enable; - struct rte_intr_handle *intr_handle; - struct virtio_vdpa_priv *priv; -}; - -#define VIRTIO_VDPA_DRIVER_NAME vdpa_virtio -#define VIRTIO_VDPA_PROTOCOL_FEATURES \ - ((1ULL << VHOST_USER_PROTOCOL_F_SLAVE_REQ) | \ - (1ULL << VHOST_USER_PROTOCOL_F_SLAVE_SEND_FD) | \ - (1ULL << VHOST_USER_PROTOCOL_F_HOST_NOTIFIER) | \ - (1ULL << VHOST_USER_PROTOCOL_F_STATUS) | \ - (1ULL << VHOST_USER_PROTOCOL_F_MQ) | \ - (1ULL << VHOST_USER_PROTOCOL_F_REPLY_ACK)) -/* (1ULL << VHOST_USER_PROTOCOL_F_LOG_SHMFD) | \ - * (1ULL << VHOST_USER_PROTOCOL_F_MQ) | \ - * (1ULL << VHOST_USER_PROTOCOL_F_NET_MTU) | \ - * (1ULL << VHOST_USER_PROTOCOL_F_STATUS)) - */ -struct virtio_vdpa_priv { - TAILQ_ENTRY(virtio_vdpa_priv) next; - struct rte_pci_device *pdev; - struct rte_vdpa_device *vdev; - struct virtio_pci_dev *vpdev; - int vfio_container_fd; - int vfio_group_fd; - int vfio_dev_fd; - int vid; - int nvec; - uint64_t guest_features; - struct virtio_vdpa_vring_info **vrings; - uint16_t nr_virtqs; /* Number of vq vhost enabled */ - uint16_t hw_nr_virtqs; /* Number of vq device supported */ - bool configured; -}; - -#define VIRTIO_VDPA_INTR_RETRIES_USEC 1000 -#define VIRTIO_VDPA_INTR_RETRIES 256 +#include "virtio_vdpa.h" RTE_LOG_REGISTER(virtio_vdpa_logtype, pmd.vdpa.virtio, NOTICE); #define DRV_LOG(level, fmt, args...) \ rte_log(RTE_LOG_ ## level, virtio_vdpa_logtype, \ "VIRTIO VDPA %s(): " fmt "\n", __func__, ##args) +#define VIRTIO_VDPA_INTR_RETRIES_USEC 1000 +#define VIRTIO_VDPA_INTR_RETRIES 256 + +extern struct virtio_vdpa_device_callback virtio_vdpa_blk_callback; +extern struct virtio_vdpa_device_callback virtio_vdpa_net_callback; + static TAILQ_HEAD(virtio_vdpa_privs, virtio_vdpa_priv) virtio_priv_list = TAILQ_HEAD_INITIALIZER(virtio_priv_list); static pthread_mutex_t priv_list_lock = PTHREAD_MUTEX_INITIALIZER; @@ -138,7 +94,8 @@ virtio_vdpa_protocol_features_get(struct rte_vdpa_device *vdev, DRV_LOG(ERR, "Invalid vDPA device: %s", vdev->device->name); return -ENODEV; } - *features = VIRTIO_VDPA_PROTOCOL_FEATURES; + + priv->dev_ops->vhost_feature_get(features); return 0; } @@ -747,6 +704,21 @@ virtio_vdpa_notify_area_get(int vid, int qid, uint64_t *offset, uint64_t *size) vid, qid, *offset, *size); return 0; } +static int +virtio_vdpa_dev_config_get(int vid, uint8_t *payload, uint32_t len) +{ + struct rte_vdpa_device *vdev = rte_vhost_get_vdpa_device(vid); + struct virtio_vdpa_priv *priv = virtio_vdpa_find_priv_resource_by_vdev(vdev); + + if (priv == NULL) { + DRV_LOG(ERR, "Invalid vDPA device: %s.", vdev->device->name); + return -EINVAL; + } + virtio_pci_dev_config_read(priv->vpdev, 0, payload, len); + DRV_LOG(INFO, "vDPA device %d get config len %d", vid, len); + + return 0; +} static struct rte_vdpa_dev_ops virtio_vdpa_ops = { .get_queue_num = virtio_vdpa_vqs_max_get, @@ -763,6 +735,7 @@ static struct rte_vdpa_dev_ops virtio_vdpa_ops = { .get_stats_names = NULL, .get_stats = NULL, .reset_stats = NULL, + .get_dev_config = virtio_vdpa_dev_config_get, }; static int vdpa_check_handler(__rte_unused const char *key, @@ -935,6 +908,11 @@ virtio_vdpa_dev_probe(struct rte_pci_driver *pci_drv __rte_unused, goto error; } + if (priv->pdev->id.device_id == VIRTIO_PCI_MODERN_DEVICEID_NET) + priv->dev_ops = &virtio_vdpa_net_callback; + else if (priv->pdev->id.device_id == VIRTIO_PCI_MODERN_DEVICEID_BLK) + priv->dev_ops = &virtio_vdpa_blk_callback; + priv->vfio_dev_fd = rte_intr_dev_fd_get(pci_dev->intr_handle); if (priv->vfio_dev_fd < 0) { DRV_LOG(ERR, "%s failed to get vfio dev fd", devname); @@ -1027,6 +1005,7 @@ virtio_vdpa_dev_remove(struct rte_pci_device *pci_dev) */ static const struct rte_pci_id pci_id_virtio_map[] = { { RTE_PCI_DEVICE(VIRTIO_PCI_VENDORID, VIRTIO_PCI_MODERN_DEVICEID_NET) }, + { RTE_PCI_DEVICE(VIRTIO_PCI_VENDORID, VIRTIO_PCI_MODERN_DEVICEID_BLK) }, { .vendor_id = 0, /* sentinel */ }, }; diff --git a/drivers/vdpa/virtio/virtio_vdpa.h b/drivers/vdpa/virtio/virtio_vdpa.h new file mode 100644 index 00000000000..c6af12b328d --- /dev/null +++ b/drivers/vdpa/virtio/virtio_vdpa.h @@ -0,0 +1,50 @@ +/* SPDX-License-Identifier: BSD-3-Clause + * Copyright (c) 2022 NVIDIA Corporation & Affiliates + */ + +#ifndef _VIRTIO_VDPA_H_ +#define _VIRTIO_VDPA_H_ + +enum { + VIRTIO_VDPA_NOTIFIER_STATE_DISABLED, + VIRTIO_VDPA_NOTIFIER_STATE_ENABLED, + VIRTIO_VDPA_NOTIFIER_STATE_ERR +}; + +struct virtio_vdpa_vring_info { + uint64_t desc; + uint64_t avail; + uint64_t used; + uint16_t size; + uint16_t index; + uint8_t notifier_state; + bool enable; + struct rte_intr_handle *intr_handle; + struct virtio_vdpa_priv *priv; +}; + +#define VIRTIO_VDPA_DRIVER_NAME vdpa_virtio + +struct virtio_vdpa_device_callback { + void (*vhost_feature_get)(uint64_t *features); +}; + +struct virtio_vdpa_priv { + TAILQ_ENTRY(virtio_vdpa_priv) next; + struct rte_pci_device *pdev; + struct rte_vdpa_device *vdev; + struct virtio_pci_dev *vpdev; + const struct virtio_vdpa_device_callback *dev_ops; + int vfio_container_fd; + int vfio_group_fd; + int vfio_dev_fd; + int vid; + int nvec; + uint64_t guest_features; + struct virtio_vdpa_vring_info **vrings; + uint16_t nr_virtqs; /* Number of vq vhost enabled */ + uint16_t hw_nr_virtqs; /* Number of vq device supported */ + bool configured; +}; + +#endif /* _VIRTIO_VDPA_H_ */ diff --git a/drivers/vdpa/virtio/virtio_vdpa_blk.c b/drivers/vdpa/virtio/virtio_vdpa_blk.c new file mode 100644 index 00000000000..1829a1e10b0 --- /dev/null +++ b/drivers/vdpa/virtio/virtio_vdpa_blk.c @@ -0,0 +1,27 @@ +/* SPDX-License-Identifier: BSD-3-Clause + * Copyright (c) 2022 NVIDIA Corporation & Affiliates + */ +#include +#include +#include +#include "virtio_vdpa.h" + +#define VIRTIO_VDPA_BLK_PROTOCOL_FEATURES \ + ((1ULL << VHOST_USER_PROTOCOL_F_SLAVE_REQ) | \ + (1ULL << VHOST_USER_PROTOCOL_F_SLAVE_SEND_FD) | \ + (1ULL << VHOST_USER_PROTOCOL_F_CONFIG) | \ + (1ULL << VHOST_USER_PROTOCOL_F_STATUS) | \ + (1ULL << VHOST_USER_PROTOCOL_F_MQ) | \ + (1ULL << VHOST_USER_PROTOCOL_F_HOST_NOTIFIER) | \ + (1ULL << VHOST_USER_PROTOCOL_F_REPLY_ACK)) + +static void +virtio_vdpa_blk_vhost_feature_get(uint64_t *features) +{ + *features = VIRTIO_VDPA_BLK_PROTOCOL_FEATURES; +} + +struct virtio_vdpa_device_callback virtio_vdpa_blk_callback = { + .vhost_feature_get = virtio_vdpa_blk_vhost_feature_get, +}; + diff --git a/drivers/vdpa/virtio/virtio_vdpa_net.c b/drivers/vdpa/virtio/virtio_vdpa_net.c new file mode 100644 index 00000000000..a01a133e3f1 --- /dev/null +++ b/drivers/vdpa/virtio/virtio_vdpa_net.c @@ -0,0 +1,24 @@ +/* SPDX-License-Identifier: BSD-3-Clause + * Copyright (c) 2022 NVIDIA Corporation & Affiliates + */ +#include +#include +#include "virtio_vdpa.h" + +#define VIRTIO_VDPA_NET_PROTOCOL_FEATURES \ + ((1ULL << VHOST_USER_PROTOCOL_F_SLAVE_REQ) | \ + (1ULL << VHOST_USER_PROTOCOL_F_SLAVE_SEND_FD) | \ + (1ULL << VHOST_USER_PROTOCOL_F_HOST_NOTIFIER) | \ + (1ULL << VHOST_USER_PROTOCOL_F_STATUS) | \ + (1ULL << VHOST_USER_PROTOCOL_F_MQ) | \ + (1ULL << VHOST_USER_PROTOCOL_F_REPLY_ACK)) + +static void +virtio_vdpa_net_vhost_feature_get(uint64_t *features) +{ + *features = VIRTIO_VDPA_NET_PROTOCOL_FEATURES; +} +struct virtio_vdpa_device_callback virtio_vdpa_net_callback = { + .vhost_feature_get = virtio_vdpa_net_vhost_feature_get, +}; + diff --git a/examples/vdpa/main.c b/examples/vdpa/main.c index 5ab07655aed..1dd2039dbcd 100644 --- a/examples/vdpa/main.c +++ b/examples/vdpa/main.c @@ -163,6 +163,7 @@ start_vdpa(struct vdpa_port *vport) { int ret; char *socket_path = vport->ifname; + uint64_t features; if (client_mode) vport->flags |= RTE_VHOST_USER_CLIENT; @@ -174,20 +175,33 @@ start_vdpa(struct vdpa_port *vport) return -1; } ret = rte_vhost_driver_register(socket_path, vport->flags); - if (ret != 0) + if (ret) rte_exit(EXIT_FAILURE, "register driver failed: %s\n", socket_path); + /* vdpa device should get feature from device and not use builtin_net_driver */ + ret = rte_vdpa_get_features(vport->dev, &features); + if (ret) + rte_exit(EXIT_FAILURE, + "get vdpa feature fail: %s\n", + socket_path); + + ret = rte_vhost_driver_set_features(socket_path, features); + if (ret) + rte_exit(EXIT_FAILURE, + "set feature failed: %s\n", + socket_path); + ret = rte_vhost_driver_callback_register(socket_path, &vdpa_sample_devops); - if (ret != 0) + if (ret) rte_exit(EXIT_FAILURE, "register driver ops failed: %s\n", socket_path); ret = rte_vhost_driver_attach_vdpa_device(socket_path, vport->dev); - if (ret != 0) + if (ret) rte_exit(EXIT_FAILURE, "attach vdpa device failed: %s\n", socket_path);