* [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>
---
| 194 +++++++++++++++++++++++++++++++++++++++
1 file changed, 194 insertions(+)
create mode 100644 linux-headers/linux/virtio_pci.h
--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, ¬ify.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),
+ ¬ify_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).