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>
This commit is contained in:
Michael S. Tsirkin 2011-01-10 14:28:40 +02:00
parent 3dbca8e6a7
commit 85cf2a8d74
3 changed files with 32 additions and 21 deletions

View File

@ -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);

View File

@ -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;
} }

View File

@ -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)