===
Appendix:
To test the patch 6, we are using the following patch for qemu-kvm.
---
configure | 2 +-
qemu-kvm.c | 22 +++++++++++++++++-----
2 files changed, 18 insertions(+), 6 deletions(-)
@@ -1498,7 +1498,7 @@ fi
if test "$kvm" != "no" ; then
cat > $TMPC <<EOF
#include <linux/kvm.h>
-#if !defined(KVM_API_VERSION) || KVM_API_VERSION < 12 || KVM_API_VERSION > 12
+#if !defined(KVM_API_VERSION) || KVM_API_VERSION < 13 || KVM_API_VERSION > 13
#error Invalid KVM version
#endif
#if !defined(KVM_CAP_USER_MEMORY)
@@ -44,7 +44,7 @@
#define BUS_MCEERR_AO 5
#endif
-#define EXPECTED_KVM_API_VERSION 12
+#define EXPECTED_KVM_API_VERSION 13
#if EXPECTED_KVM_API_VERSION != KVM_API_VERSION
#error libkvm: userspace and kernel version mismatch
@@ -684,6 +684,21 @@ static int kvm_get_map(kvm_context_t kvm, int ioctl_num, int slot, void *buf)
return 0;
}
+static int kvm_switch_map(kvm_context_t kvm, int slot, void **buf)
+{
+ int r;
+ struct kvm_dirty_log log = {
+ .slot = slot,
+ };
+
+ r = kvm_vm_ioctl(kvm_state, KVM_SWITCH_DIRTY_LOG, &log);
+ if (r < 0)
+ return r;
+
+ *buf = (void *)log.addr;
+ return 0;
+}
+
int kvm_get_dirty_pages(kvm_context_t kvm, unsigned long phys_addr, void *buf)
{
int slot;
@@ -706,14 +721,11 @@ int kvm_get_dirty_pages_range(kvm_context_t kvm, unsigned long phys_addr,
for (i = 0; i < KVM_MAX_NUM_MEM_REGIONS; ++i) {
if ((slots[i].len && (uint64_t) slots[i].phys_addr >= phys_addr)
&& ((uint64_t) slots[i].phys_addr + slots[i].len <= end_addr)) {
- buf = qemu_malloc(BITMAP_SIZE(slots[i].len));
- r = kvm_get_map(kvm, KVM_GET_DIRTY_LOG, i, buf);
+ r = kvm_switch_map(kvm, i, &buf);
if (r) {
- qemu_free(buf);
return r;
}
r = cb(slots[i].phys_addr, slots[i].len, buf, opaque);
- qemu_free(buf);
if (r)
return r;
}