virtio, pci fixes, enhancements

Most notably this includes virtio cross-endian patches.
 
 Signed-off-by: Michael S. Tsirkin <mst@redhat.com>
 -----BEGIN PGP SIGNATURE-----
 Version: GnuPG v1
 
 iQEcBAABAgAGBQJVg+xdAAoJECgfDbjSjVRp6AAH/3ILznMtvJZjQ/WOjLEsL13M
 +0cYEM1LI6LbLhqeruQVVcY9/hx61yHxZMoLkVg/I2po7F4HDNI2vo5Y7eGx+xN0
 5rlcAw9/ZQ6SkCVmjN/VZfISW5mSqCaKH8gNzu8AigjsryJSj5iDXv1YJimwsF+5
 cgCerhLIVvEkXmNj1ChwR+fz1IgFzJ8TRaZ0N2glxLyVjgKS57diqZF3Rbg2DdQl
 BPbekbbtxesPgmKRvtarbhjx26TlnP1YShjhWA5r72gBNlqblLDycpaIGXr34b3a
 sLIZjxzQtTEGcaGtkifMgazyK3rY3JmzOshD0onFOWY1r6Abxuj7eTZOEE6JQXk=
 =tju/
 -----END PGP SIGNATURE-----

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>
This commit is contained in:
Peter Maydell 2015-06-19 11:30:57 +01:00
commit 89e9429c3c
26 changed files with 246 additions and 91 deletions

View file

@ -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.
*/