aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--hw/virtio/trace-events3
-rw-r--r--hw/virtio/virtio-rng.c29
-rw-r--r--include/hw/virtio/virtio-rng.h2
3 files changed, 28 insertions, 6 deletions
diff --git a/hw/virtio/trace-events b/hw/virtio/trace-events
index 6926eed..1f7a7c1 100644
--- a/hw/virtio/trace-events
+++ b/hw/virtio/trace-events
@@ -11,8 +11,11 @@ virtio_set_status(void *vdev, uint8_t val) "vdev %p val %u"
# hw/virtio/virtio-rng.c
virtio_rng_guest_not_ready(void *rng) "rng %p: guest not ready"
+virtio_rng_cpu_is_stopped(void *rng, int size) "rng %p: cpu is stopped, dropping %d bytes"
+virtio_rng_popped(void *rng) "rng %p: elem popped"
virtio_rng_pushed(void *rng, size_t len) "rng %p: %zd bytes pushed"
virtio_rng_request(void *rng, size_t size, unsigned quota) "rng %p: %zd bytes requested, %u bytes quota left"
+virtio_rng_vm_state_change(void *rng, int running, int state) "rng %p: state change to running %d state %d"
# hw/virtio/virtio-balloon.c
#
diff --git a/hw/virtio/virtio-rng.c b/hw/virtio/virtio-rng.c
index 9639f4e..a6ee501 100644
--- a/hw/virtio/virtio-rng.c
+++ b/hw/virtio/virtio-rng.c
@@ -53,6 +53,15 @@ static void chr_read(void *opaque, const void *buf, size_t size)
return;
}
+ /* we can't modify the virtqueue until
+ * our state is fully synced
+ */
+
+ if (!runstate_check(RUN_STATE_RUNNING)) {
+ trace_virtio_rng_cpu_is_stopped(vrng, size);
+ return;
+ }
+
vrng->quota_remaining -= size;
offset = 0;
@@ -61,6 +70,7 @@ static void chr_read(void *opaque, const void *buf, size_t size)
if (!elem) {
break;
}
+ trace_virtio_rng_popped(vrng);
len = iov_from_buf(elem->in_sg, elem->in_num,
0, buf + offset, size - offset);
offset += len;
@@ -120,17 +130,21 @@ static uint64_t get_features(VirtIODevice *vdev, uint64_t f, Error **errp)
return f;
}
-static int virtio_rng_post_load(void *opaque, int version_id)
+static void virtio_rng_vm_state_change(void *opaque, int running,
+ RunState state)
{
VirtIORNG *vrng = opaque;
+ trace_virtio_rng_vm_state_change(vrng, running, state);
+
/* We may have an element ready but couldn't process it due to a quota
- * limit. Make sure to try again after live migration when the quota may
- * have been reset.
+ * limit or because CPU was stopped. Make sure to try again when the
+ * CPU restart.
*/
- virtio_rng_process(vrng);
- return 0;
+ if (running && is_guest_ready(vrng)) {
+ virtio_rng_process(vrng);
+ }
}
static void check_rate_limit(void *opaque)
@@ -198,6 +212,9 @@ static void virtio_rng_device_realize(DeviceState *dev, Error **errp)
vrng->rate_limit_timer = timer_new_ms(QEMU_CLOCK_VIRTUAL,
check_rate_limit, vrng);
vrng->activate_timer = true;
+
+ vrng->vmstate = qemu_add_vm_change_state_handler(virtio_rng_vm_state_change,
+ vrng);
}
static void virtio_rng_device_unrealize(DeviceState *dev, Error **errp)
@@ -205,6 +222,7 @@ static void virtio_rng_device_unrealize(DeviceState *dev, Error **errp)
VirtIODevice *vdev = VIRTIO_DEVICE(dev);
VirtIORNG *vrng = VIRTIO_RNG(dev);
+ qemu_del_vm_change_state_handler(vrng->vmstate);
timer_del(vrng->rate_limit_timer);
timer_free(vrng->rate_limit_timer);
virtio_cleanup(vdev);
@@ -218,7 +236,6 @@ static const VMStateDescription vmstate_virtio_rng = {
VMSTATE_VIRTIO_DEVICE,
VMSTATE_END_OF_LIST()
},
- .post_load = virtio_rng_post_load,
};
static Property virtio_rng_properties[] = {
diff --git a/include/hw/virtio/virtio-rng.h b/include/hw/virtio/virtio-rng.h
index 2d40abd..922dce7 100644
--- a/include/hw/virtio/virtio-rng.h
+++ b/include/hw/virtio/virtio-rng.h
@@ -45,6 +45,8 @@ typedef struct VirtIORNG {
QEMUTimer *rate_limit_timer;
int64_t quota_remaining;
bool activate_timer;
+
+ VMChangeStateEntry *vmstate;
} VirtIORNG;
#endif