Browse Source

virtio: move vmstate change tracking to core

Move tracking vmstate change from virtio-net to virtio.c
as it is going to be used by virito-blk and virtio-pci
for the ioeventfd support.

Signed-off-by: Michael S. Tsirkin <mst@redhat.com>
Michael S. Tsirkin 14 years ago
parent
commit
85cf2a8d74
3 changed files with 32 additions and 21 deletions
  1. 7 21
      hw/virtio-net.c
  2. 22 0
      hw/virtio.c
  3. 3 0
      hw/virtio.h

+ 7 - 21
hw/virtio-net.c

@@ -54,8 +54,6 @@ typedef struct VirtIONet
     uint8_t nouni;
     uint8_t nouni;
     uint8_t nobcast;
     uint8_t nobcast;
     uint8_t vhost_started;
     uint8_t vhost_started;
-    bool vm_running;
-    VMChangeStateEntry *vmstate;
     struct {
     struct {
         int in_use;
         int in_use;
         int first_multi;
         int first_multi;
@@ -102,7 +100,7 @@ static void virtio_net_set_config(VirtIODevice *vdev, const uint8_t *config)
 static bool virtio_net_started(VirtIONet *n, uint8_t status)
 static bool virtio_net_started(VirtIONet *n, uint8_t status)
 {
 {
     return (status & VIRTIO_CONFIG_S_DRIVER_OK) &&
     return (status & VIRTIO_CONFIG_S_DRIVER_OK) &&
-        (n->status & VIRTIO_NET_S_LINK_UP) && n->vm_running;
+        (n->status & VIRTIO_NET_S_LINK_UP) && n->vdev.vm_running;
 }
 }
 
 
 static void virtio_net_vhost_status(VirtIONet *n, uint8_t status)
 static void virtio_net_vhost_status(VirtIONet *n, uint8_t status)
@@ -453,7 +451,7 @@ static void virtio_net_handle_rx(VirtIODevice *vdev, VirtQueue *vq)
 static int virtio_net_can_receive(VLANClientState *nc)
 static int virtio_net_can_receive(VLANClientState *nc)
 {
 {
     VirtIONet *n = DO_UPCAST(NICState, nc, nc)->opaque;
     VirtIONet *n = DO_UPCAST(NICState, nc, nc)->opaque;
-    if (!n->vm_running) {
+    if (!n->vdev.vm_running) {
         return 0;
         return 0;
     }
     }
 
 
@@ -708,7 +706,7 @@ static int32_t virtio_net_flush_tx(VirtIONet *n, VirtQueue *vq)
         return num_packets;
         return num_packets;
     }
     }
 
 
-    assert(n->vm_running);
+    assert(n->vdev.vm_running);
 
 
     if (n->async_tx.elem.out_num) {
     if (n->async_tx.elem.out_num) {
         virtio_queue_set_notification(n->tx_vq, 0);
         virtio_queue_set_notification(n->tx_vq, 0);
@@ -769,7 +767,7 @@ static void virtio_net_handle_tx_timer(VirtIODevice *vdev, VirtQueue *vq)
     VirtIONet *n = to_virtio_net(vdev);
     VirtIONet *n = to_virtio_net(vdev);
 
 
     /* This happens when device was stopped but VCPU wasn't. */
     /* This happens when device was stopped but VCPU wasn't. */
-    if (!n->vm_running) {
+    if (!n->vdev.vm_running) {
         n->tx_waiting = 1;
         n->tx_waiting = 1;
         return;
         return;
     }
     }
@@ -796,7 +794,7 @@ static void virtio_net_handle_tx_bh(VirtIODevice *vdev, VirtQueue *vq)
     }
     }
     n->tx_waiting = 1;
     n->tx_waiting = 1;
     /* This happens when device was stopped but VCPU wasn't. */
     /* This happens when device was stopped but VCPU wasn't. */
-    if (!n->vm_running) {
+    if (!n->vdev.vm_running) {
         return;
         return;
     }
     }
     virtio_queue_set_notification(vq, 0);
     virtio_queue_set_notification(vq, 0);
@@ -806,7 +804,7 @@ static void virtio_net_handle_tx_bh(VirtIODevice *vdev, VirtQueue *vq)
 static void virtio_net_tx_timer(void *opaque)
 static void virtio_net_tx_timer(void *opaque)
 {
 {
     VirtIONet *n = opaque;
     VirtIONet *n = opaque;
-    assert(n->vm_running);
+    assert(n->vdev.vm_running);
 
 
     n->tx_waiting = 0;
     n->tx_waiting = 0;
 
 
@@ -823,7 +821,7 @@ static void virtio_net_tx_bh(void *opaque)
     VirtIONet *n = opaque;
     VirtIONet *n = opaque;
     int32_t ret;
     int32_t ret;
 
 
-    assert(n->vm_running);
+    assert(n->vdev.vm_running);
 
 
     n->tx_waiting = 0;
     n->tx_waiting = 0;
 
 
@@ -988,16 +986,6 @@ static NetClientInfo net_virtio_info = {
     .link_status_changed = virtio_net_set_link_status,
     .link_status_changed = virtio_net_set_link_status,
 };
 };
 
 
-static void virtio_net_vmstate_change(void *opaque, int running, int reason)
-{
-    VirtIONet *n = opaque;
-    n->vm_running = running;
-    /* This is called when vm is started/stopped,
-     * it will start/stop vhost backend if appropriate
-     * e.g. after migration. */
-    virtio_net_set_status(&n->vdev, n->vdev.status);
-}
-
 VirtIODevice *virtio_net_init(DeviceState *dev, NICConf *conf,
 VirtIODevice *virtio_net_init(DeviceState *dev, NICConf *conf,
                               virtio_net_conf *net)
                               virtio_net_conf *net)
 {
 {
@@ -1052,7 +1040,6 @@ VirtIODevice *virtio_net_init(DeviceState *dev, NICConf *conf,
     n->qdev = dev;
     n->qdev = dev;
     register_savevm(dev, "virtio-net", -1, VIRTIO_NET_VM_VERSION,
     register_savevm(dev, "virtio-net", -1, VIRTIO_NET_VM_VERSION,
                     virtio_net_save, virtio_net_load, n);
                     virtio_net_save, virtio_net_load, n);
-    n->vmstate = qemu_add_vm_change_state_handler(virtio_net_vmstate_change, n);
 
 
     add_boot_device_path(conf->bootindex, dev, "/ethernet-phy@0");
     add_boot_device_path(conf->bootindex, dev, "/ethernet-phy@0");
 
 
@@ -1062,7 +1049,6 @@ VirtIODevice *virtio_net_init(DeviceState *dev, NICConf *conf,
 void virtio_net_exit(VirtIODevice *vdev)
 void virtio_net_exit(VirtIODevice *vdev)
 {
 {
     VirtIONet *n = DO_UPCAST(VirtIONet, vdev, vdev);
     VirtIONet *n = DO_UPCAST(VirtIONet, vdev, vdev);
-    qemu_del_vm_change_state_handler(n->vmstate);
 
 
     /* This will stop vhost backend if appropriate. */
     /* This will stop vhost backend if appropriate. */
     virtio_net_set_status(vdev, 0);
     virtio_net_set_status(vdev, 0);

+ 22 - 0
hw/virtio.c

@@ -743,11 +743,31 @@ int virtio_load(VirtIODevice *vdev, QEMUFile *f)
 
 
 void virtio_cleanup(VirtIODevice *vdev)
 void virtio_cleanup(VirtIODevice *vdev)
 {
 {
+    qemu_del_vm_change_state_handler(vdev->vmstate);
     if (vdev->config)
     if (vdev->config)
         qemu_free(vdev->config);
         qemu_free(vdev->config);
     qemu_free(vdev->vq);
     qemu_free(vdev->vq);
 }
 }
 
 
+static void virtio_vmstate_change(void *opaque, int running, int reason)
+{
+    VirtIODevice *vdev = opaque;
+    bool backend_run = running && (vdev->status & VIRTIO_CONFIG_S_DRIVER_OK);
+    vdev->vm_running = running;
+
+    if (backend_run) {
+        virtio_set_status(vdev, vdev->status);
+    }
+
+    if (vdev->binding->vmstate_change) {
+        vdev->binding->vmstate_change(vdev->binding_opaque, backend_run);
+    }
+
+    if (!backend_run) {
+        virtio_set_status(vdev, vdev->status);
+    }
+}
+
 VirtIODevice *virtio_common_init(const char *name, uint16_t device_id,
 VirtIODevice *virtio_common_init(const char *name, uint16_t device_id,
                                  size_t config_size, size_t struct_size)
                                  size_t config_size, size_t struct_size)
 {
 {
@@ -774,6 +794,8 @@ VirtIODevice *virtio_common_init(const char *name, uint16_t device_id,
     else
     else
         vdev->config = NULL;
         vdev->config = NULL;
 
 
+    vdev->vmstate = qemu_add_vm_change_state_handler(virtio_vmstate_change, vdev);
+
     return vdev;
     return vdev;
 }
 }
 
 

+ 3 - 0
hw/virtio.h

@@ -95,6 +95,7 @@ typedef struct {
     unsigned (*get_features)(void * opaque);
     unsigned (*get_features)(void * opaque);
     int (*set_guest_notifiers)(void * opaque, bool assigned);
     int (*set_guest_notifiers)(void * opaque, bool assigned);
     int (*set_host_notifier)(void * opaque, int n, bool assigned);
     int (*set_host_notifier)(void * opaque, int n, bool assigned);
+    void (*vmstate_change)(void * opaque, bool running);
 } VirtIOBindings;
 } VirtIOBindings;
 
 
 #define VIRTIO_PCI_QUEUE_MAX 64
 #define VIRTIO_PCI_QUEUE_MAX 64
@@ -123,6 +124,8 @@ struct VirtIODevice
     const VirtIOBindings *binding;
     const VirtIOBindings *binding;
     void *binding_opaque;
     void *binding_opaque;
     uint16_t device_id;
     uint16_t device_id;
+    bool vm_running;
+    VMChangeStateEntry *vmstate;
 };
 };
 
 
 static inline void virtio_set_status(VirtIODevice *vdev, uint8_t val)
 static inline void virtio_set_status(VirtIODevice *vdev, uint8_t val)