aboutsummaryrefslogtreecommitdiff
path: root/hw
diff options
context:
space:
mode:
authorPeter Maydell <peter.maydell@linaro.org>2015-06-19 11:30:57 +0100
committerPeter Maydell <peter.maydell@linaro.org>2015-06-19 11:30:57 +0100
commit89e9429c3cb42400f3a80890e0c20b18aa62a11d (patch)
treedef7ec8a0e0f12d04827b06086e129c13e2e273e /hw
parent473a49460db0a90bfda046b8f3662b49f94098eb (diff)
parent1e7398a140f7a6bd9f5a438e7ad0f1ef50990e25 (diff)
downloadqemu-arm-89e9429c3cb42400f3a80890e0c20b18aa62a11d.tar.gz
Merge remote-tracking branch 'remotes/mst/tags/for_upstream' into staging
virtio, pci fixes, enhancements Most notably this includes virtio cross-endian patches. Signed-off-by: Michael S. Tsirkin <mst@redhat.com> # gpg: Signature made Fri Jun 19 11:18:05 2015 BST using RSA key ID D28D5469 # gpg: Good signature from "Michael S. Tsirkin <mst@kernel.org>" # gpg: aka "Michael S. Tsirkin <mst@redhat.com>" * remotes/mst/tags/for_upstream: vhost: enable vhost without without MSI-X pci: Don't register a specialized 'config_write' if default behavior is intended hw/core: rebase sysbus_get_fw_dev_path() to g_strdup_printf() vhost_net: re-enable when cross endian vhost-net: tell tap backend about the vnet endianness tap: fix non-linux build tap: add VNET_LE/VNET_BE operations vhost: set vring endianness for legacy virtio virtio: introduce virtio_legacy_is_cross_endian() linux-headers: sync vhost.h vhost-user: part of virtio Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
Diffstat (limited to 'hw')
-rw-r--r--hw/core/sysbus.c16
-rw-r--r--hw/misc/ivshmem.c1
-rw-r--r--hw/net/vhost_net.c60
-rw-r--r--hw/net/virtio-net.c4
-rw-r--r--hw/net/vmxnet3.c9
-rw-r--r--hw/scsi/megasas.c8
-rw-r--r--hw/scsi/vhost-scsi.c2
-rw-r--r--hw/scsi/vmw_pvscsi.c8
-rw-r--r--hw/virtio/vhost.c64
9 files changed, 88 insertions, 84 deletions
diff --git a/hw/core/sysbus.c b/hw/core/sysbus.c
index b53c351aa4..92eced9424 100644
--- a/hw/core/sysbus.c
+++ b/hw/core/sysbus.c
@@ -281,19 +281,15 @@ static void sysbus_dev_print(Monitor *mon, DeviceState *dev, int indent)
static char *sysbus_get_fw_dev_path(DeviceState *dev)
{
SysBusDevice *s = SYS_BUS_DEVICE(dev);
- char path[40];
- int off;
-
- off = snprintf(path, sizeof(path), "%s", qdev_fw_name(dev));
if (s->num_mmio) {
- snprintf(path + off, sizeof(path) - off, "@"TARGET_FMT_plx,
- s->mmio[0].addr);
- } else if (s->num_pio) {
- snprintf(path + off, sizeof(path) - off, "@i%04x", s->pio[0]);
+ return g_strdup_printf("%s@" TARGET_FMT_plx, qdev_fw_name(dev),
+ s->mmio[0].addr);
}
-
- return g_strdup(path);
+ if (s->num_pio) {
+ return g_strdup_printf("%s@i%04x", qdev_fw_name(dev), s->pio[0]);
+ }
+ return g_strdup(qdev_fw_name(dev));
}
void sysbus_add_io(SysBusDevice *dev, hwaddr addr,
diff --git a/hw/misc/ivshmem.c b/hw/misc/ivshmem.c
index 5d272c84e9..231c35fdef 100644
--- a/hw/misc/ivshmem.c
+++ b/hw/misc/ivshmem.c
@@ -698,7 +698,6 @@ static void ivshmem_write_config(PCIDevice *pci_dev, uint32_t address,
uint32_t val, int len)
{
pci_default_write_config(pci_dev, address, val, len);
- msix_write_config(pci_dev, address, val, len);
}
static int pci_ivshmem_init(PCIDevice *dev)
diff --git a/hw/net/vhost_net.c b/hw/net/vhost_net.c
index 1c55517e36..9bd360bd17 100644
--- a/hw/net/vhost_net.c
+++ b/hw/net/vhost_net.c
@@ -38,6 +38,7 @@
#include "standard-headers/linux/virtio_ring.h"
#include "hw/virtio/vhost.h"
#include "hw/virtio/virtio-bus.h"
+#include "hw/virtio/virtio-access.h"
struct vhost_net {
struct vhost_dev dev;
@@ -162,7 +163,7 @@ struct vhost_net *vhost_net_init(VhostNetOptions *options)
net->dev.vq_index = net->nc->queue_index;
r = vhost_dev_init(&net->dev, options->opaque,
- options->backend_type, options->force);
+ options->backend_type);
if (r < 0) {
goto fail;
}
@@ -187,14 +188,30 @@ fail:
return NULL;
}
-bool vhost_net_query(VHostNetState *net, VirtIODevice *dev)
+static void vhost_net_set_vq_index(struct vhost_net *net, int vq_index)
{
- return vhost_dev_query(&net->dev, dev);
+ net->dev.vq_index = vq_index;
}
-static void vhost_net_set_vq_index(struct vhost_net *net, int vq_index)
+static int vhost_net_set_vnet_endian(VirtIODevice *dev, NetClientState *peer,
+ bool set)
{
- net->dev.vq_index = vq_index;
+ int r = 0;
+
+ if (virtio_has_feature(dev, VIRTIO_F_VERSION_1) ||
+ (virtio_legacy_is_cross_endian(dev) && !virtio_is_big_endian(dev))) {
+ r = qemu_set_vnet_le(peer, set);
+ if (r) {
+ error_report("backend does not support LE vnet headers");
+ }
+ } else if (virtio_legacy_is_cross_endian(dev)) {
+ r = qemu_set_vnet_be(peer, set);
+ if (r) {
+ error_report("backend does not support BE vnet headers");
+ }
+ }
+
+ return r;
}
static int vhost_net_start_one(struct vhost_net *net,
@@ -281,19 +298,6 @@ static void vhost_net_stop_one(struct vhost_net *net,
vhost_dev_disable_notifiers(&net->dev, dev);
}
-static bool vhost_net_device_endian_ok(VirtIODevice *vdev)
-{
-#ifdef TARGET_IS_BIENDIAN
-#ifdef HOST_WORDS_BIGENDIAN
- return virtio_is_big_endian(vdev);
-#else
- return !virtio_is_big_endian(vdev);
-#endif
-#else
- return true;
-#endif
-}
-
int vhost_net_start(VirtIODevice *dev, NetClientState *ncs,
int total_queues)
{
@@ -302,15 +306,14 @@ int vhost_net_start(VirtIODevice *dev, NetClientState *ncs,
VirtioBusClass *k = VIRTIO_BUS_GET_CLASS(vbus);
int r, e, i;
- if (!vhost_net_device_endian_ok(dev)) {
- error_report("vhost-net does not support cross-endian");
+ if (!k->set_guest_notifiers) {
+ error_report("binding does not support guest notifiers");
r = -ENOSYS;
goto err;
}
- if (!k->set_guest_notifiers) {
- error_report("binding does not support guest notifiers");
- r = -ENOSYS;
+ r = vhost_net_set_vnet_endian(dev, ncs[0].peer, true);
+ if (r < 0) {
goto err;
}
@@ -321,7 +324,7 @@ int vhost_net_start(VirtIODevice *dev, NetClientState *ncs,
r = k->set_guest_notifiers(qbus->parent, total_queues * 2, true);
if (r < 0) {
error_report("Error binding guest notifier: %d", -r);
- goto err;
+ goto err_endian;
}
for (i = 0; i < total_queues; i++) {
@@ -343,6 +346,8 @@ err_start:
fprintf(stderr, "vhost guest notifier cleanup failed: %d\n", e);
fflush(stderr);
}
+err_endian:
+ vhost_net_set_vnet_endian(dev, ncs[0].peer, false);
err:
return r;
}
@@ -365,6 +370,8 @@ void vhost_net_stop(VirtIODevice *dev, NetClientState *ncs,
fflush(stderr);
}
assert(r >= 0);
+
+ assert(vhost_net_set_vnet_endian(dev, ncs[0].peer, false) >= 0);
}
void vhost_net_cleanup(struct vhost_net *net)
@@ -412,11 +419,6 @@ struct vhost_net *vhost_net_init(VhostNetOptions *options)
return NULL;
}
-bool vhost_net_query(VHostNetState *net, VirtIODevice *dev)
-{
- return false;
-}
-
int vhost_net_start(VirtIODevice *dev,
NetClientState *ncs,
int total_queues)
diff --git a/hw/net/virtio-net.c b/hw/net/virtio-net.c
index 9281aa107c..d7282335de 100644
--- a/hw/net/virtio-net.c
+++ b/hw/net/virtio-net.c
@@ -128,10 +128,6 @@ static void virtio_net_vhost_status(VirtIONet *n, uint8_t status)
if (!n->vhost_started) {
int r, i;
- if (!vhost_net_query(get_vhost_net(nc->peer), vdev)) {
- return;
- }
-
/* Any packets outstanding? Purge them to avoid touching rings
* when vhost is running.
*/
diff --git a/hw/net/vmxnet3.c b/hw/net/vmxnet3.c
index 8bcdf3ed77..104a0f599b 100644
--- a/hw/net/vmxnet3.c
+++ b/hw/net/vmxnet3.c
@@ -2477,14 +2477,6 @@ static const VMStateDescription vmstate_vmxnet3 = {
}
};
-static void
-vmxnet3_write_config(PCIDevice *pci_dev, uint32_t addr, uint32_t val, int len)
-{
- pci_default_write_config(pci_dev, addr, val, len);
- msix_write_config(pci_dev, addr, val, len);
- msi_write_config(pci_dev, addr, val, len);
-}
-
static Property vmxnet3_properties[] = {
DEFINE_NIC_PROPERTIES(VMXNET3State, conf),
DEFINE_PROP_END_OF_LIST(),
@@ -2503,7 +2495,6 @@ static void vmxnet3_class_init(ObjectClass *class, void *data)
c->class_id = PCI_CLASS_NETWORK_ETHERNET;
c->subsystem_vendor_id = PCI_VENDOR_ID_VMWARE;
c->subsystem_id = PCI_DEVICE_ID_VMWARE_VMXNET3;
- c->config_write = vmxnet3_write_config,
dc->desc = "VMWare Paravirtualized Ethernet v3";
dc->reset = vmxnet3_qdev_reset;
dc->vmsd = &vmstate_vmxnet3;
diff --git a/hw/scsi/megasas.c b/hw/scsi/megasas.c
index 91a5d97c73..51ba9e0e6e 100644
--- a/hw/scsi/megasas.c
+++ b/hw/scsi/megasas.c
@@ -2407,13 +2407,6 @@ static void megasas_scsi_realize(PCIDevice *dev, Error **errp)
}
}
-static void
-megasas_write_config(PCIDevice *pci, uint32_t addr, uint32_t val, int len)
-{
- pci_default_write_config(pci, addr, val, len);
- msi_write_config(pci, addr, val, len);
-}
-
static Property megasas_properties_gen1[] = {
DEFINE_PROP_UINT32("max_sge", MegasasState, fw_sge,
MEGASAS_DEFAULT_SGE),
@@ -2516,7 +2509,6 @@ static void megasas_class_init(ObjectClass *oc, void *data)
dc->vmsd = info->vmsd;
set_bit(DEVICE_CATEGORY_STORAGE, dc->categories);
dc->desc = info->desc;
- pc->config_write = megasas_write_config;
}
static const TypeInfo megasas_info = {
diff --git a/hw/scsi/vhost-scsi.c b/hw/scsi/vhost-scsi.c
index 1941aa15c0..1c389c4d7e 100644
--- a/hw/scsi/vhost-scsi.c
+++ b/hw/scsi/vhost-scsi.c
@@ -246,7 +246,7 @@ static void vhost_scsi_realize(DeviceState *dev, Error **errp)
s->dev.backend_features = 0;
ret = vhost_dev_init(&s->dev, (void *)(uintptr_t)vhostfd,
- VHOST_BACKEND_TYPE_KERNEL, true);
+ VHOST_BACKEND_TYPE_KERNEL);
if (ret < 0) {
error_setg(errp, "vhost-scsi: vhost initialization failed: %s",
strerror(-ret));
diff --git a/hw/scsi/vmw_pvscsi.c b/hw/scsi/vmw_pvscsi.c
index c6148d380e..9c71f31fe2 100644
--- a/hw/scsi/vmw_pvscsi.c
+++ b/hw/scsi/vmw_pvscsi.c
@@ -1174,13 +1174,6 @@ static const VMStateDescription vmstate_pvscsi = {
}
};
-static void
-pvscsi_write_config(PCIDevice *pci, uint32_t addr, uint32_t val, int len)
-{
- pci_default_write_config(pci, addr, val, len);
- msi_write_config(pci, addr, val, len);
-}
-
static Property pvscsi_properties[] = {
DEFINE_PROP_UINT8("use_msg", PVSCSIState, use_msg, 1),
DEFINE_PROP_END_OF_LIST(),
@@ -1202,7 +1195,6 @@ static void pvscsi_class_init(ObjectClass *klass, void *data)
dc->vmsd = &vmstate_pvscsi;
dc->props = pvscsi_properties;
set_bit(DEVICE_CATEGORY_STORAGE, dc->categories);
- k->config_write = pvscsi_write_config;
hc->unplug = pvscsi_hot_unplug;
hc->plug = pvscsi_hotplug;
}
diff --git a/hw/virtio/vhost.c b/hw/virtio/vhost.c
index 2d6c27af8d..a6dcc79399 100644
--- a/hw/virtio/vhost.c
+++ b/hw/virtio/vhost.c
@@ -17,9 +17,11 @@
#include "hw/hw.h"
#include "qemu/atomic.h"
#include "qemu/range.h"
+#include "qemu/error-report.h"
#include <linux/vhost.h>
#include "exec/address-spaces.h"
#include "hw/virtio/virtio-bus.h"
+#include "hw/virtio/virtio-access.h"
#include "migration/migration.h"
static struct vhost_log *vhost_log;
@@ -689,6 +691,27 @@ static void vhost_log_stop(MemoryListener *listener,
/* FIXME: implement */
}
+static int vhost_virtqueue_set_vring_endian_legacy(struct vhost_dev *dev,
+ bool is_big_endian,
+ int vhost_vq_index)
+{
+ struct vhost_vring_state s = {
+ .index = vhost_vq_index,
+ .num = is_big_endian
+ };
+
+ if (!dev->vhost_ops->vhost_call(dev, VHOST_SET_VRING_ENDIAN, &s)) {
+ return 0;
+ }
+
+ if (errno == ENOTTY) {
+ error_report("vhost does not support cross-endian");
+ return -ENOSYS;
+ }
+
+ return -errno;
+}
+
static int vhost_virtqueue_start(struct vhost_dev *dev,
struct VirtIODevice *vdev,
struct vhost_virtqueue *vq,
@@ -719,6 +742,16 @@ static int vhost_virtqueue_start(struct vhost_dev *dev,
return -errno;
}
+ if (!virtio_has_feature(vdev, VIRTIO_F_VERSION_1) &&
+ virtio_legacy_is_cross_endian(vdev)) {
+ r = vhost_virtqueue_set_vring_endian_legacy(dev,
+ virtio_is_big_endian(vdev),
+ vhost_vq_index);
+ if (r) {
+ return -errno;
+ }
+ }
+
s = l = virtio_queue_get_desc_size(vdev, idx);
a = virtio_queue_get_desc_addr(vdev, idx);
vq->desc = cpu_physical_memory_map(a, &l, 0);
@@ -789,8 +822,9 @@ static void vhost_virtqueue_stop(struct vhost_dev *dev,
struct vhost_virtqueue *vq,
unsigned idx)
{
+ int vhost_vq_index = idx - dev->vq_index;
struct vhost_vring_state state = {
- .index = idx - dev->vq_index
+ .index = vhost_vq_index,
};
int r;
assert(idx >= dev->vq_index && idx < dev->vq_index + dev->nvqs);
@@ -801,6 +835,20 @@ static void vhost_virtqueue_stop(struct vhost_dev *dev,
}
virtio_queue_set_last_avail_idx(vdev, idx, state.num);
virtio_queue_invalidate_signalled_used(vdev, idx);
+
+ /* In the cross-endian case, we need to reset the vring endianness to
+ * native as legacy devices expect so by default.
+ */
+ if (!virtio_has_feature(vdev, VIRTIO_F_VERSION_1) &&
+ virtio_legacy_is_cross_endian(vdev)) {
+ r = vhost_virtqueue_set_vring_endian_legacy(dev,
+ !virtio_is_big_endian(vdev),
+ vhost_vq_index);
+ if (r < 0) {
+ error_report("failed to reset vring endianness");
+ }
+ }
+
assert (r >= 0);
cpu_physical_memory_unmap(vq->ring, virtio_queue_get_ring_size(vdev, idx),
0, virtio_queue_get_ring_size(vdev, idx));
@@ -853,7 +901,7 @@ static void vhost_virtqueue_cleanup(struct vhost_virtqueue *vq)
}
int vhost_dev_init(struct vhost_dev *hdev, void *opaque,
- VhostBackendType backend_type, bool force)
+ VhostBackendType backend_type)
{
uint64_t features;
int i, r;
@@ -916,7 +964,6 @@ int vhost_dev_init(struct vhost_dev *hdev, void *opaque,
hdev->started = false;
hdev->memory_changed = false;
memory_listener_register(&hdev->memory_listener, &address_space_memory);
- hdev->force = force;
return 0;
fail_vq:
while (--i >= 0) {
@@ -944,17 +991,6 @@ void vhost_dev_cleanup(struct vhost_dev *hdev)
hdev->vhost_ops->vhost_backend_cleanup(hdev);
}
-bool vhost_dev_query(struct vhost_dev *hdev, VirtIODevice *vdev)
-{
- BusState *qbus = BUS(qdev_get_parent_bus(DEVICE(vdev)));
- VirtioBusState *vbus = VIRTIO_BUS(qbus);
- VirtioBusClass *k = VIRTIO_BUS_GET_CLASS(vbus);
-
- return !k->query_guest_notifiers ||
- k->query_guest_notifiers(qbus->parent) ||
- hdev->force;
-}
-
/* Stop processing guest IO notifications in qemu.
* Start processing them in vhost in kernel.
*/