|
|
76daa3 |
From 9edf80a5eff51ebc6944876018952dc2505160bd Mon Sep 17 00:00:00 2001
|
|
|
76daa3 |
From: Laurent Vivier <lvivier@redhat.com>
|
|
|
76daa3 |
Date: Mon, 24 Apr 2017 16:45:25 +0200
|
|
|
76daa3 |
Subject: [PATCH 15/23] virtio-rng: stop virtqueue while the CPU is stopped
|
|
|
76daa3 |
|
|
|
76daa3 |
RH-Author: Laurent Vivier <lvivier@redhat.com>
|
|
|
76daa3 |
Message-id: <20170424164525.31342-1-lvivier@redhat.com>
|
|
|
76daa3 |
Patchwork-id: 74859
|
|
|
76daa3 |
O-Subject: [RHV-7.4 qemu-kvm-rhev PATCH] virtio-rng: stop virtqueue while the CPU is stopped
|
|
|
76daa3 |
Bugzilla: 1435521
|
|
|
76daa3 |
RH-Acked-by: Juan Quintela <quintela@redhat.com>
|
|
|
76daa3 |
RH-Acked-by: Dr. David Alan Gilbert <dgilbert@redhat.com>
|
|
|
76daa3 |
RH-Acked-by: Miroslav Rezanina <mrezanin@redhat.com>
|
|
|
76daa3 |
|
|
|
76daa3 |
If we modify the virtio-rng virqueue while the
|
|
|
76daa3 |
vmstate is already migrated we can have some
|
|
|
76daa3 |
inconsistencies between the virtqueue state and
|
|
|
76daa3 |
the memory content.
|
|
|
76daa3 |
|
|
|
76daa3 |
To avoid this, stop the virtqueue while the CPU
|
|
|
76daa3 |
is stopped.
|
|
|
76daa3 |
|
|
|
76daa3 |
Signed-off-by: Laurent Vivier <lvivier@redhat.com>
|
|
|
76daa3 |
Reviewed-by: Amit Shah <amit@kernel.org>
|
|
|
76daa3 |
Reviewed-by: Stefan Hajnoczi <stefanha@redhat.com>
|
|
|
76daa3 |
Reviewed-by: Juan Quintela <quintela@redhat.com>
|
|
|
76daa3 |
Signed-off-by: Juan Quintela <quintela@redhat.com>
|
|
|
76daa3 |
(cherry picked from commit a23a6d183986ef38b705e85cabdd2af6cdc95276)
|
|
|
76daa3 |
Signed-off-by: Laurent Vivier <lvivier@redhat.com>
|
|
|
76daa3 |
|
|
|
76daa3 |
BZ: https://bugzilla.redhat.com/show_bug.cgi?id=1435521
|
|
|
76daa3 |
BREW: https://brewweb.engineering.redhat.com/brew/taskinfo?taskID=13071542
|
|
|
76daa3 |
Signed-off-by: Miroslav Rezanina <mrezanin@redhat.com>
|
|
|
76daa3 |
---
|
|
|
76daa3 |
hw/virtio/trace-events | 3 +++
|
|
|
76daa3 |
hw/virtio/virtio-rng.c | 29 +++++++++++++++++++++++------
|
|
|
76daa3 |
include/hw/virtio/virtio-rng.h | 2 ++
|
|
|
76daa3 |
3 files changed, 28 insertions(+), 6 deletions(-)
|
|
|
76daa3 |
|
|
|
76daa3 |
diff --git a/hw/virtio/trace-events b/hw/virtio/trace-events
|
|
|
76daa3 |
index 6926eed..1f7a7c1 100644
|
|
|
76daa3 |
--- a/hw/virtio/trace-events
|
|
|
76daa3 |
+++ b/hw/virtio/trace-events
|
|
|
76daa3 |
@@ -11,8 +11,11 @@ virtio_set_status(void *vdev, uint8_t val) "vdev %p val %u"
|
|
|
76daa3 |
|
|
|
76daa3 |
# hw/virtio/virtio-rng.c
|
|
|
76daa3 |
virtio_rng_guest_not_ready(void *rng) "rng %p: guest not ready"
|
|
|
76daa3 |
+virtio_rng_cpu_is_stopped(void *rng, int size) "rng %p: cpu is stopped, dropping %d bytes"
|
|
|
76daa3 |
+virtio_rng_popped(void *rng) "rng %p: elem popped"
|
|
|
76daa3 |
virtio_rng_pushed(void *rng, size_t len) "rng %p: %zd bytes pushed"
|
|
|
76daa3 |
virtio_rng_request(void *rng, size_t size, unsigned quota) "rng %p: %zd bytes requested, %u bytes quota left"
|
|
|
76daa3 |
+virtio_rng_vm_state_change(void *rng, int running, int state) "rng %p: state change to running %d state %d"
|
|
|
76daa3 |
|
|
|
76daa3 |
# hw/virtio/virtio-balloon.c
|
|
|
76daa3 |
#
|
|
|
76daa3 |
diff --git a/hw/virtio/virtio-rng.c b/hw/virtio/virtio-rng.c
|
|
|
76daa3 |
index 9639f4e..a6ee501 100644
|
|
|
76daa3 |
--- a/hw/virtio/virtio-rng.c
|
|
|
76daa3 |
+++ b/hw/virtio/virtio-rng.c
|
|
|
76daa3 |
@@ -53,6 +53,15 @@ static void chr_read(void *opaque, const void *buf, size_t size)
|
|
|
76daa3 |
return;
|
|
|
76daa3 |
}
|
|
|
76daa3 |
|
|
|
76daa3 |
+ /* we can't modify the virtqueue until
|
|
|
76daa3 |
+ * our state is fully synced
|
|
|
76daa3 |
+ */
|
|
|
76daa3 |
+
|
|
|
76daa3 |
+ if (!runstate_check(RUN_STATE_RUNNING)) {
|
|
|
76daa3 |
+ trace_virtio_rng_cpu_is_stopped(vrng, size);
|
|
|
76daa3 |
+ return;
|
|
|
76daa3 |
+ }
|
|
|
76daa3 |
+
|
|
|
76daa3 |
vrng->quota_remaining -= size;
|
|
|
76daa3 |
|
|
|
76daa3 |
offset = 0;
|
|
|
76daa3 |
@@ -61,6 +70,7 @@ static void chr_read(void *opaque, const void *buf, size_t size)
|
|
|
76daa3 |
if (!elem) {
|
|
|
76daa3 |
break;
|
|
|
76daa3 |
}
|
|
|
76daa3 |
+ trace_virtio_rng_popped(vrng);
|
|
|
76daa3 |
len = iov_from_buf(elem->in_sg, elem->in_num,
|
|
|
76daa3 |
0, buf + offset, size - offset);
|
|
|
76daa3 |
offset += len;
|
|
|
76daa3 |
@@ -120,17 +130,21 @@ static uint64_t get_features(VirtIODevice *vdev, uint64_t f, Error **errp)
|
|
|
76daa3 |
return f;
|
|
|
76daa3 |
}
|
|
|
76daa3 |
|
|
|
76daa3 |
-static int virtio_rng_post_load(void *opaque, int version_id)
|
|
|
76daa3 |
+static void virtio_rng_vm_state_change(void *opaque, int running,
|
|
|
76daa3 |
+ RunState state)
|
|
|
76daa3 |
{
|
|
|
76daa3 |
VirtIORNG *vrng = opaque;
|
|
|
76daa3 |
|
|
|
76daa3 |
+ trace_virtio_rng_vm_state_change(vrng, running, state);
|
|
|
76daa3 |
+
|
|
|
76daa3 |
/* We may have an element ready but couldn't process it due to a quota
|
|
|
76daa3 |
- * limit. Make sure to try again after live migration when the quota may
|
|
|
76daa3 |
- * have been reset.
|
|
|
76daa3 |
+ * limit or because CPU was stopped. Make sure to try again when the
|
|
|
76daa3 |
+ * CPU restart.
|
|
|
76daa3 |
*/
|
|
|
76daa3 |
- virtio_rng_process(vrng);
|
|
|
76daa3 |
|
|
|
76daa3 |
- return 0;
|
|
|
76daa3 |
+ if (running && is_guest_ready(vrng)) {
|
|
|
76daa3 |
+ virtio_rng_process(vrng);
|
|
|
76daa3 |
+ }
|
|
|
76daa3 |
}
|
|
|
76daa3 |
|
|
|
76daa3 |
static void check_rate_limit(void *opaque)
|
|
|
76daa3 |
@@ -198,6 +212,9 @@ static void virtio_rng_device_realize(DeviceState *dev, Error **errp)
|
|
|
76daa3 |
vrng->rate_limit_timer = timer_new_ms(QEMU_CLOCK_VIRTUAL,
|
|
|
76daa3 |
check_rate_limit, vrng);
|
|
|
76daa3 |
vrng->activate_timer = true;
|
|
|
76daa3 |
+
|
|
|
76daa3 |
+ vrng->vmstate = qemu_add_vm_change_state_handler(virtio_rng_vm_state_change,
|
|
|
76daa3 |
+ vrng);
|
|
|
76daa3 |
}
|
|
|
76daa3 |
|
|
|
76daa3 |
static void virtio_rng_device_unrealize(DeviceState *dev, Error **errp)
|
|
|
76daa3 |
@@ -205,6 +222,7 @@ static void virtio_rng_device_unrealize(DeviceState *dev, Error **errp)
|
|
|
76daa3 |
VirtIODevice *vdev = VIRTIO_DEVICE(dev);
|
|
|
76daa3 |
VirtIORNG *vrng = VIRTIO_RNG(dev);
|
|
|
76daa3 |
|
|
|
76daa3 |
+ qemu_del_vm_change_state_handler(vrng->vmstate);
|
|
|
76daa3 |
timer_del(vrng->rate_limit_timer);
|
|
|
76daa3 |
timer_free(vrng->rate_limit_timer);
|
|
|
76daa3 |
virtio_cleanup(vdev);
|
|
|
76daa3 |
@@ -218,7 +236,6 @@ static const VMStateDescription vmstate_virtio_rng = {
|
|
|
76daa3 |
VMSTATE_VIRTIO_DEVICE,
|
|
|
76daa3 |
VMSTATE_END_OF_LIST()
|
|
|
76daa3 |
},
|
|
|
76daa3 |
- .post_load = virtio_rng_post_load,
|
|
|
76daa3 |
};
|
|
|
76daa3 |
|
|
|
76daa3 |
static Property virtio_rng_properties[] = {
|
|
|
76daa3 |
diff --git a/include/hw/virtio/virtio-rng.h b/include/hw/virtio/virtio-rng.h
|
|
|
76daa3 |
index 2d40abd..922dce7 100644
|
|
|
76daa3 |
--- a/include/hw/virtio/virtio-rng.h
|
|
|
76daa3 |
+++ b/include/hw/virtio/virtio-rng.h
|
|
|
76daa3 |
@@ -45,6 +45,8 @@ typedef struct VirtIORNG {
|
|
|
76daa3 |
QEMUTimer *rate_limit_timer;
|
|
|
76daa3 |
int64_t quota_remaining;
|
|
|
76daa3 |
bool activate_timer;
|
|
|
76daa3 |
+
|
|
|
76daa3 |
+ VMChangeStateEntry *vmstate;
|
|
|
76daa3 |
} VirtIORNG;
|
|
|
76daa3 |
|
|
|
76daa3 |
#endif
|
|
|
76daa3 |
--
|
|
|
76daa3 |
1.8.3.1
|
|
|
76daa3 |
|