From: Takuya Yoshikawa <takuya.yoshikawa@gmail.com>
To: Takuya Yoshikawa <takuya.yoshikawa@gmail.com>
Cc: linux-arch@vger.kernel.org, x86@kernel.org, arnd@arndb.de,
kvm@vger.kernel.org, kvm-ia64@vger.kernel.org,
fernando@oss.ntt.co.jp, mtosatti@redhat.com, agraf@suse.de,
kvm-ppc@vger.kernel.org, linux-kernel@vger.kernel.org,
yoshikawa.takuya@oss.ntt.co.jp, linuxppc-dev@ozlabs.org,
mingo@redhat.com, paulus@samba.org, avi@redhat.com,
hpa@zytor.com, tglx@linutronix.de
Subject: [RFC][PATCH 12/12 sample] qemu-kvm: use new API for getting/switching dirty bitmaps
Date: Tue, 4 May 2010 22:11:18 +0900 [thread overview]
Message-ID: <20100504221118.e4942f18.takuya.yoshikawa@gmail.com> (raw)
In-Reply-To: <20100504215645.6448af8f.takuya.yoshikawa@gmail.com>
We use new API for light dirty log access if KVM supports it.
This conflicts with Marcelo's patches. So please take this as a sample patch.
Signed-off-by: Takuya Yoshikawa <yoshikawa.takuya@oss.ntt.co.jp>
---
kvm/include/linux/kvm.h | 11 ++++++
qemu-kvm.c | 81 ++++++++++++++++++++++++++++++++++++++++++-----
qemu-kvm.h | 1 +
3 files changed, 85 insertions(+), 8 deletions(-)
diff --git a/kvm/include/linux/kvm.h b/kvm/include/linux/kvm.h
index 6485981..efd9538 100644
--- a/kvm/include/linux/kvm.h
+++ b/kvm/include/linux/kvm.h
@@ -317,6 +317,14 @@ struct kvm_dirty_log {
};
};
+/* for KVM_GET_USER_DIRTY_LOG_ADDR */
+struct kvm_user_dirty_log {
+ __u32 slot;
+ __u32 flags;
+ __u64 dirty_bitmap;
+ __u64 dirty_bitmap_old;
+};
+
/* for KVM_SET_SIGNAL_MASK */
struct kvm_signal_mask {
__u32 len;
@@ -499,6 +507,7 @@ struct kvm_ioeventfd {
#define KVM_CAP_PPC_SEGSTATE 43
#define KVM_CAP_PCI_SEGMENT 47
+#define KVM_CAP_USER_DIRTY_LOG 55
#ifdef KVM_CAP_IRQ_ROUTING
@@ -595,6 +604,8 @@ struct kvm_clock_data {
struct kvm_userspace_memory_region)
#define KVM_SET_TSS_ADDR _IO(KVMIO, 0x47)
#define KVM_SET_IDENTITY_MAP_ADDR _IOW(KVMIO, 0x48, __u64)
+#define KVM_GET_USER_DIRTY_LOG_ADDR _IOW(KVMIO, 0x49, struct kvm_user_dirty_log)
+#define KVM_SWITCH_DIRTY_LOG _IO(KVMIO, 0x4a)
/* Device model IOC */
#define KVM_CREATE_IRQCHIP _IO(KVMIO, 0x60)
#define KVM_IRQ_LINE _IOW(KVMIO, 0x61, struct kvm_irq_level)
diff --git a/qemu-kvm.c b/qemu-kvm.c
index 91f0222..98777f0 100644
--- a/qemu-kvm.c
+++ b/qemu-kvm.c
@@ -143,6 +143,8 @@ struct slot_info {
unsigned long userspace_addr;
unsigned flags;
int logging_count;
+ unsigned long *dirty_bitmap;
+ unsigned long *dirty_bitmap_old;
};
struct slot_info slots[KVM_MAX_NUM_MEM_REGIONS];
@@ -232,6 +234,29 @@ int kvm_is_containing_region(kvm_context_t kvm, unsigned long phys_addr,
return 1;
}
+static int kvm_user_dirty_log_works(void)
+{
+ return kvm_state->user_dirty_log;
+}
+
+static int kvm_set_user_dirty_log(int slot)
+{
+ int r;
+ struct kvm_user_dirty_log dlog;
+
+ dlog.slot = slot;
+ r = kvm_vm_ioctl(kvm_state, KVM_GET_USER_DIRTY_LOG_ADDR, &dlog);
+ if (r < 0) {
+ DPRINTF("KVM_GET_USER_DIRTY_LOG_ADDR failed: %s\n", strerror(-r));
+ return r;
+ }
+ slots[slot].dirty_bitmap = (unsigned long *)
+ ((unsigned long)dlog.dirty_bitmap);
+ slots[slot].dirty_bitmap_old = (unsigned long *)
+ ((unsigned long)dlog.dirty_bitmap_old);
+ return r;
+}
+
/*
* dirty pages logging control
*/
@@ -265,8 +290,16 @@ static int kvm_dirty_pages_log_change(kvm_context_t kvm,
DPRINTF("slot %d start %llx len %llx flags %x\n",
mem.slot, mem.guest_phys_addr, mem.memory_size, mem.flags);
r = kvm_vm_ioctl(kvm_state, KVM_SET_USER_MEMORY_REGION, &mem);
- if (r < 0)
+ if (r < 0) {
fprintf(stderr, "%s: %m\n", __FUNCTION__);
+ return r;
+ }
+ }
+ if (flags & KVM_MEM_LOG_DIRTY_PAGES) {
+ r = kvm_set_user_dirty_log(slot);
+ } else {
+ slots[slot].dirty_bitmap = NULL;
+ slots[slot].dirty_bitmap_old = NULL;
}
return r;
}
@@ -589,7 +622,6 @@ int kvm_register_phys_mem(kvm_context_t kvm,
unsigned long phys_start, void *userspace_addr,
unsigned long len, int log)
{
-
struct kvm_userspace_memory_region memory = {
.memory_size = len,
.guest_phys_addr = phys_start,
@@ -608,6 +640,9 @@ int kvm_register_phys_mem(kvm_context_t kvm,
fprintf(stderr, "create_userspace_phys_mem: %s\n", strerror(-r));
return -1;
}
+ if (log) {
+ r = kvm_set_user_dirty_log(memory.slot);
+ }
register_slot(memory.slot, memory.guest_phys_addr, memory.memory_size,
memory.userspace_addr, memory.flags);
return 0;
@@ -652,6 +687,8 @@ void kvm_destroy_phys_mem(kvm_context_t kvm, unsigned long phys_start,
fprintf(stderr, "destroy_userspace_phys_mem: %s", strerror(-r));
return;
}
+ slots[memory.slot].dirty_bitmap = NULL;
+ slots[memory.slot].dirty_bitmap_old = NULL;
free_slot(memory.slot);
}
@@ -692,6 +729,21 @@ int kvm_get_dirty_pages(kvm_context_t kvm, unsigned long phys_addr, void *buf)
return kvm_get_map(kvm, KVM_GET_DIRTY_LOG, slot, buf);
}
+static int kvm_switch_map(int slot)
+{
+ int r;
+
+ r = kvm_vm_ioctl(kvm_state, KVM_SWITCH_DIRTY_LOG, slot);
+ if (r == 0) {
+ unsigned long *dirty_bitmap;
+
+ dirty_bitmap = slots[slot].dirty_bitmap;
+ slots[slot].dirty_bitmap = slots[slot].dirty_bitmap_old;
+ slots[slot].dirty_bitmap_old = dirty_bitmap;
+ }
+ return r;
+}
+
int kvm_get_dirty_pages_range(kvm_context_t kvm, unsigned long phys_addr,
unsigned long len, void *opaque,
int (*cb)(unsigned long start,
@@ -706,14 +758,25 @@ 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);
- if (r) {
+ if (kvm_user_dirty_log_works()) {
+ r = kvm_switch_map(i);
+ if (r == 1) { /* slot was clean */
+ continue;
+ } else if (r < 0) {
+ return r;
+ }
+ r = cb(slots[i].phys_addr, slots[i].len,
+ slots[i].dirty_bitmap_old, opaque);
+ } else {
+ buf = qemu_malloc(BITMAP_SIZE(slots[i].len));
+ r = kvm_get_map(kvm, KVM_GET_DIRTY_LOG, i, buf);
+ if (r) {
+ qemu_free(buf);
+ return r;
+ }
+ r = cb(slots[i].phys_addr, slots[i].len, buf, opaque);
qemu_free(buf);
- return r;
}
- r = cb(slots[i].phys_addr, slots[i].len, buf, opaque);
- qemu_free(buf);
if (r)
return r;
}
@@ -2097,6 +2160,8 @@ static int kvm_create_context(void)
#ifdef TARGET_I386
destroy_region_works = kvm_destroy_memory_region_works(kvm_context);
#endif
+ kvm_state->user_dirty_log
+ = kvm_check_extension(kvm_state, KVM_CAP_USER_DIRTY_LOG);
r = kvm_arch_init_irq_routing();
if (r < 0) {
diff --git a/qemu-kvm.h b/qemu-kvm.h
index ba3808a..aea89df 100644
--- a/qemu-kvm.h
+++ b/qemu-kvm.h
@@ -973,6 +973,7 @@ struct KVMState {
#endif
int irqchip_in_kernel;
int pit_in_kernel;
+ int user_dirty_log;
struct kvm_context kvm_context;
};
--
1.7.0.4
next prev parent reply other threads:[~2010-05-04 13:11 UTC|newest]
Thread overview: 36+ messages / expand[flat|nested] mbox.gz Atom feed top
2010-05-04 12:56 [RFC][PATCH 0/12] KVM, x86, ppc, asm-generic: moving dirty bitmaps to user space Takuya Yoshikawa
2010-05-04 12:58 ` [RFC][PATCH 1/12 applied today] KVM: x86: avoid unnecessary bitmap allocation when memslot is clean Takuya Yoshikawa
2010-05-04 13:00 ` [RFC][PATCH 2/12] KVM: introduce slot level dirty state management Takuya Yoshikawa
2010-05-04 13:01 ` [RFC][PATCH 3/12] KVM: introduce wrapper functions to create and destroy dirty bitmaps Takuya Yoshikawa
2010-05-04 13:02 ` [RFC][PATCH 4/12] x86: introduce copy_in_user() for 32-bit Takuya Yoshikawa
2010-05-04 13:02 ` [RFC][PATCH 5/12] x86: introduce __set_bit() like function for bitmaps in user space Takuya Yoshikawa
2010-05-04 13:03 ` [RFC][PATCH 6/12 not tested yet] PPC: introduce copy_in_user() for 32-bit Takuya Yoshikawa
2010-05-04 13:04 ` [RFC][PATCH 7/12 not tested yet] PPC: introduce __set_bit() like function for bitmaps in user space Takuya Yoshikawa
2010-05-11 16:00 ` Alexander Graf
2010-05-12 9:25 ` Takuya Yoshikawa
2010-05-04 13:05 ` [RFC][PATCH resend 8/12] asm-generic: bitops: introduce le bit offset macro Takuya Yoshikawa
2010-05-04 15:03 ` Arnd Bergmann
2010-05-04 16:08 ` Avi Kivity
2010-05-05 2:59 ` Takuya Yoshikawa
2010-05-06 13:38 ` Arnd Bergmann
2010-05-10 11:46 ` Takuya Yoshikawa
2010-05-10 12:01 ` Avi Kivity
2010-05-10 12:01 ` Arnd Bergmann
2010-05-10 12:09 ` Takuya Yoshikawa
2010-05-04 13:06 ` [RFC][PATCH 9/12] KVM: introduce a wrapper function of set_bit_user_non_atomic() Takuya Yoshikawa
2010-05-04 13:07 ` [RFC][PATCH RFC 10/12] KVM: move dirty bitmaps to user space Takuya Yoshikawa
2010-05-11 3:28 ` Marcelo Tosatti
2010-05-12 6:27 ` Takuya Yoshikawa
2010-05-04 13:08 ` [RFC][PATCH 11/12] KVM: introduce new API for getting/switching dirty bitmaps Takuya Yoshikawa
2010-05-11 3:43 ` Marcelo Tosatti
2010-05-11 5:53 ` Takuya Yoshikawa
2010-05-11 14:07 ` Marcelo Tosatti
2010-05-12 6:03 ` Takuya Yoshikawa
2010-05-04 13:11 ` Takuya Yoshikawa [this message]
2010-05-10 12:06 ` [RFC][PATCH 0/12] KVM, x86, ppc, asm-generic: moving dirty bitmaps to user space Avi Kivity
2010-05-10 12:26 ` Takuya Yoshikawa
2010-05-11 10:11 ` Takuya Yoshikawa
2010-05-13 11:47 ` Avi Kivity
2010-05-17 9:06 ` Takuya Yoshikawa
2010-05-11 15:55 ` Alexander Graf
2010-05-12 9:19 ` Takuya Yoshikawa
Reply instructions:
You may reply publicly to this message via plain-text email
using any one of the following methods:
* Save the following mbox file, import it into your mail client,
and reply-to-all from there: mbox
Avoid top-posting and favor interleaved quoting:
https://en.wikipedia.org/wiki/Posting_style#Interleaved_style
* Reply using the --to, --cc, and --in-reply-to
switches of git-send-email(1):
git send-email \
--in-reply-to=20100504221118.e4942f18.takuya.yoshikawa@gmail.com \
--to=takuya.yoshikawa@gmail.com \
--cc=agraf@suse.de \
--cc=arnd@arndb.de \
--cc=avi@redhat.com \
--cc=fernando@oss.ntt.co.jp \
--cc=hpa@zytor.com \
--cc=kvm-ia64@vger.kernel.org \
--cc=kvm-ppc@vger.kernel.org \
--cc=kvm@vger.kernel.org \
--cc=linux-arch@vger.kernel.org \
--cc=linux-kernel@vger.kernel.org \
--cc=linuxppc-dev@ozlabs.org \
--cc=mingo@redhat.com \
--cc=mtosatti@redhat.com \
--cc=paulus@samba.org \
--cc=tglx@linutronix.de \
--cc=x86@kernel.org \
--cc=yoshikawa.takuya@oss.ntt.co.jp \
/path/to/YOUR_REPLY
https://kernel.org/pub/software/scm/git/docs/git-send-email.html
* If your mail client supports setting the In-Reply-To header
via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line
before the message body.
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox;
as well as URLs for NNTP newsgroup(s).