Re: [PATCH RFC] virtio-pci: new config layout: using memory BAR

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

 



"Michael S. Tsirkin" <mst@xxxxxxxxxx> writes:

> This adds support for new config, and is designed to work with
> the new layout code in Rusty's new layout branch.
>
> At the moment all fields are in the same memory BAR (bar 2).
> This will be used to test performance and compare
> memory, io and hypercall latency.
>
> Compiles but does not work yet.
> Migration isn't handled yet.
>
> It's not clear what do queue_enable/queue_disable
> fields do, not yet implemented.
>
> Gateway for config access with config cycles
> not yet implemented.
>
> Sending out for early review/flames.
>
> Signed-off-by: Michael S. Tsirkin <mst@xxxxxxxxxx>
> ---
>  hw/virtio/virtio-pci.c     | 393 +++++++++++++++++++++++++++++++++++++++++++--
>  hw/virtio/virtio-pci.h     |  55 +++++++
>  hw/virtio/virtio.c         |  20 +++
>  include/hw/virtio/virtio.h |   4 +
>  4 files changed, 458 insertions(+), 14 deletions(-)
>
> diff --git a/hw/virtio/virtio-pci.c b/hw/virtio/virtio-pci.c
> index 752991a..f4db224 100644
> --- a/hw/virtio/virtio-pci.c
> +++ b/hw/virtio/virtio-pci.c
> @@ -259,6 +259,26 @@ static void virtio_pci_stop_ioeventfd(VirtIOPCIProxy *proxy)
>      proxy->ioeventfd_started = false;
>  }
>  
> +static void virtio_pci_set_status(VirtIOPCIProxy *proxy, uint8_t val)
> +{
> +    VirtIODevice *vdev = proxy->vdev;
> +
> +    if (!(val & VIRTIO_CONFIG_S_DRIVER_OK)) {
> +        virtio_pci_stop_ioeventfd(proxy);
> +    }
> +
> +    virtio_set_status(vdev, val & 0xFF);
> +
> +    if (val & VIRTIO_CONFIG_S_DRIVER_OK) {
> +        virtio_pci_start_ioeventfd(proxy);
> +    }
> +
> +    if (vdev->status == 0) {
> +        virtio_reset(proxy->vdev);
> +        msix_unuse_all_vectors(&proxy->pci_dev);
> +    }
> +}
> +
>  static void virtio_ioport_write(void *opaque, uint32_t addr, uint32_t val)
>  {
>      VirtIOPCIProxy *proxy = opaque;
> @@ -293,20 +313,7 @@ static void virtio_ioport_write(void *opaque, uint32_t addr, uint32_t val)
>          }
>          break;
>      case VIRTIO_PCI_STATUS:
> -        if (!(val & VIRTIO_CONFIG_S_DRIVER_OK)) {
> -            virtio_pci_stop_ioeventfd(proxy);
> -        }
> -
> -        virtio_set_status(vdev, val & 0xFF);
> -
> -        if (val & VIRTIO_CONFIG_S_DRIVER_OK) {
> -            virtio_pci_start_ioeventfd(proxy);
> -        }
> -
> -        if (vdev->status == 0) {
> -            virtio_reset(proxy->vdev);
> -            msix_unuse_all_vectors(&proxy->pci_dev);
> -        }
> +        virtio_pci_set_status(proxy, val);
>  
>          /* Linux before 2.6.34 sets the device as OK without enabling
>             the PCI device bus master bit. In this case we need to disable
> @@ -455,6 +462,226 @@ static void virtio_pci_config_write(void *opaque, hwaddr addr,
>      }
>  }
>  
> +static uint64_t virtio_pci_config_common_read(void *opaque, hwaddr addr,
> +                                              unsigned size)
> +{
> +    VirtIOPCIProxy *proxy = opaque;
> +    VirtIODevice *vdev = proxy->vdev;
> +
> +    uint64_t low = 0xffffffffull;
> +
> +    switch (addr) {
> +    case offsetof(struct virtio_pci_common_cfg, device_feature_select):
> +        return proxy->device_feature_select;

Oh dear no...  Please use defines like the rest of QEMU.

>From a QEMU pov, take a look at:

https://github.com/aliguori/qemu/commit/587c35c1a3fe90f6af0f97927047ef4d3182a659

And:

https://github.com/aliguori/qemu/commit/01ba80a23cf2eb1e15056f82b44b94ec381565cb

Which lets virtio-pci be subclassable and then remaps the config space to
BAR2.

Haven't looked at the proposed new ring layout yet.

Regards,

Anthony Liguori

> +    case offsetof(struct virtio_pci_common_cfg, device_feature):
> +        /* TODO: 64-bit features */
> +	return proxy->device_feature_select ? 0 : proxy->host_features;
> +    case offsetof(struct virtio_pci_common_cfg, guest_feature_select):
> +        return proxy->guest_feature_select;
> +    case offsetof(struct virtio_pci_common_cfg, guest_feature):
> +        /* TODO: 64-bit features */
> +	return proxy->guest_feature_select ? 0 : vdev->guest_features;
> +    case offsetof(struct virtio_pci_common_cfg, msix_config):
> +	return vdev->config_vector;
> +    case offsetof(struct virtio_pci_common_cfg, num_queues):
> +        /* TODO: more exact limit? */
> +	return VIRTIO_PCI_QUEUE_MAX;
> +    case offsetof(struct virtio_pci_common_cfg, device_status):
> +        return vdev->status;
> +
> +	/* About a specific virtqueue. */
> +    case offsetof(struct virtio_pci_common_cfg, queue_select):
> +        return  vdev->queue_sel;
> +    case offsetof(struct virtio_pci_common_cfg, queue_size):
> +        return virtio_queue_get_num(vdev, vdev->queue_sel);
> +    case offsetof(struct virtio_pci_common_cfg, queue_msix_vector):
> +	return virtio_queue_vector(vdev, vdev->queue_sel);
> +    case offsetof(struct virtio_pci_common_cfg, queue_enable):
> +        /* TODO */
> +	return 0;
> +    case offsetof(struct virtio_pci_common_cfg, queue_notify_off):
> +        return vdev->queue_sel;
> +    case offsetof(struct virtio_pci_common_cfg, queue_desc):
> +        return virtio_queue_get_desc_addr(vdev, vdev->queue_sel) & low;
> +    case offsetof(struct virtio_pci_common_cfg, queue_desc) + 4:
> +        return virtio_queue_get_desc_addr(vdev, vdev->queue_sel) >> 32;
> +    case offsetof(struct virtio_pci_common_cfg, queue_avail):
> +        return virtio_queue_get_avail_addr(vdev, vdev->queue_sel) & low;
> +    case offsetof(struct virtio_pci_common_cfg, queue_avail) + 4:
> +        return virtio_queue_get_avail_addr(vdev, vdev->queue_sel) >> 32;
> +    case offsetof(struct virtio_pci_common_cfg, queue_used):
> +        return virtio_queue_get_used_addr(vdev, vdev->queue_sel) & low;
> +    case offsetof(struct virtio_pci_common_cfg, queue_used) + 4:
> +        return virtio_queue_get_used_addr(vdev, vdev->queue_sel) >> 32;
> +    default:
> +        return 0;
> +    }
> +}
> +
> +static void virtio_pci_config_common_write(void *opaque, hwaddr addr,
> +                                           uint64_t val, unsigned size)
> +{
> +    VirtIOPCIProxy *proxy = opaque;
> +    VirtIODevice *vdev = proxy->vdev;
> +
> +    uint64_t low = 0xffffffffull;
> +    uint64_t high = ~low;
> +
> +    switch (addr) {
> +    case offsetof(struct virtio_pci_common_cfg, device_feature_select):
> +        proxy->device_feature_select = val;
> +        break;
> +    case offsetof(struct virtio_pci_common_cfg, device_feature):
> +        break;
> +    case offsetof(struct virtio_pci_common_cfg, guest_feature_select):
> +        proxy->guest_feature_select = val;
> +        break;
> +    case offsetof(struct virtio_pci_common_cfg, guest_feature):
> +        /* TODO: 64-bit features */
> +	if (!proxy->guest_feature_select) {
> +            virtio_set_features(vdev, val);
> +        }
> +        break;
> +    case offsetof(struct virtio_pci_common_cfg, msix_config):
> +	vdev->config_vector = val;
> +        break;
> +    case offsetof(struct virtio_pci_common_cfg, num_queues):
> +        break;
> +    case offsetof(struct virtio_pci_common_cfg, device_status):
> +        virtio_pci_set_status(proxy, val);
> +        break;
> +	/* About a specific virtqueue. */
> +    case offsetof(struct virtio_pci_common_cfg, queue_select):
> +        assert(val < VIRTIO_PCI_QUEUE_MAX);
> +        vdev->queue_sel = val;
> +        break;
> +    case offsetof(struct virtio_pci_common_cfg, queue_size):
> +        assert(val && val < 0x8ffff && !(val & (val - 1)));
> +        virtio_queue_set_num(vdev, vdev->queue_sel, val);
> +        break;
> +    case offsetof(struct virtio_pci_common_cfg, queue_msix_vector):
> +	virtio_queue_set_vector(vdev, vdev->queue_sel, val);
> +        break;
> +    case offsetof(struct virtio_pci_common_cfg, queue_enable):
> +        /* TODO */
> +	break;
> +    case offsetof(struct virtio_pci_common_cfg, queue_notify_off):
> +        break;
> +    case offsetof(struct virtio_pci_common_cfg, queue_desc):
> +        val &= low;
> +        val |= virtio_queue_get_desc_addr(vdev, vdev->queue_sel) & high;
> +        virtio_queue_set_desc_addr(vdev, vdev->queue_sel, val);
> +        break;
> +    case offsetof(struct virtio_pci_common_cfg, queue_desc) + 4:
> +        val = val << 32;
> +        val |= virtio_queue_get_desc_addr(vdev, vdev->queue_sel) & low;
> +        virtio_queue_set_desc_addr(vdev, vdev->queue_sel, val);
> +        break;
> +    case offsetof(struct virtio_pci_common_cfg, queue_avail):
> +        val &= low;
> +        val |= virtio_queue_get_avail_addr(vdev, vdev->queue_sel) & high;
> +        virtio_queue_set_avail_addr(vdev, vdev->queue_sel, val);
> +        break;
> +    case offsetof(struct virtio_pci_common_cfg, queue_avail) + 4:
> +        val = val << 32;
> +        val |= virtio_queue_get_avail_addr(vdev, vdev->queue_sel) & low;
> +        virtio_queue_set_avail_addr(vdev, vdev->queue_sel, val);
> +        break;
> +    case offsetof(struct virtio_pci_common_cfg, queue_used):
> +        val &= low;
> +        val |= virtio_queue_get_used_addr(vdev, vdev->queue_sel) & high;
> +        virtio_queue_set_used_addr(vdev, vdev->queue_sel, val);
> +        break;
> +    case offsetof(struct virtio_pci_common_cfg, queue_used) + 4:
> +        val = val << 32;
> +        val |= virtio_queue_get_used_addr(vdev, vdev->queue_sel) & low;
> +        virtio_queue_set_used_addr(vdev, vdev->queue_sel, val);
> +        break;
> +    default:
> +        break;
> +    }
> +}
> +
> +static uint64_t virtio_pci_config_isr_read(void *opaque, hwaddr addr,
> +                                           unsigned size)
> +{
> +    VirtIOPCIProxy *proxy = opaque;
> +    VirtIODevice *vdev = proxy->vdev;
> +    uint8_t ret;
> +
> +    /* reading from the ISR also clears it. */
> +    ret = vdev->isr;
> +    vdev->isr = 0;
> +    qemu_set_irq(proxy->pci_dev.irq[0], 0);
> +    return ret;
> +}
> +
> +static void virtio_pci_config_isr_write(void *opaque, hwaddr addr,
> +                                           uint64_t val, unsigned size)
> +{
> +}
> +
> +static uint64_t virtio_pci_config_notify_read(void *opaque, hwaddr addr,
> +                                              unsigned size)
> +{
> +    return 0;
> +}
> +
> +static void virtio_pci_config_notify_write(void *opaque, hwaddr addr,
> +                                           uint64_t val, unsigned size)
> +{
> +    VirtIOPCIProxy *proxy = opaque;
> +    VirtIODevice *vdev = proxy->vdev;
> +    if (val < VIRTIO_PCI_QUEUE_MAX) {
> +        virtio_queue_notify(vdev, val);
> +    }
> +}
> +
> +static uint64_t virtio_pci_config_device_read(void *opaque, hwaddr addr,
> +                                              unsigned size)
> +{
> +    VirtIOPCIProxy *proxy = opaque;
> +    uint64_t val = 0;
> +    switch (size) {
> +    case 1:
> +        val = virtio_config_readb(proxy->vdev, addr);
> +        break;
> +    case 2:
> +        val = virtio_config_readw(proxy->vdev, addr);
> +        break;
> +    case 4:
> +        /* Most devices don't have 64 bit config fields.
> +         * Block is an exception: first 8 bytes include
> +         * a 64 bit capacity field.
> +         */
> +        if (VIRTIO_HOST_IS_BIG_ENDIAN &&
> +            proxy->vdev->device_id == VIRTIO_ID_BLOCK && addr < 8) {
> +            /* Swap first two words */
> +            addr ^= 0x4;
> +        }
> +        val = virtio_config_readl(proxy->vdev, addr);
> +        break;
> +    }
> +    return val;
> +}
> +
> +static void virtio_pci_config_device_write(void *opaque, hwaddr addr,
> +                                           uint64_t val, unsigned size)
> +{
> +    VirtIOPCIProxy *proxy = opaque;
> +    switch (size) {
> +    case 1:
> +        virtio_config_writeb(proxy->vdev, addr, val);
> +        break;
> +    case 2:
> +        virtio_config_writew(proxy->vdev, addr, val);
> +        break;
> +    case 4:
> +        virtio_config_writel(proxy->vdev, addr, val);
> +        break;
> +    }
> +}
> +
>  static const MemoryRegionOps virtio_pci_config_ops = {
>      .read = virtio_pci_config_read,
>      .write = virtio_pci_config_write,
> @@ -465,6 +692,46 @@ static const MemoryRegionOps virtio_pci_config_ops = {
>      .endianness = DEVICE_LITTLE_ENDIAN,
>  };
>  
> +static const MemoryRegionOps virtio_pci_config_common_ops = {
> +    .read = virtio_pci_config_common_read,
> +    .write = virtio_pci_config_common_write,
> +    .impl = {
> +        .min_access_size = 1,
> +        .max_access_size = 4,
> +    },
> +    .endianness = DEVICE_LITTLE_ENDIAN,
> +};
> +
> +static const MemoryRegionOps virtio_pci_config_isr_ops = {
> +    .read = virtio_pci_config_isr_read,
> +    .write = virtio_pci_config_isr_write,
> +    .impl = {
> +        .min_access_size = 1,
> +        .max_access_size = 1,
> +    },
> +    .endianness = DEVICE_LITTLE_ENDIAN,
> +};
> +
> +static const MemoryRegionOps virtio_pci_config_notify_ops = {
> +    .read = virtio_pci_config_notify_read,
> +    .write = virtio_pci_config_notify_write,
> +    .impl = {
> +        .min_access_size = 2,
> +        .max_access_size = 2,
> +    },
> +    .endianness = DEVICE_LITTLE_ENDIAN,
> +};
> +
> +static const MemoryRegionOps virtio_pci_config_device_ops = {
> +    .read = virtio_pci_config_device_read,
> +    .write = virtio_pci_config_device_write,
> +    .impl = {
> +        .min_access_size = 1,
> +        .max_access_size = 4,
> +    },
> +    .endianness = DEVICE_LITTLE_ENDIAN,
> +};
> +
>  static void virtio_write_config(PCIDevice *pci_dev, uint32_t address,
>                                  uint32_t val, int len)
>  {
> @@ -949,11 +1216,49 @@ static const TypeInfo virtio_9p_pci_info = {
>   * virtio-pci: This is the PCIDevice which has a virtio-pci-bus.
>   */
>  
> +#define VIRTIO_PCI_CONFIG_BAR_NUM 2
> +
> +static void *virtio_pci_cap_add(VirtIOPCIProxy *proxy,
> +                                const char *name,
> +                                MemoryRegion *reg,
> +                                const MemoryRegionOps *ops,
> +                                unsigned offset,
> +                                unsigned size,
> +                                unsigned cap_type,
> +                                unsigned cap_length)
> +{
> +    struct virtio_pci_cap *cap;
> +    int c;
> +    memory_region_init_io(reg, ops, proxy, name, size);
> +    memory_region_add_subregion(&proxy->config_bar, offset, reg);
> +
> +    if (!cap_length) {
> +        cap_length = sizeof *cap;
> +    }
> +    c = pci_add_capability(&proxy->pci_dev, PCI_CAP_ID_VNDR, 0, cap_length);
> +    assert(c > 0);
> +    cap = (void *)proxy->pci_dev.config + c;
> +    cap->cap_length = cap_length;
> +    cap->cfg_type = cap_type;
> +    cap->bar = VIRTIO_PCI_CONFIG_BAR_NUM;
> +    cap->offset = offset;
> +    cap->length = size;
> +
> +    return cap;
> +}
> +
> +static void virtio_pci_cap_del(VirtIOPCIProxy *proxy, MemoryRegion *reg)
> +{
> +    memory_region_del_subregion(&proxy->config_bar, reg);
> +    memory_region_destroy(reg);
> +}
> +
>  /* This is called by virtio-bus just after the device is plugged. */
>  static void virtio_pci_device_plugged(DeviceState *d)
>  {
>      VirtIOPCIProxy *proxy = VIRTIO_PCI(d);
>      VirtioBusState *bus = &proxy->bus;
> +    struct virtio_pci_notify_cap *notify_cap;
>      uint8_t *config;
>      uint32_t size;
>  
> @@ -986,6 +1291,59 @@ static void virtio_pci_device_plugged(DeviceState *d)
>      pci_register_bar(&proxy->pci_dev, 0, PCI_BASE_ADDRESS_SPACE_IO,
>                       &proxy->bar);
>  
> +    /* New config layout */
> +    /* Four capabilities: common, notify, isr, device cfg */
> +#define VIRTIO_PCI_CONFIG_BAR_SIZE 0x1000
> +#define VIRTIO_PCI_CONFIG_COMMON 0x0
> +#define VIRTIO_PCI_CONFIG_NOTIFY 0x100
> +#define VIRTIO_PCI_CONFIG_ISR 0x200
> +#define VIRTIO_PCI_CONFIG_DEVICE 0x300
> +
> +    /* Make sure we left enough space for all vqs */
> +    assert(VIRTIO_PCI_CONFIG_ISR - VIRTIO_PCI_CONFIG_NOTIFY >=
> +           VIRTIO_PCI_QUEUE_MAX * 2);
> +    assert(VIRTIO_PCI_CONFIG_BAR_SIZE - VIRTIO_PCI_CONFIG_DEVICE >=
> +           proxy->vdev->config_len);
> +
> +    memory_region_init(&proxy->config_bar, "virtio-pci-config",
> +                       VIRTIO_PCI_CONFIG_BAR_SIZE);
> +
> +    virtio_pci_cap_add(proxy, "virtio-pci-common", 
> +                       &proxy->config_common,
> +                       &virtio_pci_config_common_ops,
> +                       VIRTIO_PCI_CONFIG_COMMON,
> +                       sizeof(struct virtio_pci_common_cfg),
> +                       VIRTIO_PCI_CAP_COMMON_CFG,
> +                       0);
> +    notify_cap = virtio_pci_cap_add(proxy, "virtio-pci-notify", 
> +                                    &proxy->config_notify,
> +                                    &virtio_pci_config_notify_ops,
> +                                    VIRTIO_PCI_CONFIG_NOTIFY,
> +                                    VIRTIO_PCI_QUEUE_MAX * 2,
> +                                    VIRTIO_PCI_CAP_NOTIFY_CFG,
> +                                    sizeof *notify_cap);
> +    notify_cap->notify_off_multiplier = 0x2;
> +    virtio_pci_cap_add(proxy, "virtio-pci-isr", 
> +                       &proxy->config_isr,
> +                       &virtio_pci_config_isr_ops,
> +                       VIRTIO_PCI_CONFIG_ISR,
> +                       0x1,
> +                       VIRTIO_PCI_CAP_ISR_CFG,
> +                       0);
> +    if (proxy->vdev->config_len) {
> +        virtio_pci_cap_add(proxy, "virtio-pci-device", 
> +                           &proxy->config_device,
> +                           &virtio_pci_config_device_ops,
> +                           VIRTIO_PCI_CONFIG_DEVICE,
> +                           proxy->vdev->config_len,
> +                           VIRTIO_PCI_CAP_DEVICE_CFG,
> +                           0);
> +    }
> +
> +    pci_register_bar(&proxy->pci_dev, VIRTIO_PCI_CONFIG_BAR_NUM,
> +                     PCI_BASE_ADDRESS_SPACE_MEMORY,
> +                     &proxy->config_bar);
> +
>      if (!kvm_has_many_ioeventfds()) {
>          proxy->flags &= ~VIRTIO_PCI_FLAG_USE_IOEVENTFD;
>      }
> @@ -1012,6 +1370,13 @@ static void virtio_pci_exit(PCIDevice *pci_dev)
>      VirtIOPCIProxy *proxy = VIRTIO_PCI(pci_dev);
>      virtio_pci_stop_ioeventfd(proxy);
>      memory_region_destroy(&proxy->bar);
> +    virtio_pci_cap_del(proxy, &proxy->config_common);
> +    virtio_pci_cap_del(proxy, &proxy->config_notify);
> +    virtio_pci_cap_del(proxy, &proxy->config_isr);
> +    if (&proxy->vdev->config_len) {
> +        virtio_pci_cap_del(proxy, &proxy->config_device);
> +    }
> +    memory_region_destroy(&proxy->config_bar);
>      msix_uninit_exclusive_bar(pci_dev);
>  }
>  
> diff --git a/hw/virtio/virtio-pci.h b/hw/virtio/virtio-pci.h
> index 917bcc5..01005e7 100644
> --- a/hw/virtio/virtio-pci.h
> +++ b/hw/virtio/virtio-pci.h
> @@ -84,6 +84,11 @@ struct VirtIOPCIProxy {
>      PCIDevice pci_dev;
>      VirtIODevice *vdev;
>      MemoryRegion bar;
> +    MemoryRegion config_bar;
> +    MemoryRegion config_common;
> +    MemoryRegion config_isr;
> +    MemoryRegion config_notify;
> +    MemoryRegion config_device;
>      uint32_t flags;
>      uint32_t class_code;
>      uint32_t nvectors;
> @@ -93,6 +98,8 @@ struct VirtIOPCIProxy {
>      VirtIOIRQFD *vector_irqfd;
>      int nvqs_with_notifiers;
>      VirtioBusState bus;
> +    unsigned device_feature_select;
> +    unsigned guest_feature_select;
>  };
>  
>  
> @@ -203,4 +210,52 @@ struct VirtIORngPCI {
>  /* Virtio ABI version, if we increment this, we break the guest driver. */
>  #define VIRTIO_PCI_ABI_VERSION          0
>  
> +/* IDs for different capabilities.  Must all exist. */
> +/* Common configuration */
> +#define VIRTIO_PCI_CAP_COMMON_CFG	1
> +/* Notifications */
> +#define VIRTIO_PCI_CAP_NOTIFY_CFG	2
> +/* ISR access */
> +#define VIRTIO_PCI_CAP_ISR_CFG		3
> +/* Device specific confiuration */
> +#define VIRTIO_PCI_CAP_DEVICE_CFG	4
> +
> +/* This is the PCI capability header: */
> +struct virtio_pci_cap {
> +	uint8_t cap_vndr;	/* Generic PCI field: PCI_CAP_ID_VNDR */
> +	uint8_t cap_next;	/* Generic PCI field: next ptr. */
> +	uint8_t cap_length;	/* Generic PCI field: capability length. */
> +	uint8_t cfg_type;	/* One of the VIRTIO_PCI_CAP_*_CFG. */
> +	uint8_t bar;		/* Where to find it. */
> +	uint32_t offset;	/* Offset within bar. */
> +	uint32_t length;	/* Length. */
> +};
> +
> +struct virtio_pci_notify_cap {
> +	struct virtio_pci_cap cap;
> +	uint32_t notify_off_multiplier;	/* Multiplier for queue_notify_off. */
> +};
> +
> +/* Fields in VIRTIO_PCI_CAP_COMMON_CFG: */
> +struct virtio_pci_common_cfg {
> +	/* About the whole device. */
> +	uint32_t device_feature_select;	/* read-write */
> +	uint32_t device_feature;		/* read-only */
> +	uint32_t guest_feature_select;	/* read-write */
> +	uint32_t guest_feature;		/* read-only */
> +	uint16_t msix_config;		/* read-write */
> +	uint16_t num_queues;		/* read-only */
> +	uint8_t device_status;		/* read-write */
> +	uint8_t unused1;
> +
> +	/* About a specific virtqueue. */
> +	uint16_t queue_select;		/* read-write */
> +	uint16_t queue_size;		/* read-write, power of 2. */
> +	uint16_t queue_msix_vector;	/* read-write */
> +	uint16_t queue_enable;		/* read-write */
> +	uint16_t queue_notify_off;	/* read-only */
> +	uint64_t queue_desc;		/* read-write */
> +	uint64_t queue_avail;		/* read-write */
> +	uint64_t queue_used;		/* read-write */
> +};
>  #endif
> diff --git a/hw/virtio/virtio.c b/hw/virtio/virtio.c
> index 8176c14..e54d692 100644
> --- a/hw/virtio/virtio.c
> +++ b/hw/virtio/virtio.c
> @@ -672,6 +672,11 @@ int virtio_queue_get_num(VirtIODevice *vdev, int n)
>      return vdev->vq[n].vring.num;
>  }
>  
> +void virtio_queue_set_num(VirtIODevice *vdev, int n, int num)
> +{
> +    vdev->vq[n].vring.num = num;
> +}
> +
>  int virtio_queue_get_id(VirtQueue *vq)
>  {
>      VirtIODevice *vdev = vq->vdev;
> @@ -987,6 +992,21 @@ hwaddr virtio_queue_get_used_addr(VirtIODevice *vdev, int n)
>      return vdev->vq[n].vring.used;
>  }
>  
> +void virtio_queue_set_desc_addr(VirtIODevice *vdev, int n, hwaddr addr)
> +{
> +    vdev->vq[n].vring.desc = addr;
> +}
> +
> +void virtio_queue_set_avail_addr(VirtIODevice *vdev, int n, hwaddr addr)
> +{
> +    vdev->vq[n].vring.avail = addr;
> +}
> +
> +void virtio_queue_set_used_addr(VirtIODevice *vdev, int n, hwaddr addr)
> +{
> +    vdev->vq[n].vring.used = addr;
> +}
> +
>  hwaddr virtio_queue_get_ring_addr(VirtIODevice *vdev, int n)
>  {
>      return vdev->vq[n].vring.desc;
> diff --git a/include/hw/virtio/virtio.h b/include/hw/virtio/virtio.h
> index a6c5c53..d056d58 100644
> --- a/include/hw/virtio/virtio.h
> +++ b/include/hw/virtio/virtio.h
> @@ -199,6 +199,7 @@ void virtio_config_writel(VirtIODevice *vdev, uint32_t addr, uint32_t data);
>  void virtio_queue_set_addr(VirtIODevice *vdev, int n, hwaddr addr);
>  hwaddr virtio_queue_get_addr(VirtIODevice *vdev, int n);
>  int virtio_queue_get_num(VirtIODevice *vdev, int n);
> +void virtio_queue_set_num(VirtIODevice *vdev, int n, int num);
>  void virtio_queue_notify(VirtIODevice *vdev, int n);
>  uint16_t virtio_queue_vector(VirtIODevice *vdev, int n);
>  void virtio_queue_set_vector(VirtIODevice *vdev, int n, uint16_t vector);
> @@ -226,6 +227,9 @@ typedef struct VirtIORNGConf VirtIORNGConf;
>  hwaddr virtio_queue_get_desc_addr(VirtIODevice *vdev, int n);
>  hwaddr virtio_queue_get_avail_addr(VirtIODevice *vdev, int n);
>  hwaddr virtio_queue_get_used_addr(VirtIODevice *vdev, int n);
> +void virtio_queue_set_desc_addr(VirtIODevice *vdev, int n, hwaddr addr);
> +void virtio_queue_set_avail_addr(VirtIODevice *vdev, int n, hwaddr addr);
> +void virtio_queue_set_used_addr(VirtIODevice *vdev, int n, hwaddr addr);
>  hwaddr virtio_queue_get_ring_addr(VirtIODevice *vdev, int n);
>  hwaddr virtio_queue_get_desc_size(VirtIODevice *vdev, int n);
>  hwaddr virtio_queue_get_avail_size(VirtIODevice *vdev, int n);
> -- 
> MST
> --
> To unsubscribe from this list: send the line "unsubscribe kvm" in
> the body of a message to majordomo@xxxxxxxxxxxxxxx
> More majordomo info at  http://vger.kernel.org/majordomo-info.html

--
To unsubscribe from this list: send the line "unsubscribe kvm" in
the body of a message to majordomo@xxxxxxxxxxxxxxx
More majordomo info at  http://vger.kernel.org/majordomo-info.html




[Index of Archives]     [KVM ARM]     [KVM ia64]     [KVM ppc]     [Virtualization Tools]     [Spice Development]     [Libvirt]     [Libvirt Users]     [Linux USB Devel]     [Linux Audio Users]     [Yosemite Questions]     [Linux Kernel]     [Linux SCSI]     [XFree86]
  Powered by Linux