summaryrefslogtreecommitdiffstats
path: root/accel
diff options
context:
space:
mode:
Diffstat (limited to 'accel')
-rw-r--r--accel/kvm/kvm-all.c18
1 files changed, 17 insertions, 1 deletions
diff --git a/accel/kvm/kvm-all.c b/accel/kvm/kvm-all.c
index 136c8eaed3..7c8ce18bdd 100644
--- a/accel/kvm/kvm-all.c
+++ b/accel/kvm/kvm-all.c
@@ -728,7 +728,23 @@ static bool dirty_gfn_is_dirtied(struct kvm_dirty_gfn *gfn)
static void dirty_gfn_set_collected(struct kvm_dirty_gfn *gfn)
{
- gfn->flags = KVM_DIRTY_GFN_F_RESET;
+ /*
+ * Use a store-release so that the CPU that executes KVM_RESET_DIRTY_RINGS
+ * sees the full content of the ring:
+ *
+ * CPU0 CPU1 CPU2
+ * ------------------------------------------------------------------------------
+ * fill gfn0
+ * store-rel flags for gfn0
+ * load-acq flags for gfn0
+ * store-rel RESET for gfn0
+ * ioctl(RESET_RINGS)
+ * load-acq flags for gfn0
+ * check if flags have RESET
+ *
+ * The synchronization goes from CPU2 to CPU0 to CPU1.
+ */
+ qatomic_store_release(&gfn->flags, KVM_DIRTY_GFN_F_RESET);
}
/*