[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]
[Qemu-devel] [PULL 07/28] migration: sync all address spaces
From: |
Paolo Bonzini |
Subject: |
[Qemu-devel] [PULL 07/28] migration: sync all address spaces |
Date: |
Mon, 26 Sep 2016 15:40:37 +0200 |
Migrating a VM during reboot sometimes results in differences
between the source and destination in the SMRAM area.
This is because migration_bitmap_sync() only fetches from KVM
the dirty log of address_space_memory. SMRAM memory slots
are ignored and the modifications to SMRAM are not sent to the
destination.
Reported-by: He Rongguang <address@hidden>
Reviewed-by: He Rongguang <address@hidden>
Signed-off-by: Paolo Bonzini <address@hidden>
---
include/exec/memory.h | 7 +++----
memory.c | 46 +++++++++++++++++++++++++++++++++-------------
migration/ram.c | 2 +-
3 files changed, 37 insertions(+), 18 deletions(-)
diff --git a/include/exec/memory.h b/include/exec/memory.h
index a3f988b..10d7eac 100644
--- a/include/exec/memory.h
+++ b/include/exec/memory.h
@@ -1188,12 +1188,11 @@ MemoryRegionSection memory_region_find(MemoryRegion *mr,
hwaddr addr, uint64_t size);
/**
- * address_space_sync_dirty_bitmap: synchronize the dirty log for all memory
+ * memory_global_dirty_log_sync: synchronize the dirty log for all memory
*
- * Synchronizes the dirty page log for an entire address space.
- * @as: the address space that contains the memory being synchronized
+ * Synchronizes the dirty page log for all address spaces.
*/
-void address_space_sync_dirty_bitmap(AddressSpace *as);
+void memory_global_dirty_log_sync(void);
/**
* memory_region_transaction_begin: Start a transaction.
diff --git a/memory.c b/memory.c
index 27a3f2f..58f9269 100644
--- a/memory.c
+++ b/memory.c
@@ -158,14 +158,10 @@ static bool memory_listener_match(MemoryListener
*listener,
/* No need to ref/unref .mr, the FlatRange keeps it alive. */
#define MEMORY_LISTENER_UPDATE_REGION(fr, as, dir, callback, _args...) \
- MEMORY_LISTENER_CALL(callback, dir, (&(MemoryRegionSection) { \
- .mr = (fr)->mr, \
- .address_space = (as), \
- .offset_within_region = (fr)->offset_in_region, \
- .size = (fr)->addr.size, \
- .offset_within_address_space = int128_get64((fr)->addr.start), \
- .readonly = (fr)->readonly, \
- }), ##_args)
+ do { \
+ MemoryRegionSection mrs = section_from_flat_range(fr, as); \
+ MEMORY_LISTENER_CALL(callback, dir, &mrs, ##_args); \
+ } while(0)
struct CoalescedMemoryRange {
AddrRange addr;
@@ -245,6 +241,19 @@ typedef struct AddressSpaceOps AddressSpaceOps;
#define FOR_EACH_FLAT_RANGE(var, view) \
for (var = (view)->ranges; var < (view)->ranges + (view)->nr; ++var)
+static inline MemoryRegionSection
+section_from_flat_range(FlatRange *fr, AddressSpace *as)
+{
+ return (MemoryRegionSection) {
+ .mr = fr->mr,
+ .address_space = as,
+ .offset_within_region = fr->offset_in_region,
+ .size = fr->addr.size,
+ .offset_within_address_space = int128_get64(fr->addr.start),
+ .readonly = fr->readonly,
+ };
+}
+
static bool flatrange_equal(FlatRange *a, FlatRange *b)
{
return a->mr == b->mr
@@ -2156,16 +2165,27 @@ bool memory_region_present(MemoryRegion *container,
hwaddr addr)
return mr && mr != container;
}
-void address_space_sync_dirty_bitmap(AddressSpace *as)
+void memory_global_dirty_log_sync(void)
{
+ MemoryListener *listener;
+ AddressSpace *as;
FlatView *view;
FlatRange *fr;
- view = address_space_get_flatview(as);
- FOR_EACH_FLAT_RANGE(fr, view) {
- MEMORY_LISTENER_UPDATE_REGION(fr, as, Forward, log_sync);
+ QTAILQ_FOREACH(listener, &memory_listeners, link) {
+ if (!listener->log_sync) {
+ continue;
+ }
+ /* Global listeners are being phased out. */
+ assert(listener->address_space_filter);
+ as = listener->address_space_filter;
+ view = address_space_get_flatview(as);
+ FOR_EACH_FLAT_RANGE(fr, view) {
+ MemoryRegionSection mrs = section_from_flat_range(fr, as);
+ listener->log_sync(listener, &mrs);
+ }
+ flatview_unref(view);
}
- flatview_unref(view);
}
void memory_global_dirty_log_start(void)
diff --git a/migration/ram.c b/migration/ram.c
index a6e1c63..c8ec9f2 100644
--- a/migration/ram.c
+++ b/migration/ram.c
@@ -626,7 +626,7 @@ static void migration_bitmap_sync(void)
}
trace_migration_bitmap_sync_start();
- address_space_sync_dirty_bitmap(&address_space_memory);
+ memory_global_dirty_log_sync();
qemu_mutex_lock(&migration_bitmap_mutex);
rcu_read_lock();
--
2.7.4
- [Qemu-devel] [PULL 00/28] Misc patches for 2016-09-26, Paolo Bonzini, 2016/09/26
- [Qemu-devel] [PULL 01/28] memory: introduce IOMMUNotifier and its caps, Paolo Bonzini, 2016/09/26
- [Qemu-devel] [PULL 03/28] intel_iommu: allow UNMAP notifiers, Paolo Bonzini, 2016/09/26
- [Qemu-devel] [PULL 02/28] memory: introduce IOMMUOps.notify_flag_changed, Paolo Bonzini, 2016/09/26
- [Qemu-devel] [PULL 04/28] x86: ioapic: boost default version to 0x20, Paolo Bonzini, 2016/09/26
- [Qemu-devel] [PULL 05/28] checkpatch: downgrade "architecture specific defines should be avoided", Paolo Bonzini, 2016/09/26
- [Qemu-devel] [PULL 07/28] migration: sync all address spaces,
Paolo Bonzini <=
- [Qemu-devel] [PULL 09/28] build-sys: put glib_cflags in QEMU_CFLAGS, Paolo Bonzini, 2016/09/26
- [Qemu-devel] [PULL 08/28] build-sys: remove unused GLIB_CFLAGS, Paolo Bonzini, 2016/09/26
- [Qemu-devel] [PULL 06/28] compiler: Swap 'public domain' header for license, Paolo Bonzini, 2016/09/26
- [Qemu-devel] [PULL 10/28] cpus: pass CPUState to run_on_cpu helpers, Paolo Bonzini, 2016/09/26
- [Qemu-devel] [PULL 12/28] cpus: Rename flush_queued_work(), Paolo Bonzini, 2016/09/26
- [Qemu-devel] [PULL 11/28] cpus: Move common code out of {async_, }run_on_cpu(), Paolo Bonzini, 2016/09/26
- [Qemu-devel] [PULL 13/28] linux-user: Use QemuMutex and QemuCond, Paolo Bonzini, 2016/09/26
- [Qemu-devel] [PULL 14/28] linux-user: Add qemu_cpu_is_self() and qemu_cpu_kick(), Paolo Bonzini, 2016/09/26
- [Qemu-devel] [PULL 15/28] cpus-common: move CPU list management to common code, Paolo Bonzini, 2016/09/26
- [Qemu-devel] [PULL 17/28] cpus-common: fix uninitialized variable use in run_on_cpu, Paolo Bonzini, 2016/09/26