* [Qemu-devel] [RFC v2 00/12] Virtio-mmio refactoring.
@ 2012-09-17 10:00 Evgeny Voevodin
2012-09-17 10:00 ` [Qemu-devel] [RFC v2 01/12] virtio: Add support for guest setting of queue size Evgeny Voevodin
` (12 more replies)
0 siblings, 13 replies; 17+ messages in thread
From: Evgeny Voevodin @ 2012-09-17 10:00 UTC (permalink / raw)
To: qemu-devel; +Cc: peter.maydell, kyungmin.park, aliguori, Evgeny Voevodin
Previous RFC you can find at
http://lists.gnu.org/archive/html/qemu-devel/2012-04/msg03665.html
Yes, long time ago...
Since I'm not sure when I'll be able to continue on this,
I'm publishing this work as is.
In this patchset I tried to split virtio-xxx-pci devices into
virtio-pci + virtio-xxx (blk, net, serial,...). Also virtio-mmio
transport is introduced based on Peter's work which is accessible
here: http://lists.gnu.org/archive/html/qemu-devel/2011-11/msg01870.html
The main idea was to let users specify
-device virtio-pci,id=virtio-pci.0
-device virtio-blk,transport=virtio-pci.0,...
and
-device virtio-mmio,id=virtio-mmio.0
-device virtio-blk,transport=virtio-mmio.0,...
I created virtio-pci and virtio-mmio transport devices and tried to enclose
back-end functionality into virtio-blk, virtio-net, etc. On
initialization of transport device it creates a bus to which a back-end device
could be connected. Each back-end device is implemented in corresponding source
file. As for PCI transport, I temporary placed it in a new virtio-pci-new.c file
to not break a functionality of still presented virtio-xxx-pci devices.
Known issues to be resolved:
1. On creation of back-end we need to resolve somehow if props were explicitly set
by user.
2. Back-end device can't be initialized if there are no free bus created by transport,
so you can't specify
-device virtio-blk,transport=virtio-pci.0,...
-device virtio-pci,id=virtio-pci.0
3. Implement virtio-xxx-devices such that they just create virtio-pci and virtio-xxx
devices during initialization.
4. Refactor all remaining back-ends since I just tried blk, net, serial and balloon.
5. Refactor s390
6. Further?
Evgeny Voevodin (9):
Virtio: Add transport bindings.
hw/qdev-properties.c: Add "transport" property.
hw/pci.c: Make pci_add_option_rom global visible
hw/virtio-serial-bus.c: Add virtio-serial device.
hw/virtio-balloon.c: Add virtio-balloon device.
hw/virtio-net.c: Add virtio-net device.
hw/virtio-blk.c: Add virtio-blk device.
hw/virtio-pci-new.c: Add VirtIOPCI device.
hw/exynos4210.c: Create two virtio-mmio transport instances.
Peter Maydell (3):
virtio: Add support for guest setting of queue size
virtio: Support transports which can specify the vring alignment
Add MMIO based virtio transport
hw/Makefile.objs | 3 +
hw/exynos4210.c | 13 +
hw/pci.c | 3 +-
hw/pci.h | 2 +
hw/qdev-properties.c | 29 ++
hw/qdev.h | 3 +
hw/virtio-balloon.c | 42 +++
hw/virtio-balloon.h | 9 +
hw/virtio-blk.c | 65 ++++
hw/virtio-blk.h | 15 +
hw/virtio-mmio.c | 400 +++++++++++++++++++++
hw/virtio-net.c | 59 +++
hw/virtio-net.h | 16 +
hw/virtio-pci-new.c | 925 ++++++++++++++++++++++++++++++++++++++++++++++++
hw/virtio-pci.h | 18 +
hw/virtio-serial-bus.c | 44 +++
hw/virtio-serial.h | 11 +
hw/virtio-transport.c | 147 ++++++++
hw/virtio-transport.h | 74 ++++
hw/virtio.c | 20 +-
hw/virtio.h | 2 +
21 files changed, 1896 insertions(+), 4 deletions(-)
create mode 100644 hw/virtio-mmio.c
create mode 100644 hw/virtio-pci-new.c
create mode 100644 hw/virtio-transport.c
create mode 100644 hw/virtio-transport.h
--
1.7.9.5
^ permalink raw reply [flat|nested] 17+ messages in thread
* [Qemu-devel] [RFC v2 01/12] virtio: Add support for guest setting of queue size
2012-09-17 10:00 [Qemu-devel] [RFC v2 00/12] Virtio-mmio refactoring Evgeny Voevodin
@ 2012-09-17 10:00 ` Evgeny Voevodin
2012-09-17 10:00 ` [Qemu-devel] [RFC v2 02/12] virtio: Support transports which can specify the vring alignment Evgeny Voevodin
` (11 subsequent siblings)
12 siblings, 0 replies; 17+ messages in thread
From: Evgeny Voevodin @ 2012-09-17 10:00 UTC (permalink / raw)
To: qemu-devel; +Cc: peter.maydell, kyungmin.park, aliguori, Evgeny Voevodin
From: Peter Maydell <peter.maydell@linaro.org>
The MMIO virtio transport spec allows the guest to tell the host how
large the queue size is. Add virtio_queue_set_num() function which
implements this in the QEMU common virtio support code.
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
Signed-off-by: Evgeny Voevodin <e.voevodin@samsung.com>
---
hw/virtio.c | 6 ++++++
hw/virtio.h | 1 +
2 files changed, 7 insertions(+)
diff --git a/hw/virtio.c b/hw/virtio.c
index 209c763..5334326 100644
--- a/hw/virtio.c
+++ b/hw/virtio.c
@@ -628,6 +628,12 @@ target_phys_addr_t virtio_queue_get_addr(VirtIODevice *vdev, int n)
return vdev->vq[n].pa;
}
+void virtio_queue_set_num(VirtIODevice *vdev, int n, int num)
+{
+ vdev->vq[n].vring.num = num;
+ virtqueue_init(&vdev->vq[n]);
+}
+
int virtio_queue_get_num(VirtIODevice *vdev, int n)
{
return vdev->vq[n].vring.num;
diff --git a/hw/virtio.h b/hw/virtio.h
index 7a4f564..eb9953f 100644
--- a/hw/virtio.h
+++ b/hw/virtio.h
@@ -177,6 +177,7 @@ void virtio_config_writew(VirtIODevice *vdev, uint32_t addr, uint32_t data);
void virtio_config_writel(VirtIODevice *vdev, uint32_t addr, uint32_t data);
void virtio_queue_set_addr(VirtIODevice *vdev, int n, target_phys_addr_t addr);
target_phys_addr_t virtio_queue_get_addr(VirtIODevice *vdev, int n);
+void virtio_queue_set_num(VirtIODevice *vdev, int n, int num);
int virtio_queue_get_num(VirtIODevice *vdev, int n);
void virtio_queue_notify(VirtIODevice *vdev, int n);
uint16_t virtio_queue_vector(VirtIODevice *vdev, int n);
--
1.7.9.5
^ permalink raw reply related [flat|nested] 17+ messages in thread
* [Qemu-devel] [RFC v2 02/12] virtio: Support transports which can specify the vring alignment
2012-09-17 10:00 [Qemu-devel] [RFC v2 00/12] Virtio-mmio refactoring Evgeny Voevodin
2012-09-17 10:00 ` [Qemu-devel] [RFC v2 01/12] virtio: Add support for guest setting of queue size Evgeny Voevodin
@ 2012-09-17 10:00 ` Evgeny Voevodin
2012-09-17 10:00 ` [Qemu-devel] [RFC v2 03/12] Virtio: Add transport bindings Evgeny Voevodin
` (10 subsequent siblings)
12 siblings, 0 replies; 17+ messages in thread
From: Evgeny Voevodin @ 2012-09-17 10:00 UTC (permalink / raw)
To: qemu-devel; +Cc: peter.maydell, kyungmin.park, aliguori, Evgeny Voevodin
From: Peter Maydell <peter.maydell@linaro.org>
Support virtio transports which can specify the vring alignment
(ie where the guest communicates this to the host) by providing
a new virtio_queue_set_align() function. (The default alignment
remains as before.)
FIXME save/load support for this new field!
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
Signed-off-by: Evgeny Voevodin <e.voevodin@samsung.com>
---
hw/virtio.c | 14 ++++++++++++--
hw/virtio.h | 1 +
2 files changed, 13 insertions(+), 2 deletions(-)
diff --git a/hw/virtio.c b/hw/virtio.c
index 5334326..4f47d4e 100644
--- a/hw/virtio.c
+++ b/hw/virtio.c
@@ -19,7 +19,9 @@
#include "qemu-barrier.h"
/* The alignment to use between consumer and producer parts of vring.
- * x86 pagesize again. */
+ * x86 pagesize again. This is the default, used by transports like PCI
+ * which don't provide a means for the guest to tell the host the alignment.
+ */
#define VIRTIO_PCI_VRING_ALIGN 4096
typedef struct VRingDesc
@@ -53,6 +55,7 @@ typedef struct VRingUsed
typedef struct VRing
{
unsigned int num;
+ unsigned int align;
target_phys_addr_t desc;
target_phys_addr_t avail;
target_phys_addr_t used;
@@ -90,7 +93,7 @@ static void virtqueue_init(VirtQueue *vq)
vq->vring.avail = pa + vq->vring.num * sizeof(VRingDesc);
vq->vring.used = vring_align(vq->vring.avail +
offsetof(VRingAvail, ring[vq->vring.num]),
- VIRTIO_PCI_VRING_ALIGN);
+ vq->vring.align);
}
static inline uint64_t vring_desc_addr(target_phys_addr_t desc_pa, int i)
@@ -646,6 +649,12 @@ int virtio_queue_get_id(VirtQueue *vq)
return vq - &vdev->vq[0];
}
+void virtio_queue_set_align(VirtIODevice *vdev, int n, int align)
+{
+ vdev->vq[n].vring.align = align;
+ virtqueue_init(&vdev->vq[n]);
+}
+
void virtio_queue_notify_vq(VirtQueue *vq)
{
if (vq->vring.desc) {
@@ -686,6 +695,7 @@ VirtQueue *virtio_add_queue(VirtIODevice *vdev, int queue_size,
abort();
vdev->vq[i].vring.num = queue_size;
+ vdev->vq[i].vring.align = VIRTIO_PCI_VRING_ALIGN;
vdev->vq[i].handle_output = handle_output;
return &vdev->vq[i];
diff --git a/hw/virtio.h b/hw/virtio.h
index eb9953f..3f16367 100644
--- a/hw/virtio.h
+++ b/hw/virtio.h
@@ -179,6 +179,7 @@ void virtio_queue_set_addr(VirtIODevice *vdev, int n, target_phys_addr_t addr);
target_phys_addr_t virtio_queue_get_addr(VirtIODevice *vdev, int n);
void virtio_queue_set_num(VirtIODevice *vdev, int n, int num);
int virtio_queue_get_num(VirtIODevice *vdev, int n);
+void virtio_queue_set_align(VirtIODevice *vdev, int n, int align);
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);
--
1.7.9.5
^ permalink raw reply related [flat|nested] 17+ messages in thread
* [Qemu-devel] [RFC v2 03/12] Virtio: Add transport bindings.
2012-09-17 10:00 [Qemu-devel] [RFC v2 00/12] Virtio-mmio refactoring Evgeny Voevodin
2012-09-17 10:00 ` [Qemu-devel] [RFC v2 01/12] virtio: Add support for guest setting of queue size Evgeny Voevodin
2012-09-17 10:00 ` [Qemu-devel] [RFC v2 02/12] virtio: Support transports which can specify the vring alignment Evgeny Voevodin
@ 2012-09-17 10:00 ` Evgeny Voevodin
2012-09-17 10:00 ` [Qemu-devel] [RFC v2 04/12] hw/qdev-properties.c: Add "transport" property Evgeny Voevodin
` (9 subsequent siblings)
12 siblings, 0 replies; 17+ messages in thread
From: Evgeny Voevodin @ 2012-09-17 10:00 UTC (permalink / raw)
To: qemu-devel; +Cc: peter.maydell, kyungmin.park, aliguori, Evgeny Voevodin
Signed-off-by: Evgeny Voevodin <e.voevodin@samsung.com>
---
hw/Makefile.objs | 1 +
hw/virtio-transport.c | 147 +++++++++++++++++++++++++++++++++++++++++++++++++
hw/virtio-transport.h | 74 +++++++++++++++++++++++++
3 files changed, 222 insertions(+)
create mode 100644 hw/virtio-transport.c
create mode 100644 hw/virtio-transport.h
diff --git a/hw/Makefile.objs b/hw/Makefile.objs
index 6dfebd2..db4c16d 100644
--- a/hw/Makefile.objs
+++ b/hw/Makefile.objs
@@ -2,6 +2,7 @@ hw-obj-y = usb/ ide/
hw-obj-y += loader.o
hw-obj-$(CONFIG_VIRTIO) += virtio-console.o
hw-obj-$(CONFIG_VIRTIO_PCI) += virtio-pci.o
+hw-obj-$(CONFIG_VIRTIO) += virtio-transport.o
hw-obj-y += fw_cfg.o
hw-obj-$(CONFIG_PCI) += pci.o pci_bridge.o pci_bridge_dev.o
hw-obj-$(CONFIG_PCI) += msix.o msi.o
diff --git a/hw/virtio-transport.c b/hw/virtio-transport.c
new file mode 100644
index 0000000..76360ba
--- /dev/null
+++ b/hw/virtio-transport.c
@@ -0,0 +1,147 @@
+/*
+ * Virtio transport bindings
+ *
+ * Copyright (c) 2011 - 2012 Samsung Electronics Co., Ltd.
+ *
+ * Author:
+ * Evgeny Voevodin <e.voevodin@samsung.com>
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License; either version 2
+ * of the License, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License along
+ * with this program; if not, see <http://www.gnu.org/licenses/>.
+ */
+
+#include "virtio-transport.h"
+
+#define VIRTIO_TRANSPORT_BUS "virtio-transport"
+
+static QTAILQ_HEAD(, VirtIOTransportLink) transport_links =
+ QTAILQ_HEAD_INITIALIZER(transport_links);
+
+/*
+ * Find transport device by its ID.
+ */
+VirtIOTransportLink* virtio_find_transport(const char *name)
+{
+ VirtIOTransportLink *trl;
+
+ assert(name != NULL);
+
+ QTAILQ_FOREACH(trl, &transport_links, sibling) {
+ if (trl->tr->id != NULL) {
+ if (!strcmp(name, trl->tr->id)) {
+ return trl;
+ }
+ }
+ }
+
+ return NULL;
+}
+
+/*
+ * Count transport devices by ID.
+ */
+uint32_t virtio_count_transports(const char *name)
+{
+ VirtIOTransportLink *trl;
+ uint32_t i = 0;
+
+ QTAILQ_FOREACH(trl, &transport_links, sibling) {
+ if (name == NULL) {
+ i++;
+ continue;
+ }
+
+ if (trl->tr->id != NULL) {
+ if (!strncmp(name, trl->tr->id,strlen(name))) {
+ i++;
+ }
+ }
+ }
+ return i;
+}
+
+/*
+ * Initialize new transport device
+ */
+char* virtio_init_transport(DeviceState *dev, VirtIOTransportLink **trl,
+ const char* name, virtio_backend_init_cb cb)
+{
+ VirtIOTransportLink *link = g_malloc0(sizeof(VirtIOTransportLink));
+ char *buf;
+ size_t len;
+ uint32_t i;
+
+ assert(dev != NULL);
+ assert(name != NULL);
+ assert(trl != NULL);
+
+ i = virtio_count_transports(name);
+ len = strlen(name) + 16;
+ buf = g_malloc(len);
+ snprintf(buf, len, "%s.%d", name, i);
+ qbus_create(TYPE_VIRTIO_BUS, dev, buf);
+
+ /* Add new transport */
+ QTAILQ_INSERT_TAIL(&transport_links, link, sibling);
+ link->tr = dev;
+ link->cb = cb;
+ // TODO: Add a link property
+ *trl = link;
+ return buf;
+}
+
+/*
+ * Unplug back-end from system bus and plug it into transport bus.
+ */
+void virtio_plug_into_transport(DeviceState *dev, VirtIOTransportLink *trl)
+{
+ BusChild *kid;
+
+ /* Unplug back-end from system bus */
+ QTAILQ_FOREACH(kid, &qdev_get_parent_bus(dev)->children, sibling) {
+ if (kid->child == dev) {
+ QTAILQ_REMOVE(&qdev_get_parent_bus(dev)->children, kid, sibling);
+ break;
+ }
+ }
+
+ /* Plug back-end into transport's bus */
+ qdev_set_parent_bus(dev, QLIST_FIRST(&trl->tr->child_bus));
+
+}
+
+/*
+ * Execute call-back on back-end initialization.
+ * Performs initialization of MMIO or PCI transport.
+ */
+int virtio_call_backend_init_cb(DeviceState *dev, VirtIOTransportLink *trl,
+ VirtIODevice *vdev)
+{
+ if (trl->cb) {
+ return trl->cb(dev, vdev, trl);
+ }
+
+ return 0;
+}
+
+static const TypeInfo virtio_bus_info = {
+ .name = TYPE_VIRTIO_BUS,
+ .parent = TYPE_BUS,
+ .instance_size = sizeof(BusState),
+};
+
+static void virtio_register_types(void)
+{
+ type_register_static(&virtio_bus_info);
+}
+
+type_init(virtio_register_types)
diff --git a/hw/virtio-transport.h b/hw/virtio-transport.h
new file mode 100644
index 0000000..43200dc
--- /dev/null
+++ b/hw/virtio-transport.h
@@ -0,0 +1,74 @@
+/*
+ * Virtio transport header
+ *
+ * Copyright (c) 2011 - 2012 Samsung Electronics Co., Ltd.
+ *
+ * Author:
+ * Evgeny Voevodin <e.voevodin@samsung.com>
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License; either version 2
+ * of the License, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License along
+ * with this program; if not, see <http://www.gnu.org/licenses/>.
+ */
+
+#ifndef VIRTIO_TRANSPORT_H_
+#define VIRTIO_TRANSPORT_H_
+
+#include "qdev.h"
+#include "qemu-common.h"
+
+#define VIRTIO_MMIO "virtio-mmio"
+#define VIRTIO_PCI "virtio-pci"
+
+#define TYPE_VIRTIO_BUS "virtio-bus"
+#define VIRTIO_BUS(obj) OBJECT_CHECK(virtio_bus, (obj), TYPE_VIRTIO_BUS)
+
+struct VirtIOTransportLink;
+
+typedef int (*virtio_backend_init_cb)(DeviceState *dev, VirtIODevice *vdev,
+ struct VirtIOTransportLink *trl);
+
+typedef struct VirtIOTransportLink {
+ DeviceState *tr;
+ virtio_backend_init_cb cb;
+ uint32_t host_features;
+ QTAILQ_ENTRY(VirtIOTransportLink) sibling;
+} VirtIOTransportLink;
+
+/*
+ * Find transport device by its ID.
+ */
+VirtIOTransportLink* virtio_find_transport(const char *name);
+
+/*
+ * Count transport devices by ID.
+ */
+uint32_t virtio_count_transports(const char *name);
+
+/*
+ * Initialize new transport device
+ */
+char* virtio_init_transport(DeviceState *dev, VirtIOTransportLink **trl,
+ const char* name, virtio_backend_init_cb cb);
+
+/*
+ * Unplug back-end from system bus and plug it into transport bus.
+ */
+void virtio_plug_into_transport(DeviceState *dev, VirtIOTransportLink *trl);
+
+/*
+ * Execute call-back on back-end initialization.
+ * Performs initialization of MMIO or PCI transport.
+ */
+int virtio_call_backend_init_cb(DeviceState *dev, VirtIOTransportLink *trl,
+ VirtIODevice *vdev);
+
+#endif /* VIRTIO_TRANSPORT_H_ */
--
1.7.9.5
^ permalink raw reply related [flat|nested] 17+ messages in thread
* [Qemu-devel] [RFC v2 04/12] hw/qdev-properties.c: Add "transport" property.
2012-09-17 10:00 [Qemu-devel] [RFC v2 00/12] Virtio-mmio refactoring Evgeny Voevodin
` (2 preceding siblings ...)
2012-09-17 10:00 ` [Qemu-devel] [RFC v2 03/12] Virtio: Add transport bindings Evgeny Voevodin
@ 2012-09-17 10:00 ` Evgeny Voevodin
2012-09-17 12:42 ` Paolo Bonzini
2012-09-17 10:00 ` [Qemu-devel] [RFC v2 05/12] hw/pci.c: Make pci_add_option_rom global visible Evgeny Voevodin
` (8 subsequent siblings)
12 siblings, 1 reply; 17+ messages in thread
From: Evgeny Voevodin @ 2012-09-17 10:00 UTC (permalink / raw)
To: qemu-devel; +Cc: peter.maydell, kyungmin.park, aliguori, Evgeny Voevodin
Virtio back-end devices can be plugged into both transports:
VIRTIO_PCI and VIRTIO_MMIO. In order to choose the desired
transport we have a property "transport" in every back-end
state struct. By specifying -device virtio-blk-pci user chooses
VIRTIO_PCI transport and "transport" property is set automatically.
But in order to provide full control to user we need to have
"transport" property available to be set through command line:
-device virtio-pci,id=virtio-pci.0
-device virtio-blk,transport=virtio-pci.0,...
Signed-off-by: Evgeny Voevodin <e.voevodin@samsung.com>
---
hw/qdev-properties.c | 29 +++++++++++++++++++++++++++++
hw/qdev.h | 3 +++
2 files changed, 32 insertions(+)
diff --git a/hw/qdev-properties.c b/hw/qdev-properties.c
index 8aca0d4..4226a02 100644
--- a/hw/qdev-properties.c
+++ b/hw/qdev-properties.c
@@ -2,6 +2,7 @@
#include "qdev.h"
#include "qerror.h"
#include "blockdev.h"
+#include "virtio-transport.h"
#include "hw/block-common.h"
#include "net/hub.h"
@@ -526,6 +527,34 @@ PropertyInfo qdev_prop_drive = {
.release = release_drive,
};
+/* --- virtio transport --- */
+
+static int parse_transport(DeviceState *dev, const char *str, void **ptr)
+{
+ VirtIOTransportLink *trl;
+
+ trl = virtio_find_transport(str);
+
+ if (trl == NULL) {
+ return -ENOENT;
+ }
+
+ *ptr = trl;
+
+ return 0;
+}
+
+static void set_transport(Object *obj, Visitor *v, void *opaque,
+ const char *name, Error **errp)
+{
+ set_pointer(obj, v, opaque, parse_transport, name, errp);
+}
+
+PropertyInfo qdev_prop_transport = {
+ .name = "transport",
+ .set = set_transport,
+};
+
/* --- character device --- */
static int parse_chr(DeviceState *dev, const char *str, void **ptr)
diff --git a/hw/qdev.h b/hw/qdev.h
index d699194..bd6aa6e 100644
--- a/hw/qdev.h
+++ b/hw/qdev.h
@@ -233,6 +233,7 @@ extern PropertyInfo qdev_prop_macaddr;
extern PropertyInfo qdev_prop_losttickpolicy;
extern PropertyInfo qdev_prop_bios_chs_trans;
extern PropertyInfo qdev_prop_drive;
+extern PropertyInfo qdev_prop_transport;
extern PropertyInfo qdev_prop_netdev;
extern PropertyInfo qdev_prop_vlan;
extern PropertyInfo qdev_prop_pci_devfn;
@@ -294,6 +295,8 @@ extern PropertyInfo qdev_prop_pci_host_devaddr;
DEFINE_PROP(_n, _s, _f, qdev_prop_vlan, NetClientState*)
#define DEFINE_PROP_DRIVE(_n, _s, _f) \
DEFINE_PROP(_n, _s, _f, qdev_prop_drive, BlockDriverState *)
+#define DEFINE_PROP_TRANSPORT(_n, _s, _f) \
+ DEFINE_PROP(_n, _s, _f, qdev_prop_transport, VirtIOTransportLink *)
#define DEFINE_PROP_MACADDR(_n, _s, _f) \
DEFINE_PROP(_n, _s, _f, qdev_prop_macaddr, MACAddr)
#define DEFINE_PROP_LOSTTICKPOLICY(_n, _s, _f, _d) \
--
1.7.9.5
^ permalink raw reply related [flat|nested] 17+ messages in thread
* [Qemu-devel] [RFC v2 05/12] hw/pci.c: Make pci_add_option_rom global visible
2012-09-17 10:00 [Qemu-devel] [RFC v2 00/12] Virtio-mmio refactoring Evgeny Voevodin
` (3 preceding siblings ...)
2012-09-17 10:00 ` [Qemu-devel] [RFC v2 04/12] hw/qdev-properties.c: Add "transport" property Evgeny Voevodin
@ 2012-09-17 10:00 ` Evgeny Voevodin
2012-09-17 10:00 ` [Qemu-devel] [RFC v2 06/12] Add MMIO based virtio transport Evgeny Voevodin
` (7 subsequent siblings)
12 siblings, 0 replies; 17+ messages in thread
From: Evgeny Voevodin @ 2012-09-17 10:00 UTC (permalink / raw)
To: qemu-devel; +Cc: peter.maydell, kyungmin.park, aliguori, Evgeny Voevodin
We need to use this function to load rom for virtio-net backend.
Signed-off-by: Evgeny Voevodin <e.voevodin@samsung.com>
---
hw/pci.c | 3 +--
hw/pci.h | 2 ++
2 files changed, 3 insertions(+), 2 deletions(-)
diff --git a/hw/pci.c b/hw/pci.c
index f855cf3..bba69ef 100644
--- a/hw/pci.c
+++ b/hw/pci.c
@@ -77,7 +77,6 @@ static const TypeInfo pci_bus_info = {
static PCIBus *pci_find_bus_nr(PCIBus *bus, int bus_num);
static void pci_update_mappings(PCIDevice *d);
static void pci_set_irq(void *opaque, int irq_num, int level);
-static int pci_add_option_rom(PCIDevice *pdev, bool is_default_rom);
static void pci_del_option_rom(PCIDevice *pdev);
static uint16_t pci_default_sub_vendor_id = PCI_SUBVENDOR_ID_REDHAT_QUMRANET;
@@ -1733,7 +1732,7 @@ static void pci_patch_ids(PCIDevice *pdev, uint8_t *ptr, int size)
}
/* Add an option rom for the device */
-static int pci_add_option_rom(PCIDevice *pdev, bool is_default_rom)
+int pci_add_option_rom(PCIDevice *pdev, bool is_default_rom)
{
int size;
char *path;
diff --git a/hw/pci.h b/hw/pci.h
index 4b6ab3d..5f47618 100644
--- a/hw/pci.h
+++ b/hw/pci.h
@@ -274,6 +274,8 @@ void pci_register_bar(PCIDevice *pci_dev, int region_num,
uint8_t attr, MemoryRegion *memory);
pcibus_t pci_get_bar_addr(PCIDevice *pci_dev, int region_num);
+int pci_add_option_rom(PCIDevice *pdev, bool is_default_rom);
+
int pci_add_capability(PCIDevice *pdev, uint8_t cap_id,
uint8_t offset, uint8_t size);
--
1.7.9.5
^ permalink raw reply related [flat|nested] 17+ messages in thread
* [Qemu-devel] [RFC v2 06/12] Add MMIO based virtio transport
2012-09-17 10:00 [Qemu-devel] [RFC v2 00/12] Virtio-mmio refactoring Evgeny Voevodin
` (4 preceding siblings ...)
2012-09-17 10:00 ` [Qemu-devel] [RFC v2 05/12] hw/pci.c: Make pci_add_option_rom global visible Evgeny Voevodin
@ 2012-09-17 10:00 ` Evgeny Voevodin
2012-09-17 10:00 ` [Qemu-devel] [RFC v2 07/12] hw/virtio-serial-bus.c: Add virtio-serial device Evgeny Voevodin
` (6 subsequent siblings)
12 siblings, 0 replies; 17+ messages in thread
From: Evgeny Voevodin @ 2012-09-17 10:00 UTC (permalink / raw)
To: qemu-devel; +Cc: peter.maydell, kyungmin.park, aliguori, Evgeny Voevodin
From: Peter Maydell <peter.maydell@linaro.org>
Add support for the generic MMIO based virtio transport.
This patch is a modyfied patch of
Peter Maydell <peter.maydell@linaro.org>. Changes are to have
virtio-mmio bridge device which provides virtio-mmio bus. To this bus
virtio-mmio-transport device is connected and in turn provides
virtio-transport bus. Then virtio backends could be connected to this
bus.
Also this patch includes some fixes for bugs spotted by
Ying-Shiuan Pan <yspan@itri.org.tw>.
Signed-off-by: Evgeny Voevodin <e.voevodin@samsung.com>
Conflicts:
Makefile.objs
---
hw/Makefile.objs | 1 +
hw/virtio-mmio.c | 400 ++++++++++++++++++++++++++++++++++++++++++++++++++++++
2 files changed, 401 insertions(+)
create mode 100644 hw/virtio-mmio.c
diff --git a/hw/Makefile.objs b/hw/Makefile.objs
index db4c16d..0c112af 100644
--- a/hw/Makefile.objs
+++ b/hw/Makefile.objs
@@ -3,6 +3,7 @@ hw-obj-y += loader.o
hw-obj-$(CONFIG_VIRTIO) += virtio-console.o
hw-obj-$(CONFIG_VIRTIO_PCI) += virtio-pci.o
hw-obj-$(CONFIG_VIRTIO) += virtio-transport.o
+hw-obj-$(CONFIG_VIRTIO) += virtio-mmio.o
hw-obj-y += fw_cfg.o
hw-obj-$(CONFIG_PCI) += pci.o pci_bridge.o pci_bridge_dev.o
hw-obj-$(CONFIG_PCI) += msix.o msi.o
diff --git a/hw/virtio-mmio.c b/hw/virtio-mmio.c
new file mode 100644
index 0000000..88e5d9f
--- /dev/null
+++ b/hw/virtio-mmio.c
@@ -0,0 +1,400 @@
+/*
+ * Virtio MMIO bindings
+ *
+ * Copyright (c) 2011 Linaro Limited
+ *
+ * Authors:
+ * Peter Maydell <peter.maydell@linaro.org>
+ * Evgeny Voevodin <e.voevodin@samsung.com>
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License; either version 2
+ * of the License, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License along
+ * with this program; if not, see <http://www.gnu.org/licenses/>.
+ */
+
+/* TODO:
+ * * save/load support
+ * * test net, serial, balloon
+ */
+
+#include "sysbus.h"
+#include "virtio.h"
+#include "virtio-transport.h"
+#include "virtio-blk.h"
+#include "virtio-net.h"
+#include "virtio-serial.h"
+#include "host-utils.h"
+
+/* #define DEBUG_VIRTIO_MMIO */
+
+#ifdef DEBUG_VIRTIO_MMIO
+
+#define DPRINTF(fmt, ...) \
+do { printf("virtio_mmio: " fmt , ## __VA_ARGS__); } while (0)
+#else
+#define DPRINTF(fmt, ...) do {} while (0)
+#endif
+
+/* Memory mapped register offsets */
+#define VIRTIO_MMIO_MAGIC 0x0
+#define VIRTIO_MMIO_VERSION 0x4
+#define VIRTIO_MMIO_DEVICEID 0x8
+#define VIRTIO_MMIO_VENDORID 0xc
+#define VIRTIO_MMIO_HOSTFEATURES 0x10
+#define VIRTIO_MMIO_HOSTFEATURESSEL 0x14
+#define VIRTIO_MMIO_GUESTFEATURES 0x20
+#define VIRTIO_MMIO_GUESTFEATURESSEL 0x24
+#define VIRTIO_MMIO_GUESTPAGESIZE 0x28
+#define VIRTIO_MMIO_QUEUESEL 0x30
+#define VIRTIO_MMIO_QUEUENUMMAX 0x34
+#define VIRTIO_MMIO_QUEUENUM 0x38
+#define VIRTIO_MMIO_QUEUEALIGN 0x3c
+#define VIRTIO_MMIO_QUEUEPFN 0x40
+#define VIRTIO_MMIO_QUEUENOTIFY 0x50
+#define VIRTIO_MMIO_INTERRUPTSTATUS 0x60
+#define VIRTIO_MMIO_INTERRUPTACK 0x64
+#define VIRTIO_MMIO_STATUS 0x70
+/* Device specific config space starts here */
+#define VIRTIO_MMIO_CONFIG 0x100
+
+#define VIRT_MAGIC 0x74726976 /* 'virt' */
+#define VIRT_VERSION 1
+#define VIRT_VENDOR 0x554D4551 /* 'QEMU' */
+
+enum VIRTIO_MMIO_MAPPINGS {
+ VIRTIO_MMIO_IOMAP,
+ VIRTIO_MMIO_IOMEM,
+};
+
+typedef struct {
+ SysBusDevice busdev;
+ VirtIODevice *vdev;
+ VirtIOTransportLink *trl;
+
+ MemoryRegion iomap; /* hold base address */
+ MemoryRegion iomem; /* hold io funcs */
+ MemoryRegion alias;
+ qemu_irq irq;
+ uint32_t int_enable;
+ uint32_t host_features;
+ uint32_t host_features_sel;
+ uint32_t guest_features_sel;
+ uint32_t guest_page_shift;
+} VirtIOMMIO;
+
+static uint64_t virtio_mmio_read(void *opaque, target_phys_addr_t offset,
+ unsigned size)
+{
+ VirtIOMMIO *s = (VirtIOMMIO *)opaque;
+ VirtIODevice *vdev = s->vdev;
+ DPRINTF("virtio_mmio_read offset 0x%x\n", (int)offset);
+ if (offset >= VIRTIO_MMIO_CONFIG) {
+ offset -= VIRTIO_MMIO_CONFIG;
+ switch (size) {
+ case 1:
+ return virtio_config_readb(vdev, offset);
+ case 2:
+ return virtio_config_readw(vdev, offset);
+ case 4:
+ return virtio_config_readl(vdev, offset);
+ default:
+ abort();
+ }
+ }
+ if (size != 4) {
+ DPRINTF("wrong size access to register!\n");
+ return 0;
+ }
+ switch (offset) {
+ case VIRTIO_MMIO_MAGIC:
+ return VIRT_MAGIC;
+ case VIRTIO_MMIO_VERSION:
+ return VIRT_VERSION;
+ case VIRTIO_MMIO_DEVICEID:
+ return vdev->device_id;
+ case VIRTIO_MMIO_VENDORID:
+ return VIRT_VENDOR;
+ case VIRTIO_MMIO_HOSTFEATURES:
+ if (s->host_features_sel) {
+ return 0;
+ }
+ return s->host_features;
+ case VIRTIO_MMIO_QUEUENUMMAX:
+ return VIRTQUEUE_MAX_SIZE;
+ case VIRTIO_MMIO_QUEUEPFN:
+ return virtio_queue_get_addr(vdev, vdev->queue_sel)
+ >> s->guest_page_shift;
+ case VIRTIO_MMIO_INTERRUPTSTATUS:
+ return vdev->isr;
+ case VIRTIO_MMIO_STATUS:
+ return vdev->status;
+ case VIRTIO_MMIO_HOSTFEATURESSEL:
+ case VIRTIO_MMIO_GUESTFEATURES:
+ case VIRTIO_MMIO_GUESTFEATURESSEL:
+ case VIRTIO_MMIO_GUESTPAGESIZE:
+ case VIRTIO_MMIO_QUEUESEL:
+ case VIRTIO_MMIO_QUEUENUM:
+ case VIRTIO_MMIO_QUEUEALIGN:
+ case VIRTIO_MMIO_QUEUENOTIFY:
+ case VIRTIO_MMIO_INTERRUPTACK:
+ DPRINTF("read of write-only register\n");
+ return 0;
+ default:
+ DPRINTF("bad register offset\n");
+ return 0;
+ }
+ return 0;
+}
+
+static void virtio_mmio_write(void *opaque, target_phys_addr_t offset,
+ uint64_t value, unsigned size)
+{
+ VirtIOMMIO *s = (VirtIOMMIO *)opaque;
+ VirtIODevice *vdev = s->vdev;
+ DPRINTF("virtio_mmio_write offset 0x%x value 0x%" PRIx64 "\n",
+ (int)offset, value);
+ if (offset >= VIRTIO_MMIO_CONFIG) {
+ offset -= VIRTIO_MMIO_CONFIG;
+ switch (size) {
+ case 1:
+ virtio_config_writeb(vdev, offset, value);
+ break;
+ case 2:
+ virtio_config_writew(vdev, offset, value);
+ break;
+ case 4:
+ virtio_config_writel(vdev, offset, value);
+ break;
+ default:
+ abort();
+ }
+ return;
+ }
+ if (size != 4) {
+ DPRINTF("wrong size access to register!\n");
+ return;
+ }
+ switch (offset) {
+ case VIRTIO_MMIO_HOSTFEATURESSEL:
+ s->host_features_sel = value;
+ break;
+ case VIRTIO_MMIO_GUESTFEATURES:
+ if (!s->guest_features_sel) {
+ virtio_set_features(vdev, value);
+ }
+ break;
+ case VIRTIO_MMIO_GUESTFEATURESSEL:
+ s->guest_features_sel = value;
+ break;
+ case VIRTIO_MMIO_GUESTPAGESIZE:
+ s->guest_page_shift = ctz32(value);
+ if (s->guest_page_shift > 31) {
+ s->guest_page_shift = 0;
+ }
+ DPRINTF("guest page size %" PRIx64 " shift %d\n", value,
+ s->guest_page_shift);
+ break;
+ case VIRTIO_MMIO_QUEUESEL:
+ if (value < VIRTIO_PCI_QUEUE_MAX) {
+ vdev->queue_sel = value;
+ }
+ break;
+ case VIRTIO_MMIO_QUEUENUM:
+ DPRINTF("mmio_queue write %d max %d\n", (int)value, VIRTQUEUE_MAX_SIZE);
+ if (value <= VIRTQUEUE_MAX_SIZE) {
+ DPRINTF("calling virtio_queue_set_num\n");
+ virtio_queue_set_num(vdev, vdev->queue_sel, value);
+ }
+ break;
+ case VIRTIO_MMIO_QUEUEALIGN:
+ virtio_queue_set_align(vdev, vdev->queue_sel, value);
+ break;
+ case VIRTIO_MMIO_QUEUEPFN:
+ if (value == 0) {
+ virtio_reset(vdev);
+ } else {
+ virtio_queue_set_addr(vdev, vdev->queue_sel,
+ value << s->guest_page_shift);
+ }
+ break;
+ case VIRTIO_MMIO_QUEUENOTIFY:
+ if (value < VIRTIO_PCI_QUEUE_MAX) {
+ virtio_queue_notify(vdev, value);
+ }
+ break;
+ case VIRTIO_MMIO_INTERRUPTACK:
+ vdev->isr &= ~value;
+ virtio_update_irq(vdev);
+ break;
+ case VIRTIO_MMIO_STATUS:
+ virtio_set_status(vdev, value & 0xff);
+ if (vdev->status == 0) {
+ virtio_reset(vdev);
+ }
+ break;
+ case VIRTIO_MMIO_MAGIC:
+ case VIRTIO_MMIO_VERSION:
+ case VIRTIO_MMIO_DEVICEID:
+ case VIRTIO_MMIO_VENDORID:
+ case VIRTIO_MMIO_HOSTFEATURES:
+ case VIRTIO_MMIO_QUEUENUMMAX:
+ case VIRTIO_MMIO_INTERRUPTSTATUS:
+ DPRINTF("write to readonly register\n");
+ break;
+
+ default:
+ DPRINTF("bad register offset\n");
+ }
+}
+
+static const MemoryRegionOps virtio_mem_ops = {
+ .read = virtio_mmio_read,
+ .write = virtio_mmio_write,
+ .endianness = DEVICE_NATIVE_ENDIAN,
+};
+
+static void virtio_mmio_update_irq(void *opaque, uint16_t vector)
+{
+ VirtIOMMIO *s = opaque;
+ int level = (s->vdev->isr != 0);
+ DPRINTF("virtio_mmio setting IRQ %d\n", level);
+ qemu_set_irq(s->irq, level);
+}
+
+static unsigned int virtio_mmio_get_features(void *opaque)
+{
+ VirtIOMMIO *s = opaque;
+ return s->host_features;
+}
+
+static int virtio_mmio_load_config(void *opaque, QEMUFile *f)
+{
+ VirtIOMMIO *s = opaque;
+ s->int_enable = qemu_get_be32(f);
+ s->host_features = qemu_get_be32(f);
+ s->host_features_sel = qemu_get_be32(f);
+ s->guest_features_sel = qemu_get_be32(f);
+ s->guest_page_shift = qemu_get_be32(f);
+ return 0;
+}
+
+static void virtio_mmio_save_config(void *opaque, QEMUFile *f)
+{
+ VirtIOMMIO *s = opaque;
+ qemu_put_be32(f, s->int_enable);
+ qemu_put_be32(f, s->host_features);
+ qemu_put_be32(f, s->host_features_sel);
+ qemu_put_be32(f, s->guest_features_sel);
+ qemu_put_be32(f, s->guest_page_shift);
+}
+
+static VirtIOBindings virtio_mmio_bindings = {
+ .notify = virtio_mmio_update_irq,
+ .get_features = virtio_mmio_get_features,
+ .save_config = virtio_mmio_save_config,
+ .load_config = virtio_mmio_load_config,
+};
+
+static int virtio_mmio_transport_cb(DeviceState *dev, VirtIODevice *vdev,
+ VirtIOTransportLink *trl)
+{
+ VirtIOMMIO *s =
+ FROM_SYSBUS(VirtIOMMIO, sysbus_from_qdev(trl->tr));
+
+ virtio_plug_into_transport(dev, trl);
+
+ s->vdev = vdev;
+ s->vdev->nvectors = 0;
+ sysbus_init_irq(&s->busdev, &s->irq);
+ memory_region_init_io(&s->iomem, &virtio_mem_ops, s,
+ "virtio-mmio-iomem", 0x1000);
+ sysbus_init_mmio(&s->busdev, &s->iomem);
+ virtio_bind_device(vdev, &virtio_mmio_bindings, s);
+ s->host_features |= (0x1 << VIRTIO_F_NOTIFY_ON_EMPTY);
+ s->host_features =
+ vdev->get_features(vdev, s->host_features);
+
+ /* Create alias and add it as subregion to s iomem */
+ memory_region_init_alias(&s->alias,
+ "virtio-mmio-alias",
+ &s->iomem,
+ 0,
+ 0x1000);
+ /* add alias as subregion to s iomap */
+ memory_region_add_subregion(&s->iomap,
+ 0,
+ &s->alias);
+ return 0;
+}
+
+static void virtio_mmio_handler(void *opaque, int irq, int level)
+{
+ VirtIOMMIO *s = (VirtIOMMIO *)opaque;
+
+ qemu_set_irq(s->irq, level);
+
+ return;
+}
+
+static int sice_init(SysBusDevice *busdev)
+{
+ VirtIOMMIO *s =
+ DO_UPCAST(VirtIOMMIO, busdev, busdev);
+ char *buf;
+
+ /* Count transports before we assigned a device ID to our new transport */
+ buf = virtio_init_transport(&busdev->qdev, &s->trl, VIRTIO_MMIO,
+ virtio_mmio_transport_cb);
+
+ /* assign new device id */
+ busdev->qdev.id = buf;
+
+ qdev_init_gpio_in(&s->busdev.qdev, virtio_mmio_handler, 1);
+ sysbus_init_irq(busdev, &s->irq);
+ memory_region_init(&s->iomap, "virtio-mmio-iomap", 0x1000);
+ sysbus_init_mmio(busdev, &s->iomap);
+
+ return 0;
+}
+
+static void virtio_mmio_reset(DeviceState *d)
+{
+ VirtIOMMIO *s = FROM_SYSBUS(VirtIOMMIO, sysbus_from_qdev(d));
+ if (s->vdev) {
+ virtio_reset(s->vdev);
+ }
+}
+
+/******************** VirtIOMMIO Device *********************/
+
+static void virtio_mmio_class_init(ObjectClass *klass, void *data)
+{
+ DeviceClass *dc = DEVICE_CLASS(klass);
+ SysBusDeviceClass *k = SYS_BUS_DEVICE_CLASS(klass);
+ k->init = sice_init;
+ dc->reset = virtio_mmio_reset;
+}
+
+static TypeInfo virtio_mmio_info = {
+ .name = VIRTIO_MMIO,
+ .parent = TYPE_SYS_BUS_DEVICE,
+ .instance_size = sizeof(VirtIOMMIO),
+ .class_init = virtio_mmio_class_init,
+};
+
+/************************************************************/
+
+static void virtio_mmio_register_types(void)
+{
+ type_register_static(&virtio_mmio_info);
+}
+
+type_init(virtio_mmio_register_types)
--
1.7.9.5
^ permalink raw reply related [flat|nested] 17+ messages in thread
* [Qemu-devel] [RFC v2 07/12] hw/virtio-serial-bus.c: Add virtio-serial device.
2012-09-17 10:00 [Qemu-devel] [RFC v2 00/12] Virtio-mmio refactoring Evgeny Voevodin
` (5 preceding siblings ...)
2012-09-17 10:00 ` [Qemu-devel] [RFC v2 06/12] Add MMIO based virtio transport Evgeny Voevodin
@ 2012-09-17 10:00 ` Evgeny Voevodin
2012-09-17 10:00 ` [Qemu-devel] [RFC v2 08/12] hw/virtio-balloon.c: Add virtio-balloon device Evgeny Voevodin
` (5 subsequent siblings)
12 siblings, 0 replies; 17+ messages in thread
From: Evgeny Voevodin @ 2012-09-17 10:00 UTC (permalink / raw)
To: qemu-devel; +Cc: peter.maydell, kyungmin.park, aliguori, Evgeny Voevodin
Signed-off-by: Evgeny Voevodin <e.voevodin@samsung.com>
---
hw/virtio-serial-bus.c | 44 ++++++++++++++++++++++++++++++++++++++++++++
hw/virtio-serial.h | 11 +++++++++++
2 files changed, 55 insertions(+)
diff --git a/hw/virtio-serial-bus.c b/hw/virtio-serial-bus.c
index 82073f5..699a485 100644
--- a/hw/virtio-serial-bus.c
+++ b/hw/virtio-serial-bus.c
@@ -24,6 +24,7 @@
#include "sysbus.h"
#include "trace.h"
#include "virtio-serial.h"
+#include "virtio-transport.h"
/* The virtio-serial bus on top of which the ports will ride as devices */
struct VirtIOSerialBus {
@@ -1014,3 +1015,46 @@ static void virtio_serial_register_types(void)
}
type_init(virtio_serial_register_types)
+
+/******************** VirtIOSer Device **********************/
+
+static int virtio_serialdev_init(DeviceState *dev)
+{
+ VirtIODevice *vdev;
+ VirtIOSerState *s = VIRTIO_SERIAL_FROM_QDEV(dev);
+ vdev = virtio_serial_init(dev, &s->serial);
+ if (!vdev) {
+ return -1;
+ }
+
+ assert(s->trl != NULL);
+
+ return virtio_call_backend_init_cb(dev, s->trl, vdev);
+}
+
+static Property virtio_serial_properties[] = {
+ DEFINE_PROP_UINT32("max_ports", VirtIOSerState,
+ serial.max_virtserial_ports, 31),
+ DEFINE_PROP_END_OF_LIST(),
+};
+
+static void virtio_serial_class_init(ObjectClass *klass, void *data)
+{
+ DeviceClass *dc = DEVICE_CLASS(klass);
+ dc->init = virtio_serialdev_init;
+ dc->props = virtio_serial_properties;
+}
+
+static TypeInfo virtio_serial_info = {
+ .name = "virtio-serial",
+ .parent = TYPE_DEVICE,
+ .instance_size = sizeof(VirtIOSerState),
+ .class_init = virtio_serial_class_init,
+};
+
+static void virtio_ser_register_types(void)
+{
+ type_register_static(&virtio_serial_info);
+}
+
+type_init(virtio_ser_register_types)
diff --git a/hw/virtio-serial.h b/hw/virtio-serial.h
index 16e3982..c6b916a 100644
--- a/hw/virtio-serial.h
+++ b/hw/virtio-serial.h
@@ -15,8 +15,10 @@
#ifndef _QEMU_VIRTIO_SERIAL_H
#define _QEMU_VIRTIO_SERIAL_H
+#include "sysbus.h"
#include "qdev.h"
#include "virtio.h"
+#include "virtio-transport.h"
/* == Interface shared between the guest kernel and qemu == */
@@ -173,6 +175,15 @@ struct VirtIOSerialPort {
bool throttled;
};
+typedef struct {
+ DeviceState qdev;
+ /* virtio-serial */
+ virtio_serial_conf serial;
+ VirtIOTransportLink *trl;
+} VirtIOSerState;
+
+#define VIRTIO_SERIAL_FROM_QDEV(dev) DO_UPCAST(VirtIOSerState, qdev, dev)
+
/* Interface to the virtio-serial bus */
/*
--
1.7.9.5
^ permalink raw reply related [flat|nested] 17+ messages in thread
* [Qemu-devel] [RFC v2 08/12] hw/virtio-balloon.c: Add virtio-balloon device.
2012-09-17 10:00 [Qemu-devel] [RFC v2 00/12] Virtio-mmio refactoring Evgeny Voevodin
` (6 preceding siblings ...)
2012-09-17 10:00 ` [Qemu-devel] [RFC v2 07/12] hw/virtio-serial-bus.c: Add virtio-serial device Evgeny Voevodin
@ 2012-09-17 10:00 ` Evgeny Voevodin
2012-09-17 10:00 ` [Qemu-devel] [RFC v2 09/12] hw/virtio-net.c: Add virtio-net device Evgeny Voevodin
` (4 subsequent siblings)
12 siblings, 0 replies; 17+ messages in thread
From: Evgeny Voevodin @ 2012-09-17 10:00 UTC (permalink / raw)
To: qemu-devel; +Cc: peter.maydell, kyungmin.park, aliguori, Evgeny Voevodin
Signed-off-by: Evgeny Voevodin <e.voevodin@samsung.com>
---
hw/virtio-balloon.c | 42 ++++++++++++++++++++++++++++++++++++++++++
hw/virtio-balloon.h | 9 +++++++++
2 files changed, 51 insertions(+)
diff --git a/hw/virtio-balloon.c b/hw/virtio-balloon.c
index dd1a650..d6fe2aa 100644
--- a/hw/virtio-balloon.c
+++ b/hw/virtio-balloon.c
@@ -20,6 +20,7 @@
#include "cpu.h"
#include "balloon.h"
#include "virtio-balloon.h"
+#include "virtio-transport.h"
#include "kvm.h"
#include "exec-memory.h"
@@ -272,3 +273,44 @@ void virtio_balloon_exit(VirtIODevice *vdev)
unregister_savevm(s->qdev, "virtio-balloon", s);
virtio_cleanup(vdev);
}
+
+/******************** VirtIOBaloon Device **********************/
+
+static int virtio_balloondev_init(DeviceState *dev)
+{
+ VirtIODevice *vdev;
+ VirtIOBaloonState *s = VIRTIO_BALLOON_FROM_QDEV(dev);
+ vdev = virtio_balloon_init(dev);
+ if (!vdev) {
+ return -1;
+ }
+
+ assert(s->trl != NULL);
+
+ return virtio_call_backend_init_cb(dev, s->trl, vdev);
+}
+
+static Property virtio_balloon_properties[] = {
+ DEFINE_PROP_END_OF_LIST(),
+};
+
+static void virtio_balloon_class_init(ObjectClass *klass, void *data)
+{
+ DeviceClass *dc = DEVICE_CLASS(klass);
+ dc->init = virtio_balloondev_init;
+ dc->props = virtio_balloon_properties;
+}
+
+static TypeInfo virtio_balloon_info = {
+ .name = "virtio-balloon",
+ .parent = TYPE_DEVICE,
+ .instance_size = sizeof(VirtIOBaloonState),
+ .class_init = virtio_balloon_class_init,
+};
+
+static void virtio_baloon_register_types(void)
+{
+ type_register_static(&virtio_balloon_info);
+}
+
+type_init(virtio_baloon_register_types)
diff --git a/hw/virtio-balloon.h b/hw/virtio-balloon.h
index 73300dd..b925186 100644
--- a/hw/virtio-balloon.h
+++ b/hw/virtio-balloon.h
@@ -15,8 +15,10 @@
#ifndef _QEMU_VIRTIO_BALLOON_H
#define _QEMU_VIRTIO_BALLOON_H
+#include "sysbus.h"
#include "virtio.h"
#include "pci.h"
+#include "virtio-transport.h"
/* from Linux's linux/virtio_balloon.h */
@@ -52,4 +54,11 @@ typedef struct VirtIOBalloonStat {
uint64_t val;
} QEMU_PACKED VirtIOBalloonStat;
+typedef struct {
+ DeviceState qdev;
+ VirtIOTransportLink *trl;
+} VirtIOBaloonState;
+
+#define VIRTIO_BALLOON_FROM_QDEV(dev) DO_UPCAST(VirtIOBaloonState, qdev, dev)
+
#endif
--
1.7.9.5
^ permalink raw reply related [flat|nested] 17+ messages in thread
* [Qemu-devel] [RFC v2 09/12] hw/virtio-net.c: Add virtio-net device.
2012-09-17 10:00 [Qemu-devel] [RFC v2 00/12] Virtio-mmio refactoring Evgeny Voevodin
` (7 preceding siblings ...)
2012-09-17 10:00 ` [Qemu-devel] [RFC v2 08/12] hw/virtio-balloon.c: Add virtio-balloon device Evgeny Voevodin
@ 2012-09-17 10:00 ` Evgeny Voevodin
2012-09-17 10:00 ` [Qemu-devel] [RFC v2 10/12] hw/virtio-blk.c: Add virtio-blk device Evgeny Voevodin
` (3 subsequent siblings)
12 siblings, 0 replies; 17+ messages in thread
From: Evgeny Voevodin @ 2012-09-17 10:00 UTC (permalink / raw)
To: qemu-devel; +Cc: peter.maydell, kyungmin.park, aliguori, Evgeny Voevodin
Signed-off-by: Evgeny Voevodin <e.voevodin@samsung.com>
---
hw/virtio-net.c | 59 +++++++++++++++++++++++++++++++++++++++++++++++++++++++
hw/virtio-net.h | 16 +++++++++++++++
2 files changed, 75 insertions(+)
diff --git a/hw/virtio-net.c b/hw/virtio-net.c
index b1998b2..b7cfb1c 100644
--- a/hw/virtio-net.c
+++ b/hw/virtio-net.c
@@ -13,6 +13,8 @@
#include "iov.h"
#include "virtio.h"
+#include "virtio-transport.h"
+#include "virtio-pci.h"
#include "net.h"
#include "net/checksum.h"
#include "net/tap.h"
@@ -1080,3 +1082,60 @@ void virtio_net_exit(VirtIODevice *vdev)
qemu_del_net_client(&n->nic->nc);
virtio_cleanup(&n->vdev);
}
+
+/******************** VirtIONet Device **********************/
+
+static int virtio_netdev_init(DeviceState *dev)
+{
+ VirtIODevice *vdev;
+ VirtIONetState *s = VIRTIO_NET_FROM_QDEV(dev);
+
+ assert(s->trl != NULL);
+
+ vdev = virtio_net_init(dev, &s->nic, &s->net);
+
+ /* Pass default host_features to transport */
+ s->trl->host_features = s->host_features;
+
+ if (virtio_call_backend_init_cb(dev, s->trl, vdev) != 0) {
+ return -1;
+ }
+
+ /* Binding should be ready here, let's get final features */
+ if (vdev->binding->get_features) {
+ s->host_features = vdev->binding->get_features(vdev->binding_opaque);
+ }
+ return 0;
+}
+
+static Property virtio_net_properties[] = {
+ DEFINE_VIRTIO_NET_FEATURES(VirtIONetState, host_features),
+ DEFINE_NIC_PROPERTIES(VirtIONetState, nic),
+ DEFINE_PROP_UINT32("x-txtimer", VirtIONetState, net.txtimer,
+ TX_TIMER_INTERVAL),
+ DEFINE_PROP_INT32("x-txburst", VirtIONetState, net.txburst, TX_BURST),
+ DEFINE_PROP_STRING("tx", VirtIONetState, net.tx),
+ DEFINE_PROP_TRANSPORT("transport", VirtIONetState, trl),
+ DEFINE_PROP_END_OF_LIST(),
+};
+
+static void virtio_net_class_init(ObjectClass *klass, void *data)
+{
+ DeviceClass *dc = DEVICE_CLASS(klass);
+ dc->init = virtio_netdev_init;
+ dc->props = virtio_net_properties;
+}
+
+static TypeInfo virtio_net_info = {
+ .name = "virtio-net",
+ .parent = TYPE_DEVICE,
+ .instance_size = sizeof(VirtIONetState),
+ .class_init = virtio_net_class_init,
+};
+
+static void virtio_net_register_types(void)
+{
+ type_register_static(&virtio_net_info);
+}
+
+type_init(virtio_net_register_types)
diff --git a/hw/virtio-net.h b/hw/virtio-net.h
index 36aa463..8dd49d3 100644
--- a/hw/virtio-net.h
+++ b/hw/virtio-net.h
@@ -14,7 +14,9 @@
#ifndef _QEMU_VIRTIO_NET_H
#define _QEMU_VIRTIO_NET_H
+#include "sysbus.h"
#include "virtio.h"
+#include "virtio-transport.h"
#include "net.h"
#include "pci.h"
@@ -187,4 +189,18 @@ struct virtio_net_ctrl_mac {
DEFINE_PROP_BIT("ctrl_rx", _state, _field, VIRTIO_NET_F_CTRL_RX, true), \
DEFINE_PROP_BIT("ctrl_vlan", _state, _field, VIRTIO_NET_F_CTRL_VLAN, true), \
DEFINE_PROP_BIT("ctrl_rx_extra", _state, _field, VIRTIO_NET_F_CTRL_RX_EXTRA, true)
+
+typedef struct {
+ DeviceState qdev;
+ /* virtio-net */
+ NICConf nic;
+ virtio_net_conf net;
+
+ uint32_t host_features;
+
+ VirtIOTransportLink *trl;
+} VirtIONetState;
+
+#define VIRTIO_NET_FROM_QDEV(dev) DO_UPCAST(VirtIONetState, qdev, dev)
+
#endif
--
1.7.9.5
^ permalink raw reply related [flat|nested] 17+ messages in thread
* [Qemu-devel] [RFC v2 10/12] hw/virtio-blk.c: Add virtio-blk device.
2012-09-17 10:00 [Qemu-devel] [RFC v2 00/12] Virtio-mmio refactoring Evgeny Voevodin
` (8 preceding siblings ...)
2012-09-17 10:00 ` [Qemu-devel] [RFC v2 09/12] hw/virtio-net.c: Add virtio-net device Evgeny Voevodin
@ 2012-09-17 10:00 ` Evgeny Voevodin
2012-09-17 10:00 ` [Qemu-devel] [RFC v2 11/12] hw/virtio-pci-new.c: Add VirtIOPCI device Evgeny Voevodin
` (2 subsequent siblings)
12 siblings, 0 replies; 17+ messages in thread
From: Evgeny Voevodin @ 2012-09-17 10:00 UTC (permalink / raw)
To: qemu-devel; +Cc: peter.maydell, kyungmin.park, aliguori, Evgeny Voevodin
Signed-off-by: Evgeny Voevodin <e.voevodin@samsung.com>
---
hw/virtio-blk.c | 65 +++++++++++++++++++++++++++++++++++++++++++++++++++++++
hw/virtio-blk.h | 15 +++++++++++++
2 files changed, 80 insertions(+)
diff --git a/hw/virtio-blk.c b/hw/virtio-blk.c
index 6f6d172..0a23352 100644
--- a/hw/virtio-blk.c
+++ b/hw/virtio-blk.c
@@ -16,6 +16,8 @@
#include "trace.h"
#include "hw/block-common.h"
#include "blockdev.h"
+#include "virtio-transport.h"
+#include "virtio-pci.h"
#include "virtio-blk.h"
#include "scsi-defs.h"
#ifdef __linux__
@@ -665,3 +667,66 @@ void virtio_blk_exit(VirtIODevice *vdev)
blockdev_mark_auto_del(s->bs);
virtio_cleanup(vdev);
}
+
+/******************** VirtIOBlk Device **********************/
+
+static int virtio_blkdev_init(DeviceState *dev)
+{
+ VirtIODevice *vdev;
+ VirtIOBlockState *s = VIRTIO_BLK_FROM_QDEV(dev);
+
+ assert(s->trl != NULL);
+
+ vdev = virtio_blk_init(dev, &s->blk);
+ if (!vdev) {
+ return -1;
+ }
+
+ /* Pass default host_features to transport */
+ s->trl->host_features = s->host_features;
+
+ if (virtio_call_backend_init_cb(dev, s->trl, vdev) != 0) {
+ return -1;
+ }
+
+ /* Binding should be ready here, let's get final features */
+ if (vdev->binding->get_features) {
+ s->host_features = vdev->binding->get_features(vdev->binding_opaque);
+ }
+ return 0;
+}
+
+static Property virtio_blkdev_properties[] = {
+ DEFINE_BLOCK_PROPERTIES(VirtIOBlockState, blk.conf),
+ DEFINE_BLOCK_CHS_PROPERTIES(VirtIOBlockState, blk.conf),
+ DEFINE_PROP_STRING("serial", VirtIOBlockState, blk.serial),
+#ifdef __linux__
+ DEFINE_PROP_BIT("scsi", VirtIOBlockState, blk.scsi, 0, true),
+#endif
+ DEFINE_PROP_BIT("config-wce", VirtIOBlockState, blk.config_wce, 0, true),
+ DEFINE_VIRTIO_BLK_FEATURES(VirtIOBlockState, host_features),
+
+ DEFINE_PROP_TRANSPORT("transport", VirtIOBlockState, trl),
+ DEFINE_PROP_END_OF_LIST(),
+};
+
+static void virtio_blkdev_class_init(ObjectClass *klass, void *data)
+{
+ DeviceClass *dc = DEVICE_CLASS(klass);
+ dc->init = virtio_blkdev_init;
+ dc->props = virtio_blkdev_properties;
+}
+
+static TypeInfo virtio_blkdev_info = {
+ .name = "virtio-blk",
+ .parent = TYPE_DEVICE,
+ .instance_size = sizeof(VirtIOBlockState),
+ .class_init = virtio_blkdev_class_init,
+};
+
+static void virtio_blk_register_types(void)
+{
+ type_register_static(&virtio_blkdev_info);
+}
+
+type_init(virtio_blk_register_types)
diff --git a/hw/virtio-blk.h b/hw/virtio-blk.h
index f0740d0..0886818 100644
--- a/hw/virtio-blk.h
+++ b/hw/virtio-blk.h
@@ -14,7 +14,9 @@
#ifndef _QEMU_VIRTIO_BLK_H
#define _QEMU_VIRTIO_BLK_H
+#include "sysbus.h"
#include "virtio.h"
+#include "virtio-transport.h"
#include "hw/block-common.h"
/* from Linux's linux/virtio_blk.h */
@@ -111,4 +113,17 @@ struct VirtIOBlkConf
DEFINE_VIRTIO_COMMON_FEATURES(_state, _field), \
DEFINE_PROP_BIT("config-wce", _state, _field, VIRTIO_BLK_F_CONFIG_WCE, true)
+
+typedef struct {
+ DeviceState qdev;
+ /* virtio-blk */
+ VirtIOBlkConf blk;
+
+ uint32_t host_features;
+
+ VirtIOTransportLink *trl;
+} VirtIOBlockState;
+
+#define VIRTIO_BLK_FROM_QDEV(dev) DO_UPCAST(VirtIOBlockState, qdev, dev)
+
#endif
--
1.7.9.5
^ permalink raw reply related [flat|nested] 17+ messages in thread
* [Qemu-devel] [RFC v2 11/12] hw/virtio-pci-new.c: Add VirtIOPCI device.
2012-09-17 10:00 [Qemu-devel] [RFC v2 00/12] Virtio-mmio refactoring Evgeny Voevodin
` (9 preceding siblings ...)
2012-09-17 10:00 ` [Qemu-devel] [RFC v2 10/12] hw/virtio-blk.c: Add virtio-blk device Evgeny Voevodin
@ 2012-09-17 10:00 ` Evgeny Voevodin
2012-09-17 10:00 ` [Qemu-devel] [RFC v2 12/12] hw/exynos4210.c: Create two virtio-mmio transport instances Evgeny Voevodin
2012-09-27 17:31 ` [Qemu-devel] [RFC v2 00/12] Virtio-mmio refactoring KONRAD Frédéric
12 siblings, 0 replies; 17+ messages in thread
From: Evgeny Voevodin @ 2012-09-17 10:00 UTC (permalink / raw)
To: qemu-devel; +Cc: peter.maydell, kyungmin.park, aliguori, Evgeny Voevodin
This commit adds VirtIOPCI device implementation which is temporary
held in virtio-pci-new.c file. We need this file until virtio-xxx-pci
devices in hw/virtio-pci.c are not implemented in the way that they
just create virtio-pci and virtio-xxx devices during initialization.
Signed-off-by: Evgeny Voevodin <e.voevodin@samsung.com>
---
hw/Makefile.objs | 1 +
hw/virtio-pci-new.c | 925 +++++++++++++++++++++++++++++++++++++++++++++++++++
hw/virtio-pci.h | 18 +
3 files changed, 944 insertions(+)
create mode 100644 hw/virtio-pci-new.c
diff --git a/hw/Makefile.objs b/hw/Makefile.objs
index 0c112af..e5bda7f 100644
--- a/hw/Makefile.objs
+++ b/hw/Makefile.objs
@@ -2,6 +2,7 @@ hw-obj-y = usb/ ide/
hw-obj-y += loader.o
hw-obj-$(CONFIG_VIRTIO) += virtio-console.o
hw-obj-$(CONFIG_VIRTIO_PCI) += virtio-pci.o
+hw-obj-$(CONFIG_VIRTIO_PCI) += virtio-pci-new.o
hw-obj-$(CONFIG_VIRTIO) += virtio-transport.o
hw-obj-$(CONFIG_VIRTIO) += virtio-mmio.o
hw-obj-y += fw_cfg.o
diff --git a/hw/virtio-pci-new.c b/hw/virtio-pci-new.c
new file mode 100644
index 0000000..c1650b5
--- /dev/null
+++ b/hw/virtio-pci-new.c
@@ -0,0 +1,925 @@
+/*
+ * Virtio PCI Bindings
+ *
+ * Copyright IBM, Corp. 2007
+ * Copyright (c) 2009 CodeSourcery
+ *
+ * Authors:
+ * Anthony Liguori <aliguori@us.ibm.com>
+ * Paul Brook <paul@codesourcery.com>
+ *
+ * This work is licensed under the terms of the GNU GPL, version 2. See
+ * the COPYING file in the top-level directory.
+ *
+ * Contributions after 2012-01-13 are licensed under the terms of the
+ * GNU GPL, version 2 or (at your option) any later version.
+ */
+
+#include <inttypes.h>
+
+#include "virtio.h"
+#include "virtio-transport.h"
+#include "virtio-blk.h"
+#include "virtio-net.h"
+#include "virtio-serial.h"
+#include "virtio-scsi.h"
+#include "virtio-balloon.h"
+#include "pci.h"
+#include "qemu-error.h"
+#include "msi.h"
+#include "msix.h"
+#include "net.h"
+#include "loader.h"
+#include "kvm.h"
+#include "blockdev.h"
+#include "virtio-pci.h"
+#include "range.h"
+
+/* from Linux's linux/virtio_pci.h */
+
+/* A 32-bit r/o bitmask of the features supported by the host */
+#define VIRTIO_PCI_HOST_FEATURES 0
+
+/* A 32-bit r/w bitmask of features activated by the guest */
+#define VIRTIO_PCI_GUEST_FEATURES 4
+
+/* A 32-bit r/w PFN for the currently selected queue */
+#define VIRTIO_PCI_QUEUE_PFN 8
+
+/* A 16-bit r/o queue size for the currently selected queue */
+#define VIRTIO_PCI_QUEUE_NUM 12
+
+/* A 16-bit r/w queue selector */
+#define VIRTIO_PCI_QUEUE_SEL 14
+
+/* A 16-bit r/w queue notifier */
+#define VIRTIO_PCI_QUEUE_NOTIFY 16
+
+/* An 8-bit device status register. */
+#define VIRTIO_PCI_STATUS 18
+
+/* An 8-bit r/o interrupt status register. Reading the value will return the
+ * current contents of the ISR and will also clear it. This is effectively
+ * a read-and-acknowledge. */
+#define VIRTIO_PCI_ISR 19
+
+/* MSI-X registers: only enabled if MSI-X is enabled. */
+/* A 16-bit vector for configuration changes. */
+#define VIRTIO_MSI_CONFIG_VECTOR 20
+/* A 16-bit vector for selected queue notifications. */
+#define VIRTIO_MSI_QUEUE_VECTOR 22
+
+/* Config space size */
+#define VIRTIO_PCI_CONFIG_NOMSI 20
+#define VIRTIO_PCI_CONFIG_MSI 24
+#define VIRTIO_PCI_REGION_SIZE(dev) (msix_present(dev) ? \
+ VIRTIO_PCI_CONFIG_MSI : \
+ VIRTIO_PCI_CONFIG_NOMSI)
+
+/* The remaining space is defined by each driver as the per-driver
+ * configuration space */
+#define VIRTIO_PCI_CONFIG(dev) (msix_enabled(dev) ? \
+ VIRTIO_PCI_CONFIG_MSI : \
+ VIRTIO_PCI_CONFIG_NOMSI)
+
+/* How many bits to shift physical queue address written to QUEUE_PFN.
+ * 12 is historical, and due to x86 page size. */
+#define VIRTIO_PCI_QUEUE_ADDR_SHIFT 12
+
+/* Flags track per-device state like workarounds for quirks in older guests. */
+#define VIRTIO_PCI_FLAG_BUS_MASTER_BUG (1 << 0)
+
+/* QEMU doesn't strictly need write barriers since everything runs in
+ * lock-step. We'll leave the calls to wmb() in though to make it obvious for
+ * KVM or if kqemu gets SMP support.
+ */
+#define wmb() do { } while (0)
+
+/* HACK for virtio to determine if it's running a big endian guest */
+bool virtio_is_big_endian(void);
+
+/* virtio device */
+
+static void virtio_pci_notify(void *opaque, uint16_t vector)
+{
+ VirtIOPCI *s = opaque;
+ if (msix_enabled(&s->pci_dev)) {
+ msix_notify(&s->pci_dev, vector);
+ }
+ else {
+ qemu_set_irq(s->pci_dev.irq[0], s->vdev->isr & 1);
+ }
+}
+
+static void virtio_pci_save_config(void * opaque, QEMUFile *f)
+{
+ VirtIOPCI *s = opaque;
+ pci_device_save(&s->pci_dev, f);
+ msix_save(&s->pci_dev, f);
+ if (msix_present(&s->pci_dev)) {
+ qemu_put_be16(f, s->vdev->config_vector);
+ }
+}
+
+static void virtio_pci_save_queue(void * opaque, int n, QEMUFile *f)
+{
+ VirtIOPCI *s = opaque;
+ if (msix_present(&s->pci_dev)) {
+ qemu_put_be16(f, virtio_queue_vector(s->vdev, n));
+ }
+}
+
+static int virtio_pci_load_config(void * opaque, QEMUFile *f)
+{
+ VirtIOPCI *s = opaque;
+ int ret;
+ ret = pci_device_load(&s->pci_dev, f);
+ if (ret) {
+ return ret;
+ }
+ msix_unuse_all_vectors(&s->pci_dev);
+ msix_load(&s->pci_dev, f);
+ if (msix_present(&s->pci_dev)) {
+ qemu_get_be16s(f, &s->vdev->config_vector);
+ } else {
+ s->vdev->config_vector = VIRTIO_NO_VECTOR;
+ }
+ if (s->vdev->config_vector != VIRTIO_NO_VECTOR) {
+ return msix_vector_use(&s->pci_dev, s->vdev->config_vector);
+ }
+ return 0;
+}
+
+static int virtio_pci_load_queue(void * opaque, int n, QEMUFile *f)
+{
+ VirtIOPCI *s = opaque;
+ uint16_t vector;
+ if (msix_present(&s->pci_dev)) {
+ qemu_get_be16s(f, &vector);
+ } else {
+ vector = VIRTIO_NO_VECTOR;
+ }
+ virtio_queue_set_vector(s->vdev, n, vector);
+ if (vector != VIRTIO_NO_VECTOR) {
+ return msix_vector_use(&s->pci_dev, vector);
+ }
+ return 0;
+}
+
+static int virtio_pci_set_host_notifier_internal(VirtIOPCI *s, int n,
+ bool assign, bool set_handler)
+{
+ VirtQueue *vq = virtio_get_queue(s->vdev, n);
+ EventNotifier *notifier = virtio_queue_get_host_notifier(vq);
+ int r = 0;
+
+ if (assign) {
+ r = event_notifier_init(notifier, 1);
+ if (r < 0) {
+ error_report("%s: unable to init event notifier: %d", __func__, r);
+ return r;
+ }
+ virtio_queue_set_host_notifier_fd_handler(vq, true, set_handler);
+ memory_region_add_eventfd(&s->bar, VIRTIO_PCI_QUEUE_NOTIFY, 2, true, n,
+ notifier);
+ } else {
+ memory_region_del_eventfd(&s->bar, VIRTIO_PCI_QUEUE_NOTIFY, 2, true, n,
+ notifier);
+ virtio_queue_set_host_notifier_fd_handler(vq, false, false);
+ event_notifier_cleanup(notifier);
+ }
+ return r;
+}
+
+static void virtio_pci_start_ioeventfd(VirtIOPCI *s)
+{
+ int n, r;
+
+ if (!(s->flags & VIRTIO_PCI_FLAG_USE_IOEVENTFD) ||
+ s->ioeventfd_disabled ||
+ s->ioeventfd_started) {
+ return;
+ }
+
+ for (n = 0; n < VIRTIO_PCI_QUEUE_MAX; n++) {
+ if (!virtio_queue_get_num(s->vdev, n)) {
+ continue;
+ }
+
+ r = virtio_pci_set_host_notifier_internal(s, n, true, true);
+ if (r < 0) {
+ goto assign_error;
+ }
+ }
+ s->ioeventfd_started = true;
+ return;
+
+assign_error:
+ while (--n >= 0) {
+ if (!virtio_queue_get_num(s->vdev, n)) {
+ continue;
+ }
+
+ r = virtio_pci_set_host_notifier_internal(s, n, false, false);
+ assert(r >= 0);
+ }
+ s->ioeventfd_started = false;
+ error_report("%s: failed. Fallback to a userspace (slower).", __func__);
+}
+
+static void virtio_pci_stop_ioeventfd(VirtIOPCI *s)
+{
+ int r;
+ int n;
+
+ if (!s->ioeventfd_started) {
+ return;
+ }
+
+ for (n = 0; n < VIRTIO_PCI_QUEUE_MAX; n++) {
+ if (!virtio_queue_get_num(s->vdev, n)) {
+ continue;
+ }
+
+ r = virtio_pci_set_host_notifier_internal(s, n, false, false);
+ assert(r >= 0);
+ }
+ s->ioeventfd_started = false;
+}
+
+void virtio_pci_reset_(DeviceState *d)
+{
+ VirtIOPCI *s =
+ container_of(d, VirtIOPCI, pci_dev.qdev);
+ virtio_pci_stop_ioeventfd(s);
+ if (s->vdev) {
+ virtio_reset(s->vdev);
+ }
+ msix_unuse_all_vectors(&s->pci_dev);
+ s->flags &= ~VIRTIO_PCI_FLAG_BUS_MASTER_BUG;
+}
+
+static void virtio_ioport_write(void *opaque, uint32_t addr, uint32_t val)
+{
+ VirtIOPCI *s = opaque;
+ VirtIODevice *vdev = s->vdev;
+ target_phys_addr_t pa;
+
+ switch (addr) {
+ case VIRTIO_PCI_GUEST_FEATURES:
+ /* Guest does not negotiate properly? We have to assume nothing. */
+ if (val & (1 << VIRTIO_F_BAD_FEATURE)) {
+ val = vdev->bad_features ? vdev->bad_features(vdev) : 0;
+ }
+ virtio_set_features(vdev, val);
+ break;
+ case VIRTIO_PCI_QUEUE_PFN:
+ pa = (target_phys_addr_t)val << VIRTIO_PCI_QUEUE_ADDR_SHIFT;
+ if (pa == 0) {
+ virtio_pci_stop_ioeventfd(s);
+ virtio_reset(s->vdev);
+ msix_unuse_all_vectors(&s->pci_dev);
+ }
+ else
+ virtio_queue_set_addr(vdev, vdev->queue_sel, pa);
+ break;
+ case VIRTIO_PCI_QUEUE_SEL:
+ if (val < VIRTIO_PCI_QUEUE_MAX)
+ vdev->queue_sel = val;
+ break;
+ case VIRTIO_PCI_QUEUE_NOTIFY:
+ if (val < VIRTIO_PCI_QUEUE_MAX) {
+ virtio_queue_notify(vdev, val);
+ }
+ break;
+ case VIRTIO_PCI_STATUS:
+ if (!(val & VIRTIO_CONFIG_S_DRIVER_OK)) {
+ virtio_pci_stop_ioeventfd(s);
+ }
+
+ virtio_set_status(vdev, val & 0xFF);
+
+ if (val & VIRTIO_CONFIG_S_DRIVER_OK) {
+ virtio_pci_start_ioeventfd(s);
+ }
+
+ if (vdev->status == 0) {
+ virtio_reset(s->vdev);
+ msix_unuse_all_vectors(&s->pci_dev);
+ }
+
+ /* 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
+ some safety checks. */
+ if ((val & VIRTIO_CONFIG_S_DRIVER_OK) &&
+ !(s->pci_dev.config[PCI_COMMAND] & PCI_COMMAND_MASTER)) {
+ s->flags |= VIRTIO_PCI_FLAG_BUS_MASTER_BUG;
+ }
+ break;
+ case VIRTIO_MSI_CONFIG_VECTOR:
+ msix_vector_unuse(&s->pci_dev, vdev->config_vector);
+ /* Make it possible for guest to discover an error took place. */
+ if (msix_vector_use(&s->pci_dev, val) < 0)
+ val = VIRTIO_NO_VECTOR;
+ vdev->config_vector = val;
+ break;
+ case VIRTIO_MSI_QUEUE_VECTOR:
+ msix_vector_unuse(&s->pci_dev,
+ virtio_queue_vector(vdev, vdev->queue_sel));
+ /* Make it possible for guest to discover an error took place. */
+ if (msix_vector_use(&s->pci_dev, val) < 0)
+ val = VIRTIO_NO_VECTOR;
+ virtio_queue_set_vector(vdev, vdev->queue_sel, val);
+ break;
+ default:
+ error_report("%s: unexpected address 0x%x value 0x%x",
+ __func__, addr, val);
+ break;
+ }
+}
+
+static uint32_t virtio_ioport_read(VirtIOPCI *s, uint32_t addr)
+{
+ VirtIODevice *vdev = s->vdev;
+ uint32_t ret = 0xFFFFFFFF;
+
+ switch (addr) {
+ case VIRTIO_PCI_HOST_FEATURES:
+ ret = s->host_features;
+ break;
+ case VIRTIO_PCI_GUEST_FEATURES:
+ ret = vdev->guest_features;
+ break;
+ case VIRTIO_PCI_QUEUE_PFN:
+ ret = virtio_queue_get_addr(vdev, vdev->queue_sel)
+ >> VIRTIO_PCI_QUEUE_ADDR_SHIFT;
+ break;
+ case VIRTIO_PCI_QUEUE_NUM:
+ ret = virtio_queue_get_num(vdev, vdev->queue_sel);
+ break;
+ case VIRTIO_PCI_QUEUE_SEL:
+ ret = vdev->queue_sel;
+ break;
+ case VIRTIO_PCI_STATUS:
+ ret = vdev->status;
+ break;
+ case VIRTIO_PCI_ISR:
+ /* reading from the ISR also clears it. */
+ ret = vdev->isr;
+ vdev->isr = 0;
+ qemu_set_irq(s->pci_dev.irq[0], 0);
+ break;
+ case VIRTIO_MSI_CONFIG_VECTOR:
+ ret = vdev->config_vector;
+ break;
+ case VIRTIO_MSI_QUEUE_VECTOR:
+ ret = virtio_queue_vector(vdev, vdev->queue_sel);
+ break;
+ default:
+ break;
+ }
+
+ return ret;
+}
+
+static uint32_t virtio_pci_config_readb(void *opaque, uint32_t addr)
+{
+ VirtIOPCI *s = opaque;
+ uint32_t config = VIRTIO_PCI_CONFIG(&s->pci_dev);
+ if (addr < config)
+ return virtio_ioport_read(s, addr);
+ addr -= config;
+ return virtio_config_readb(s->vdev, addr);
+}
+
+static uint32_t virtio_pci_config_readw(void *opaque, uint32_t addr)
+{
+ VirtIOPCI *s = opaque;
+ uint32_t config = VIRTIO_PCI_CONFIG(&s->pci_dev);
+ uint16_t val;
+ if (addr < config)
+ return virtio_ioport_read(s, addr);
+ addr -= config;
+ val = virtio_config_readw(s->vdev, addr);
+ if (virtio_is_big_endian()) {
+ /*
+ * virtio is odd, ioports are LE but config space is target native
+ * endian. However, in qemu, all PIO is LE, so we need to re-swap
+ * on BE targets
+ */
+ val = bswap16(val);
+ }
+ return val;
+}
+
+static uint32_t virtio_pci_config_readl(void *opaque, uint32_t addr)
+{
+ VirtIOPCI *s = opaque;
+ uint32_t config = VIRTIO_PCI_CONFIG(&s->pci_dev);
+ uint32_t val;
+ if (addr < config)
+ return virtio_ioport_read(s, addr);
+ addr -= config;
+ val = virtio_config_readl(s->vdev, addr);
+ if (virtio_is_big_endian()) {
+ val = bswap32(val);
+ }
+ return val;
+}
+
+static void virtio_pci_config_writeb(void *opaque, uint32_t addr, uint32_t val)
+{
+ VirtIOPCI *s = opaque;
+ uint32_t config = VIRTIO_PCI_CONFIG(&s->pci_dev);
+ if (addr < config) {
+ virtio_ioport_write(s, addr, val);
+ return;
+ }
+ addr -= config;
+ virtio_config_writeb(s->vdev, addr, val);
+}
+
+static void virtio_pci_config_writew(void *opaque, uint32_t addr, uint32_t val)
+{
+ VirtIOPCI *s = opaque;
+ uint32_t config = VIRTIO_PCI_CONFIG(&s->pci_dev);
+ if (addr < config) {
+ virtio_ioport_write(s, addr, val);
+ return;
+ }
+ addr -= config;
+ if (virtio_is_big_endian()) {
+ val = bswap16(val);
+ }
+ virtio_config_writew(s->vdev, addr, val);
+}
+
+static void virtio_pci_config_writel(void *opaque, uint32_t addr, uint32_t val)
+{
+ VirtIOPCI *s = opaque;
+ uint32_t config = VIRTIO_PCI_CONFIG(&s->pci_dev);
+ if (addr < config) {
+ virtio_ioport_write(s, addr, val);
+ return;
+ }
+ addr -= config;
+ if (virtio_is_big_endian()) {
+ val = bswap32(val);
+ }
+ virtio_config_writel(s->vdev, addr, val);
+}
+
+static const MemoryRegionPortio virtio_portio[] = {
+ { 0, 0x10000, 1, .write = virtio_pci_config_writeb, },
+ { 0, 0x10000, 2, .write = virtio_pci_config_writew, },
+ { 0, 0x10000, 4, .write = virtio_pci_config_writel, },
+ { 0, 0x10000, 1, .read = virtio_pci_config_readb, },
+ { 0, 0x10000, 2, .read = virtio_pci_config_readw, },
+ { 0, 0x10000, 4, .read = virtio_pci_config_readl, },
+ PORTIO_END_OF_LIST()
+};
+
+static const MemoryRegionOps virtio_pci_config_ops = {
+ .old_portio = virtio_portio,
+ .endianness = DEVICE_LITTLE_ENDIAN,
+};
+
+static void virtio_write_config(PCIDevice *pci_dev, uint32_t address,
+ uint32_t val, int len)
+{
+ VirtIOPCI *s = DO_UPCAST(VirtIOPCI,
+ pci_dev, pci_dev);
+
+ pci_default_write_config(pci_dev, address, val, len);
+
+ if (range_covers_byte(address, len, PCI_COMMAND) &&
+ !(pci_dev->config[PCI_COMMAND] & PCI_COMMAND_MASTER) &&
+ !(s->flags & VIRTIO_PCI_FLAG_BUS_MASTER_BUG)) {
+ virtio_pci_stop_ioeventfd(s);
+ virtio_set_status(s->vdev,
+ s->vdev->status & ~VIRTIO_CONFIG_S_DRIVER_OK);
+ }
+}
+
+static unsigned virtio_pci_get_features(void *opaque)
+{
+ VirtIOPCI *s = opaque;
+ return s->host_features;
+}
+
+static int kvm_virtio_pci_vq_vector_use(VirtIOPCI *s,
+ unsigned int queue_no,
+ unsigned int vector,
+ MSIMessage msg)
+{
+ VirtQueue *vq = virtio_get_queue(s->vdev, queue_no);
+ EventNotifier *n = virtio_queue_get_guest_notifier(vq);
+ VirtIOIRQFD *irqfd = &s->vector_irqfd[vector];
+ int ret;
+
+ if (irqfd->users == 0) {
+ ret = kvm_irqchip_add_msi_route(kvm_state, msg);
+ if (ret < 0) {
+ return ret;
+ }
+ irqfd->virq = ret;
+ }
+ irqfd->users++;
+
+ ret = kvm_irqchip_add_irqfd_notifier(kvm_state, n, irqfd->virq);
+ if (ret < 0) {
+ if (--irqfd->users == 0) {
+ kvm_irqchip_release_virq(kvm_state, irqfd->virq);
+ }
+ return ret;
+ }
+
+ virtio_queue_set_guest_notifier_fd_handler(vq, true, true);
+ return 0;
+}
+
+static void kvm_virtio_pci_vq_vector_release(VirtIOPCI *s,
+ unsigned int queue_no,
+ unsigned int vector)
+{
+ VirtQueue *vq = virtio_get_queue(s->vdev, queue_no);
+ EventNotifier *n = virtio_queue_get_guest_notifier(vq);
+ VirtIOIRQFD *irqfd = &s->vector_irqfd[vector];
+ int ret;
+
+ ret = kvm_irqchip_remove_irqfd_notifier(kvm_state, n, irqfd->virq);
+ assert(ret == 0);
+
+ if (--irqfd->users == 0) {
+ kvm_irqchip_release_virq(kvm_state, irqfd->virq);
+ }
+
+ virtio_queue_set_guest_notifier_fd_handler(vq, true, false);
+}
+
+static int kvm_virtio_pci_vector_use(PCIDevice *dev, unsigned vector,
+ MSIMessage msg)
+{
+ VirtIOPCI *s = container_of(dev, VirtIOPCI, pci_dev);
+ VirtIODevice *vdev = s->vdev;
+ int ret, queue_no;
+
+ for (queue_no = 0; queue_no < VIRTIO_PCI_QUEUE_MAX; queue_no++) {
+ if (!virtio_queue_get_num(vdev, queue_no)) {
+ break;
+ }
+ if (virtio_queue_vector(vdev, queue_no) != vector) {
+ continue;
+ }
+ ret = kvm_virtio_pci_vq_vector_use(s, queue_no, vector, msg);
+ if (ret < 0) {
+ goto undo;
+ }
+ }
+ return 0;
+
+undo:
+ while (--queue_no >= 0) {
+ if (virtio_queue_vector(vdev, queue_no) != vector) {
+ continue;
+ }
+ kvm_virtio_pci_vq_vector_release(s, queue_no, vector);
+ }
+ return ret;
+}
+
+static void kvm_virtio_pci_vector_release(PCIDevice *dev, unsigned vector)
+{
+ VirtIOPCI *s = container_of(dev, VirtIOPCI, pci_dev);
+ VirtIODevice *vdev = s->vdev;
+ int queue_no;
+
+ for (queue_no = 0; queue_no < VIRTIO_PCI_QUEUE_MAX; queue_no++) {
+ if (!virtio_queue_get_num(vdev, queue_no)) {
+ break;
+ }
+ if (virtio_queue_vector(vdev, queue_no) != vector) {
+ continue;
+ }
+ kvm_virtio_pci_vq_vector_release(s, queue_no, vector);
+ }
+}
+
+static int virtio_pci_set_guest_notifier(void *opaque, int n, bool assign)
+{
+ VirtIOPCI *s = opaque;
+ VirtQueue *vq = virtio_get_queue(s->vdev, n);
+ EventNotifier *notifier = virtio_queue_get_guest_notifier(vq);
+
+ if (assign) {
+ int r = event_notifier_init(notifier, 0);
+ if (r < 0) {
+ return r;
+ }
+ virtio_queue_set_guest_notifier_fd_handler(vq, true, false);
+ } else {
+ virtio_queue_set_guest_notifier_fd_handler(vq, false, false);
+ event_notifier_cleanup(notifier);
+ }
+
+ return 0;
+}
+
+static bool virtio_pci_query_guest_notifiers(void *opaque)
+{
+ VirtIOPCI *s = opaque;
+ return msix_enabled(&s->pci_dev);
+}
+
+static int virtio_pci_set_guest_notifiers(void *opaque, bool assign)
+{
+ VirtIOPCI *s = opaque;
+ VirtIODevice *vdev = s->vdev;
+ int r, n;
+
+ /* Must unset vector notifier while guest notifier is still assigned */
+ if (kvm_msi_via_irqfd_enabled() && !assign) {
+ msix_unset_vector_notifiers(&s->pci_dev);
+ g_free(s->vector_irqfd);
+ s->vector_irqfd = NULL;
+ }
+
+ for (n = 0; n < VIRTIO_PCI_QUEUE_MAX; n++) {
+ if (!virtio_queue_get_num(vdev, n)) {
+ break;
+ }
+
+ r = virtio_pci_set_guest_notifier(opaque, n, assign);
+ if (r < 0) {
+ goto assign_error;
+ }
+ }
+
+ /* Must set vector notifier after guest notifier has been assigned */
+ if (kvm_msi_via_irqfd_enabled() && assign) {
+ s->vector_irqfd =
+ g_malloc0(sizeof(*s->vector_irqfd) *
+ msix_nr_vectors_allocated(&s->pci_dev));
+ r = msix_set_vector_notifiers(&s->pci_dev,
+ kvm_virtio_pci_vector_use,
+ kvm_virtio_pci_vector_release);
+ if (r < 0) {
+ goto assign_error;
+ }
+ }
+
+ return 0;
+
+assign_error:
+ /* We get here on assignment failure. Recover by undoing for VQs 0 .. n. */
+ assert(assign);
+ while (--n >= 0) {
+ virtio_pci_set_guest_notifier(opaque, n, !assign);
+ }
+ return r;
+}
+
+static int virtio_pci_set_host_notifier(void *opaque, int n, bool assign)
+{
+ VirtIOPCI *s = opaque;
+
+ /* Stop using ioeventfd for virtqueue kick if the device starts using host
+ * notifiers. This makes it easy to avoid stepping on each others' toes.
+ */
+ s->ioeventfd_disabled = assign;
+ if (assign) {
+ virtio_pci_stop_ioeventfd(s);
+ }
+ /* We don't need to start here: it's not needed because backend
+ * currently only stops on status change away from ok,
+ * reset, vmstop and such. If we do add code to start here,
+ * need to check vmstate, device state etc. */
+ return virtio_pci_set_host_notifier_internal(s, n, assign, false);
+}
+
+static void virtio_pci_vmstate_change(void *opaque, bool running)
+{
+ VirtIOPCI *s = opaque;
+
+ if (running) {
+ /* Try to find out if the guest has bus master disabled, but is
+ in ready state. Then we have a buggy guest OS. */
+ if ((s->vdev->status & VIRTIO_CONFIG_S_DRIVER_OK) &&
+ !(s->pci_dev.config[PCI_COMMAND] & PCI_COMMAND_MASTER)) {
+ s->flags |= VIRTIO_PCI_FLAG_BUS_MASTER_BUG;
+ }
+ virtio_pci_start_ioeventfd(s);
+ } else {
+ virtio_pci_stop_ioeventfd(s);
+ }
+}
+
+static const VirtIOBindings virtio_pci_bindings = {
+ .notify = virtio_pci_notify,
+ .save_config = virtio_pci_save_config,
+ .load_config = virtio_pci_load_config,
+ .save_queue = virtio_pci_save_queue,
+ .load_queue = virtio_pci_load_queue,
+ .get_features = virtio_pci_get_features,
+ .query_guest_notifiers = virtio_pci_query_guest_notifiers,
+ .set_host_notifier = virtio_pci_set_host_notifier,
+ .set_guest_notifiers = virtio_pci_set_guest_notifiers,
+ .vmstate_change = virtio_pci_vmstate_change,
+};
+
+static void virtio_init_pci_(VirtIOPCI *s, VirtIODevice *vdev)
+{
+ uint8_t *config;
+ uint32_t size;
+
+ s->vdev = vdev;
+
+ config = s->pci_dev.config;
+
+ if (s->class_code) {
+ pci_config_set_class(config, s->class_code);
+ }
+ pci_set_word(config + PCI_SUBSYSTEM_VENDOR_ID,
+ pci_get_word(config + PCI_VENDOR_ID));
+ pci_set_word(config + PCI_SUBSYSTEM_ID, vdev->device_id);
+ config[PCI_INTERRUPT_PIN] = 1;
+
+ if (vdev->nvectors &&
+ msix_init_exclusive_bar(&s->pci_dev, vdev->nvectors, 1)) {
+ vdev->nvectors = 0;
+ }
+
+ s->pci_dev.config_write = virtio_write_config;
+
+ size = VIRTIO_PCI_REGION_SIZE(&s->pci_dev) + vdev->config_len;
+ if (size & (size-1))
+ size = 1 << qemu_fls(size);
+
+ memory_region_init_io(&s->bar, &virtio_pci_config_ops, s,
+ "virtio-pci", size);
+ pci_register_bar(&s->pci_dev, 0, PCI_BASE_ADDRESS_SPACE_IO,
+ &s->bar);
+
+ if (!kvm_has_many_ioeventfds()) {
+ s->flags &= ~VIRTIO_PCI_FLAG_USE_IOEVENTFD;
+ }
+
+ virtio_bind_device(vdev, &virtio_pci_bindings, s);
+ s->host_features |= 0x1 << VIRTIO_F_NOTIFY_ON_EMPTY;
+ s->host_features |= 0x1 << VIRTIO_F_BAD_FEATURE;
+ s->host_features = vdev->get_features(vdev, s->host_features);
+}
+
+static void virtio_exit_pci(PCIDevice *pci_dev)
+{
+ VirtIOPCI *s = DO_UPCAST(VirtIOPCI, pci_dev, pci_dev);
+
+ memory_region_destroy(&s->bar);
+ msix_uninit_exclusive_bar(pci_dev);
+}
+
+static int virtio_pci_transport_cb(DeviceState *dev, VirtIODevice *vdev,
+ VirtIOTransportLink *trl)
+{
+ PCIDevice *pci_dev = DO_UPCAST(PCIDevice, qdev, trl->tr);
+ VirtIOPCI *s = DO_UPCAST(VirtIOPCI, pci_dev, pci_dev);
+
+ virtio_plug_into_transport(dev, trl);
+
+ // TODO: Figure out if props were explicitly set before
+
+ /* Get default host_features passed from back-end */
+ s->host_features = s->trl->host_features;
+
+ switch (vdev->device_id) {
+ case VIRTIO_ID_BLOCK:
+ s->flags |= VIRTIO_PCI_FLAG_USE_IOEVENTFD;
+ s->nvectors = 2;
+
+ if (s->class_code != PCI_CLASS_STORAGE_SCSI &&
+ s->class_code != PCI_CLASS_STORAGE_OTHER) {
+ s->class_code = PCI_CLASS_STORAGE_SCSI;
+ }
+
+ vdev->nvectors = s->nvectors;
+ pci_config_set_device_id(s->pci_dev.config, PCI_DEVICE_ID_VIRTIO_BLOCK);
+ pci_config_set_class(s->pci_dev.config, PCI_CLASS_STORAGE_SCSI);
+ virtio_init_pci_(s, vdev);
+ s->nvectors = vdev->nvectors;
+ break;
+ case VIRTIO_ID_NET:
+ s->nvectors = 3;
+
+ /* load rom */
+ pci_dev->romfile = g_strdup("pxe-virtio.rom");
+ pci_add_option_rom(pci_dev, false);
+
+ vdev->nvectors = s->nvectors;
+ pci_config_set_device_id(s->pci_dev.config, PCI_DEVICE_ID_VIRTIO_NET);
+ pci_config_set_class(s->pci_dev.config, PCI_CLASS_NETWORK_ETHERNET);
+ virtio_init_pci_(s, vdev);
+ s->nvectors = vdev->nvectors;
+ break;
+ case VIRTIO_ID_BALLOON:
+ break;
+ case VIRTIO_ID_SCSI:
+ break;
+ case VIRTIO_ID_CONSOLE:
+ {
+ break;
+ }
+ default:
+ fprintf(stderr,
+ "Unknown back-end device id: 0x%" PRIx16 "\n", vdev->device_id);
+ return -1;
+ }
+
+ return 0;
+}
+
+static int virtio_pci_device_init(PCIDevice *pci_dev)
+{
+ VirtIOPCI *s =
+ DO_UPCAST(VirtIOPCI, pci_dev, pci_dev);
+
+ virtio_init_transport(&pci_dev->qdev, &s->trl, VIRTIO_PCI,
+ virtio_pci_transport_cb);
+
+ return 0;
+}
+
+static void virtio_pci_device_exit(PCIDevice *pci_dev)
+{
+ VirtIOPCI *s =
+ DO_UPCAST(VirtIOPCI, pci_dev, pci_dev);
+
+ switch (s->vdev->device_id) {
+ case VIRTIO_ID_BLOCK:
+ virtio_pci_stop_ioeventfd(s);
+ virtio_blk_exit(s->vdev);
+ break;
+ case VIRTIO_ID_NET:
+ virtio_pci_stop_ioeventfd(s);
+ virtio_net_exit(s->vdev);
+ break;
+ case VIRTIO_ID_BALLOON:
+ virtio_pci_stop_ioeventfd(s);
+ virtio_balloon_exit(s->vdev);
+ break;
+ case VIRTIO_ID_SCSI:
+ virtio_scsi_exit(s->vdev);
+ break;
+ case VIRTIO_ID_CONSOLE:
+ virtio_pci_stop_ioeventfd(s);
+ virtio_serial_exit(s->vdev);
+ break;
+ default:
+ fprintf(stderr,
+ "Unknown back-end device id: 0x%" PRIx16 "\n",
+ s->vdev->device_id);
+ return;
+ }
+
+ virtio_exit_pci(pci_dev);
+
+ return;
+}
+
+/******************** VirtIOPCI Device **********************/
+
+static Property virtio_pci_properties[] = {
+ DEFINE_PROP_HEX32("class", VirtIOPCI, class_code, 0),
+ DEFINE_PROP_BIT("ioeventfd", VirtIOPCI, flags,
+ VIRTIO_PCI_FLAG_USE_IOEVENTFD_BIT, false),
+ DEFINE_PROP_UINT32("vectors", VirtIOPCI, nvectors, 0),
+ DEFINE_PROP_END_OF_LIST(),
+};
+
+static void virtio_pci_class_init(ObjectClass *klass, void *data)
+{
+ DeviceClass *dc = DEVICE_CLASS(klass);
+ PCIDeviceClass *k = PCI_DEVICE_CLASS(klass);
+ k->init = virtio_pci_device_init;
+ k->exit = virtio_pci_device_exit;
+ k->vendor_id = PCI_VENDOR_ID_REDHAT_QUMRANET;
+ k->revision = VIRTIO_PCI_ABI_VERSION;
+ k->class_id = PCI_CLASS_OTHERS;
+ dc->reset = virtio_pci_reset_;
+ dc->props = virtio_pci_properties;
+}
+
+static TypeInfo virtio_pci_info = {
+ .name = VIRTIO_PCI,
+ .parent = TYPE_PCI_DEVICE,
+ .instance_size = sizeof(VirtIOPCI),
+ .class_init = virtio_pci_class_init,
+};
+
+/************************************************************/
+
+static void virtio_pci_register_types(void)
+{
+ type_register_static(&virtio_pci_info);
+}
+
+type_init(virtio_pci_register_types)
diff --git a/hw/virtio-pci.h b/hw/virtio-pci.h
index ac9d522..2cddd67 100644
--- a/hw/virtio-pci.h
+++ b/hw/virtio-pci.h
@@ -51,8 +51,26 @@ typedef struct {
VirtIOIRQFD *vector_irqfd;
} VirtIOPCIProxy;
+typedef struct {
+ PCIDevice pci_dev;
+ VirtIODevice *vdev;
+ MemoryRegion bar;
+
+ uint32_t flags;
+ uint32_t class_code;
+ uint32_t nvectors;
+ uint32_t host_features;
+
+ VirtIOTransportLink *trl;
+
+ bool ioeventfd_disabled;
+ bool ioeventfd_started;
+ VirtIOIRQFD *vector_irqfd;
+} VirtIOPCI;
+
void virtio_init_pci(VirtIOPCIProxy *proxy, VirtIODevice *vdev);
void virtio_pci_reset(DeviceState *d);
+void virtio_pci_reset_(DeviceState *d);
/* Virtio ABI version, if we increment this, we break the guest driver. */
#define VIRTIO_PCI_ABI_VERSION 0
--
1.7.9.5
^ permalink raw reply related [flat|nested] 17+ messages in thread
* [Qemu-devel] [RFC v2 12/12] hw/exynos4210.c: Create two virtio-mmio transport instances.
2012-09-17 10:00 [Qemu-devel] [RFC v2 00/12] Virtio-mmio refactoring Evgeny Voevodin
` (10 preceding siblings ...)
2012-09-17 10:00 ` [Qemu-devel] [RFC v2 11/12] hw/virtio-pci-new.c: Add VirtIOPCI device Evgeny Voevodin
@ 2012-09-17 10:00 ` Evgeny Voevodin
2012-09-27 17:31 ` [Qemu-devel] [RFC v2 00/12] Virtio-mmio refactoring KONRAD Frédéric
12 siblings, 0 replies; 17+ messages in thread
From: Evgeny Voevodin @ 2012-09-17 10:00 UTC (permalink / raw)
To: qemu-devel; +Cc: peter.maydell, kyungmin.park, aliguori, Evgeny Voevodin
NB: This is for test purposes only.
Signed-off-by: Evgeny Voevodin <e.voevodin@samsung.com>
---
hw/exynos4210.c | 13 +++++++++++++
1 file changed, 13 insertions(+)
diff --git a/hw/exynos4210.c b/hw/exynos4210.c
index 00d4db8..70fcdd6 100644
--- a/hw/exynos4210.c
+++ b/hw/exynos4210.c
@@ -26,6 +26,7 @@
#include "sysbus.h"
#include "arm-misc.h"
#include "loader.h"
+#include "virtio-transport.h"
#include "exynos4210.h"
#define EXYNOS4210_CHIPID_ADDR 0x10000000
@@ -72,6 +73,10 @@
/* Display controllers (FIMD) */
#define EXYNOS4210_FIMD0_BASE_ADDR 0x11C00000
+/* VirtIO MMIO */
+#define EXYNOS4210_VIRTIO_MMIO0_BASE_ADDR 0x10AD0000
+#define EXYNOS4210_VIRTIO_MMIO1_BASE_ADDR 0x10AC0000
+
static uint8_t chipid_and_omr[] = { 0x11, 0x02, 0x21, 0x43,
0x09, 0x00, 0x00, 0x00 };
@@ -334,5 +339,13 @@ Exynos4210State *exynos4210_init(MemoryRegion *system_mem,
s->irq_table[exynos4210_get_irq(11, 2)],
NULL);
+ sysbus_create_simple(VIRTIO_MMIO,
+ EXYNOS4210_VIRTIO_MMIO0_BASE_ADDR,
+ s->irq_table[exynos4210_get_irq(37, 3)]);
+
+ sysbus_create_simple(VIRTIO_MMIO,
+ EXYNOS4210_VIRTIO_MMIO1_BASE_ADDR,
+ s->irq_table[exynos4210_get_irq(37, 2)]);
+
return s;
}
--
1.7.9.5
^ permalink raw reply related [flat|nested] 17+ messages in thread
* Re: [Qemu-devel] [RFC v2 04/12] hw/qdev-properties.c: Add "transport" property.
2012-09-17 10:00 ` [Qemu-devel] [RFC v2 04/12] hw/qdev-properties.c: Add "transport" property Evgeny Voevodin
@ 2012-09-17 12:42 ` Paolo Bonzini
2012-09-18 4:48 ` Evgeny Voevodin
0 siblings, 1 reply; 17+ messages in thread
From: Paolo Bonzini @ 2012-09-17 12:42 UTC (permalink / raw)
To: Evgeny Voevodin; +Cc: peter.maydell, kyungmin.park, qemu-devel, aliguori
Il 17/09/2012 12:00, Evgeny Voevodin ha scritto:
> Virtio back-end devices can be plugged into both transports:
> VIRTIO_PCI and VIRTIO_MMIO. In order to choose the desired
> transport we have a property "transport" in every back-end
> state struct. By specifying -device virtio-blk-pci user chooses
> VIRTIO_PCI transport and "transport" property is set automatically.
> But in order to provide full control to user we need to have
> "transport" property available to be set through command line:
>
> -device virtio-pci,id=virtio-pci.0
> -device virtio-blk,transport=virtio-pci.0,...
What's the difference between this and "bus"? i.e.
-device virtio-pci,id=virtio-pci-0
-device virtio-blk,bus=virtio-pci-0.0,...
Paolo
^ permalink raw reply [flat|nested] 17+ messages in thread
* Re: [Qemu-devel] [RFC v2 04/12] hw/qdev-properties.c: Add "transport" property.
2012-09-17 12:42 ` Paolo Bonzini
@ 2012-09-18 4:48 ` Evgeny Voevodin
0 siblings, 0 replies; 17+ messages in thread
From: Evgeny Voevodin @ 2012-09-18 4:48 UTC (permalink / raw)
To: Paolo Bonzini; +Cc: peter.maydell, kyungmin.park, qemu-devel, aliguori
On 09/17/2012 04:42 PM, Paolo Bonzini wrote:
> Il 17/09/2012 12:00, Evgeny Voevodin ha scritto:
>> Virtio back-end devices can be plugged into both transports:
>> VIRTIO_PCI and VIRTIO_MMIO. In order to choose the desired
>> transport we have a property "transport" in every back-end
>> state struct. By specifying -device virtio-blk-pci user chooses
>> VIRTIO_PCI transport and "transport" property is set automatically.
>> But in order to provide full control to user we need to have
>> "transport" property available to be set through command line:
>>
>> -device virtio-pci,id=virtio-pci.0
>> -device virtio-blk,transport=virtio-pci.0,...
> What's the difference between this and "bus"? i.e.
>
> -device virtio-pci,id=virtio-pci-0
> -device virtio-blk,bus=virtio-pci-0.0,...
>
> Paolo
>
The difference is that with "transport" I used a linked list like, say,
bdrv_states in block.c.
It's much simpler then use buses. Also I was planning to use a <link>.
In this approach buses are used only to reflect hierarchy of devices in
emulator manager.
And yes, cover letter contains quite misleading information because
attach to transport
is based on a list of links, not on buses. Sorry, I forgot that when
wrote the cover.
--
Kind regards,
Evgeny Voevodin,
Technical Leader,
Mobile Group,
Samsung Moscow Research Center,
e-mail: e.voevodin@samsung.com
^ permalink raw reply [flat|nested] 17+ messages in thread
* Re: [Qemu-devel] [RFC v2 00/12] Virtio-mmio refactoring.
2012-09-17 10:00 [Qemu-devel] [RFC v2 00/12] Virtio-mmio refactoring Evgeny Voevodin
` (11 preceding siblings ...)
2012-09-17 10:00 ` [Qemu-devel] [RFC v2 12/12] hw/exynos4210.c: Create two virtio-mmio transport instances Evgeny Voevodin
@ 2012-09-27 17:31 ` KONRAD Frédéric
2012-09-28 3:37 ` Evgeny Voevodin
12 siblings, 1 reply; 17+ messages in thread
From: KONRAD Frédéric @ 2012-09-27 17:31 UTC (permalink / raw)
To: Evgeny Voevodin, qemu-devel, Mark Burton, fred.konrad
Hi,
We actually want to add virtio models for arm, therefore these patches
are really helpful.
We will try it, start looking at the issues.
Any feedback ?
On 17/09/2012 12:00, Evgeny Voevodin wrote:
> Previous RFC you can find at
> http://lists.gnu.org/archive/html/qemu-devel/2012-04/msg03665.html
> Yes, long time ago...
> Since I'm not sure when I'll be able to continue on this,
> I'm publishing this work as is.
> In this patchset I tried to split virtio-xxx-pci devices into
> virtio-pci + virtio-xxx (blk, net, serial,...). Also virtio-mmio
> transport is introduced based on Peter's work which is accessible
> here: http://lists.gnu.org/archive/html/qemu-devel/2011-11/msg01870.html
>
> The main idea was to let users specify
> -device virtio-pci,id=virtio-pci.0
> -device virtio-blk,transport=virtio-pci.0,...
>
> and
>
> -device virtio-mmio,id=virtio-mmio.0
> -device virtio-blk,transport=virtio-mmio.0,...
>
> I created virtio-pci and virtio-mmio transport devices and tried to enclose
> back-end functionality into virtio-blk, virtio-net, etc. On
> initialization of transport device it creates a bus to which a back-end device
> could be connected. Each back-end device is implemented in corresponding source
> file. As for PCI transport, I temporary placed it in a new virtio-pci-new.c file
> to not break a functionality of still presented virtio-xxx-pci devices.
>
> Known issues to be resolved:
> 1. On creation of back-end we need to resolve somehow if props were explicitly set
> by user.
> 2. Back-end device can't be initialized if there are no free bus created by transport,
> so you can't specify
> -device virtio-blk,transport=virtio-pci.0,...
> -device virtio-pci,id=virtio-pci.0
> 3. Implement virtio-xxx-devices such that they just create virtio-pci and virtio-xxx
> devices during initialization.
> 4. Refactor all remaining back-ends since I just tried blk, net, serial and balloon.
> 5. Refactor s390
> 6. Further?
>
> Evgeny Voevodin (9):
> Virtio: Add transport bindings.
> hw/qdev-properties.c: Add "transport" property.
> hw/pci.c: Make pci_add_option_rom global visible
> hw/virtio-serial-bus.c: Add virtio-serial device.
> hw/virtio-balloon.c: Add virtio-balloon device.
> hw/virtio-net.c: Add virtio-net device.
> hw/virtio-blk.c: Add virtio-blk device.
> hw/virtio-pci-new.c: Add VirtIOPCI device.
> hw/exynos4210.c: Create two virtio-mmio transport instances.
>
> Peter Maydell (3):
> virtio: Add support for guest setting of queue size
> virtio: Support transports which can specify the vring alignment
> Add MMIO based virtio transport
>
> hw/Makefile.objs | 3 +
> hw/exynos4210.c | 13 +
> hw/pci.c | 3 +-
> hw/pci.h | 2 +
> hw/qdev-properties.c | 29 ++
> hw/qdev.h | 3 +
> hw/virtio-balloon.c | 42 +++
> hw/virtio-balloon.h | 9 +
> hw/virtio-blk.c | 65 ++++
> hw/virtio-blk.h | 15 +
> hw/virtio-mmio.c | 400 +++++++++++++++++++++
> hw/virtio-net.c | 59 +++
> hw/virtio-net.h | 16 +
> hw/virtio-pci-new.c | 925 ++++++++++++++++++++++++++++++++++++++++++++++++
> hw/virtio-pci.h | 18 +
> hw/virtio-serial-bus.c | 44 +++
> hw/virtio-serial.h | 11 +
> hw/virtio-transport.c | 147 ++++++++
> hw/virtio-transport.h | 74 ++++
> hw/virtio.c | 20 +-
> hw/virtio.h | 2 +
> 21 files changed, 1896 insertions(+), 4 deletions(-)
> create mode 100644 hw/virtio-mmio.c
> create mode 100644 hw/virtio-pci-new.c
> create mode 100644 hw/virtio-transport.c
> create mode 100644 hw/virtio-transport.h
>
^ permalink raw reply [flat|nested] 17+ messages in thread
* Re: [Qemu-devel] [RFC v2 00/12] Virtio-mmio refactoring.
2012-09-27 17:31 ` [Qemu-devel] [RFC v2 00/12] Virtio-mmio refactoring KONRAD Frédéric
@ 2012-09-28 3:37 ` Evgeny Voevodin
0 siblings, 0 replies; 17+ messages in thread
From: Evgeny Voevodin @ 2012-09-28 3:37 UTC (permalink / raw)
To: KONRAD Frédéric
Cc: Kyungmin Park, Mark Burton, qemu-devel, Ekaterina Gorelkina
On 09/27/2012 09:31 PM, KONRAD Frédéric wrote:
> Hi,
>
> We actually want to add virtio models for arm, therefore these patches
> are really helpful.
>
> We will try it, start looking at the issues.
>
> Any feedback ?
>
Ok. Feel free.
> On 17/09/2012 12:00, Evgeny Voevodin wrote:
>> Previous RFC you can find at
>> http://lists.gnu.org/archive/html/qemu-devel/2012-04/msg03665.html
>> Yes, long time ago...
>> Since I'm not sure when I'll be able to continue on this,
>> I'm publishing this work as is.
>> In this patchset I tried to split virtio-xxx-pci devices into
>> virtio-pci + virtio-xxx (blk, net, serial,...). Also virtio-mmio
>> transport is introduced based on Peter's work which is accessible
>> here: http://lists.gnu.org/archive/html/qemu-devel/2011-11/msg01870.html
>>
>> The main idea was to let users specify
>> -device virtio-pci,id=virtio-pci.0
>> -device virtio-blk,transport=virtio-pci.0,...
>> and
>>
>> -device virtio-mmio,id=virtio-mmio.0
>> -device virtio-blk,transport=virtio-mmio.0,...
>>
>> I created virtio-pci and virtio-mmio transport devices and tried to
>> enclose
>> back-end functionality into virtio-blk, virtio-net, etc. On
>> initialization of transport device it creates a bus to which a
>> back-end device
>> could be connected. Each back-end device is implemented in
>> corresponding source
>> file. As for PCI transport, I temporary placed it in a new
>> virtio-pci-new.c file
>> to not break a functionality of still presented virtio-xxx-pci devices.
>>
>> Known issues to be resolved:
>> 1. On creation of back-end we need to resolve somehow if props were
>> explicitly set
>> by user.
>> 2. Back-end device can't be initialized if there are no free bus
>> created by transport,
>> so you can't specify
>> -device virtio-blk,transport=virtio-pci.0,...
>> -device virtio-pci,id=virtio-pci.0
>> 3. Implement virtio-xxx-devices such that they just create virtio-pci
>> and virtio-xxx
>> devices during initialization.
>> 4. Refactor all remaining back-ends since I just tried blk, net,
>> serial and balloon.
>> 5. Refactor s390
>> 6. Further?
>>
>> Evgeny Voevodin (9):
>> Virtio: Add transport bindings.
>> hw/qdev-properties.c: Add "transport" property.
>> hw/pci.c: Make pci_add_option_rom global visible
>> hw/virtio-serial-bus.c: Add virtio-serial device.
>> hw/virtio-balloon.c: Add virtio-balloon device.
>> hw/virtio-net.c: Add virtio-net device.
>> hw/virtio-blk.c: Add virtio-blk device.
>> hw/virtio-pci-new.c: Add VirtIOPCI device.
>> hw/exynos4210.c: Create two virtio-mmio transport instances.
>>
>> Peter Maydell (3):
>> virtio: Add support for guest setting of queue size
>> virtio: Support transports which can specify the vring alignment
>> Add MMIO based virtio transport
>>
>> hw/Makefile.objs | 3 +
>> hw/exynos4210.c | 13 +
>> hw/pci.c | 3 +-
>> hw/pci.h | 2 +
>> hw/qdev-properties.c | 29 ++
>> hw/qdev.h | 3 +
>> hw/virtio-balloon.c | 42 +++
>> hw/virtio-balloon.h | 9 +
>> hw/virtio-blk.c | 65 ++++
>> hw/virtio-blk.h | 15 +
>> hw/virtio-mmio.c | 400 +++++++++++++++++++++
>> hw/virtio-net.c | 59 +++
>> hw/virtio-net.h | 16 +
>> hw/virtio-pci-new.c | 925
>> ++++++++++++++++++++++++++++++++++++++++++++++++
>> hw/virtio-pci.h | 18 +
>> hw/virtio-serial-bus.c | 44 +++
>> hw/virtio-serial.h | 11 +
>> hw/virtio-transport.c | 147 ++++++++
>> hw/virtio-transport.h | 74 ++++
>> hw/virtio.c | 20 +-
>> hw/virtio.h | 2 +
>> 21 files changed, 1896 insertions(+), 4 deletions(-)
>> create mode 100644 hw/virtio-mmio.c
>> create mode 100644 hw/virtio-pci-new.c
>> create mode 100644 hw/virtio-transport.c
>> create mode 100644 hw/virtio-transport.h
>>
>
>
--
Kind regards,
Evgeny Voevodin,
Technical Leader,
Mobile Group,
Samsung Moscow Research Center,
e-mail: e.voevodin@samsung.com
^ permalink raw reply [flat|nested] 17+ messages in thread
end of thread, other threads:[~2012-09-28 3:37 UTC | newest]
Thread overview: 17+ messages (download: mbox.gz follow: Atom feed
-- links below jump to the message on this page --
2012-09-17 10:00 [Qemu-devel] [RFC v2 00/12] Virtio-mmio refactoring Evgeny Voevodin
2012-09-17 10:00 ` [Qemu-devel] [RFC v2 01/12] virtio: Add support for guest setting of queue size Evgeny Voevodin
2012-09-17 10:00 ` [Qemu-devel] [RFC v2 02/12] virtio: Support transports which can specify the vring alignment Evgeny Voevodin
2012-09-17 10:00 ` [Qemu-devel] [RFC v2 03/12] Virtio: Add transport bindings Evgeny Voevodin
2012-09-17 10:00 ` [Qemu-devel] [RFC v2 04/12] hw/qdev-properties.c: Add "transport" property Evgeny Voevodin
2012-09-17 12:42 ` Paolo Bonzini
2012-09-18 4:48 ` Evgeny Voevodin
2012-09-17 10:00 ` [Qemu-devel] [RFC v2 05/12] hw/pci.c: Make pci_add_option_rom global visible Evgeny Voevodin
2012-09-17 10:00 ` [Qemu-devel] [RFC v2 06/12] Add MMIO based virtio transport Evgeny Voevodin
2012-09-17 10:00 ` [Qemu-devel] [RFC v2 07/12] hw/virtio-serial-bus.c: Add virtio-serial device Evgeny Voevodin
2012-09-17 10:00 ` [Qemu-devel] [RFC v2 08/12] hw/virtio-balloon.c: Add virtio-balloon device Evgeny Voevodin
2012-09-17 10:00 ` [Qemu-devel] [RFC v2 09/12] hw/virtio-net.c: Add virtio-net device Evgeny Voevodin
2012-09-17 10:00 ` [Qemu-devel] [RFC v2 10/12] hw/virtio-blk.c: Add virtio-blk device Evgeny Voevodin
2012-09-17 10:00 ` [Qemu-devel] [RFC v2 11/12] hw/virtio-pci-new.c: Add VirtIOPCI device Evgeny Voevodin
2012-09-17 10:00 ` [Qemu-devel] [RFC v2 12/12] hw/exynos4210.c: Create two virtio-mmio transport instances Evgeny Voevodin
2012-09-27 17:31 ` [Qemu-devel] [RFC v2 00/12] Virtio-mmio refactoring KONRAD Frédéric
2012-09-28 3:37 ` Evgeny Voevodin
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox;
as well as URLs for NNTP newsgroup(s).