qemu-devel.nongnu.org archive mirror
 help / color / mirror / Atom feed
* [Qemu-devel] [PATCH RFC 0/3] virtio-pci: towards virtio 1.0 host support
@ 2014-12-30 16:28 Michael S. Tsirkin
  2014-12-30 16:28 ` [Qemu-devel] [PATCH RFC 1/3] linux-headers: add virtio_pci Michael S. Tsirkin
                   ` (2 more replies)
  0 siblings, 3 replies; 5+ messages in thread
From: Michael S. Tsirkin @ 2014-12-30 16:28 UTC (permalink / raw)
  To: qemu-devel; +Cc: cornelia.huck, Rusty Russell

Partial implementation for virtio 1.0.
Some bits are still missing, but this is already
somewhat useful for driver development.

Michael S. Tsirkin (3):
  linux-headers: add virtio_pci
  virtio: misc fixes, include linux header
  virtio-pci: initial virtio 1.0 support

 hw/virtio/virtio-pci.h           |  16 ++
 linux-headers/linux/virtio_pci.h | 194 ++++++++++++++++++++
 hw/net/virtio-net.c              |   2 +-
 hw/virtio/virtio-pci.c           | 378 +++++++++++++++++++++++++++++++++++++++
 hw/virtio/virtio.c               |  13 +-
 5 files changed, 598 insertions(+), 5 deletions(-)
 create mode 100644 linux-headers/linux/virtio_pci.h

-- 
MST

^ permalink raw reply	[flat|nested] 5+ messages in thread

* [Qemu-devel] [PATCH RFC 1/3] linux-headers: add virtio_pci
  2014-12-30 16:28 [Qemu-devel] [PATCH RFC 0/3] virtio-pci: towards virtio 1.0 host support Michael S. Tsirkin
@ 2014-12-30 16:28 ` Michael S. Tsirkin
  2014-12-30 16:28 ` [Qemu-devel] [PATCH RFC 2/3] virtio: misc fixes, include linux header Michael S. Tsirkin
  2014-12-30 16:28 ` [Qemu-devel] [PATCH RFC 3/3] virtio-pci: initial virtio 1.0 support Michael S. Tsirkin
  2 siblings, 0 replies; 5+ messages in thread
From: Michael S. Tsirkin @ 2014-12-30 16:28 UTC (permalink / raw)
  To: qemu-devel; +Cc: cornelia.huck, Rusty Russell

Easier than duplicating code.

Signed-off-by: Michael S. Tsirkin <mst@redhat.com>
---
 linux-headers/linux/virtio_pci.h | 194 +++++++++++++++++++++++++++++++++++++++
 1 file changed, 194 insertions(+)
 create mode 100644 linux-headers/linux/virtio_pci.h

diff --git a/linux-headers/linux/virtio_pci.h b/linux-headers/linux/virtio_pci.h
new file mode 100644
index 0000000..e841edd
--- /dev/null
+++ b/linux-headers/linux/virtio_pci.h
@@ -0,0 +1,194 @@
+/*
+ * Virtio PCI driver
+ *
+ * This module allows virtio devices to be used over a virtual PCI device.
+ * This can be used with QEMU based VMMs like KVM or Xen.
+ *
+ * Copyright IBM Corp. 2007
+ *
+ * Authors:
+ *  Anthony Liguori  <aliguori@us.ibm.com>
+ *
+ * This header is BSD licensed so anyone can use the definitions to implement
+ * compatible drivers/servers.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ *    notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ *    notice, this list of conditions and the following disclaimer in the
+ *    documentation and/or other materials provided with the distribution.
+ * 3. Neither the name of IBM nor the names of its contributors
+ *    may be used to endorse or promote products derived from this software
+ *    without specific prior written permission.
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED.  IN NO EVENT SHALL IBM OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ */
+
+#ifndef _LINUX_VIRTIO_PCI_H
+#define _LINUX_VIRTIO_PCI_H
+
+#include <linux/types.h>
+
+#ifndef VIRTIO_PCI_NO_LEGACY
+
+/* 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
+
+/* The remaining space is defined by each driver as the per-driver
+ * configuration space */
+#define VIRTIO_PCI_CONFIG_OFF(msix_enabled)	((msix_enabled) ? 24 : 20)
+/* Deprecated: please use VIRTIO_PCI_CONFIG_OFF instead */
+#define VIRTIO_PCI_CONFIG(dev)	VIRTIO_PCI_CONFIG_OFF((dev)->msix_enabled)
+
+/* Virtio ABI version, this must match exactly */
+#define VIRTIO_PCI_ABI_VERSION		0
+
+/* 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
+
+/* The alignment to use between consumer and producer parts of vring.
+ * x86 pagesize again. */
+#define VIRTIO_PCI_VRING_ALIGN		4096
+
+#endif /* VIRTIO_PCI_NO_LEGACY */
+
+/* The bit of the ISR which indicates a device configuration change. */
+#define VIRTIO_PCI_ISR_CONFIG		0x2
+/* Vector value used to disable MSI for queue */
+#define VIRTIO_MSI_NO_VECTOR            0xffff
+
+#ifndef VIRTIO_PCI_NO_MODERN
+
+/* 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 {
+	__u8 cap_vndr;		/* Generic PCI field: PCI_CAP_ID_VNDR */
+	__u8 cap_next;		/* Generic PCI field: next ptr. */
+	__u8 cap_len;		/* Generic PCI field: capability length */
+	__u8 type_and_bar;	/* Upper 3 bits: bar.
+				 * Lower 3 is VIRTIO_PCI_CAP_*_CFG. */
+	__le32 offset;		/* Offset within bar. */
+	__le32 length;		/* Length. */
+};
+
+#define VIRTIO_PCI_CAP_BAR_SHIFT	5
+#define VIRTIO_PCI_CAP_BAR_MASK		0x7
+#define VIRTIO_PCI_CAP_TYPE_SHIFT	0
+#define VIRTIO_PCI_CAP_TYPE_MASK	0x7
+
+struct virtio_pci_notify_cap {
+	struct virtio_pci_cap cap;
+	__le32 notify_off_multiplier;	/* Multiplier for queue_notify_off. */
+};
+
+/* Fields in VIRTIO_PCI_CAP_COMMON_CFG: */
+struct virtio_pci_common_cfg {
+	/* About the whole device. */
+	__le32 device_feature_select;	/* read-write */
+	__le32 device_feature;		/* read-only */
+	__le32 guest_feature_select;	/* read-write */
+	__le32 guest_feature;		/* read-write */
+	__le16 msix_config;		/* read-write */
+	__le16 num_queues;		/* read-only */
+	__u8 device_status;		/* read-write */
+	__u8 config_generation;		/* read-only */
+
+	/* About a specific virtqueue. */
+	__le16 queue_select;		/* read-write */
+	__le16 queue_size;		/* read-write, power of 2. */
+	__le16 queue_msix_vector;	/* read-write */
+	__le16 queue_enable;		/* read-write */
+	__le16 queue_notify_off;	/* read-only */
+	__le32 queue_desc_lo;		/* read-write */
+	__le32 queue_desc_hi;		/* read-write */
+	__le32 queue_avail_lo;		/* read-write */
+	__le32 queue_avail_hi;		/* read-write */
+	__le32 queue_used_lo;		/* read-write */
+	__le32 queue_used_hi;		/* read-write */
+};
+
+/* Macro versions of offsets for the Old Timers! */
+#define VIRTIO_PCI_CAP_VNDR		0
+#define VIRTIO_PCI_CAP_NEXT		1
+#define VIRTIO_PCI_CAP_LEN		2
+#define VIRTIO_PCI_CAP_TYPE_AND_BAR	3
+#define VIRTIO_PCI_CAP_OFFSET		4
+#define VIRTIO_PCI_CAP_LENGTH		8
+
+#define VIRTIO_PCI_NOTIFY_CAP_MULT	12
+
+#define VIRTIO_PCI_COMMON_DFSELECT	0
+#define VIRTIO_PCI_COMMON_DF		4
+#define VIRTIO_PCI_COMMON_GFSELECT	8
+#define VIRTIO_PCI_COMMON_GF		12
+#define VIRTIO_PCI_COMMON_MSIX		16
+#define VIRTIO_PCI_COMMON_NUMQ		18
+#define VIRTIO_PCI_COMMON_STATUS	20
+#define VIRTIO_PCI_COMMON_CFGGENERATION	21
+#define VIRTIO_PCI_COMMON_Q_SELECT	22
+#define VIRTIO_PCI_COMMON_Q_SIZE	24
+#define VIRTIO_PCI_COMMON_Q_MSIX	26
+#define VIRTIO_PCI_COMMON_Q_ENABLE	28
+#define VIRTIO_PCI_COMMON_Q_NOFF	30
+#define VIRTIO_PCI_COMMON_Q_DESCLO	32
+#define VIRTIO_PCI_COMMON_Q_DESCHI	36
+#define VIRTIO_PCI_COMMON_Q_AVAILLO	40
+#define VIRTIO_PCI_COMMON_Q_AVAILHI	44
+#define VIRTIO_PCI_COMMON_Q_USEDLO	48
+#define VIRTIO_PCI_COMMON_Q_USEDHI	52
+
+#endif /* VIRTIO_PCI_NO_MODERN */
+
+#endif
-- 
MST

^ permalink raw reply related	[flat|nested] 5+ messages in thread

* [Qemu-devel] [PATCH RFC 2/3] virtio: misc fixes, include linux header
  2014-12-30 16:28 [Qemu-devel] [PATCH RFC 0/3] virtio-pci: towards virtio 1.0 host support Michael S. Tsirkin
  2014-12-30 16:28 ` [Qemu-devel] [PATCH RFC 1/3] linux-headers: add virtio_pci Michael S. Tsirkin
@ 2014-12-30 16:28 ` Michael S. Tsirkin
  2014-12-30 22:25   ` Peter Maydell
  2014-12-30 16:28 ` [Qemu-devel] [PATCH RFC 3/3] virtio-pci: initial virtio 1.0 support Michael S. Tsirkin
  2 siblings, 1 reply; 5+ messages in thread
From: Michael S. Tsirkin @ 2014-12-30 16:28 UTC (permalink / raw)
  To: qemu-devel; +Cc: cornelia.huck, Rusty Russell, Anthony Liguori

Tweak virtio core so we can use linux virtio pci header
directly without duplicating code.

Signed-off-by: Michael S. Tsirkin <mst@redhat.com>
---
 hw/net/virtio-net.c    |  2 +-
 hw/virtio/virtio-pci.c |  3 +++
 hw/virtio/virtio.c     | 13 +++++++++----
 3 files changed, 13 insertions(+), 5 deletions(-)

diff --git a/hw/net/virtio-net.c b/hw/net/virtio-net.c
index b5dd356..5fff769 100644
--- a/hw/net/virtio-net.c
+++ b/hw/net/virtio-net.c
@@ -1046,7 +1046,7 @@ static ssize_t virtio_net_receive(NetClientState *nc, const uint8_t *buf, size_t
                 return -1;
             error_report("virtio-net unexpected empty queue: "
                     "i %zd mergeable %d offset %zd, size %zd, "
-                    "guest hdr len %zd, host hdr len %zd guest features 0x%lx",
+                    "guest hdr len %zd, host hdr len %zd guest features 0x%"PRIx64,
                     i, n->mergeable_rx_bufs, offset, size,
                     n->guest_hdr_len, n->host_hdr_len, vdev->guest_features);
             exit(1);
diff --git a/hw/virtio/virtio-pci.c b/hw/virtio/virtio-pci.c
index 7382705..bc11d3d 100644
--- a/hw/virtio/virtio-pci.c
+++ b/hw/virtio/virtio-pci.c
@@ -17,6 +17,7 @@
 
 #include <inttypes.h>
 
+#include "linux-headers/linux/virtio_pci.h"
 #include "hw/virtio/virtio.h"
 #include "hw/virtio/virtio-blk.h"
 #include "hw/virtio/virtio-net.h"
@@ -76,6 +77,8 @@
                                          VIRTIO_PCI_CONFIG_MSI : \
                                          VIRTIO_PCI_CONFIG_NOMSI)
 
+#undef VIRTIO_PCI_CONFIG
+
 /* The remaining space is defined by each driver as the per-driver
  * configuration space */
 #define VIRTIO_PCI_CONFIG(dev)          (msix_enabled(dev) ? \
diff --git a/hw/virtio/virtio.c b/hw/virtio/virtio.c
index 90eedd3..301b83f 100644
--- a/hw/virtio/virtio.c
+++ b/hw/virtio/virtio.c
@@ -1033,7 +1033,8 @@ int virtio_load(VirtIODevice *vdev, QEMUFile *f, int version_id)
     int i, ret;
     int32_t config_len;
     uint32_t num;
-    uint32_t features;
+    uint32_t features_lo, features_hi;
+    uint64_t features;
     uint64_t supported_features;
     BusState *qbus = qdev_get_parent_bus(DEVICE(vdev));
     VirtioBusClass *k = VIRTIO_BUS_GET_CLASS(qbus);
@@ -1057,12 +1058,16 @@ int virtio_load(VirtIODevice *vdev, QEMUFile *f, int version_id)
     if (vdev->queue_sel >= VIRTIO_PCI_QUEUE_MAX) {
         return -1;
     }
-    qemu_get_be32s(f, &features);
+    qemu_get_be32s(f, &features_lo);
+
+    //if (features_lo & (1UL << VIRTIO_F_VERSION_1)) {
+        qemu_get_be32s(f, &features_hi);
+    //}
+    features = (((uint64_t)features_hi) << 32) | features_lo;
 
-    /* XXX features >= 32 */
     if (__virtio_set_features(vdev, features) < 0) {
         supported_features = k->get_features(qbus->parent);
-        error_report("Features 0x%x unsupported. Allowed features: 0x%lx",
+        error_report("Features 0x%"PRIx64" unsupported. Allowed features: 0x%"PRIx64,
                      features, supported_features);
         return -1;
     }
-- 
MST

^ permalink raw reply related	[flat|nested] 5+ messages in thread

* [Qemu-devel] [PATCH RFC 3/3] virtio-pci: initial virtio 1.0 support
  2014-12-30 16:28 [Qemu-devel] [PATCH RFC 0/3] virtio-pci: towards virtio 1.0 host support Michael S. Tsirkin
  2014-12-30 16:28 ` [Qemu-devel] [PATCH RFC 1/3] linux-headers: add virtio_pci Michael S. Tsirkin
  2014-12-30 16:28 ` [Qemu-devel] [PATCH RFC 2/3] virtio: misc fixes, include linux header Michael S. Tsirkin
@ 2014-12-30 16:28 ` Michael S. Tsirkin
  2 siblings, 0 replies; 5+ messages in thread
From: Michael S. Tsirkin @ 2014-12-30 16:28 UTC (permalink / raw)
  To: qemu-devel; +Cc: cornelia.huck, Rusty Russell, Anthony Liguori

This is somewhat functional.  With this, and linux driver from my tree,
I was able to use virtio net as virtio 1.0 device for light browsing.

At the moment, dataplane and vhost code is
still missing.

Based on Cornelia's virtio 1.0 patchset:
    Date: Thu, 11 Dec 2014 14:25:02 +0100
    From: Cornelia Huck <cornelia.huck@de.ibm.com>
    To: virtualization@lists.linux-foundation.org, qemu-devel@nongnu.org
    Cc: rusty@rustcorp.com.au, thuth@linux.vnet.ibm.com, mst@redhat.com,
    Cornelia Huck <cornelia.huck@de.ibm.com>
    Subject: [PATCH RFC v6 00/20] qemu: towards virtio-1 host support
    Message-Id: <1418304322-7546-1-git-send-email-cornelia.huck@de.ibm.com>

which is itself still missing some core bits.

Signed-off-by: Michael S. Tsirkin <mst@redhat.com>
---
 hw/virtio/virtio-pci.h |  16 +++
 hw/virtio/virtio-pci.c | 375 +++++++++++++++++++++++++++++++++++++++++++++++++
 2 files changed, 391 insertions(+)

diff --git a/hw/virtio/virtio-pci.h b/hw/virtio/virtio-pci.h
index 85f102d..2cddd6a 100644
--- a/hw/virtio/virtio-pci.h
+++ b/hw/virtio/virtio-pci.h
@@ -88,10 +88,26 @@ typedef struct VirtioPCIClass {
 struct VirtIOPCIProxy {
     PCIDevice pci_dev;
     MemoryRegion bar;
+    MemoryRegion common;
+    MemoryRegion isr;
+    MemoryRegion device;
+    MemoryRegion notify;
+    MemoryRegion modern_bar;
     uint32_t flags;
     uint32_t class_code;
     uint32_t nvectors;
     uint64_t host_features;
+    uint32_t dfselect;
+    uint32_t gfselect;
+    uint32_t guest_features[2];
+    struct {
+        uint16_t num;
+        bool enabled;
+        uint32_t desc[2];
+        uint32_t avail[2];
+        uint32_t used[2];
+    } vqs[VIRTIO_PCI_QUEUE_MAX];
+
     bool ioeventfd_disabled;
     bool ioeventfd_started;
     VirtIOIRQFD *vector_irqfd;
diff --git a/hw/virtio/virtio-pci.c b/hw/virtio/virtio-pci.c
index bc11d3d..51c33c5 100644
--- a/hw/virtio/virtio-pci.c
+++ b/hw/virtio/virtio-pci.c
@@ -959,6 +959,275 @@ static const TypeInfo virtio_9p_pci_info = {
  * virtio-pci: This is the PCIDevice which has a virtio-pci-bus.
  */
 
+static void virtio_pci_add_mem_cap(VirtIOPCIProxy *proxy,
+                                   struct virtio_pci_cap *cap)
+{
+    PCIDevice *dev = &proxy->pci_dev;
+    int offset;
+
+    cap->type_and_bar |= 2 << VIRTIO_PCI_CAP_BAR_SHIFT;
+
+    offset = pci_add_capability(dev, PCI_CAP_ID_VNDR, 0, cap->cap_len);
+    assert(offset > 0);
+
+    assert(cap->cap_len >= sizeof *cap);
+    memcpy(dev->config + offset + PCI_CAP_FLAGS, &cap->cap_len,
+           cap->cap_len - PCI_CAP_FLAGS);
+}
+
+#define QEMU_VIRTIO_PCI_QUEUE_MEM_MULT 0x10000
+
+static uint64_t virtio_pci_common_read(void *opaque, hwaddr addr,
+                                       unsigned size)
+{
+    VirtIOPCIProxy *proxy = opaque;
+    VirtIODevice *vdev = virtio_bus_get_device(&proxy->bus);
+    uint32_t val = 0;
+    int i;
+
+    switch (addr) {
+    case VIRTIO_PCI_COMMON_DFSELECT:
+        val = proxy->dfselect;
+        break;
+    case VIRTIO_PCI_COMMON_DF:
+        if (proxy->dfselect <= 1) {
+            val = proxy->host_features >> (32 * proxy->dfselect);
+        }
+        break;
+    case VIRTIO_PCI_COMMON_GFSELECT:
+        val = proxy->gfselect;
+        break;
+    case VIRTIO_PCI_COMMON_GF:
+        if (proxy->gfselect <= ARRAY_SIZE(proxy->guest_features)) {
+            val = proxy->guest_features[proxy->gfselect];
+        }
+        break;
+    case VIRTIO_PCI_COMMON_MSIX:
+        val = vdev->config_vector;
+        break;
+    case VIRTIO_PCI_COMMON_NUMQ:
+        for (i = 0; i < VIRTIO_PCI_QUEUE_MAX; ++i) {
+            if (virtio_queue_get_num(vdev, i)) {
+                val = i + 1;
+            }
+        }
+        break;
+    case VIRTIO_PCI_COMMON_STATUS:
+        val = vdev->status;
+        break;
+    case VIRTIO_PCI_COMMON_CFGGENERATION:
+        val = 0; /* TODO */
+        break;
+    case VIRTIO_PCI_COMMON_Q_SELECT:
+        val = vdev->queue_sel;
+        break;
+    case VIRTIO_PCI_COMMON_Q_SIZE:
+        val = virtio_queue_get_num(vdev, vdev->queue_sel);
+        break;
+    case VIRTIO_PCI_COMMON_Q_MSIX:
+        val = virtio_queue_vector(vdev, vdev->queue_sel);
+        break;
+    case VIRTIO_PCI_COMMON_Q_ENABLE:
+        val = proxy->vqs[vdev->queue_sel].enabled;
+        break;
+    case VIRTIO_PCI_COMMON_Q_NOFF:
+        /* Simply map queues in order */
+        val = vdev->queue_sel;
+        break;
+    case VIRTIO_PCI_COMMON_Q_DESCLO:
+        val = proxy->vqs[vdev->queue_sel].desc[0];
+        break;
+    case VIRTIO_PCI_COMMON_Q_DESCHI:
+        val = proxy->vqs[vdev->queue_sel].desc[1];
+        break;
+    case VIRTIO_PCI_COMMON_Q_AVAILLO:
+        val = proxy->vqs[vdev->queue_sel].avail[0];
+        break;
+    case VIRTIO_PCI_COMMON_Q_AVAILHI:
+        val = proxy->vqs[vdev->queue_sel].avail[1];
+        break;
+    case VIRTIO_PCI_COMMON_Q_USEDLO:
+        val = proxy->vqs[vdev->queue_sel].used[0];
+        break;
+    case VIRTIO_PCI_COMMON_Q_USEDHI:
+        val = proxy->vqs[vdev->queue_sel].used[1];
+        break;
+    default:
+        val = 0;
+    }
+
+    return val;
+}
+
+static void virtio_pci_common_write(void *opaque, hwaddr addr,
+                                    uint64_t val, unsigned size)
+{
+    VirtIOPCIProxy *proxy = opaque;
+    VirtIODevice *vdev = virtio_bus_get_device(&proxy->bus);
+
+    switch (addr) {
+    case VIRTIO_PCI_COMMON_DFSELECT:
+        proxy->dfselect = val;
+        break;
+    case VIRTIO_PCI_COMMON_GFSELECT:
+        proxy->gfselect = val;
+        break;
+    case VIRTIO_PCI_COMMON_GF:
+        if (proxy->gfselect <= ARRAY_SIZE(proxy->guest_features)) {
+            proxy->guest_features[proxy->gfselect] = val;
+            virtio_set_features(vdev,
+                                (((uint64_t)proxy->guest_features[1]) << 32) |
+                                proxy->guest_features[0]);
+        }
+        break;
+    case VIRTIO_PCI_COMMON_MSIX:
+        msix_vector_unuse(&proxy->pci_dev, vdev->config_vector);
+        /* Make it possible for guest to discover an error took place. */
+        if (msix_vector_use(&proxy->pci_dev, val) < 0)
+            val = VIRTIO_NO_VECTOR;
+        vdev->config_vector = val;
+        break;
+    case VIRTIO_PCI_COMMON_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(vdev);
+            msix_unuse_all_vectors(&proxy->pci_dev);
+        }
+
+        break;
+    case VIRTIO_PCI_COMMON_Q_SELECT:
+        if (val < VIRTIO_PCI_QUEUE_MAX)
+            vdev->queue_sel = val;
+        break;
+    case VIRTIO_PCI_COMMON_Q_SIZE:
+        proxy->vqs[vdev->queue_sel].num = val;
+        break;
+    case VIRTIO_PCI_COMMON_Q_MSIX:
+        msix_vector_unuse(&proxy->pci_dev,
+                          virtio_queue_vector(vdev, vdev->queue_sel));
+        /* Make it possible for guest to discover an error took place. */
+        if (msix_vector_use(&proxy->pci_dev, val) < 0)
+            val = VIRTIO_NO_VECTOR;
+        virtio_queue_set_vector(vdev, vdev->queue_sel, val);
+        break;
+    case VIRTIO_PCI_COMMON_Q_ENABLE:
+        /* TODO: need a way to put num back on reset. */
+        virtio_queue_set_num(vdev, vdev->queue_sel,
+                             proxy->vqs[vdev->queue_sel].num);
+        virtio_queue_set_rings(vdev, vdev->queue_sel,
+                       ((uint64_t)proxy->vqs[vdev->queue_sel].desc[1]) << 32 |
+                       proxy->vqs[vdev->queue_sel].desc[0],
+                       ((uint64_t)proxy->vqs[vdev->queue_sel].avail[1]) << 32 |
+                       proxy->vqs[vdev->queue_sel].avail[0],
+                       ((uint64_t)proxy->vqs[vdev->queue_sel].used[1]) << 32 |
+                       proxy->vqs[vdev->queue_sel].used[0]);
+        break;
+    case VIRTIO_PCI_COMMON_Q_DESCLO:
+        proxy->vqs[vdev->queue_sel].desc[0] = val;
+        break;
+    case VIRTIO_PCI_COMMON_Q_DESCHI:
+        proxy->vqs[vdev->queue_sel].desc[1] = val;
+        break;
+    case VIRTIO_PCI_COMMON_Q_AVAILLO:
+        proxy->vqs[vdev->queue_sel].avail[0] = val;
+        break;
+    case VIRTIO_PCI_COMMON_Q_AVAILHI:
+        proxy->vqs[vdev->queue_sel].avail[1] = val;
+        break;
+    case VIRTIO_PCI_COMMON_Q_USEDLO:
+        proxy->vqs[vdev->queue_sel].used[0] = val;
+        break;
+    case VIRTIO_PCI_COMMON_Q_USEDHI:
+        proxy->vqs[vdev->queue_sel].used[1] = val;
+        break;
+    default:
+        break;
+    }
+}
+
+
+static uint64_t virtio_pci_notify_read(void *opaque, hwaddr addr,
+                                       unsigned size)
+{
+    return 0;
+}
+
+static void virtio_pci_notify_write(void *opaque, hwaddr addr,
+                                    uint64_t val, unsigned size)
+{
+    VirtIODevice *vdev = opaque;
+    unsigned queue = addr / QEMU_VIRTIO_PCI_QUEUE_MEM_MULT;
+
+    if (queue < VIRTIO_PCI_QUEUE_MAX) {
+        virtio_queue_notify(vdev, queue);
+    }
+}
+
+static uint64_t virtio_pci_isr_read(void *opaque, hwaddr addr,
+                                    unsigned size)
+{
+    VirtIOPCIProxy *proxy = opaque;
+    VirtIODevice *vdev = virtio_bus_get_device(&proxy->bus);
+    uint64_t val = vdev->isr;
+
+    vdev->isr = 0;
+    pci_irq_deassert(&proxy->pci_dev);
+
+    return val;
+}
+
+static void virtio_pci_isr_write(void *opaque, hwaddr addr,
+                                 uint64_t val, unsigned size)
+{
+}
+
+static uint64_t virtio_pci_device_read(void *opaque, hwaddr addr,
+                                       unsigned size)
+{
+    VirtIODevice *vdev = opaque;
+    uint64_t val = 0;
+
+    switch (size) {
+    case 1:
+        val = virtio_config_readb(vdev, addr);
+        break;
+    case 2:
+        val = virtio_config_readw(vdev, addr);
+        break;
+    case 4:
+        val = virtio_config_readl(vdev, addr);
+        break;
+    }
+    return val;
+}
+
+static void virtio_pci_device_write(void *opaque, hwaddr addr,
+                                    uint64_t val, unsigned size)
+{
+    VirtIODevice *vdev = opaque;
+    switch (size) {
+    case 1:
+        virtio_config_writeb(vdev, addr, val);
+        break;
+    case 2:
+        virtio_config_writew(vdev, addr, val);
+        break;
+    case 4:
+        virtio_config_writel(vdev, addr, val);
+        break;
+    }
+}
+
+
 /* This is called by virtio-bus just after the device is plugged. */
 static void virtio_pci_device_plugged(DeviceState *d)
 {
@@ -976,6 +1245,111 @@ static void virtio_pci_device_plugged(DeviceState *d)
     pci_set_word(config + PCI_SUBSYSTEM_ID, virtio_bus_get_vdev_id(bus));
     config[PCI_INTERRUPT_PIN] = 1;
 
+
+    if (1) { /* TODO: Make this optional, dependent on virtio 1.0 */
+        struct virtio_pci_cap common = {
+            .type_and_bar = VIRTIO_PCI_CAP_COMMON_CFG,
+            .cap_len = sizeof common,
+            .offset = cpu_to_le32(0x0),
+            .length = cpu_to_le32(0x1000),
+        };
+        struct virtio_pci_cap isr = {
+            .type_and_bar = VIRTIO_PCI_CAP_ISR_CFG,
+            .cap_len = sizeof isr,
+            .offset = cpu_to_le32(0x1000),
+            .length = cpu_to_le32(0x1000),
+        };
+        struct virtio_pci_cap device = {
+            .type_and_bar = VIRTIO_PCI_CAP_DEVICE_CFG,
+            .cap_len = sizeof device,
+            .offset = cpu_to_le32(0x2000),
+            .length = cpu_to_le32(0x1000),
+        };
+        struct virtio_pci_notify_cap notify = {
+            .cap.type_and_bar = VIRTIO_PCI_CAP_NOTIFY_CFG,
+            .cap.cap_len = sizeof notify,
+            .cap.offset = cpu_to_le32(0x3000),
+            .cap.length = cpu_to_le32(QEMU_VIRTIO_PCI_QUEUE_MEM_MULT *
+                                      VIRTIO_PCI_QUEUE_MAX),
+            .notify_off_multiplier = cpu_to_le32(QEMU_VIRTIO_PCI_QUEUE_MEM_MULT),
+        };
+
+        static const MemoryRegionOps common_ops = {
+            .read = virtio_pci_common_read,
+            .write = virtio_pci_common_write,
+            .impl = {
+                .min_access_size = 1,
+                .max_access_size = 4,
+            },
+            .endianness = DEVICE_LITTLE_ENDIAN,
+        };
+
+        static const MemoryRegionOps isr_ops = {
+            .read = virtio_pci_isr_read,
+            .write = virtio_pci_isr_write,
+            .impl = {
+                .min_access_size = 1,
+                .max_access_size = 4,
+            },
+            .endianness = DEVICE_LITTLE_ENDIAN,
+        };
+
+        static const MemoryRegionOps device_ops = {
+            .read = virtio_pci_device_read,
+            .write = virtio_pci_device_write,
+            .impl = {
+                .min_access_size = 1,
+                .max_access_size = 4,
+            },
+            .endianness = DEVICE_LITTLE_ENDIAN,
+        };
+
+        static const MemoryRegionOps notify_ops = {
+            .read = virtio_pci_notify_read,
+            .write = virtio_pci_notify_write,
+            .impl = {
+                .min_access_size = 1,
+                .max_access_size = 4,
+            },
+            .endianness = DEVICE_LITTLE_ENDIAN,
+        };
+
+        /* TODO: add io access for speed */
+        virtio_pci_add_mem_cap(proxy, &common);
+        virtio_pci_add_mem_cap(proxy, &isr);
+        virtio_pci_add_mem_cap(proxy, &device);
+        virtio_pci_add_mem_cap(proxy, &notify.cap);
+
+        virtio_add_feature(&proxy->host_features, VIRTIO_F_VERSION_1);
+        memory_region_init(&proxy->modern_bar, OBJECT(proxy), "virtio-pci",
+                           2 * QEMU_VIRTIO_PCI_QUEUE_MEM_MULT *
+                           VIRTIO_PCI_QUEUE_MAX);
+        memory_region_init_io(&proxy->common, OBJECT(proxy),
+                              &common_ops,
+                              proxy,
+                              "virtio-pci-common", 0x1000);
+        memory_region_add_subregion(&proxy->modern_bar, 0, &proxy->common);
+        memory_region_init_io(&proxy->isr, OBJECT(proxy),
+                              &isr_ops,
+                              proxy,
+                              "virtio-pci-isr", 0x1000);
+        memory_region_add_subregion(&proxy->modern_bar, 0x1000, &proxy->isr);
+        memory_region_init_io(&proxy->device, OBJECT(proxy),
+                              &device_ops,
+                              virtio_bus_get_device(&proxy->bus),
+                              "virtio-pci-device", 0x1000);
+        memory_region_add_subregion(&proxy->modern_bar, 0x2000, &proxy->device);
+        memory_region_init_io(&proxy->notify, OBJECT(proxy),
+                              &notify_ops,
+                              virtio_bus_get_device(&proxy->bus),
+                              "virtio-pci-notify",
+                              QEMU_VIRTIO_PCI_QUEUE_MEM_MULT *
+                              VIRTIO_PCI_QUEUE_MAX);
+        memory_region_add_subregion(&proxy->modern_bar, 0x3000, &proxy->notify);
+        pci_register_bar(&proxy->pci_dev, 2, PCI_BASE_ADDRESS_SPACE_MEMORY,
+                         &proxy->modern_bar);
+    }
+
     if (proxy->nvectors &&
         msix_init_exclusive_bar(&proxy->pci_dev, proxy->nvectors, 1)) {
         error_report("unable to init msix vectors to %" PRIu32,
@@ -993,6 +1367,7 @@ static void virtio_pci_device_plugged(DeviceState *d)
 
     memory_region_init_io(&proxy->bar, OBJECT(proxy), &virtio_pci_config_ops,
                           proxy, "virtio-pci", size);
+
     pci_register_bar(&proxy->pci_dev, 0, PCI_BASE_ADDRESS_SPACE_IO,
                      &proxy->bar);
 
-- 
MST

^ permalink raw reply related	[flat|nested] 5+ messages in thread

* Re: [Qemu-devel] [PATCH RFC 2/3] virtio: misc fixes, include linux header
  2014-12-30 16:28 ` [Qemu-devel] [PATCH RFC 2/3] virtio: misc fixes, include linux header Michael S. Tsirkin
@ 2014-12-30 22:25   ` Peter Maydell
  0 siblings, 0 replies; 5+ messages in thread
From: Peter Maydell @ 2014-12-30 22:25 UTC (permalink / raw)
  To: Michael S. Tsirkin
  Cc: Cornelia Huck, Rusty Russell, QEMU Developers, Anthony Liguori

On 30 December 2014 at 16:28, Michael S. Tsirkin <mst@redhat.com> wrote:
> Tweak virtio core so we can use linux virtio pci header
> directly without duplicating code.
>
> Signed-off-by: Michael S. Tsirkin <mst@redhat.com>

> diff --git a/hw/virtio/virtio-pci.c b/hw/virtio/virtio-pci.c
> index 7382705..bc11d3d 100644
> --- a/hw/virtio/virtio-pci.c
> +++ b/hw/virtio/virtio-pci.c
> @@ -17,6 +17,7 @@
>
>  #include <inttypes.h>
>
> +#include "linux-headers/linux/virtio_pci.h"

I'm afraid this won't work. You can only pull in the Linux headers
inside CONFIG_KVM ifdefs. Otherwise you're liable to break the
build on non-Linux platforms, because the kernel headers make
no guarantees about being usable on any hosts other than Linux.

Indeed in this specific case MacOSX won't build:

In file included from /Users/pm215/src/qemu/hw/virtio/virtio-pci.c:20:
/Users/pm215/src/qemu/linux-headers/linux/virtio_pci.h:42:10: fatal
error: 'linux/types.h' file not found
#include <linux/types.h>
         ^

If you need the virtio_pci.h header you'll need to make a
portable copy of it in include/hw/virtio/, the same way we
have already for the other headers.

thanks
-- PMM

^ permalink raw reply	[flat|nested] 5+ messages in thread

end of thread, other threads:[~2014-12-30 22:25 UTC | newest]

Thread overview: 5+ messages (download: mbox.gz follow: Atom feed
-- links below jump to the message on this page --
2014-12-30 16:28 [Qemu-devel] [PATCH RFC 0/3] virtio-pci: towards virtio 1.0 host support Michael S. Tsirkin
2014-12-30 16:28 ` [Qemu-devel] [PATCH RFC 1/3] linux-headers: add virtio_pci Michael S. Tsirkin
2014-12-30 16:28 ` [Qemu-devel] [PATCH RFC 2/3] virtio: misc fixes, include linux header Michael S. Tsirkin
2014-12-30 22:25   ` Peter Maydell
2014-12-30 16:28 ` [Qemu-devel] [PATCH RFC 3/3] virtio-pci: initial virtio 1.0 support Michael S. Tsirkin

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).