162306a36Sopenharmony_ci// SPDX-License-Identifier: GPL-2.0 262306a36Sopenharmony_ci#define _GNU_SOURCE 362306a36Sopenharmony_ci#include <getopt.h> 462306a36Sopenharmony_ci#include <limits.h> 562306a36Sopenharmony_ci#include <string.h> 662306a36Sopenharmony_ci#include <poll.h> 762306a36Sopenharmony_ci#include <sys/eventfd.h> 862306a36Sopenharmony_ci#include <stdlib.h> 962306a36Sopenharmony_ci#include <assert.h> 1062306a36Sopenharmony_ci#include <unistd.h> 1162306a36Sopenharmony_ci#include <sys/ioctl.h> 1262306a36Sopenharmony_ci#include <sys/stat.h> 1362306a36Sopenharmony_ci#include <sys/types.h> 1462306a36Sopenharmony_ci#include <fcntl.h> 1562306a36Sopenharmony_ci#include <stdbool.h> 1662306a36Sopenharmony_ci#include <linux/virtio_types.h> 1762306a36Sopenharmony_ci#include <linux/vhost.h> 1862306a36Sopenharmony_ci#include <linux/virtio.h> 1962306a36Sopenharmony_ci#include <linux/virtio_ring.h> 2062306a36Sopenharmony_ci#include "../../drivers/vhost/test.h" 2162306a36Sopenharmony_ci 2262306a36Sopenharmony_ci#define RANDOM_BATCH -1 2362306a36Sopenharmony_ci 2462306a36Sopenharmony_ci/* Unused */ 2562306a36Sopenharmony_civoid *__kmalloc_fake, *__kfree_ignore_start, *__kfree_ignore_end; 2662306a36Sopenharmony_ci 2762306a36Sopenharmony_cistruct vq_info { 2862306a36Sopenharmony_ci int kick; 2962306a36Sopenharmony_ci int call; 3062306a36Sopenharmony_ci int num; 3162306a36Sopenharmony_ci int idx; 3262306a36Sopenharmony_ci void *ring; 3362306a36Sopenharmony_ci /* copy used for control */ 3462306a36Sopenharmony_ci struct vring vring; 3562306a36Sopenharmony_ci struct virtqueue *vq; 3662306a36Sopenharmony_ci}; 3762306a36Sopenharmony_ci 3862306a36Sopenharmony_cistruct vdev_info { 3962306a36Sopenharmony_ci struct virtio_device vdev; 4062306a36Sopenharmony_ci int control; 4162306a36Sopenharmony_ci struct pollfd fds[1]; 4262306a36Sopenharmony_ci struct vq_info vqs[1]; 4362306a36Sopenharmony_ci int nvqs; 4462306a36Sopenharmony_ci void *buf; 4562306a36Sopenharmony_ci size_t buf_size; 4662306a36Sopenharmony_ci struct vhost_memory *mem; 4762306a36Sopenharmony_ci}; 4862306a36Sopenharmony_ci 4962306a36Sopenharmony_cistatic const struct vhost_vring_file no_backend = { .fd = -1 }, 5062306a36Sopenharmony_ci backend = { .fd = 1 }; 5162306a36Sopenharmony_cistatic const struct vhost_vring_state null_state = {}; 5262306a36Sopenharmony_ci 5362306a36Sopenharmony_cibool vq_notify(struct virtqueue *vq) 5462306a36Sopenharmony_ci{ 5562306a36Sopenharmony_ci struct vq_info *info = vq->priv; 5662306a36Sopenharmony_ci unsigned long long v = 1; 5762306a36Sopenharmony_ci int r; 5862306a36Sopenharmony_ci r = write(info->kick, &v, sizeof v); 5962306a36Sopenharmony_ci assert(r == sizeof v); 6062306a36Sopenharmony_ci return true; 6162306a36Sopenharmony_ci} 6262306a36Sopenharmony_ci 6362306a36Sopenharmony_civoid vq_callback(struct virtqueue *vq) 6462306a36Sopenharmony_ci{ 6562306a36Sopenharmony_ci} 6662306a36Sopenharmony_ci 6762306a36Sopenharmony_ci 6862306a36Sopenharmony_civoid vhost_vq_setup(struct vdev_info *dev, struct vq_info *info) 6962306a36Sopenharmony_ci{ 7062306a36Sopenharmony_ci struct vhost_vring_state state = { .index = info->idx }; 7162306a36Sopenharmony_ci struct vhost_vring_file file = { .index = info->idx }; 7262306a36Sopenharmony_ci unsigned long long features = dev->vdev.features; 7362306a36Sopenharmony_ci struct vhost_vring_addr addr = { 7462306a36Sopenharmony_ci .index = info->idx, 7562306a36Sopenharmony_ci .desc_user_addr = (uint64_t)(unsigned long)info->vring.desc, 7662306a36Sopenharmony_ci .avail_user_addr = (uint64_t)(unsigned long)info->vring.avail, 7762306a36Sopenharmony_ci .used_user_addr = (uint64_t)(unsigned long)info->vring.used, 7862306a36Sopenharmony_ci }; 7962306a36Sopenharmony_ci int r; 8062306a36Sopenharmony_ci r = ioctl(dev->control, VHOST_SET_FEATURES, &features); 8162306a36Sopenharmony_ci assert(r >= 0); 8262306a36Sopenharmony_ci state.num = info->vring.num; 8362306a36Sopenharmony_ci r = ioctl(dev->control, VHOST_SET_VRING_NUM, &state); 8462306a36Sopenharmony_ci assert(r >= 0); 8562306a36Sopenharmony_ci state.num = 0; 8662306a36Sopenharmony_ci r = ioctl(dev->control, VHOST_SET_VRING_BASE, &state); 8762306a36Sopenharmony_ci assert(r >= 0); 8862306a36Sopenharmony_ci r = ioctl(dev->control, VHOST_SET_VRING_ADDR, &addr); 8962306a36Sopenharmony_ci assert(r >= 0); 9062306a36Sopenharmony_ci file.fd = info->kick; 9162306a36Sopenharmony_ci r = ioctl(dev->control, VHOST_SET_VRING_KICK, &file); 9262306a36Sopenharmony_ci assert(r >= 0); 9362306a36Sopenharmony_ci file.fd = info->call; 9462306a36Sopenharmony_ci r = ioctl(dev->control, VHOST_SET_VRING_CALL, &file); 9562306a36Sopenharmony_ci assert(r >= 0); 9662306a36Sopenharmony_ci} 9762306a36Sopenharmony_ci 9862306a36Sopenharmony_cistatic void vq_reset(struct vq_info *info, int num, struct virtio_device *vdev) 9962306a36Sopenharmony_ci{ 10062306a36Sopenharmony_ci if (info->vq) 10162306a36Sopenharmony_ci vring_del_virtqueue(info->vq); 10262306a36Sopenharmony_ci 10362306a36Sopenharmony_ci memset(info->ring, 0, vring_size(num, 4096)); 10462306a36Sopenharmony_ci vring_init(&info->vring, num, info->ring, 4096); 10562306a36Sopenharmony_ci info->vq = vring_new_virtqueue(info->idx, num, 4096, vdev, true, false, 10662306a36Sopenharmony_ci info->ring, vq_notify, vq_callback, "test"); 10762306a36Sopenharmony_ci assert(info->vq); 10862306a36Sopenharmony_ci info->vq->priv = info; 10962306a36Sopenharmony_ci} 11062306a36Sopenharmony_ci 11162306a36Sopenharmony_cistatic void vq_info_add(struct vdev_info *dev, int num) 11262306a36Sopenharmony_ci{ 11362306a36Sopenharmony_ci struct vq_info *info = &dev->vqs[dev->nvqs]; 11462306a36Sopenharmony_ci int r; 11562306a36Sopenharmony_ci info->idx = dev->nvqs; 11662306a36Sopenharmony_ci info->kick = eventfd(0, EFD_NONBLOCK); 11762306a36Sopenharmony_ci info->call = eventfd(0, EFD_NONBLOCK); 11862306a36Sopenharmony_ci r = posix_memalign(&info->ring, 4096, vring_size(num, 4096)); 11962306a36Sopenharmony_ci assert(r >= 0); 12062306a36Sopenharmony_ci vq_reset(info, num, &dev->vdev); 12162306a36Sopenharmony_ci vhost_vq_setup(dev, info); 12262306a36Sopenharmony_ci dev->fds[info->idx].fd = info->call; 12362306a36Sopenharmony_ci dev->fds[info->idx].events = POLLIN; 12462306a36Sopenharmony_ci dev->nvqs++; 12562306a36Sopenharmony_ci} 12662306a36Sopenharmony_ci 12762306a36Sopenharmony_cistatic void vdev_info_init(struct vdev_info* dev, unsigned long long features) 12862306a36Sopenharmony_ci{ 12962306a36Sopenharmony_ci int r; 13062306a36Sopenharmony_ci memset(dev, 0, sizeof *dev); 13162306a36Sopenharmony_ci dev->vdev.features = features; 13262306a36Sopenharmony_ci INIT_LIST_HEAD(&dev->vdev.vqs); 13362306a36Sopenharmony_ci spin_lock_init(&dev->vdev.vqs_list_lock); 13462306a36Sopenharmony_ci dev->buf_size = 1024; 13562306a36Sopenharmony_ci dev->buf = malloc(dev->buf_size); 13662306a36Sopenharmony_ci assert(dev->buf); 13762306a36Sopenharmony_ci dev->control = open("/dev/vhost-test", O_RDWR); 13862306a36Sopenharmony_ci assert(dev->control >= 0); 13962306a36Sopenharmony_ci r = ioctl(dev->control, VHOST_SET_OWNER, NULL); 14062306a36Sopenharmony_ci assert(r >= 0); 14162306a36Sopenharmony_ci dev->mem = malloc(offsetof(struct vhost_memory, regions) + 14262306a36Sopenharmony_ci sizeof dev->mem->regions[0]); 14362306a36Sopenharmony_ci assert(dev->mem); 14462306a36Sopenharmony_ci memset(dev->mem, 0, offsetof(struct vhost_memory, regions) + 14562306a36Sopenharmony_ci sizeof dev->mem->regions[0]); 14662306a36Sopenharmony_ci dev->mem->nregions = 1; 14762306a36Sopenharmony_ci dev->mem->regions[0].guest_phys_addr = (long)dev->buf; 14862306a36Sopenharmony_ci dev->mem->regions[0].userspace_addr = (long)dev->buf; 14962306a36Sopenharmony_ci dev->mem->regions[0].memory_size = dev->buf_size; 15062306a36Sopenharmony_ci r = ioctl(dev->control, VHOST_SET_MEM_TABLE, dev->mem); 15162306a36Sopenharmony_ci assert(r >= 0); 15262306a36Sopenharmony_ci} 15362306a36Sopenharmony_ci 15462306a36Sopenharmony_ci/* TODO: this is pretty bad: we get a cache line bounce 15562306a36Sopenharmony_ci * for the wait queue on poll and another one on read, 15662306a36Sopenharmony_ci * plus the read which is there just to clear the 15762306a36Sopenharmony_ci * current state. */ 15862306a36Sopenharmony_cistatic void wait_for_interrupt(struct vdev_info *dev) 15962306a36Sopenharmony_ci{ 16062306a36Sopenharmony_ci int i; 16162306a36Sopenharmony_ci unsigned long long val; 16262306a36Sopenharmony_ci poll(dev->fds, dev->nvqs, -1); 16362306a36Sopenharmony_ci for (i = 0; i < dev->nvqs; ++i) 16462306a36Sopenharmony_ci if (dev->fds[i].revents & POLLIN) { 16562306a36Sopenharmony_ci read(dev->fds[i].fd, &val, sizeof val); 16662306a36Sopenharmony_ci } 16762306a36Sopenharmony_ci} 16862306a36Sopenharmony_ci 16962306a36Sopenharmony_cistatic void run_test(struct vdev_info *dev, struct vq_info *vq, 17062306a36Sopenharmony_ci bool delayed, int batch, int reset_n, int bufs) 17162306a36Sopenharmony_ci{ 17262306a36Sopenharmony_ci struct scatterlist sl; 17362306a36Sopenharmony_ci long started = 0, completed = 0, next_reset = reset_n; 17462306a36Sopenharmony_ci long completed_before, started_before; 17562306a36Sopenharmony_ci int r, test = 1; 17662306a36Sopenharmony_ci unsigned int len; 17762306a36Sopenharmony_ci long long spurious = 0; 17862306a36Sopenharmony_ci const bool random_batch = batch == RANDOM_BATCH; 17962306a36Sopenharmony_ci 18062306a36Sopenharmony_ci r = ioctl(dev->control, VHOST_TEST_RUN, &test); 18162306a36Sopenharmony_ci assert(r >= 0); 18262306a36Sopenharmony_ci if (!reset_n) { 18362306a36Sopenharmony_ci next_reset = INT_MAX; 18462306a36Sopenharmony_ci } 18562306a36Sopenharmony_ci 18662306a36Sopenharmony_ci for (;;) { 18762306a36Sopenharmony_ci virtqueue_disable_cb(vq->vq); 18862306a36Sopenharmony_ci completed_before = completed; 18962306a36Sopenharmony_ci started_before = started; 19062306a36Sopenharmony_ci do { 19162306a36Sopenharmony_ci const bool reset = completed > next_reset; 19262306a36Sopenharmony_ci if (random_batch) 19362306a36Sopenharmony_ci batch = (random() % vq->vring.num) + 1; 19462306a36Sopenharmony_ci 19562306a36Sopenharmony_ci while (started < bufs && 19662306a36Sopenharmony_ci (started - completed) < batch) { 19762306a36Sopenharmony_ci sg_init_one(&sl, dev->buf, dev->buf_size); 19862306a36Sopenharmony_ci r = virtqueue_add_outbuf(vq->vq, &sl, 1, 19962306a36Sopenharmony_ci dev->buf + started, 20062306a36Sopenharmony_ci GFP_ATOMIC); 20162306a36Sopenharmony_ci if (unlikely(r != 0)) { 20262306a36Sopenharmony_ci if (r == -ENOSPC && 20362306a36Sopenharmony_ci started > started_before) 20462306a36Sopenharmony_ci r = 0; 20562306a36Sopenharmony_ci else 20662306a36Sopenharmony_ci r = -1; 20762306a36Sopenharmony_ci break; 20862306a36Sopenharmony_ci } 20962306a36Sopenharmony_ci 21062306a36Sopenharmony_ci ++started; 21162306a36Sopenharmony_ci 21262306a36Sopenharmony_ci if (unlikely(!virtqueue_kick(vq->vq))) { 21362306a36Sopenharmony_ci r = -1; 21462306a36Sopenharmony_ci break; 21562306a36Sopenharmony_ci } 21662306a36Sopenharmony_ci } 21762306a36Sopenharmony_ci 21862306a36Sopenharmony_ci if (started >= bufs) 21962306a36Sopenharmony_ci r = -1; 22062306a36Sopenharmony_ci 22162306a36Sopenharmony_ci if (reset) { 22262306a36Sopenharmony_ci r = ioctl(dev->control, VHOST_TEST_SET_BACKEND, 22362306a36Sopenharmony_ci &no_backend); 22462306a36Sopenharmony_ci assert(!r); 22562306a36Sopenharmony_ci } 22662306a36Sopenharmony_ci 22762306a36Sopenharmony_ci /* Flush out completed bufs if any */ 22862306a36Sopenharmony_ci while (virtqueue_get_buf(vq->vq, &len)) { 22962306a36Sopenharmony_ci ++completed; 23062306a36Sopenharmony_ci r = 0; 23162306a36Sopenharmony_ci } 23262306a36Sopenharmony_ci 23362306a36Sopenharmony_ci if (reset) { 23462306a36Sopenharmony_ci struct vhost_vring_state s = { .index = 0 }; 23562306a36Sopenharmony_ci 23662306a36Sopenharmony_ci vq_reset(vq, vq->vring.num, &dev->vdev); 23762306a36Sopenharmony_ci 23862306a36Sopenharmony_ci r = ioctl(dev->control, VHOST_GET_VRING_BASE, 23962306a36Sopenharmony_ci &s); 24062306a36Sopenharmony_ci assert(!r); 24162306a36Sopenharmony_ci 24262306a36Sopenharmony_ci s.num = 0; 24362306a36Sopenharmony_ci r = ioctl(dev->control, VHOST_SET_VRING_BASE, 24462306a36Sopenharmony_ci &null_state); 24562306a36Sopenharmony_ci assert(!r); 24662306a36Sopenharmony_ci 24762306a36Sopenharmony_ci r = ioctl(dev->control, VHOST_TEST_SET_BACKEND, 24862306a36Sopenharmony_ci &backend); 24962306a36Sopenharmony_ci assert(!r); 25062306a36Sopenharmony_ci 25162306a36Sopenharmony_ci started = completed; 25262306a36Sopenharmony_ci while (completed > next_reset) 25362306a36Sopenharmony_ci next_reset += completed; 25462306a36Sopenharmony_ci } 25562306a36Sopenharmony_ci } while (r == 0); 25662306a36Sopenharmony_ci if (completed == completed_before && started == started_before) 25762306a36Sopenharmony_ci ++spurious; 25862306a36Sopenharmony_ci assert(completed <= bufs); 25962306a36Sopenharmony_ci assert(started <= bufs); 26062306a36Sopenharmony_ci if (completed == bufs) 26162306a36Sopenharmony_ci break; 26262306a36Sopenharmony_ci if (delayed) { 26362306a36Sopenharmony_ci if (virtqueue_enable_cb_delayed(vq->vq)) 26462306a36Sopenharmony_ci wait_for_interrupt(dev); 26562306a36Sopenharmony_ci } else { 26662306a36Sopenharmony_ci if (virtqueue_enable_cb(vq->vq)) 26762306a36Sopenharmony_ci wait_for_interrupt(dev); 26862306a36Sopenharmony_ci } 26962306a36Sopenharmony_ci } 27062306a36Sopenharmony_ci test = 0; 27162306a36Sopenharmony_ci r = ioctl(dev->control, VHOST_TEST_RUN, &test); 27262306a36Sopenharmony_ci assert(r >= 0); 27362306a36Sopenharmony_ci fprintf(stderr, 27462306a36Sopenharmony_ci "spurious wakeups: 0x%llx started=0x%lx completed=0x%lx\n", 27562306a36Sopenharmony_ci spurious, started, completed); 27662306a36Sopenharmony_ci} 27762306a36Sopenharmony_ci 27862306a36Sopenharmony_ciconst char optstring[] = "h"; 27962306a36Sopenharmony_ciconst struct option longopts[] = { 28062306a36Sopenharmony_ci { 28162306a36Sopenharmony_ci .name = "help", 28262306a36Sopenharmony_ci .val = 'h', 28362306a36Sopenharmony_ci }, 28462306a36Sopenharmony_ci { 28562306a36Sopenharmony_ci .name = "event-idx", 28662306a36Sopenharmony_ci .val = 'E', 28762306a36Sopenharmony_ci }, 28862306a36Sopenharmony_ci { 28962306a36Sopenharmony_ci .name = "no-event-idx", 29062306a36Sopenharmony_ci .val = 'e', 29162306a36Sopenharmony_ci }, 29262306a36Sopenharmony_ci { 29362306a36Sopenharmony_ci .name = "indirect", 29462306a36Sopenharmony_ci .val = 'I', 29562306a36Sopenharmony_ci }, 29662306a36Sopenharmony_ci { 29762306a36Sopenharmony_ci .name = "no-indirect", 29862306a36Sopenharmony_ci .val = 'i', 29962306a36Sopenharmony_ci }, 30062306a36Sopenharmony_ci { 30162306a36Sopenharmony_ci .name = "virtio-1", 30262306a36Sopenharmony_ci .val = '1', 30362306a36Sopenharmony_ci }, 30462306a36Sopenharmony_ci { 30562306a36Sopenharmony_ci .name = "no-virtio-1", 30662306a36Sopenharmony_ci .val = '0', 30762306a36Sopenharmony_ci }, 30862306a36Sopenharmony_ci { 30962306a36Sopenharmony_ci .name = "delayed-interrupt", 31062306a36Sopenharmony_ci .val = 'D', 31162306a36Sopenharmony_ci }, 31262306a36Sopenharmony_ci { 31362306a36Sopenharmony_ci .name = "no-delayed-interrupt", 31462306a36Sopenharmony_ci .val = 'd', 31562306a36Sopenharmony_ci }, 31662306a36Sopenharmony_ci { 31762306a36Sopenharmony_ci .name = "batch", 31862306a36Sopenharmony_ci .val = 'b', 31962306a36Sopenharmony_ci .has_arg = required_argument, 32062306a36Sopenharmony_ci }, 32162306a36Sopenharmony_ci { 32262306a36Sopenharmony_ci .name = "reset", 32362306a36Sopenharmony_ci .val = 'r', 32462306a36Sopenharmony_ci .has_arg = optional_argument, 32562306a36Sopenharmony_ci }, 32662306a36Sopenharmony_ci { 32762306a36Sopenharmony_ci } 32862306a36Sopenharmony_ci}; 32962306a36Sopenharmony_ci 33062306a36Sopenharmony_cistatic void help(int status) 33162306a36Sopenharmony_ci{ 33262306a36Sopenharmony_ci fprintf(stderr, "Usage: virtio_test [--help]" 33362306a36Sopenharmony_ci " [--no-indirect]" 33462306a36Sopenharmony_ci " [--no-event-idx]" 33562306a36Sopenharmony_ci " [--no-virtio-1]" 33662306a36Sopenharmony_ci " [--delayed-interrupt]" 33762306a36Sopenharmony_ci " [--batch=random/N]" 33862306a36Sopenharmony_ci " [--reset=N]" 33962306a36Sopenharmony_ci "\n"); 34062306a36Sopenharmony_ci 34162306a36Sopenharmony_ci exit(status); 34262306a36Sopenharmony_ci} 34362306a36Sopenharmony_ci 34462306a36Sopenharmony_ciint main(int argc, char **argv) 34562306a36Sopenharmony_ci{ 34662306a36Sopenharmony_ci struct vdev_info dev; 34762306a36Sopenharmony_ci unsigned long long features = (1ULL << VIRTIO_RING_F_INDIRECT_DESC) | 34862306a36Sopenharmony_ci (1ULL << VIRTIO_RING_F_EVENT_IDX) | (1ULL << VIRTIO_F_VERSION_1); 34962306a36Sopenharmony_ci long batch = 1, reset = 0; 35062306a36Sopenharmony_ci int o; 35162306a36Sopenharmony_ci bool delayed = false; 35262306a36Sopenharmony_ci 35362306a36Sopenharmony_ci for (;;) { 35462306a36Sopenharmony_ci o = getopt_long(argc, argv, optstring, longopts, NULL); 35562306a36Sopenharmony_ci switch (o) { 35662306a36Sopenharmony_ci case -1: 35762306a36Sopenharmony_ci goto done; 35862306a36Sopenharmony_ci case '?': 35962306a36Sopenharmony_ci help(2); 36062306a36Sopenharmony_ci case 'e': 36162306a36Sopenharmony_ci features &= ~(1ULL << VIRTIO_RING_F_EVENT_IDX); 36262306a36Sopenharmony_ci break; 36362306a36Sopenharmony_ci case 'h': 36462306a36Sopenharmony_ci help(0); 36562306a36Sopenharmony_ci case 'i': 36662306a36Sopenharmony_ci features &= ~(1ULL << VIRTIO_RING_F_INDIRECT_DESC); 36762306a36Sopenharmony_ci break; 36862306a36Sopenharmony_ci case '0': 36962306a36Sopenharmony_ci features &= ~(1ULL << VIRTIO_F_VERSION_1); 37062306a36Sopenharmony_ci break; 37162306a36Sopenharmony_ci case 'D': 37262306a36Sopenharmony_ci delayed = true; 37362306a36Sopenharmony_ci break; 37462306a36Sopenharmony_ci case 'b': 37562306a36Sopenharmony_ci if (0 == strcmp(optarg, "random")) { 37662306a36Sopenharmony_ci batch = RANDOM_BATCH; 37762306a36Sopenharmony_ci } else { 37862306a36Sopenharmony_ci batch = strtol(optarg, NULL, 10); 37962306a36Sopenharmony_ci assert(batch > 0); 38062306a36Sopenharmony_ci assert(batch < (long)INT_MAX + 1); 38162306a36Sopenharmony_ci } 38262306a36Sopenharmony_ci break; 38362306a36Sopenharmony_ci case 'r': 38462306a36Sopenharmony_ci if (!optarg) { 38562306a36Sopenharmony_ci reset = 1; 38662306a36Sopenharmony_ci } else { 38762306a36Sopenharmony_ci reset = strtol(optarg, NULL, 10); 38862306a36Sopenharmony_ci assert(reset > 0); 38962306a36Sopenharmony_ci assert(reset < (long)INT_MAX + 1); 39062306a36Sopenharmony_ci } 39162306a36Sopenharmony_ci break; 39262306a36Sopenharmony_ci default: 39362306a36Sopenharmony_ci assert(0); 39462306a36Sopenharmony_ci break; 39562306a36Sopenharmony_ci } 39662306a36Sopenharmony_ci } 39762306a36Sopenharmony_ci 39862306a36Sopenharmony_cidone: 39962306a36Sopenharmony_ci vdev_info_init(&dev, features); 40062306a36Sopenharmony_ci vq_info_add(&dev, 256); 40162306a36Sopenharmony_ci run_test(&dev, &dev.vqs[0], delayed, batch, reset, 0x100000); 40262306a36Sopenharmony_ci return 0; 40362306a36Sopenharmony_ci} 404