[RFC PATCH 5/6] virtio_test: support vhost-vdpa device

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

 



The new --vdpa parameter can be used to run virtio_test with
the new vdpa_sim_test.ko that implements the device.

The main differences with vhost_test are:
- control of status register
- dma map messages
- VHOST_SET_MEM_TABLE not supported by vhost-vdpa
- VHOST_TEST_RUN not supported by vhost-vdpa

The --reset option is not supported for now when using vhost-vdpa.

Signed-off-by: Stefano Garzarella <sgarzare@xxxxxxxxxx>
---
 tools/virtio/virtio_test.c | 127 +++++++++++++++++++++++++++++++------
 1 file changed, 109 insertions(+), 18 deletions(-)

diff --git a/tools/virtio/virtio_test.c b/tools/virtio/virtio_test.c
index 2d8a3e881637..91f983266d86 100644
--- a/tools/virtio/virtio_test.c
+++ b/tools/virtio/virtio_test.c
@@ -44,6 +44,8 @@ struct vdev_info {
 	void *buf;
 	size_t buf_size;
 	struct vhost_memory *mem;
+	bool vdpa;
+	uint64_t backend_features;
 };
 
 static const struct vhost_vring_file no_backend = { .fd = -1 },
@@ -64,6 +66,36 @@ void vq_callback(struct virtqueue *vq)
 {
 }
 
+static void vdpa_add_status(struct vdev_info *dev, uint8_t status)
+{
+	uint8_t current_status;
+	int r;
+
+	r = ioctl(dev->control, VHOST_VDPA_GET_STATUS, &current_status);
+	assert(r >= 0);
+	current_status |= status;
+	r = ioctl(dev->control, VHOST_VDPA_SET_STATUS, &current_status);
+	assert(r >= 0);
+	r = ioctl(dev->control, VHOST_VDPA_GET_STATUS, &current_status);
+	assert(r >= 0);
+	assert((current_status & status) == status);
+}
+
+static void vdpa_dma_map(struct vdev_info *dev, uint64_t iova, uint64_t size,
+			 uint64_t uaddr, uint8_t perm)
+{
+	struct vhost_msg_v2 msg = {};
+	int r;
+
+	msg.type = VHOST_IOTLB_MSG_V2;
+	msg.iotlb.iova = iova;
+	msg.iotlb.size = size;
+	msg.iotlb.uaddr = uaddr;
+	msg.iotlb.perm = perm;
+	msg.iotlb.type = VHOST_IOTLB_UPDATE;
+	r = write(dev->control, &msg, sizeof(msg));
+	assert(r == sizeof(msg));
+}
 
 void vhost_vq_setup(struct vdev_info *dev, struct vq_info *info)
 {
@@ -76,6 +108,12 @@ void vhost_vq_setup(struct vdev_info *dev, struct vq_info *info)
 		.used_user_addr = (uint64_t)(unsigned long)info->vring.used,
 	};
 	int r;
+	if (dev->vdpa) {
+		vdpa_dma_map(dev, (uint64_t)(unsigned long)info->ring,
+			     vring_size(info->vring.num, 4096),
+			     (uint64_t)(unsigned long)info->ring,
+			     VHOST_ACCESS_RW);
+	}
 	state.num = info->vring.num;
 	r = ioctl(dev->control, VHOST_SET_VRING_NUM, &state);
 	assert(r >= 0);
@@ -90,6 +128,11 @@ void vhost_vq_setup(struct vdev_info *dev, struct vq_info *info)
 	file.fd = info->call;
 	r = ioctl(dev->control, VHOST_SET_VRING_CALL, &file);
 	assert(r >= 0);
+	if (dev->vdpa) {
+		state.num = 1;
+		r = ioctl(dev->control, VHOST_VDPA_SET_VRING_ENABLE, &state);
+		assert(r >= 0);
+	}
 }
 
 static void vq_reset(struct vq_info *info, int num, struct virtio_device *vdev)
@@ -121,33 +164,61 @@ static void vq_info_add(struct vdev_info *dev, int num)
 	dev->nvqs++;
 }
 
-static void vdev_info_init(struct vdev_info* dev, unsigned long long features)
+static void vdev_info_init(struct vdev_info *dev, unsigned long long features,
+			   char *vdpa_dev)
 {
+	char *vhost_dev = "/dev/vhost-test";
 	int r;
 	memset(dev, 0, sizeof *dev);
 	dev->vdev.features = features;
+	if (vdpa_dev) {
+		dev->vdpa = true;
+		vhost_dev = vdpa_dev;
+	}
 	INIT_LIST_HEAD(&dev->vdev.vqs);
 	spin_lock_init(&dev->vdev.vqs_list_lock);
 	dev->buf_size = 1024;
 	dev->buf = malloc(dev->buf_size);
 	assert(dev->buf);
-        dev->control = open("/dev/vhost-test", O_RDWR);
+	dev->control = open(vhost_dev, O_RDWR);
 	assert(dev->control >= 0);
 	r = ioctl(dev->control, VHOST_SET_OWNER, NULL);
 	assert(r >= 0);
-	dev->mem = malloc(offsetof(struct vhost_memory, regions) +
-			  sizeof dev->mem->regions[0]);
-	assert(dev->mem);
-	memset(dev->mem, 0, offsetof(struct vhost_memory, regions) +
-                          sizeof dev->mem->regions[0]);
-	dev->mem->nregions = 1;
-	dev->mem->regions[0].guest_phys_addr = (long)dev->buf;
-	dev->mem->regions[0].userspace_addr = (long)dev->buf;
-	dev->mem->regions[0].memory_size = dev->buf_size;
-	r = ioctl(dev->control, VHOST_SET_MEM_TABLE, dev->mem);
-	assert(r >= 0);
+	if (!dev->vdpa) {
+		dev->mem = malloc(offsetof(struct vhost_memory, regions) +
+					   sizeof(dev->mem->regions[0]));
+		assert(dev->mem);
+		memset(dev->mem, 0, offsetof(struct vhost_memory, regions) +
+					   sizeof(dev->mem->regions[0]));
+		dev->mem->nregions = 1;
+		dev->mem->regions[0].guest_phys_addr = (long)dev->buf;
+		dev->mem->regions[0].userspace_addr = (long)dev->buf;
+		dev->mem->regions[0].memory_size = dev->buf_size;
+		r = ioctl(dev->control, VHOST_SET_MEM_TABLE, dev->mem);
+		assert(r >= 0);
+	} else {
+		uint8_t status = 0;
+
+		r = ioctl(dev->control, VHOST_GET_BACKEND_FEATURES,
+			  &dev->backend_features);
+		assert(r >= 0);
+		dev->backend_features &= 0x1ULL << VHOST_BACKEND_F_IOTLB_MSG_V2;
+		assert(dev->backend_features);
+		r = ioctl(dev->control, VHOST_SET_BACKEND_FEATURES,
+			  &dev->backend_features);
+		assert(r >= 0);
+		r = ioctl(dev->control, VHOST_VDPA_SET_STATUS, &status);
+		assert(r >= 0);
+		vdpa_add_status(dev, VIRTIO_CONFIG_S_ACKNOWLEDGE |
+				     VIRTIO_CONFIG_S_DRIVER);
+		vdpa_dma_map(dev, (uint64_t)(unsigned long)dev->buf,
+			     dev->buf_size, (uint64_t)(unsigned long)dev->buf,
+			     VHOST_ACCESS_RW);
+	}
 	r = ioctl(dev->control, VHOST_SET_FEATURES, &features);
 	assert(r >= 0);
+	if (dev->vdpa)
+		vdpa_add_status(dev, VIRTIO_CONFIG_S_FEATURES_OK);
 }
 
 /* TODO: this is pretty bad: we get a cache line bounce
@@ -177,8 +248,13 @@ static void run_test(struct vdev_info *dev, struct vq_info *vq,
 	const bool random_batch = batch == RANDOM_BATCH;
 
 	__virtio_unbreak_device(&dev->vdev);
-	r = ioctl(dev->control, VHOST_TEST_RUN, &test);
-	assert(r >= 0);
+
+	if (!dev->vdpa) {
+		r = ioctl(dev->control, VHOST_TEST_RUN, &test);
+		assert(r >= 0);
+	} else {
+		vdpa_add_status(dev, VIRTIO_CONFIG_S_DRIVER_OK);
+	}
 	if (!reset_n) {
 		next_reset = INT_MAX;
 	}
@@ -268,8 +344,10 @@ static void run_test(struct vdev_info *dev, struct vq_info *vq,
 		}
 	}
 	test = 0;
-	r = ioctl(dev->control, VHOST_TEST_RUN, &test);
-	assert(r >= 0);
+	if (!dev->vdpa) {
+		r = ioctl(dev->control, VHOST_TEST_RUN, &test);
+		assert(r >= 0);
+	}
 	fprintf(stderr,
 		"spurious wakeups: 0x%llx started=0x%lx completed=0x%lx\n",
 		spurious, started, completed);
@@ -323,6 +401,11 @@ const struct option longopts[] = {
 		.val = 'r',
 		.has_arg = optional_argument,
 	},
+	{
+		.name = "vdpa",
+		.val = 'V',
+		.has_arg = required_argument,
+	},
 	{
 	}
 };
@@ -336,6 +419,7 @@ static void help(void)
 		" [--delayed-interrupt]"
 		" [--batch=random/N]"
 		" [--reset=N]"
+		" [--vdpa=/dev/vhost-vdpa-N]"
 		"\n");
 }
 
@@ -347,6 +431,7 @@ int main(int argc, char **argv)
 	long batch = 1, reset = 0;
 	int o;
 	bool delayed = false;
+	char *vdpa_dev = NULL;
 
 	for (;;) {
 		o = getopt_long(argc, argv, optstring, longopts, NULL);
@@ -389,6 +474,10 @@ int main(int argc, char **argv)
 				assert(reset < (long)INT_MAX + 1);
 			}
 			break;
+		case 'V':
+			vdpa_dev = optarg;
+			features |= 1ULL << VIRTIO_F_ACCESS_PLATFORM;
+			break;
 		default:
 			assert(0);
 			break;
@@ -396,7 +485,9 @@ int main(int argc, char **argv)
 	}
 
 done:
-	vdev_info_init(&dev, features);
+	//TODO: support reset for vdpa
+	assert(vdpa_dev && !reset);
+	vdev_info_init(&dev, features, vdpa_dev);
 	vq_info_add(&dev, 256);
 	run_test(&dev, &dev.vqs[0], delayed, batch, reset, 0x100000);
 	return 0;
-- 
2.36.1

_______________________________________________
Virtualization mailing list
Virtualization@xxxxxxxxxxxxxxxxxxxxxxxxxx
https://lists.linuxfoundation.org/mailman/listinfo/virtualization



[Index of Archives]     [KVM Development]     [Libvirt Development]     [Libvirt Users]     [CentOS Virtualization]     [Netdev]     [Ethernet Bridging]     [Linux Wireless]     [Kernel Newbies]     [Security]     [Linux for Hams]     [Netfilter]     [Bugtraq]     [Yosemite Forum]     [MIPS Linux]     [ARM Linux]     [Linux RAID]     [Linux Admin]     [Samba]

  Powered by Linux