summaryrefslogtreecommitdiffstats
path: root/include
diff options
context:
space:
mode:
authorPaolo Bonzini2018-02-06 18:37:39 +0100
committerPaolo Bonzini2019-08-20 17:26:20 +0200
commit9458a9a1df1a4c719e24512394d548c1fc7abd22 (patch)
tree2e7dd0685486a403fda9fb52c70406a04637ef8b /include
parenttarget/i386: Return 'indefinite integer value' for invalid SSE fp->int conver... (diff)
downloadqemu-9458a9a1df1a4c719e24512394d548c1fc7abd22.tar.gz
qemu-9458a9a1df1a4c719e24512394d548c1fc7abd22.tar.xz
qemu-9458a9a1df1a4c719e24512394d548c1fc7abd22.zip
memory: fix race between TCG and accesses to dirty bitmap
There is a race between TCG and accesses to the dirty log: vCPU thread reader thread ----------------------- ----------------------- TLB check -> slow path notdirty_mem_write write to RAM set dirty flag clear dirty flag TLB check -> fast path read memory write to RAM Fortunately, in order to fix it, no change is required to the vCPU thread. However, the reader thread must delay the read after the vCPU thread has finished the write. This can be approximated conservatively by run_on_cpu, which waits for the end of the current translation block. A similar technique is used by KVM, which has to do a synchronous TLB flush after doing a test-and-clear of the dirty-page flags. Reported-by: Dr. David Alan Gilbert <dgilbert@redhat.com> Signed-off-by: Paolo Bonzini <pbonzini@redhat.com>
Diffstat (limited to 'include')
-rw-r--r--include/exec/memory.h12
1 files changed, 12 insertions, 0 deletions
diff --git a/include/exec/memory.h b/include/exec/memory.h
index d99eb25d2e..fddc2ff48a 100644
--- a/include/exec/memory.h
+++ b/include/exec/memory.h
@@ -425,6 +425,7 @@ struct MemoryListener {
void (*log_clear)(MemoryListener *listener, MemoryRegionSection *section);
void (*log_global_start)(MemoryListener *listener);
void (*log_global_stop)(MemoryListener *listener);
+ void (*log_global_after_sync)(MemoryListener *listener);
void (*eventfd_add)(MemoryListener *listener, MemoryRegionSection *section,
bool match_data, uint64_t data, EventNotifier *e);
void (*eventfd_del)(MemoryListener *listener, MemoryRegionSection *section,
@@ -1688,6 +1689,17 @@ MemoryRegionSection memory_region_find(MemoryRegion *mr,
void memory_global_dirty_log_sync(void);
/**
+ * memory_global_dirty_log_sync: synchronize the dirty log for all memory
+ *
+ * Synchronizes the vCPUs with a thread that is reading the dirty bitmap.
+ * This function must be called after the dirty log bitmap is cleared, and
+ * before dirty guest memory pages are read. If you are using
+ * #DirtyBitmapSnapshot, memory_region_snapshot_and_clear_dirty() takes
+ * care of doing this.
+ */
+void memory_global_after_dirty_log_sync(void);
+
+/**
* memory_region_transaction_begin: Start a transaction.
*
* During a transaction, changes will be accumulated and made visible