@@ -48,6 +48,8 @@
#include "hw/boards.h"
+#include "sysemu/cpu-throttle.h"
+
/* This check must be after config-host.h is included */
#ifdef CONFIG_EVENTFD
#include <sys/eventfd.h>
@@ -839,25 +841,6 @@ static uint64_t kvm_dirty_ring_reap(KVMState *s)
return total;
}
-static void do_kvm_cpu_synchronize_kick(CPUState *cpu, run_on_cpu_data arg)
-{
- /* No need to do anything */
-}
-
-/*
- * Kick all vcpus out in a synchronized way. When returned, we
- * guarantee that every vcpu has been kicked and at least returned to
- * userspace once.
- */
-static void kvm_cpu_synchronize_kick_all(void)
-{
- CPUState *cpu;
-
- CPU_FOREACH(cpu) {
- run_on_cpu(cpu, do_kvm_cpu_synchronize_kick, RUN_ON_CPU_NULL);
- }
-}
-
/*
* Flush all the existing dirty pages to the KVM slot buffers. When
* this call returns, we guarantee that all the touched dirty pages
@@ -879,7 +862,9 @@ static void kvm_dirty_ring_flush(void)
* First make sure to flush the hardware buffers by kicking all
* vcpus out in a synchronous way.
*/
- kvm_cpu_synchronize_kick_all();
+ if (!cpu_throttle_get_percentage()) {
+ qemu_kvm_cpu_synchronize_kick_all();
+ }
kvm_dirty_ring_reap(kvm_state);
trace_kvm_dirty_ring_flush(1);
}
@@ -160,4 +160,6 @@ extern int singlestep;
void list_cpus(const char *optarg);
+void qemu_kvm_cpu_synchronize_kick_all(void);
+
#endif /* CPU_COMMON_H */
@@ -61,6 +61,7 @@
#include "sysemu/cpus.h"
#include "yank_functions.h"
#include "sysemu/qtest.h"
+#include "sysemu/kvm.h"
#define MAX_THROTTLE (128 << 20) /* Migration transfer speed throttling */
@@ -3183,6 +3184,16 @@ static void migration_completion(MigrationState *s)
if (!ret) {
bool inactivate = !migrate_colo_enabled();
+ /*
+ * Before stop vm do qemu_kvm_cpu_synchronize_kick_all to
+ * fulsh hardware buffer into KVMslots for dirty ring
+ * optmiaztion, If qemu_kvm_cpu_synchronize_kick_all is not
+ * called when the CPU speed is limited to improve efficiency
+ */
+ if (kvm_dirty_ring_enabled()
+ && cpu_throttle_get_percentage()) {
+ qemu_kvm_cpu_synchronize_kick_all();
+ }
ret = vm_stop_force_state(RUN_STATE_FINISH_MIGRATE);
trace_migration_completion_vm_stop(ret);
if (ret >= 0) {
@@ -810,3 +810,21 @@ void qmp_inject_nmi(Error **errp)
nmi_monitor_handle(monitor_get_cpu_index(monitor_cur()), errp);
}
+static void do_kvm_cpu_synchronize_kick(CPUState *cpu, run_on_cpu_data arg)
+{
+ /* No need to do anything */
+}
+
+/*
+ * Kick all vcpus out in a synchronized way. When returned, we
+ * guarantee that every vcpu has been kicked and at least returned to
+ * userspace once.
+ */
+void qemu_kvm_cpu_synchronize_kick_all(void)
+{
+ CPUState *cpu;
+
+ CPU_FOREACH(cpu) {
+ run_on_cpu(cpu, do_kvm_cpu_synchronize_kick, RUN_ON_CPU_NULL);
+ }
+}