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, ¤t_status); + assert(r >= 0); + current_status |= status; + r = ioctl(dev->control, VHOST_VDPA_SET_STATUS, ¤t_status); + assert(r >= 0); + r = ioctl(dev->control, VHOST_VDPA_GET_STATUS, ¤t_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