v4:
- added support for iproute2 vdpa management tool in vdpa_sim_blk
- removed get/set_config patches
- 'vdpa: add return value to get_config/set_config callbacks'
- 'vhost/vdpa: remove vhost_vdpa_config_validate()'
- added get_config_size() patches
- 'vdpa: add get_config_size callback in vdpa_config_ops'
- 'vhost/vdpa: use get_config_size callback in vhost_vdpa_config_validate()'
v3: https://lore.kernel.org/lkml/[email protected]/
v2: https://lore.kernel.org/lkml/[email protected]/
v1: https://lore.kernel.org/lkml/[email protected]/
This series is the second part of the v1 linked above. The first part with
refactoring of vdpa_sim has already been merged.
The patches are based on Max Gurtovoy's work and extend the block simulator to
have a ramdisk behaviour.
As mentioned in the v1 there was 2 issues and I fixed them in this series:
1. The identical mapping in the IOMMU used until now in vdpa_sim created issues
when mapping different virtual pages with the same physical address.
Fixed by patch "vdpa_sim: use iova module to allocate IOVA addresses"
2. There was a race accessing the IOMMU between the vdpasim_blk_work() and the
device driver that map/unmap DMA regions. Fixed by patch "vringh: add
'iotlb_lock' to synchronize iotlb accesses"
I used the Xie's patch coming from VDUSE series to allow vhost-vdpa to use
block devices, and I added get_config_size() callback to allow any device
in vhost-vdpa.
The series also includes small fixes for vringh, vdpa, and vdpa_sim that I
discovered while implementing and testing the block simulator.
Thanks for your feedback,
Stefano
Max Gurtovoy (1):
vdpa: add vdpa simulator for block device
Stefano Garzarella (12):
vdpa_sim: use iova module to allocate IOVA addresses
vringh: add 'iotlb_lock' to synchronize iotlb accesses
vringh: reset kiov 'consumed' field in __vringh_iov()
vringh: explain more about cleaning riov and wiov
vringh: implement vringh_kiov_advance()
vringh: add vringh_kiov_length() helper
vdpa_sim: cleanup kiovs in vdpasim_free()
vdpa: add get_config_size callback in vdpa_config_ops
vhost/vdpa: use get_config_size callback in
vhost_vdpa_config_validate()
vdpa_sim_blk: implement ramdisk behaviour
vdpa_sim_blk: handle VIRTIO_BLK_T_GET_ID
vdpa_sim_blk: add support for vdpa management tool
Xie Yongji (1):
vhost/vdpa: Remove the restriction that only supports virtio-net
devices
drivers/vdpa/vdpa_sim/vdpa_sim.h | 2 +
include/linux/vdpa.h | 4 +
include/linux/vringh.h | 19 +-
drivers/vdpa/ifcvf/ifcvf_main.c | 6 +
drivers/vdpa/mlx5/net/mlx5_vnet.c | 6 +
drivers/vdpa/vdpa_sim/vdpa_sim.c | 127 ++++++----
drivers/vdpa/vdpa_sim/vdpa_sim_blk.c | 338 +++++++++++++++++++++++++++
drivers/vdpa/virtio_pci/vp_vdpa.c | 8 +
drivers/vhost/vdpa.c | 15 +-
drivers/vhost/vringh.c | 69 ++++--
drivers/vdpa/Kconfig | 8 +
drivers/vdpa/vdpa_sim/Makefile | 1 +
12 files changed, 529 insertions(+), 74 deletions(-)
create mode 100644 drivers/vdpa/vdpa_sim/vdpa_sim_blk.c
--
2.30.2
Usually iotlb accesses are synchronized with a spinlock.
Let's request it as a new parameter in vringh_set_iotlb() and
hold it when we navigate the iotlb in iotlb_translate() to avoid
race conditions with any new additions/deletions of ranges from
the ioltb.
Acked-by: Jason Wang <[email protected]>
Signed-off-by: Stefano Garzarella <[email protected]>
---
include/linux/vringh.h | 6 +++++-
drivers/vdpa/vdpa_sim/vdpa_sim.c | 3 ++-
drivers/vhost/vringh.c | 9 ++++++++-
3 files changed, 15 insertions(+), 3 deletions(-)
diff --git a/include/linux/vringh.h b/include/linux/vringh.h
index 59bd50f99291..9c077863c8f6 100644
--- a/include/linux/vringh.h
+++ b/include/linux/vringh.h
@@ -46,6 +46,9 @@ struct vringh {
/* IOTLB for this vring */
struct vhost_iotlb *iotlb;
+ /* spinlock to synchronize IOTLB accesses */
+ spinlock_t *iotlb_lock;
+
/* The function to call to notify the guest about added buffers */
void (*notify)(struct vringh *);
};
@@ -258,7 +261,8 @@ static inline __virtio64 cpu_to_vringh64(const struct vringh *vrh, u64 val)
#if IS_REACHABLE(CONFIG_VHOST_IOTLB)
-void vringh_set_iotlb(struct vringh *vrh, struct vhost_iotlb *iotlb);
+void vringh_set_iotlb(struct vringh *vrh, struct vhost_iotlb *iotlb,
+ spinlock_t *iotlb_lock);
int vringh_init_iotlb(struct vringh *vrh, u64 features,
unsigned int num, bool weak_barriers,
diff --git a/drivers/vdpa/vdpa_sim/vdpa_sim.c b/drivers/vdpa/vdpa_sim/vdpa_sim.c
index fc2ec9599753..a92c08880098 100644
--- a/drivers/vdpa/vdpa_sim/vdpa_sim.c
+++ b/drivers/vdpa/vdpa_sim/vdpa_sim.c
@@ -284,7 +284,8 @@ struct vdpasim *vdpasim_create(struct vdpasim_dev_attr *dev_attr)
goto err_iommu;
for (i = 0; i < dev_attr->nvqs; i++)
- vringh_set_iotlb(&vdpasim->vqs[i].vring, vdpasim->iommu);
+ vringh_set_iotlb(&vdpasim->vqs[i].vring, vdpasim->iommu,
+ &vdpasim->iommu_lock);
ret = iova_cache_get();
if (ret)
diff --git a/drivers/vhost/vringh.c b/drivers/vhost/vringh.c
index 85d85faba058..f68122705719 100644
--- a/drivers/vhost/vringh.c
+++ b/drivers/vhost/vringh.c
@@ -1074,6 +1074,8 @@ static int iotlb_translate(const struct vringh *vrh,
int ret = 0;
u64 s = 0;
+ spin_lock(vrh->iotlb_lock);
+
while (len > s) {
u64 size, pa, pfn;
@@ -1103,6 +1105,8 @@ static int iotlb_translate(const struct vringh *vrh,
++ret;
}
+ spin_unlock(vrh->iotlb_lock);
+
return ret;
}
@@ -1262,10 +1266,13 @@ EXPORT_SYMBOL(vringh_init_iotlb);
* vringh_set_iotlb - initialize a vringh for a ring with IOTLB.
* @vrh: the vring
* @iotlb: iotlb associated with this vring
+ * @iotlb_lock: spinlock to synchronize the iotlb accesses
*/
-void vringh_set_iotlb(struct vringh *vrh, struct vhost_iotlb *iotlb)
+void vringh_set_iotlb(struct vringh *vrh, struct vhost_iotlb *iotlb,
+ spinlock_t *iotlb_lock)
{
vrh->iotlb = iotlb;
+ vrh->iotlb_lock = iotlb_lock;
}
EXPORT_SYMBOL(vringh_set_iotlb);
--
2.30.2
riov and wiov can be reused with subsequent calls of vringh_getdesc_*().
Let's add a paragraph in the documentation of these functions to better
explain when riov and wiov need to be cleaned up.
Acked-by: Jason Wang <[email protected]>
Signed-off-by: Stefano Garzarella <[email protected]>
---
drivers/vhost/vringh.c | 15 ++++++++++++---
1 file changed, 12 insertions(+), 3 deletions(-)
diff --git a/drivers/vhost/vringh.c b/drivers/vhost/vringh.c
index bee63d68201a..2a88e087afd8 100644
--- a/drivers/vhost/vringh.c
+++ b/drivers/vhost/vringh.c
@@ -662,7 +662,10 @@ EXPORT_SYMBOL(vringh_init_user);
* *head will be vrh->vring.num. You may be able to ignore an invalid
* descriptor, but there's not much you can do with an invalid ring.
*
- * Note that you may need to clean up riov and wiov, even on error!
+ * Note that you can reuse riov and wiov with subsequent calls. Content is
+ * overwritten and memory reallocated if more space is needed.
+ * When you don't have to use riov and wiov anymore, you should clean up them
+ * calling vringh_iov_cleanup() to release the memory, even on error!
*/
int vringh_getdesc_user(struct vringh *vrh,
struct vringh_iov *riov,
@@ -932,7 +935,10 @@ EXPORT_SYMBOL(vringh_init_kern);
* *head will be vrh->vring.num. You may be able to ignore an invalid
* descriptor, but there's not much you can do with an invalid ring.
*
- * Note that you may need to clean up riov and wiov, even on error!
+ * Note that you can reuse riov and wiov with subsequent calls. Content is
+ * overwritten and memory reallocated if more space is needed.
+ * When you don't have to use riov and wiov anymore, you should clean up them
+ * calling vringh_kiov_cleanup() to release the memory, even on error!
*/
int vringh_getdesc_kern(struct vringh *vrh,
struct vringh_kiov *riov,
@@ -1292,7 +1298,10 @@ EXPORT_SYMBOL(vringh_set_iotlb);
* *head will be vrh->vring.num. You may be able to ignore an invalid
* descriptor, but there's not much you can do with an invalid ring.
*
- * Note that you may need to clean up riov and wiov, even on error!
+ * Note that you can reuse riov and wiov with subsequent calls. Content is
+ * overwritten and memory reallocated if more space is needed.
+ * When you don't have to use riov and wiov anymore, you should clean up them
+ * calling vringh_kiov_cleanup() to release the memory, even on error!
*/
int vringh_getdesc_iotlb(struct vringh *vrh,
struct vringh_kiov *riov,
--
2.30.2
vringh_getdesc_iotlb() allocates memory to store the kvec, that
is freed with vringh_kiov_cleanup().
vringh_getdesc_iotlb() is able to reuse a kvec previously allocated,
so in order to avoid to allocate the kvec for each request, we are
not calling vringh_kiov_cleanup() when we finished to handle a
request, but we should call it when we free the entire device.
Acked-by: Jason Wang <[email protected]>
Signed-off-by: Stefano Garzarella <[email protected]>
---
drivers/vdpa/vdpa_sim/vdpa_sim.c | 7 +++++++
1 file changed, 7 insertions(+)
diff --git a/drivers/vdpa/vdpa_sim/vdpa_sim.c b/drivers/vdpa/vdpa_sim/vdpa_sim.c
index a92c08880098..14dc2d3d983e 100644
--- a/drivers/vdpa/vdpa_sim/vdpa_sim.c
+++ b/drivers/vdpa/vdpa_sim/vdpa_sim.c
@@ -562,8 +562,15 @@ static int vdpasim_dma_unmap(struct vdpa_device *vdpa, u64 iova, u64 size)
static void vdpasim_free(struct vdpa_device *vdpa)
{
struct vdpasim *vdpasim = vdpa_to_sim(vdpa);
+ int i;
cancel_work_sync(&vdpasim->work);
+
+ for (i = 0; i < vdpasim->dev_attr.nvqs; i++) {
+ vringh_kiov_cleanup(&vdpasim->vqs[i].out_iov);
+ vringh_kiov_cleanup(&vdpasim->vqs[i].in_iov);
+ }
+
put_iova_domain(&vdpasim->iova);
iova_cache_put();
kvfree(vdpasim->buffer);
--
2.30.2
This new helper returns the total number of bytes covered by
a vringh_kiov.
Suggested-by: Jason Wang <[email protected]>
Acked-by: Jason Wang <[email protected]>
Signed-off-by: Stefano Garzarella <[email protected]>
---
include/linux/vringh.h | 11 +++++++++++
1 file changed, 11 insertions(+)
diff --git a/include/linux/vringh.h b/include/linux/vringh.h
index 755211ebd195..84db7b8f912f 100644
--- a/include/linux/vringh.h
+++ b/include/linux/vringh.h
@@ -199,6 +199,17 @@ static inline void vringh_kiov_cleanup(struct vringh_kiov *kiov)
kiov->iov = NULL;
}
+static inline size_t vringh_kiov_length(struct vringh_kiov *kiov)
+{
+ size_t len = 0;
+ int i;
+
+ for (i = kiov->i; i < kiov->used; i++)
+ len += kiov->iov[i].iov_len;
+
+ return len;
+}
+
void vringh_kiov_advance(struct vringh_kiov *kiov, size_t len);
int vringh_getdesc_kern(struct vringh *vrh,
--
2.30.2
From: Xie Yongji <[email protected]>
Since the config checks are done by the vDPA drivers, we can remove the
virtio-net restriction and we should be able to support all kinds of
virtio devices.
<linux/virtio_net.h> is not needed anymore, but we need to include
<linux/slab.h> to avoid compilation failures.
Signed-off-by: Xie Yongji <[email protected]>
Signed-off-by: Stefano Garzarella <[email protected]>
---
drivers/vhost/vdpa.c | 6 +-----
1 file changed, 1 insertion(+), 5 deletions(-)
diff --git a/drivers/vhost/vdpa.c b/drivers/vhost/vdpa.c
index 7ae4080e57d8..850ed4b62942 100644
--- a/drivers/vhost/vdpa.c
+++ b/drivers/vhost/vdpa.c
@@ -16,12 +16,12 @@
#include <linux/cdev.h>
#include <linux/device.h>
#include <linux/mm.h>
+#include <linux/slab.h>
#include <linux/iommu.h>
#include <linux/uuid.h>
#include <linux/vdpa.h>
#include <linux/nospec.h>
#include <linux/vhost.h>
-#include <linux/virtio_net.h>
#include "vhost.h"
@@ -1018,10 +1018,6 @@ static int vhost_vdpa_probe(struct vdpa_device *vdpa)
int minor;
int r;
- /* Currently, we only accept the network devices. */
- if (ops->get_device_id(vdpa) != VIRTIO_ID_NET)
- return -ENOTSUPP;
-
v = kzalloc(sizeof(*v), GFP_KERNEL | __GFP_RETRY_MAYFAIL);
if (!v)
return -ENOMEM;
--
2.30.2
__vringh_iov() overwrites the contents of riov and wiov, in fact it
resets the 'i' and 'used' fields, but also the 'consumed' field should
be reset to avoid an inconsistent state.
Acked-by: Jason Wang <[email protected]>
Signed-off-by: Stefano Garzarella <[email protected]>
---
drivers/vhost/vringh.c | 4 ++--
1 file changed, 2 insertions(+), 2 deletions(-)
diff --git a/drivers/vhost/vringh.c b/drivers/vhost/vringh.c
index f68122705719..bee63d68201a 100644
--- a/drivers/vhost/vringh.c
+++ b/drivers/vhost/vringh.c
@@ -290,9 +290,9 @@ __vringh_iov(struct vringh *vrh, u16 i,
return -EINVAL;
if (riov)
- riov->i = riov->used = 0;
+ riov->i = riov->used = riov->consumed = 0;
if (wiov)
- wiov->i = wiov->used = 0;
+ wiov->i = wiov->used = wiov->consumed = 0;
for (;;) {
void *addr;
--
2.30.2
Let's use the new 'get_config_size()' callback available instead of
using the 'virtio_id' to get the size of the device config space.
Signed-off-by: Stefano Garzarella <[email protected]>
---
drivers/vhost/vdpa.c | 9 ++-------
1 file changed, 2 insertions(+), 7 deletions(-)
diff --git a/drivers/vhost/vdpa.c b/drivers/vhost/vdpa.c
index e0a27e336293..7ae4080e57d8 100644
--- a/drivers/vhost/vdpa.c
+++ b/drivers/vhost/vdpa.c
@@ -188,13 +188,8 @@ static long vhost_vdpa_set_status(struct vhost_vdpa *v, u8 __user *statusp)
static int vhost_vdpa_config_validate(struct vhost_vdpa *v,
struct vhost_vdpa_config *c)
{
- long size = 0;
-
- switch (v->virtio_id) {
- case VIRTIO_ID_NET:
- size = sizeof(struct virtio_net_config);
- break;
- }
+ struct vdpa_device *vdpa = v->vdpa;
+ long size = vdpa->config->get_config_size(vdpa);
if (c->len == 0)
return -EINVAL;
--
2.30.2
Handle VIRTIO_BLK_T_GET_ID request, always answering the
"vdpa_blk_sim" string.
Acked-by: Jason Wang <[email protected]>
Reviewed-by: Stefan Hajnoczi <[email protected]>
Signed-off-by: Stefano Garzarella <[email protected]>
---
v2:
- made 'vdpasim_blk_id' static [Jason]
---
drivers/vdpa/vdpa_sim/vdpa_sim_blk.c | 15 +++++++++++++++
1 file changed, 15 insertions(+)
diff --git a/drivers/vdpa/vdpa_sim/vdpa_sim_blk.c b/drivers/vdpa/vdpa_sim/vdpa_sim_blk.c
index a31964e3e5a4..643ae3bc62c0 100644
--- a/drivers/vdpa/vdpa_sim/vdpa_sim_blk.c
+++ b/drivers/vdpa/vdpa_sim/vdpa_sim_blk.c
@@ -38,6 +38,7 @@
#define VDPASIM_BLK_VQ_NUM 1
static struct vdpasim *vdpasim_blk_dev;
+static char vdpasim_blk_id[VIRTIO_BLK_ID_BYTES] = "vdpa_blk_sim";
static bool vdpasim_blk_check_range(u64 start_sector, size_t range_size)
{
@@ -153,6 +154,20 @@ static bool vdpasim_blk_handle_req(struct vdpasim *vdpasim,
}
break;
+ case VIRTIO_BLK_T_GET_ID:
+ bytes = vringh_iov_push_iotlb(&vq->vring, &vq->in_iov,
+ vdpasim_blk_id,
+ VIRTIO_BLK_ID_BYTES);
+ if (bytes < 0) {
+ dev_err(&vdpasim->vdpa.dev,
+ "vringh_iov_push_iotlb() error: %zd\n", bytes);
+ status = VIRTIO_BLK_S_IOERR;
+ break;
+ }
+
+ pushed += bytes;
+ break;
+
default:
dev_warn(&vdpasim->vdpa.dev,
"Unsupported request type %d\n", type);
--
2.30.2
Enable the user to create vDPA block simulator devices using the
vdpa management tool:
# Show vDPA supported devices
$ vdpa mgmtdev show
vdpasim_blk:
supported_classes block
# Create a vDPA block device named as 'blk0' from the management
# device vdpasim:
$ vdpa dev add mgmtdev vdpasim_blk name blk0
# Show the info of the 'blk0' device just created
$ vdpa dev show blk0 -jp
{
"dev": {
"blk0": {
"type": "block",
"mgmtdev": "vdpasim_blk",
"vendor_id": 0,
"max_vqs": 1,
"max_vq_size": 256
}
}
}
# Delete the vDPA device after its use
$ vdpa dev del blk0
Signed-off-by: Stefano Garzarella <[email protected]>
---
drivers/vdpa/vdpa_sim/vdpa_sim_blk.c | 76 +++++++++++++++++++++++-----
1 file changed, 63 insertions(+), 13 deletions(-)
diff --git a/drivers/vdpa/vdpa_sim/vdpa_sim_blk.c b/drivers/vdpa/vdpa_sim/vdpa_sim_blk.c
index 643ae3bc62c0..5bfe1c281645 100644
--- a/drivers/vdpa/vdpa_sim/vdpa_sim_blk.c
+++ b/drivers/vdpa/vdpa_sim/vdpa_sim_blk.c
@@ -37,7 +37,6 @@
#define VDPASIM_BLK_SEG_MAX 32
#define VDPASIM_BLK_VQ_NUM 1
-static struct vdpasim *vdpasim_blk_dev;
static char vdpasim_blk_id[VIRTIO_BLK_ID_BYTES] = "vdpa_blk_sim";
static bool vdpasim_blk_check_range(u64 start_sector, size_t range_size)
@@ -241,11 +240,23 @@ static void vdpasim_blk_get_config(struct vdpasim *vdpasim, void *config)
blk_config->blk_size = cpu_to_vdpasim32(vdpasim, SECTOR_SIZE);
}
-static int __init vdpasim_blk_init(void)
+static void vdpasim_blk_mgmtdev_release(struct device *dev)
+{
+}
+
+static struct device vdpasim_blk_mgmtdev = {
+ .init_name = "vdpasim_blk",
+ .release = vdpasim_blk_mgmtdev_release,
+};
+
+static int vdpasim_blk_dev_add(struct vdpa_mgmt_dev *mdev, const char *name)
{
struct vdpasim_dev_attr dev_attr = {};
+ struct vdpasim *simdev;
int ret;
+ dev_attr.mgmt_dev = mdev;
+ dev_attr.name = name;
dev_attr.id = VIRTIO_ID_BLOCK;
dev_attr.supported_features = VDPASIM_BLK_FEATURES;
dev_attr.nvqs = VDPASIM_BLK_VQ_NUM;
@@ -254,29 +265,68 @@ static int __init vdpasim_blk_init(void)
dev_attr.work_fn = vdpasim_blk_work;
dev_attr.buffer_size = VDPASIM_BLK_CAPACITY << SECTOR_SHIFT;
- vdpasim_blk_dev = vdpasim_create(&dev_attr);
- if (IS_ERR(vdpasim_blk_dev)) {
- ret = PTR_ERR(vdpasim_blk_dev);
- goto out;
- }
+ simdev = vdpasim_create(&dev_attr);
+ if (IS_ERR(simdev))
+ return PTR_ERR(simdev);
- ret = vdpa_register_device(&vdpasim_blk_dev->vdpa, VDPASIM_BLK_VQ_NUM);
+ ret = _vdpa_register_device(&simdev->vdpa, VDPASIM_BLK_VQ_NUM);
if (ret)
goto put_dev;
return 0;
put_dev:
- put_device(&vdpasim_blk_dev->vdpa.dev);
-out:
+ put_device(&simdev->vdpa.dev);
return ret;
}
-static void __exit vdpasim_blk_exit(void)
+static void vdpasim_blk_dev_del(struct vdpa_mgmt_dev *mdev,
+ struct vdpa_device *dev)
{
- struct vdpa_device *vdpa = &vdpasim_blk_dev->vdpa;
+ struct vdpasim *simdev = container_of(dev, struct vdpasim, vdpa);
+
+ _vdpa_unregister_device(&simdev->vdpa);
+}
+
+static const struct vdpa_mgmtdev_ops vdpasim_blk_mgmtdev_ops = {
+ .dev_add = vdpasim_blk_dev_add,
+ .dev_del = vdpasim_blk_dev_del
+};
- vdpa_unregister_device(vdpa);
+static struct virtio_device_id id_table[] = {
+ { VIRTIO_ID_BLOCK, VIRTIO_DEV_ANY_ID },
+ { 0 },
+};
+
+static struct vdpa_mgmt_dev mgmt_dev = {
+ .device = &vdpasim_blk_mgmtdev,
+ .id_table = id_table,
+ .ops = &vdpasim_blk_mgmtdev_ops,
+};
+
+static int __init vdpasim_blk_init(void)
+{
+ int ret;
+
+ ret = device_register(&vdpasim_blk_mgmtdev);
+ if (ret)
+ return ret;
+
+ ret = vdpa_mgmtdev_register(&mgmt_dev);
+ if (ret)
+ goto parent_err;
+
+ return 0;
+
+parent_err:
+ device_unregister(&vdpasim_blk_mgmtdev);
+ return ret;
+}
+
+static void __exit vdpasim_blk_exit(void)
+{
+ vdpa_mgmtdev_unregister(&mgmt_dev);
+ device_unregister(&vdpasim_blk_mgmtdev);
}
module_init(vdpasim_blk_init)
--
2.30.2
The previous implementation wrote only the status of each request.
This patch implements a more accurate block device simulator,
providing a ramdisk-like behavior and adding input validation.
Acked-by: Jason Wang <[email protected]>
Reviewed-by: Stefan Hajnoczi <[email protected]>
Signed-off-by: Stefano Garzarella <[email protected]>
---
v2:
- used %zd %zx to print size_t and ssize_t variables in dev_err()
- removed unnecessary new line [Jason]
- moved VIRTIO_BLK_T_GET_ID in another patch [Jason]
- used push/pull instead of write/read terminology
- added vdpasim_blk_check_range() to avoid overflows [Stefan]
- use vdpasim*_to_cpu instead of le*_to_cpu
- used vringh_kiov_length() helper [Jason]
---
drivers/vdpa/vdpa_sim/vdpa_sim_blk.c | 164 ++++++++++++++++++++++++---
1 file changed, 146 insertions(+), 18 deletions(-)
diff --git a/drivers/vdpa/vdpa_sim/vdpa_sim_blk.c b/drivers/vdpa/vdpa_sim/vdpa_sim_blk.c
index 64926a70af5e..a31964e3e5a4 100644
--- a/drivers/vdpa/vdpa_sim/vdpa_sim_blk.c
+++ b/drivers/vdpa/vdpa_sim/vdpa_sim_blk.c
@@ -3,6 +3,7 @@
* VDPA simulator for block device.
*
* Copyright (c) 2020, NVIDIA CORPORATION. All rights reserved.
+ * Copyright (c) 2021, Red Hat Inc. All rights reserved.
*
*/
@@ -14,6 +15,7 @@
#include <linux/blkdev.h>
#include <linux/vringh.h>
#include <linux/vdpa.h>
+#include <linux/blkdev.h>
#include <uapi/linux/virtio_blk.h>
#include "vdpa_sim.h"
@@ -37,10 +39,151 @@
static struct vdpasim *vdpasim_blk_dev;
+static bool vdpasim_blk_check_range(u64 start_sector, size_t range_size)
+{
+ u64 range_sectors = range_size >> SECTOR_SHIFT;
+
+ if (range_size > VDPASIM_BLK_SIZE_MAX * VDPASIM_BLK_SEG_MAX)
+ return false;
+
+ if (start_sector > VDPASIM_BLK_CAPACITY)
+ return false;
+
+ if (range_sectors > VDPASIM_BLK_CAPACITY - start_sector)
+ return false;
+
+ return true;
+}
+
+/* Returns 'true' if the request is handled (with or without an I/O error)
+ * and the status is correctly written in the last byte of the 'in iov',
+ * 'false' otherwise.
+ */
+static bool vdpasim_blk_handle_req(struct vdpasim *vdpasim,
+ struct vdpasim_virtqueue *vq)
+{
+ size_t pushed = 0, to_pull, to_push;
+ struct virtio_blk_outhdr hdr;
+ ssize_t bytes;
+ loff_t offset;
+ u64 sector;
+ u8 status;
+ u32 type;
+ int ret;
+
+ ret = vringh_getdesc_iotlb(&vq->vring, &vq->out_iov, &vq->in_iov,
+ &vq->head, GFP_ATOMIC);
+ if (ret != 1)
+ return false;
+
+ if (vq->out_iov.used < 1 || vq->in_iov.used < 1) {
+ dev_err(&vdpasim->vdpa.dev, "missing headers - out_iov: %u in_iov %u\n",
+ vq->out_iov.used, vq->in_iov.used);
+ return false;
+ }
+
+ if (vq->in_iov.iov[vq->in_iov.used - 1].iov_len < 1) {
+ dev_err(&vdpasim->vdpa.dev, "request in header too short\n");
+ return false;
+ }
+
+ /* The last byte is the status and we checked if the last iov has
+ * enough room for it.
+ */
+ to_push = vringh_kiov_length(&vq->in_iov) - 1;
+
+ to_pull = vringh_kiov_length(&vq->out_iov);
+
+ bytes = vringh_iov_pull_iotlb(&vq->vring, &vq->out_iov, &hdr,
+ sizeof(hdr));
+ if (bytes != sizeof(hdr)) {
+ dev_err(&vdpasim->vdpa.dev, "request out header too short\n");
+ return false;
+ }
+
+ to_pull -= bytes;
+
+ type = vdpasim32_to_cpu(vdpasim, hdr.type);
+ sector = vdpasim64_to_cpu(vdpasim, hdr.sector);
+ offset = sector << SECTOR_SHIFT;
+ status = VIRTIO_BLK_S_OK;
+
+ switch (type) {
+ case VIRTIO_BLK_T_IN:
+ if (!vdpasim_blk_check_range(sector, to_push)) {
+ dev_err(&vdpasim->vdpa.dev,
+ "reading over the capacity - offset: 0x%llx len: 0x%zx\n",
+ offset, to_push);
+ status = VIRTIO_BLK_S_IOERR;
+ break;
+ }
+
+ bytes = vringh_iov_push_iotlb(&vq->vring, &vq->in_iov,
+ vdpasim->buffer + offset,
+ to_push);
+ if (bytes < 0) {
+ dev_err(&vdpasim->vdpa.dev,
+ "vringh_iov_push_iotlb() error: %zd offset: 0x%llx len: 0x%zx\n",
+ bytes, offset, to_push);
+ status = VIRTIO_BLK_S_IOERR;
+ break;
+ }
+
+ pushed += bytes;
+ break;
+
+ case VIRTIO_BLK_T_OUT:
+ if (!vdpasim_blk_check_range(sector, to_pull)) {
+ dev_err(&vdpasim->vdpa.dev,
+ "writing over the capacity - offset: 0x%llx len: 0x%zx\n",
+ offset, to_pull);
+ status = VIRTIO_BLK_S_IOERR;
+ break;
+ }
+
+ bytes = vringh_iov_pull_iotlb(&vq->vring, &vq->out_iov,
+ vdpasim->buffer + offset,
+ to_pull);
+ if (bytes < 0) {
+ dev_err(&vdpasim->vdpa.dev,
+ "vringh_iov_pull_iotlb() error: %zd offset: 0x%llx len: 0x%zx\n",
+ bytes, offset, to_pull);
+ status = VIRTIO_BLK_S_IOERR;
+ break;
+ }
+ break;
+
+ default:
+ dev_warn(&vdpasim->vdpa.dev,
+ "Unsupported request type %d\n", type);
+ status = VIRTIO_BLK_S_IOERR;
+ break;
+ }
+
+ /* If some operations fail, we need to skip the remaining bytes
+ * to put the status in the last byte
+ */
+ if (to_push - pushed > 0)
+ vringh_kiov_advance(&vq->in_iov, to_push - pushed);
+
+ /* Last byte is the status */
+ bytes = vringh_iov_push_iotlb(&vq->vring, &vq->in_iov, &status, 1);
+ if (bytes != 1)
+ return false;
+
+ pushed += bytes;
+
+ /* Make sure data is wrote before advancing index */
+ smp_wmb();
+
+ vringh_complete_iotlb(&vq->vring, vq->head, pushed);
+
+ return true;
+}
+
static void vdpasim_blk_work(struct work_struct *work)
{
struct vdpasim *vdpasim = container_of(work, struct vdpasim, work);
- u8 status = VIRTIO_BLK_S_OK;
int i;
spin_lock(&vdpasim->lock);
@@ -54,22 +197,7 @@ static void vdpasim_blk_work(struct work_struct *work)
if (!vq->ready)
continue;
- while (vringh_getdesc_iotlb(&vq->vring, &vq->out_iov,
- &vq->in_iov, &vq->head,
- GFP_ATOMIC) > 0) {
- int write;
-
- vq->in_iov.i = vq->in_iov.used - 1;
- write = vringh_iov_push_iotlb(&vq->vring, &vq->in_iov,
- &status, 1);
- if (write <= 0)
- break;
-
- /* Make sure data is wrote before advancing index */
- smp_wmb();
-
- vringh_complete_iotlb(&vq->vring, vq->head, write);
-
+ while (vdpasim_blk_handle_req(vdpasim, vq)) {
/* Make sure used is visible before rasing the interrupt. */
smp_wmb();
@@ -109,7 +237,7 @@ static int __init vdpasim_blk_init(void)
dev_attr.config_size = sizeof(struct virtio_blk_config);
dev_attr.get_config = vdpasim_blk_get_config;
dev_attr.work_fn = vdpasim_blk_work;
- dev_attr.buffer_size = PAGE_SIZE;
+ dev_attr.buffer_size = VDPASIM_BLK_CAPACITY << SECTOR_SHIFT;
vdpasim_blk_dev = vdpasim_create(&dev_attr);
if (IS_ERR(vdpasim_blk_dev)) {
--
2.30.2
On Mon, Mar 15, 2021 at 05:51:30PM +0100, Laurent Vivier wrote:
>On 15/03/2021 17:34, Stefano Garzarella wrote:
>> This new helper returns the total number of bytes covered by
>> a vringh_kiov.
>>
>> Suggested-by: Jason Wang <[email protected]>
>> Acked-by: Jason Wang <[email protected]>
>> Signed-off-by: Stefano Garzarella <[email protected]>
>> ---
>> include/linux/vringh.h | 11 +++++++++++
>> 1 file changed, 11 insertions(+)
>>
>> diff --git a/include/linux/vringh.h b/include/linux/vringh.h
>> index 755211ebd195..84db7b8f912f 100644
>> --- a/include/linux/vringh.h
>> +++ b/include/linux/vringh.h
>> @@ -199,6 +199,17 @@ static inline void vringh_kiov_cleanup(struct vringh_kiov *kiov)
>> kiov->iov = NULL;
>> }
>>
>> +static inline size_t vringh_kiov_length(struct vringh_kiov *kiov)
>> +{
>> + size_t len = 0;
>> + int i;
>> +
>> + for (i = kiov->i; i < kiov->used; i++)
>> + len += kiov->iov[i].iov_len;
>> +
>> + return len;
>> +}
>
>Do we really need an helper?
>
>For instance, we can use:
>
>len = iov_length((struct iovec *)kiov->iov, kiov->used);
>
>Or do we want to avoid the cast?
Yes, that should be fine. If we want, I can remove the helper and use
iov_length() directly. I thought vringh wanted to hide iovec from users
though.
Anyway talking to Jason, as a long term solution we should reconsider
vringh and support iov_iter.
Thanks,
Stefano
In some cases, it may be useful to provide a way to skip a number
of bytes in a vringh_kiov.
Let's implement vringh_kiov_advance() for this purpose, reusing the
code from vringh_iov_xfer().
We replace that code calling the new vringh_kiov_advance().
Acked-by: Jason Wang <[email protected]>
Signed-off-by: Stefano Garzarella <[email protected]>
---
include/linux/vringh.h | 2 ++
drivers/vhost/vringh.c | 41 +++++++++++++++++++++++++++++------------
2 files changed, 31 insertions(+), 12 deletions(-)
diff --git a/include/linux/vringh.h b/include/linux/vringh.h
index 9c077863c8f6..755211ebd195 100644
--- a/include/linux/vringh.h
+++ b/include/linux/vringh.h
@@ -199,6 +199,8 @@ static inline void vringh_kiov_cleanup(struct vringh_kiov *kiov)
kiov->iov = NULL;
}
+void vringh_kiov_advance(struct vringh_kiov *kiov, size_t len);
+
int vringh_getdesc_kern(struct vringh *vrh,
struct vringh_kiov *riov,
struct vringh_kiov *wiov,
diff --git a/drivers/vhost/vringh.c b/drivers/vhost/vringh.c
index 2a88e087afd8..4af8fa259d65 100644
--- a/drivers/vhost/vringh.c
+++ b/drivers/vhost/vringh.c
@@ -75,6 +75,34 @@ static inline int __vringh_get_head(const struct vringh *vrh,
return head;
}
+/**
+ * vringh_kiov_advance - skip bytes from vring_kiov
+ * @iov: an iov passed to vringh_getdesc_*() (updated as we consume)
+ * @len: the maximum length to advance
+ */
+void vringh_kiov_advance(struct vringh_kiov *iov, size_t len)
+{
+ while (len && iov->i < iov->used) {
+ size_t partlen = min(iov->iov[iov->i].iov_len, len);
+
+ iov->consumed += partlen;
+ iov->iov[iov->i].iov_len -= partlen;
+ iov->iov[iov->i].iov_base += partlen;
+
+ if (!iov->iov[iov->i].iov_len) {
+ /* Fix up old iov element then increment. */
+ iov->iov[iov->i].iov_len = iov->consumed;
+ iov->iov[iov->i].iov_base -= iov->consumed;
+
+ iov->consumed = 0;
+ iov->i++;
+ }
+
+ len -= partlen;
+ }
+}
+EXPORT_SYMBOL(vringh_kiov_advance);
+
/* Copy some bytes to/from the iovec. Returns num copied. */
static inline ssize_t vringh_iov_xfer(struct vringh *vrh,
struct vringh_kiov *iov,
@@ -95,19 +123,8 @@ static inline ssize_t vringh_iov_xfer(struct vringh *vrh,
done += partlen;
len -= partlen;
ptr += partlen;
- iov->consumed += partlen;
- iov->iov[iov->i].iov_len -= partlen;
- iov->iov[iov->i].iov_base += partlen;
- if (!iov->iov[iov->i].iov_len) {
- /* Fix up old iov element then increment. */
- iov->iov[iov->i].iov_len = iov->consumed;
- iov->iov[iov->i].iov_base -= iov->consumed;
-
-
- iov->consumed = 0;
- iov->i++;
- }
+ vringh_kiov_advance(iov, partlen);
}
return done;
}
--
2.30.2
This new callback is used to get the size of the configuration space
of vDPA devices.
Signed-off-by: Stefano Garzarella <[email protected]>
---
include/linux/vdpa.h | 4 ++++
drivers/vdpa/ifcvf/ifcvf_main.c | 6 ++++++
drivers/vdpa/mlx5/net/mlx5_vnet.c | 6 ++++++
drivers/vdpa/vdpa_sim/vdpa_sim.c | 9 +++++++++
drivers/vdpa/virtio_pci/vp_vdpa.c | 8 ++++++++
5 files changed, 33 insertions(+)
diff --git a/include/linux/vdpa.h b/include/linux/vdpa.h
index 15fa085fab05..1b094c1531f2 100644
--- a/include/linux/vdpa.h
+++ b/include/linux/vdpa.h
@@ -150,6 +150,9 @@ struct vdpa_iova_range {
* @set_status: Set the device status
* @vdev: vdpa device
* @status: virtio device status
+ * @get_config_size: Get the size of the configuration space
+ * @vdev: vdpa device
+ * Returns size_t: configuration size
* @get_config: Read from device specific configuration space
* @vdev: vdpa device
* @offset: offset from the beginning of
@@ -231,6 +234,7 @@ struct vdpa_config_ops {
u32 (*get_vendor_id)(struct vdpa_device *vdev);
u8 (*get_status)(struct vdpa_device *vdev);
void (*set_status)(struct vdpa_device *vdev, u8 status);
+ size_t (*get_config_size)(struct vdpa_device *vdev);
void (*get_config)(struct vdpa_device *vdev, unsigned int offset,
void *buf, unsigned int len);
void (*set_config)(struct vdpa_device *vdev, unsigned int offset,
diff --git a/drivers/vdpa/ifcvf/ifcvf_main.c b/drivers/vdpa/ifcvf/ifcvf_main.c
index d555a6a5d1ba..017ab07040c7 100644
--- a/drivers/vdpa/ifcvf/ifcvf_main.c
+++ b/drivers/vdpa/ifcvf/ifcvf_main.c
@@ -332,6 +332,11 @@ static u32 ifcvf_vdpa_get_vq_align(struct vdpa_device *vdpa_dev)
return IFCVF_QUEUE_ALIGNMENT;
}
+static size_t ifcvf_vdpa_get_config_size(struct vdpa_device *vdpa_dev)
+{
+ return sizeof(struct virtio_net_config);
+}
+
static void ifcvf_vdpa_get_config(struct vdpa_device *vdpa_dev,
unsigned int offset,
void *buf, unsigned int len)
@@ -392,6 +397,7 @@ static const struct vdpa_config_ops ifc_vdpa_ops = {
.get_device_id = ifcvf_vdpa_get_device_id,
.get_vendor_id = ifcvf_vdpa_get_vendor_id,
.get_vq_align = ifcvf_vdpa_get_vq_align,
+ .get_config_size = ifcvf_vdpa_get_config_size,
.get_config = ifcvf_vdpa_get_config,
.set_config = ifcvf_vdpa_set_config,
.set_config_cb = ifcvf_vdpa_set_config_cb,
diff --git a/drivers/vdpa/mlx5/net/mlx5_vnet.c b/drivers/vdpa/mlx5/net/mlx5_vnet.c
index 71397fdafa6a..f6e03bf49e3e 100644
--- a/drivers/vdpa/mlx5/net/mlx5_vnet.c
+++ b/drivers/vdpa/mlx5/net/mlx5_vnet.c
@@ -1814,6 +1814,11 @@ static void mlx5_vdpa_set_status(struct vdpa_device *vdev, u8 status)
ndev->mvdev.status |= VIRTIO_CONFIG_S_FAILED;
}
+static size_t mlx5_vdpa_get_config_size(struct vdpa_device *vdev)
+{
+ return sizeof(struct virtio_net_config);
+}
+
static void mlx5_vdpa_get_config(struct vdpa_device *vdev, unsigned int offset, void *buf,
unsigned int len)
{
@@ -1900,6 +1905,7 @@ static const struct vdpa_config_ops mlx5_vdpa_ops = {
.get_vendor_id = mlx5_vdpa_get_vendor_id,
.get_status = mlx5_vdpa_get_status,
.set_status = mlx5_vdpa_set_status,
+ .get_config_size = mlx5_vdpa_get_config_size,
.get_config = mlx5_vdpa_get_config,
.set_config = mlx5_vdpa_set_config,
.get_generation = mlx5_vdpa_get_generation,
diff --git a/drivers/vdpa/vdpa_sim/vdpa_sim.c b/drivers/vdpa/vdpa_sim/vdpa_sim.c
index 14dc2d3d983e..98f793bc9376 100644
--- a/drivers/vdpa/vdpa_sim/vdpa_sim.c
+++ b/drivers/vdpa/vdpa_sim/vdpa_sim.c
@@ -462,6 +462,13 @@ static void vdpasim_set_status(struct vdpa_device *vdpa, u8 status)
spin_unlock(&vdpasim->lock);
}
+static size_t vdpasim_get_config_size(struct vdpa_device *vdpa)
+{
+ struct vdpasim *vdpasim = vdpa_to_sim(vdpa);
+
+ return vdpasim->dev_attr.config_size;
+}
+
static void vdpasim_get_config(struct vdpa_device *vdpa, unsigned int offset,
void *buf, unsigned int len)
{
@@ -598,6 +605,7 @@ static const struct vdpa_config_ops vdpasim_config_ops = {
.get_vendor_id = vdpasim_get_vendor_id,
.get_status = vdpasim_get_status,
.set_status = vdpasim_set_status,
+ .get_config_size = vdpasim_get_config_size,
.get_config = vdpasim_get_config,
.set_config = vdpasim_set_config,
.get_generation = vdpasim_get_generation,
@@ -625,6 +633,7 @@ static const struct vdpa_config_ops vdpasim_batch_config_ops = {
.get_vendor_id = vdpasim_get_vendor_id,
.get_status = vdpasim_get_status,
.set_status = vdpasim_set_status,
+ .get_config_size = vdpasim_get_config_size,
.get_config = vdpasim_get_config,
.set_config = vdpasim_set_config,
.get_generation = vdpasim_get_generation,
diff --git a/drivers/vdpa/virtio_pci/vp_vdpa.c b/drivers/vdpa/virtio_pci/vp_vdpa.c
index 1321a2fcd088..dc27ec970884 100644
--- a/drivers/vdpa/virtio_pci/vp_vdpa.c
+++ b/drivers/vdpa/virtio_pci/vp_vdpa.c
@@ -295,6 +295,13 @@ static u32 vp_vdpa_get_vq_align(struct vdpa_device *vdpa)
return PAGE_SIZE;
}
+static size_t vp_vdpa_get_config_size(struct vdpa_device *vdpa)
+{
+ struct virtio_pci_modern_device *mdev = vdpa_to_mdev(vdpa);
+
+ return mdev->device_len;
+}
+
static void vp_vdpa_get_config(struct vdpa_device *vdpa,
unsigned int offset,
void *buf, unsigned int len)
@@ -354,6 +361,7 @@ static const struct vdpa_config_ops vp_vdpa_ops = {
.get_device_id = vp_vdpa_get_device_id,
.get_vendor_id = vp_vdpa_get_vendor_id,
.get_vq_align = vp_vdpa_get_vq_align,
+ .get_config_size = vp_vdpa_get_config_size,
.get_config = vp_vdpa_get_config,
.set_config = vp_vdpa_set_config,
.set_config_cb = vp_vdpa_set_config_cb,
--
2.30.2
From: Max Gurtovoy <[email protected]>
This will allow running vDPA for virtio block protocol.
It's a preliminary implementation with a simple request handling:
for each request, only the status (last byte) is set.
It's always set to VIRTIO_BLK_S_OK.
Also input validation is missing and will be added in the next commits.
Signed-off-by: Max Gurtovoy <[email protected]>
[sgarzare: various cleanups/fixes]
Acked-by: Jason Wang <[email protected]>
Signed-off-by: Stefano Garzarella <[email protected]>
---
v4:
- include linux/blkdev.h to fix a build issue
- fix vdpa_register_device() passing the new 'nvqs' params
v3:
- updated Mellanox copyright to NVIDIA [Max]
- explained in the commit message that inputs are validated in subsequent
patches [Stefan]
v2:
- rebased on top of other changes (dev_attr, get_config(), notify(), etc.)
- memset to 0 the config structure in vdpasim_blk_get_config()
- used vdpasim pointer in vdpasim_blk_get_config()
v1:
- Removed unused headers
- Used cpu_to_vdpasim*() to store config fields
- Replaced 'select VDPA_SIM' with 'depends on VDPA_SIM' since selected
option can not depend on other [Jason]
- Start with a single queue for now [Jason]
- Add comments to memory barriers
---
drivers/vdpa/vdpa_sim/vdpa_sim_blk.c | 145 +++++++++++++++++++++++++++
drivers/vdpa/Kconfig | 7 ++
drivers/vdpa/vdpa_sim/Makefile | 1 +
3 files changed, 153 insertions(+)
create mode 100644 drivers/vdpa/vdpa_sim/vdpa_sim_blk.c
diff --git a/drivers/vdpa/vdpa_sim/vdpa_sim_blk.c b/drivers/vdpa/vdpa_sim/vdpa_sim_blk.c
new file mode 100644
index 000000000000..64926a70af5e
--- /dev/null
+++ b/drivers/vdpa/vdpa_sim/vdpa_sim_blk.c
@@ -0,0 +1,145 @@
+// SPDX-License-Identifier: GPL-2.0-only
+/*
+ * VDPA simulator for block device.
+ *
+ * Copyright (c) 2020, NVIDIA CORPORATION. All rights reserved.
+ *
+ */
+
+#include <linux/init.h>
+#include <linux/module.h>
+#include <linux/device.h>
+#include <linux/kernel.h>
+#include <linux/sched.h>
+#include <linux/blkdev.h>
+#include <linux/vringh.h>
+#include <linux/vdpa.h>
+#include <uapi/linux/virtio_blk.h>
+
+#include "vdpa_sim.h"
+
+#define DRV_VERSION "0.1"
+#define DRV_AUTHOR "Max Gurtovoy <[email protected]>"
+#define DRV_DESC "vDPA Device Simulator for block device"
+#define DRV_LICENSE "GPL v2"
+
+#define VDPASIM_BLK_FEATURES (VDPASIM_FEATURES | \
+ (1ULL << VIRTIO_BLK_F_SIZE_MAX) | \
+ (1ULL << VIRTIO_BLK_F_SEG_MAX) | \
+ (1ULL << VIRTIO_BLK_F_BLK_SIZE) | \
+ (1ULL << VIRTIO_BLK_F_TOPOLOGY) | \
+ (1ULL << VIRTIO_BLK_F_MQ))
+
+#define VDPASIM_BLK_CAPACITY 0x40000
+#define VDPASIM_BLK_SIZE_MAX 0x1000
+#define VDPASIM_BLK_SEG_MAX 32
+#define VDPASIM_BLK_VQ_NUM 1
+
+static struct vdpasim *vdpasim_blk_dev;
+
+static void vdpasim_blk_work(struct work_struct *work)
+{
+ struct vdpasim *vdpasim = container_of(work, struct vdpasim, work);
+ u8 status = VIRTIO_BLK_S_OK;
+ int i;
+
+ spin_lock(&vdpasim->lock);
+
+ if (!(vdpasim->status & VIRTIO_CONFIG_S_DRIVER_OK))
+ goto out;
+
+ for (i = 0; i < VDPASIM_BLK_VQ_NUM; i++) {
+ struct vdpasim_virtqueue *vq = &vdpasim->vqs[i];
+
+ if (!vq->ready)
+ continue;
+
+ while (vringh_getdesc_iotlb(&vq->vring, &vq->out_iov,
+ &vq->in_iov, &vq->head,
+ GFP_ATOMIC) > 0) {
+ int write;
+
+ vq->in_iov.i = vq->in_iov.used - 1;
+ write = vringh_iov_push_iotlb(&vq->vring, &vq->in_iov,
+ &status, 1);
+ if (write <= 0)
+ break;
+
+ /* Make sure data is wrote before advancing index */
+ smp_wmb();
+
+ vringh_complete_iotlb(&vq->vring, vq->head, write);
+
+ /* Make sure used is visible before rasing the interrupt. */
+ smp_wmb();
+
+ local_bh_disable();
+ if (vringh_need_notify_iotlb(&vq->vring) > 0)
+ vringh_notify(&vq->vring);
+ local_bh_enable();
+ }
+ }
+out:
+ spin_unlock(&vdpasim->lock);
+}
+
+static void vdpasim_blk_get_config(struct vdpasim *vdpasim, void *config)
+{
+ struct virtio_blk_config *blk_config = config;
+
+ memset(config, 0, sizeof(struct virtio_blk_config));
+
+ blk_config->capacity = cpu_to_vdpasim64(vdpasim, VDPASIM_BLK_CAPACITY);
+ blk_config->size_max = cpu_to_vdpasim32(vdpasim, VDPASIM_BLK_SIZE_MAX);
+ blk_config->seg_max = cpu_to_vdpasim32(vdpasim, VDPASIM_BLK_SEG_MAX);
+ blk_config->num_queues = cpu_to_vdpasim16(vdpasim, VDPASIM_BLK_VQ_NUM);
+ blk_config->min_io_size = cpu_to_vdpasim16(vdpasim, 1);
+ blk_config->opt_io_size = cpu_to_vdpasim32(vdpasim, 1);
+ blk_config->blk_size = cpu_to_vdpasim32(vdpasim, SECTOR_SIZE);
+}
+
+static int __init vdpasim_blk_init(void)
+{
+ struct vdpasim_dev_attr dev_attr = {};
+ int ret;
+
+ dev_attr.id = VIRTIO_ID_BLOCK;
+ dev_attr.supported_features = VDPASIM_BLK_FEATURES;
+ dev_attr.nvqs = VDPASIM_BLK_VQ_NUM;
+ dev_attr.config_size = sizeof(struct virtio_blk_config);
+ dev_attr.get_config = vdpasim_blk_get_config;
+ dev_attr.work_fn = vdpasim_blk_work;
+ dev_attr.buffer_size = PAGE_SIZE;
+
+ vdpasim_blk_dev = vdpasim_create(&dev_attr);
+ if (IS_ERR(vdpasim_blk_dev)) {
+ ret = PTR_ERR(vdpasim_blk_dev);
+ goto out;
+ }
+
+ ret = vdpa_register_device(&vdpasim_blk_dev->vdpa, VDPASIM_BLK_VQ_NUM);
+ if (ret)
+ goto put_dev;
+
+ return 0;
+
+put_dev:
+ put_device(&vdpasim_blk_dev->vdpa.dev);
+out:
+ return ret;
+}
+
+static void __exit vdpasim_blk_exit(void)
+{
+ struct vdpa_device *vdpa = &vdpasim_blk_dev->vdpa;
+
+ vdpa_unregister_device(vdpa);
+}
+
+module_init(vdpasim_blk_init)
+module_exit(vdpasim_blk_exit)
+
+MODULE_VERSION(DRV_VERSION);
+MODULE_LICENSE(DRV_LICENSE);
+MODULE_AUTHOR(DRV_AUTHOR);
+MODULE_DESCRIPTION(DRV_DESC);
diff --git a/drivers/vdpa/Kconfig b/drivers/vdpa/Kconfig
index 6e82a0e228c2..a503c1b2bfd9 100644
--- a/drivers/vdpa/Kconfig
+++ b/drivers/vdpa/Kconfig
@@ -26,6 +26,13 @@ config VDPA_SIM_NET
help
vDPA networking device simulator which loops TX traffic back to RX.
+config VDPA_SIM_BLOCK
+ tristate "vDPA simulator for block device"
+ depends on VDPA_SIM
+ help
+ vDPA block device simulator which terminates IO request in a
+ memory buffer.
+
config IFCVF
tristate "Intel IFC VF vDPA driver"
depends on PCI_MSI
diff --git a/drivers/vdpa/vdpa_sim/Makefile b/drivers/vdpa/vdpa_sim/Makefile
index 79d4536d347e..d458103302f2 100644
--- a/drivers/vdpa/vdpa_sim/Makefile
+++ b/drivers/vdpa/vdpa_sim/Makefile
@@ -1,3 +1,4 @@
# SPDX-License-Identifier: GPL-2.0
obj-$(CONFIG_VDPA_SIM) += vdpa_sim.o
obj-$(CONFIG_VDPA_SIM_NET) += vdpa_sim_net.o
+obj-$(CONFIG_VDPA_SIM_BLOCK) += vdpa_sim_blk.o
--
2.30.2
On 15/03/2021 17:34, Stefano Garzarella wrote:
> This new helper returns the total number of bytes covered by
> a vringh_kiov.
>
> Suggested-by: Jason Wang <[email protected]>
> Acked-by: Jason Wang <[email protected]>
> Signed-off-by: Stefano Garzarella <[email protected]>
> ---
> include/linux/vringh.h | 11 +++++++++++
> 1 file changed, 11 insertions(+)
>
> diff --git a/include/linux/vringh.h b/include/linux/vringh.h
> index 755211ebd195..84db7b8f912f 100644
> --- a/include/linux/vringh.h
> +++ b/include/linux/vringh.h
> @@ -199,6 +199,17 @@ static inline void vringh_kiov_cleanup(struct vringh_kiov *kiov)
> kiov->iov = NULL;
> }
>
> +static inline size_t vringh_kiov_length(struct vringh_kiov *kiov)
> +{
> + size_t len = 0;
> + int i;
> +
> + for (i = kiov->i; i < kiov->used; i++)
> + len += kiov->iov[i].iov_len;
> +
> + return len;
> +}
Do we really need an helper?
For instance, we can use:
len = iov_length((struct iovec *)kiov->iov, kiov->used);
Or do we want to avoid the cast?
Thanks,
Laurent
?? 2021/3/16 ????12:34, Stefano Garzarella д??:
> Let's use the new 'get_config_size()' callback available instead of
> using the 'virtio_id' to get the size of the device config space.
>
> Signed-off-by: Stefano Garzarella <[email protected]>
Acked-by: Jason Wang <[email protected]>
> ---
> drivers/vhost/vdpa.c | 9 ++-------
> 1 file changed, 2 insertions(+), 7 deletions(-)
>
> diff --git a/drivers/vhost/vdpa.c b/drivers/vhost/vdpa.c
> index e0a27e336293..7ae4080e57d8 100644
> --- a/drivers/vhost/vdpa.c
> +++ b/drivers/vhost/vdpa.c
> @@ -188,13 +188,8 @@ static long vhost_vdpa_set_status(struct vhost_vdpa *v, u8 __user *statusp)
> static int vhost_vdpa_config_validate(struct vhost_vdpa *v,
> struct vhost_vdpa_config *c)
> {
> - long size = 0;
> -
> - switch (v->virtio_id) {
> - case VIRTIO_ID_NET:
> - size = sizeof(struct virtio_net_config);
> - break;
> - }
> + struct vdpa_device *vdpa = v->vdpa;
> + long size = vdpa->config->get_config_size(vdpa);
>
> if (c->len == 0)
> return -EINVAL;
?? 2021/3/16 ????12:34, Stefano Garzarella д??:
> This new callback is used to get the size of the configuration space
> of vDPA devices.
>
> Signed-off-by: Stefano Garzarella <[email protected]>
Acked-by: Jason Wang <[email protected]>
> ---
> include/linux/vdpa.h | 4 ++++
> drivers/vdpa/ifcvf/ifcvf_main.c | 6 ++++++
> drivers/vdpa/mlx5/net/mlx5_vnet.c | 6 ++++++
> drivers/vdpa/vdpa_sim/vdpa_sim.c | 9 +++++++++
> drivers/vdpa/virtio_pci/vp_vdpa.c | 8 ++++++++
> 5 files changed, 33 insertions(+)
>
> diff --git a/include/linux/vdpa.h b/include/linux/vdpa.h
> index 15fa085fab05..1b094c1531f2 100644
> --- a/include/linux/vdpa.h
> +++ b/include/linux/vdpa.h
> @@ -150,6 +150,9 @@ struct vdpa_iova_range {
> * @set_status: Set the device status
> * @vdev: vdpa device
> * @status: virtio device status
> + * @get_config_size: Get the size of the configuration space
> + * @vdev: vdpa device
> + * Returns size_t: configuration size
> * @get_config: Read from device specific configuration space
> * @vdev: vdpa device
> * @offset: offset from the beginning of
> @@ -231,6 +234,7 @@ struct vdpa_config_ops {
> u32 (*get_vendor_id)(struct vdpa_device *vdev);
> u8 (*get_status)(struct vdpa_device *vdev);
> void (*set_status)(struct vdpa_device *vdev, u8 status);
> + size_t (*get_config_size)(struct vdpa_device *vdev);
> void (*get_config)(struct vdpa_device *vdev, unsigned int offset,
> void *buf, unsigned int len);
> void (*set_config)(struct vdpa_device *vdev, unsigned int offset,
> diff --git a/drivers/vdpa/ifcvf/ifcvf_main.c b/drivers/vdpa/ifcvf/ifcvf_main.c
> index d555a6a5d1ba..017ab07040c7 100644
> --- a/drivers/vdpa/ifcvf/ifcvf_main.c
> +++ b/drivers/vdpa/ifcvf/ifcvf_main.c
> @@ -332,6 +332,11 @@ static u32 ifcvf_vdpa_get_vq_align(struct vdpa_device *vdpa_dev)
> return IFCVF_QUEUE_ALIGNMENT;
> }
>
> +static size_t ifcvf_vdpa_get_config_size(struct vdpa_device *vdpa_dev)
> +{
> + return sizeof(struct virtio_net_config);
> +}
> +
> static void ifcvf_vdpa_get_config(struct vdpa_device *vdpa_dev,
> unsigned int offset,
> void *buf, unsigned int len)
> @@ -392,6 +397,7 @@ static const struct vdpa_config_ops ifc_vdpa_ops = {
> .get_device_id = ifcvf_vdpa_get_device_id,
> .get_vendor_id = ifcvf_vdpa_get_vendor_id,
> .get_vq_align = ifcvf_vdpa_get_vq_align,
> + .get_config_size = ifcvf_vdpa_get_config_size,
> .get_config = ifcvf_vdpa_get_config,
> .set_config = ifcvf_vdpa_set_config,
> .set_config_cb = ifcvf_vdpa_set_config_cb,
> diff --git a/drivers/vdpa/mlx5/net/mlx5_vnet.c b/drivers/vdpa/mlx5/net/mlx5_vnet.c
> index 71397fdafa6a..f6e03bf49e3e 100644
> --- a/drivers/vdpa/mlx5/net/mlx5_vnet.c
> +++ b/drivers/vdpa/mlx5/net/mlx5_vnet.c
> @@ -1814,6 +1814,11 @@ static void mlx5_vdpa_set_status(struct vdpa_device *vdev, u8 status)
> ndev->mvdev.status |= VIRTIO_CONFIG_S_FAILED;
> }
>
> +static size_t mlx5_vdpa_get_config_size(struct vdpa_device *vdev)
> +{
> + return sizeof(struct virtio_net_config);
> +}
> +
> static void mlx5_vdpa_get_config(struct vdpa_device *vdev, unsigned int offset, void *buf,
> unsigned int len)
> {
> @@ -1900,6 +1905,7 @@ static const struct vdpa_config_ops mlx5_vdpa_ops = {
> .get_vendor_id = mlx5_vdpa_get_vendor_id,
> .get_status = mlx5_vdpa_get_status,
> .set_status = mlx5_vdpa_set_status,
> + .get_config_size = mlx5_vdpa_get_config_size,
> .get_config = mlx5_vdpa_get_config,
> .set_config = mlx5_vdpa_set_config,
> .get_generation = mlx5_vdpa_get_generation,
> diff --git a/drivers/vdpa/vdpa_sim/vdpa_sim.c b/drivers/vdpa/vdpa_sim/vdpa_sim.c
> index 14dc2d3d983e..98f793bc9376 100644
> --- a/drivers/vdpa/vdpa_sim/vdpa_sim.c
> +++ b/drivers/vdpa/vdpa_sim/vdpa_sim.c
> @@ -462,6 +462,13 @@ static void vdpasim_set_status(struct vdpa_device *vdpa, u8 status)
> spin_unlock(&vdpasim->lock);
> }
>
> +static size_t vdpasim_get_config_size(struct vdpa_device *vdpa)
> +{
> + struct vdpasim *vdpasim = vdpa_to_sim(vdpa);
> +
> + return vdpasim->dev_attr.config_size;
> +}
> +
> static void vdpasim_get_config(struct vdpa_device *vdpa, unsigned int offset,
> void *buf, unsigned int len)
> {
> @@ -598,6 +605,7 @@ static const struct vdpa_config_ops vdpasim_config_ops = {
> .get_vendor_id = vdpasim_get_vendor_id,
> .get_status = vdpasim_get_status,
> .set_status = vdpasim_set_status,
> + .get_config_size = vdpasim_get_config_size,
> .get_config = vdpasim_get_config,
> .set_config = vdpasim_set_config,
> .get_generation = vdpasim_get_generation,
> @@ -625,6 +633,7 @@ static const struct vdpa_config_ops vdpasim_batch_config_ops = {
> .get_vendor_id = vdpasim_get_vendor_id,
> .get_status = vdpasim_get_status,
> .set_status = vdpasim_set_status,
> + .get_config_size = vdpasim_get_config_size,
> .get_config = vdpasim_get_config,
> .set_config = vdpasim_set_config,
> .get_generation = vdpasim_get_generation,
> diff --git a/drivers/vdpa/virtio_pci/vp_vdpa.c b/drivers/vdpa/virtio_pci/vp_vdpa.c
> index 1321a2fcd088..dc27ec970884 100644
> --- a/drivers/vdpa/virtio_pci/vp_vdpa.c
> +++ b/drivers/vdpa/virtio_pci/vp_vdpa.c
> @@ -295,6 +295,13 @@ static u32 vp_vdpa_get_vq_align(struct vdpa_device *vdpa)
> return PAGE_SIZE;
> }
>
> +static size_t vp_vdpa_get_config_size(struct vdpa_device *vdpa)
> +{
> + struct virtio_pci_modern_device *mdev = vdpa_to_mdev(vdpa);
> +
> + return mdev->device_len;
> +}
> +
> static void vp_vdpa_get_config(struct vdpa_device *vdpa,
> unsigned int offset,
> void *buf, unsigned int len)
> @@ -354,6 +361,7 @@ static const struct vdpa_config_ops vp_vdpa_ops = {
> .get_device_id = vp_vdpa_get_device_id,
> .get_vendor_id = vp_vdpa_get_vendor_id,
> .get_vq_align = vp_vdpa_get_vq_align,
> + .get_config_size = vp_vdpa_get_config_size,
> .get_config = vp_vdpa_get_config,
> .set_config = vp_vdpa_set_config,
> .set_config_cb = vp_vdpa_set_config_cb,
?? 2021/3/16 ????12:34, Stefano Garzarella д??:
> From: Xie Yongji <[email protected]>
>
> Since the config checks are done by the vDPA drivers, we can remove the
> virtio-net restriction and we should be able to support all kinds of
> virtio devices.
>
> <linux/virtio_net.h> is not needed anymore, but we need to include
> <linux/slab.h> to avoid compilation failures.
>
> Signed-off-by: Xie Yongji <[email protected]>
> Signed-off-by: Stefano Garzarella <[email protected]>
Acked-by: Jason Wang <[email protected]>
> ---
> drivers/vhost/vdpa.c | 6 +-----
> 1 file changed, 1 insertion(+), 5 deletions(-)
>
> diff --git a/drivers/vhost/vdpa.c b/drivers/vhost/vdpa.c
> index 7ae4080e57d8..850ed4b62942 100644
> --- a/drivers/vhost/vdpa.c
> +++ b/drivers/vhost/vdpa.c
> @@ -16,12 +16,12 @@
> #include <linux/cdev.h>
> #include <linux/device.h>
> #include <linux/mm.h>
> +#include <linux/slab.h>
> #include <linux/iommu.h>
> #include <linux/uuid.h>
> #include <linux/vdpa.h>
> #include <linux/nospec.h>
> #include <linux/vhost.h>
> -#include <linux/virtio_net.h>
>
> #include "vhost.h"
>
> @@ -1018,10 +1018,6 @@ static int vhost_vdpa_probe(struct vdpa_device *vdpa)
> int minor;
> int r;
>
> - /* Currently, we only accept the network devices. */
> - if (ops->get_device_id(vdpa) != VIRTIO_ID_NET)
> - return -ENOTSUPP;
> -
> v = kzalloc(sizeof(*v), GFP_KERNEL | __GFP_RETRY_MAYFAIL);
> if (!v)
> return -ENOMEM;
?? 2021/3/16 ????12:34, Stefano Garzarella д??:
> Enable the user to create vDPA block simulator devices using the
> vdpa management tool:
>
> # Show vDPA supported devices
> $ vdpa mgmtdev show
> vdpasim_blk:
> supported_classes block
>
> # Create a vDPA block device named as 'blk0' from the management
> # device vdpasim:
> $ vdpa dev add mgmtdev vdpasim_blk name blk0
>
> # Show the info of the 'blk0' device just created
> $ vdpa dev show blk0 -jp
> {
> "dev": {
> "blk0": {
> "type": "block",
> "mgmtdev": "vdpasim_blk",
> "vendor_id": 0,
> "max_vqs": 1,
> "max_vq_size": 256
> }
> }
> }
>
> # Delete the vDPA device after its use
> $ vdpa dev del blk0
>
> Signed-off-by: Stefano Garzarella <[email protected]>
Acked-by: Jason Wang <[email protected]>
> ---
> drivers/vdpa/vdpa_sim/vdpa_sim_blk.c | 76 +++++++++++++++++++++++-----
> 1 file changed, 63 insertions(+), 13 deletions(-)
>
> diff --git a/drivers/vdpa/vdpa_sim/vdpa_sim_blk.c b/drivers/vdpa/vdpa_sim/vdpa_sim_blk.c
> index 643ae3bc62c0..5bfe1c281645 100644
> --- a/drivers/vdpa/vdpa_sim/vdpa_sim_blk.c
> +++ b/drivers/vdpa/vdpa_sim/vdpa_sim_blk.c
> @@ -37,7 +37,6 @@
> #define VDPASIM_BLK_SEG_MAX 32
> #define VDPASIM_BLK_VQ_NUM 1
>
> -static struct vdpasim *vdpasim_blk_dev;
> static char vdpasim_blk_id[VIRTIO_BLK_ID_BYTES] = "vdpa_blk_sim";
>
> static bool vdpasim_blk_check_range(u64 start_sector, size_t range_size)
> @@ -241,11 +240,23 @@ static void vdpasim_blk_get_config(struct vdpasim *vdpasim, void *config)
> blk_config->blk_size = cpu_to_vdpasim32(vdpasim, SECTOR_SIZE);
> }
>
> -static int __init vdpasim_blk_init(void)
> +static void vdpasim_blk_mgmtdev_release(struct device *dev)
> +{
> +}
> +
> +static struct device vdpasim_blk_mgmtdev = {
> + .init_name = "vdpasim_blk",
> + .release = vdpasim_blk_mgmtdev_release,
> +};
> +
> +static int vdpasim_blk_dev_add(struct vdpa_mgmt_dev *mdev, const char *name)
> {
> struct vdpasim_dev_attr dev_attr = {};
> + struct vdpasim *simdev;
> int ret;
>
> + dev_attr.mgmt_dev = mdev;
> + dev_attr.name = name;
> dev_attr.id = VIRTIO_ID_BLOCK;
> dev_attr.supported_features = VDPASIM_BLK_FEATURES;
> dev_attr.nvqs = VDPASIM_BLK_VQ_NUM;
> @@ -254,29 +265,68 @@ static int __init vdpasim_blk_init(void)
> dev_attr.work_fn = vdpasim_blk_work;
> dev_attr.buffer_size = VDPASIM_BLK_CAPACITY << SECTOR_SHIFT;
>
> - vdpasim_blk_dev = vdpasim_create(&dev_attr);
> - if (IS_ERR(vdpasim_blk_dev)) {
> - ret = PTR_ERR(vdpasim_blk_dev);
> - goto out;
> - }
> + simdev = vdpasim_create(&dev_attr);
> + if (IS_ERR(simdev))
> + return PTR_ERR(simdev);
>
> - ret = vdpa_register_device(&vdpasim_blk_dev->vdpa, VDPASIM_BLK_VQ_NUM);
> + ret = _vdpa_register_device(&simdev->vdpa, VDPASIM_BLK_VQ_NUM);
> if (ret)
> goto put_dev;
>
> return 0;
>
> put_dev:
> - put_device(&vdpasim_blk_dev->vdpa.dev);
> -out:
> + put_device(&simdev->vdpa.dev);
> return ret;
> }
>
> -static void __exit vdpasim_blk_exit(void)
> +static void vdpasim_blk_dev_del(struct vdpa_mgmt_dev *mdev,
> + struct vdpa_device *dev)
> {
> - struct vdpa_device *vdpa = &vdpasim_blk_dev->vdpa;
> + struct vdpasim *simdev = container_of(dev, struct vdpasim, vdpa);
> +
> + _vdpa_unregister_device(&simdev->vdpa);
> +}
> +
> +static const struct vdpa_mgmtdev_ops vdpasim_blk_mgmtdev_ops = {
> + .dev_add = vdpasim_blk_dev_add,
> + .dev_del = vdpasim_blk_dev_del
> +};
>
> - vdpa_unregister_device(vdpa);
> +static struct virtio_device_id id_table[] = {
> + { VIRTIO_ID_BLOCK, VIRTIO_DEV_ANY_ID },
> + { 0 },
> +};
> +
> +static struct vdpa_mgmt_dev mgmt_dev = {
> + .device = &vdpasim_blk_mgmtdev,
> + .id_table = id_table,
> + .ops = &vdpasim_blk_mgmtdev_ops,
> +};
> +
> +static int __init vdpasim_blk_init(void)
> +{
> + int ret;
> +
> + ret = device_register(&vdpasim_blk_mgmtdev);
> + if (ret)
> + return ret;
> +
> + ret = vdpa_mgmtdev_register(&mgmt_dev);
> + if (ret)
> + goto parent_err;
> +
> + return 0;
> +
> +parent_err:
> + device_unregister(&vdpasim_blk_mgmtdev);
> + return ret;
> +}
> +
> +static void __exit vdpasim_blk_exit(void)
> +{
> + vdpa_mgmtdev_unregister(&mgmt_dev);
> + device_unregister(&vdpasim_blk_mgmtdev);
> }
>
> module_init(vdpasim_blk_init)
Hi Michael,
do you think this series is in an acceptable state to be queued for the
next merge window?
All patches should be already acked by Jason, let me know if I need to
change anything.
Thanks,
Stefano
On Mon, Mar 15, 2021 at 05:34:36PM +0100, Stefano Garzarella wrote:
>v4:
>- added support for iproute2 vdpa management tool in vdpa_sim_blk
>- removed get/set_config patches
> - 'vdpa: add return value to get_config/set_config callbacks'
> - 'vhost/vdpa: remove vhost_vdpa_config_validate()'
>- added get_config_size() patches
> - 'vdpa: add get_config_size callback in vdpa_config_ops'
> - 'vhost/vdpa: use get_config_size callback in vhost_vdpa_config_validate()'
>
>v3: https://lore.kernel.org/lkml/[email protected]/
>v2: https://lore.kernel.org/lkml/[email protected]/
>v1: https://lore.kernel.org/lkml/[email protected]/
>
>This series is the second part of the v1 linked above. The first part with
>refactoring of vdpa_sim has already been merged.
>
>The patches are based on Max Gurtovoy's work and extend the block simulator to
>have a ramdisk behaviour.
>
>As mentioned in the v1 there was 2 issues and I fixed them in this series:
>1. The identical mapping in the IOMMU used until now in vdpa_sim created issues
> when mapping different virtual pages with the same physical address.
> Fixed by patch "vdpa_sim: use iova module to allocate IOVA addresses"
>
>2. There was a race accessing the IOMMU between the vdpasim_blk_work() and the
> device driver that map/unmap DMA regions. Fixed by patch "vringh: add
> 'iotlb_lock' to synchronize iotlb accesses"
>
>I used the Xie's patch coming from VDUSE series to allow vhost-vdpa to use
>block devices, and I added get_config_size() callback to allow any device
>in vhost-vdpa.
>
>The series also includes small fixes for vringh, vdpa, and vdpa_sim that I
>discovered while implementing and testing the block simulator.
>
>Thanks for your feedback,
>Stefano
>
>Max Gurtovoy (1):
> vdpa: add vdpa simulator for block device
>
>Stefano Garzarella (12):
> vdpa_sim: use iova module to allocate IOVA addresses
> vringh: add 'iotlb_lock' to synchronize iotlb accesses
> vringh: reset kiov 'consumed' field in __vringh_iov()
> vringh: explain more about cleaning riov and wiov
> vringh: implement vringh_kiov_advance()
> vringh: add vringh_kiov_length() helper
> vdpa_sim: cleanup kiovs in vdpasim_free()
> vdpa: add get_config_size callback in vdpa_config_ops
> vhost/vdpa: use get_config_size callback in
> vhost_vdpa_config_validate()
> vdpa_sim_blk: implement ramdisk behaviour
> vdpa_sim_blk: handle VIRTIO_BLK_T_GET_ID
> vdpa_sim_blk: add support for vdpa management tool
>
>Xie Yongji (1):
> vhost/vdpa: Remove the restriction that only supports virtio-net
> devices
>
> drivers/vdpa/vdpa_sim/vdpa_sim.h | 2 +
> include/linux/vdpa.h | 4 +
> include/linux/vringh.h | 19 +-
> drivers/vdpa/ifcvf/ifcvf_main.c | 6 +
> drivers/vdpa/mlx5/net/mlx5_vnet.c | 6 +
> drivers/vdpa/vdpa_sim/vdpa_sim.c | 127 ++++++----
> drivers/vdpa/vdpa_sim/vdpa_sim_blk.c | 338 +++++++++++++++++++++++++++
> drivers/vdpa/virtio_pci/vp_vdpa.c | 8 +
> drivers/vhost/vdpa.c | 15 +-
> drivers/vhost/vringh.c | 69 ++++--
> drivers/vdpa/Kconfig | 8 +
> drivers/vdpa/vdpa_sim/Makefile | 1 +
> 12 files changed, 529 insertions(+), 74 deletions(-)
> create mode 100644 drivers/vdpa/vdpa_sim/vdpa_sim_blk.c
>
>--
>2.30.2
>
>_______________________________________________
>Virtualization mailing list
>[email protected]
>https://lists.linuxfoundation.org/mailman/listinfo/virtualization
>