]> git.ipfire.org Git - thirdparty/qemu.git/commitdiff
kvm: Avoid COW if KVM MMU is asynchronous
authorJan Kiszka <jan.kiszka@web.de>
Sun, 26 Apr 2009 16:03:40 +0000 (18:03 +0200)
committerAnthony Liguori <aliguori@us.ibm.com>
Fri, 1 May 2009 15:11:02 +0000 (10:11 -0500)
Avi Kivity wrote:
> Suggest wrapping in a function and hiding it deep inside kvm-all.c.
>

Done in v2:

---------->

If the KVM MMU is asynchronous (kernel does not support MMU_NOTIFIER),
we have to avoid COW for the guest memory. Otherwise we risk serious
breakage when guest pages change there physical locations due to COW
after fork. Seen when forking smbd during runtime via -smb.

Signed-off-by: Jan Kiszka <jan.kiszka@siemens.com>
Signed-off-by: Anthony Liguori <aliguori@us.ibm.com>
exec.c
kvm-all.c
kvm.h

diff --git a/exec.c b/exec.c
index 37468399fc16bcccedd761662034fd91cb104ec4..61a55325ef8c0257eff5374903bd89a1248e2c9b 100644 (file)
--- a/exec.c
+++ b/exec.c
@@ -2386,6 +2386,10 @@ ram_addr_t qemu_ram_alloc(ram_addr_t size)
     }
     addr = phys_ram_alloc_offset;
     phys_ram_alloc_offset = TARGET_PAGE_ALIGN(phys_ram_alloc_offset + size);
+
+    if (kvm_enabled())
+        kvm_setup_guest_memory(phys_ram_base + addr, size);
+
     return addr;
 }
 
index 28c9c07ccbdc3fe3f560a8980529972572d28cef..2b7d5350304450ae884ec0dc23414a206de1fd6c 100644 (file)
--- a/kvm-all.c
+++ b/kvm-all.c
@@ -656,3 +656,21 @@ int kvm_has_sync_mmu(void)
 
     return 0;
 }
+
+void kvm_setup_guest_memory(void *start, size_t size)
+{
+    if (!kvm_has_sync_mmu()) {
+#ifdef MADV_DONTFORK
+        int ret = madvise(start, size, MADV_DONTFORK);
+
+        if (ret) {
+            perror("madvice");
+            exit(1);
+        }
+#else
+        fprintf(stderr,
+                "Need MADV_DONTFORK in absence of synchronous KVM MMU\n");
+        exit(1);
+#endif
+    }
+}
diff --git a/kvm.h b/kvm.h
index efce1450d598cda72d95cccc63c1237af0e0b237..5a52f51cb909a1f4b61de08bbeff38af668b7736 100644 (file)
--- a/kvm.h
+++ b/kvm.h
@@ -46,6 +46,8 @@ int kvm_log_stop(target_phys_addr_t phys_addr, target_phys_addr_t len);
 
 int kvm_has_sync_mmu(void);
 
+void kvm_setup_guest_memory(void *start, size_t size);
+
 int kvm_coalesce_mmio_region(target_phys_addr_t start, ram_addr_t size);
 int kvm_uncoalesce_mmio_region(target_phys_addr_t start, ram_addr_t size);