aboutsummaryrefslogtreecommitdiff
path: root/hw
diff options
context:
space:
mode:
Diffstat (limited to 'hw')
-rw-r--r--hw/vhost.c10
-rw-r--r--hw/vhost.h4
-rw-r--r--hw/vhost_net.c24
-rw-r--r--hw/vhost_net.h3
-rw-r--r--hw/virtio-net.c6
-rw-r--r--hw/virtio-pci.c7
-rw-r--r--hw/virtio.h1
7 files changed, 45 insertions, 10 deletions
diff --git a/hw/vhost.c b/hw/vhost.c
index 6082da287e..38cc3b365b 100644
--- a/hw/vhost.c
+++ b/hw/vhost.c
@@ -581,7 +581,7 @@ static void vhost_virtqueue_cleanup(struct vhost_dev *dev,
0, virtio_queue_get_desc_size(vdev, idx));
}
-int vhost_dev_init(struct vhost_dev *hdev, int devfd)
+int vhost_dev_init(struct vhost_dev *hdev, int devfd, bool force)
{
uint64_t features;
int r;
@@ -613,6 +613,7 @@ int vhost_dev_init(struct vhost_dev *hdev, int devfd)
hdev->log_enabled = false;
hdev->started = false;
cpu_register_phys_memory_client(&hdev->client);
+ hdev->force = force;
return 0;
fail:
r = -errno;
@@ -627,6 +628,13 @@ void vhost_dev_cleanup(struct vhost_dev *hdev)
close(hdev->control);
}
+bool vhost_dev_query(struct vhost_dev *hdev, VirtIODevice *vdev)
+{
+ return !vdev->binding->query_guest_notifiers ||
+ vdev->binding->query_guest_notifiers(vdev->binding_opaque) ||
+ hdev->force;
+}
+
int vhost_dev_start(struct vhost_dev *hdev, VirtIODevice *vdev)
{
int i, r;
diff --git a/hw/vhost.h b/hw/vhost.h
index 86dd834dbe..c8c595a147 100644
--- a/hw/vhost.h
+++ b/hw/vhost.h
@@ -38,10 +38,12 @@ struct vhost_dev {
bool log_enabled;
vhost_log_chunk_t *log;
unsigned long long log_size;
+ bool force;
};
-int vhost_dev_init(struct vhost_dev *hdev, int devfd);
+int vhost_dev_init(struct vhost_dev *hdev, int devfd, bool force);
void vhost_dev_cleanup(struct vhost_dev *hdev);
+bool vhost_dev_query(struct vhost_dev *hdev, VirtIODevice *vdev);
int vhost_dev_start(struct vhost_dev *hdev, VirtIODevice *vdev);
void vhost_dev_stop(struct vhost_dev *hdev, VirtIODevice *vdev);
diff --git a/hw/vhost_net.c b/hw/vhost_net.c
index c068be1f54..420e05f112 100644
--- a/hw/vhost_net.c
+++ b/hw/vhost_net.c
@@ -81,7 +81,8 @@ static int vhost_net_get_fd(VLANClientState *backend)
}
}
-struct vhost_net *vhost_net_init(VLANClientState *backend, int devfd)
+struct vhost_net *vhost_net_init(VLANClientState *backend, int devfd,
+ bool force)
{
int r;
struct vhost_net *net = qemu_malloc(sizeof *net);
@@ -98,7 +99,7 @@ struct vhost_net *vhost_net_init(VLANClientState *backend, int devfd)
(1 << VHOST_NET_F_VIRTIO_NET_HDR);
net->backend = r;
- r = vhost_dev_init(&net->dev, devfd);
+ r = vhost_dev_init(&net->dev, devfd, force);
if (r < 0) {
goto fail;
}
@@ -121,6 +122,11 @@ fail:
return NULL;
}
+bool vhost_net_query(VHostNetState *net, VirtIODevice *dev)
+{
+ return vhost_dev_query(&net->dev, dev);
+}
+
int vhost_net_start(struct vhost_net *net,
VirtIODevice *dev)
{
@@ -188,15 +194,21 @@ void vhost_net_cleanup(struct vhost_net *net)
qemu_free(net);
}
#else
-struct vhost_net *vhost_net_init(VLANClientState *backend, int devfd)
+struct vhost_net *vhost_net_init(VLANClientState *backend, int devfd,
+ bool force)
+{
+ return NULL;
+}
+
+bool vhost_net_query(VHostNetState *net, VirtIODevice *dev)
{
- return NULL;
+ return false;
}
int vhost_net_start(struct vhost_net *net,
VirtIODevice *dev)
{
- return -ENOSYS;
+ return -ENOSYS;
}
void vhost_net_stop(struct vhost_net *net,
VirtIODevice *dev)
@@ -209,7 +221,7 @@ void vhost_net_cleanup(struct vhost_net *net)
unsigned vhost_net_get_features(struct vhost_net *net, unsigned features)
{
- return features;
+ return features;
}
void vhost_net_ack_features(struct vhost_net *net, unsigned features)
{
diff --git a/hw/vhost_net.h b/hw/vhost_net.h
index 6c18ff7e94..91e40b195e 100644
--- a/hw/vhost_net.h
+++ b/hw/vhost_net.h
@@ -6,8 +6,9 @@
struct vhost_net;
typedef struct vhost_net VHostNetState;
-VHostNetState *vhost_net_init(VLANClientState *backend, int devfd);
+VHostNetState *vhost_net_init(VLANClientState *backend, int devfd, bool force);
+bool vhost_net_query(VHostNetState *net, VirtIODevice *dev);
int vhost_net_start(VHostNetState *net, VirtIODevice *dev);
void vhost_net_stop(VHostNetState *net, VirtIODevice *dev);
diff --git a/hw/virtio-net.c b/hw/virtio-net.c
index 161f11445f..671d952921 100644
--- a/hw/virtio-net.c
+++ b/hw/virtio-net.c
@@ -119,7 +119,11 @@ static void virtio_net_vhost_status(VirtIONet *n, uint8_t status)
return;
}
if (!n->vhost_started) {
- int r = vhost_net_start(tap_get_vhost_net(n->nic->nc.peer), &n->vdev);
+ int r;
+ if (!vhost_net_query(tap_get_vhost_net(n->nic->nc.peer), &n->vdev)) {
+ return;
+ }
+ r = vhost_net_start(tap_get_vhost_net(n->nic->nc.peer), &n->vdev);
if (r < 0) {
error_report("unable to start vhost net: %d: "
"falling back on userspace virtio", -r);
diff --git a/hw/virtio-pci.c b/hw/virtio-pci.c
index d07ff976be..3911b09b07 100644
--- a/hw/virtio-pci.c
+++ b/hw/virtio-pci.c
@@ -595,6 +595,12 @@ static int virtio_pci_set_guest_notifier(void *opaque, int n, bool assign)
return 0;
}
+static bool virtio_pci_query_guest_notifiers(void *opaque)
+{
+ VirtIOPCIProxy *proxy = opaque;
+ return msix_enabled(&proxy->pci_dev);
+}
+
static int virtio_pci_set_guest_notifiers(void *opaque, bool assign)
{
VirtIOPCIProxy *proxy = opaque;
@@ -658,6 +664,7 @@ static const VirtIOBindings virtio_pci_bindings = {
.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,
diff --git a/hw/virtio.h b/hw/virtio.h
index d8546d5b30..31d16e1c31 100644
--- a/hw/virtio.h
+++ b/hw/virtio.h
@@ -93,6 +93,7 @@ typedef struct {
int (*load_config)(void * opaque, QEMUFile *f);
int (*load_queue)(void * opaque, int n, QEMUFile *f);
unsigned (*get_features)(void * opaque);
+ bool (*query_guest_notifiers)(void * opaque);
int (*set_guest_notifiers)(void * opaque, bool assigned);
int (*set_host_notifier)(void * opaque, int n, bool assigned);
void (*vmstate_change)(void * opaque, bool running);