This patch introduces in libkvm the common part of MMIO batching interface.

It checks the MMIO batching availability with ioctl(KVM_CHECK_EXTENSION).
If KVM_CAP_DELAYED_MMIO is available, it processes the MMIO ring buffer
at the return of ioctl(KVM_RUN).
It defines kvm_register_delayed_mmio() to register a delayed MMIO zone, and 
kvm_unregister_delayed_mmio() to unregister it.

Signed-off-by: Laurent Vivier <[EMAIL PROTECTED]>
---
 libkvm/kvm-common.h |    2 +
 libkvm/libkvm.c     |   73 +++++++++++++++++++++++++++++++++++++++++++++++++++
 libkvm/libkvm.h     |    2 +
 3 files changed, 77 insertions(+), 0 deletions(-)

diff --git a/libkvm/kvm-common.h b/libkvm/kvm-common.h
index a3549e2..f975d56 100644
--- a/libkvm/kvm-common.h
+++ b/libkvm/kvm-common.h
@@ -49,6 +49,8 @@ struct kvm_context {
        int no_pit_creation;
        /// in-kernel pit status
        int pit_in_kernel;
+       /// in-kernel delayed mmio
+       int delayed_mmio;
 };
 
 void init_slots(void);
diff --git a/libkvm/libkvm.c b/libkvm/libkvm.c
index d1e95a4..718f4c6 100644
--- a/libkvm/libkvm.c
+++ b/libkvm/libkvm.c
@@ -879,6 +879,20 @@ again:
 
        post_kvm_run(kvm, vcpu);
 
+#if defined(KVM_CAP_DELAYED_MMIO)
+       if (kvm->delayed_mmio) {
+               struct kvm_batch *batch = (void *)run +
+                                         kvm->delayed_mmio * PAGE_SIZE;
+               while (batch->first != batch->last) {
+                       kvm->callbacks->mmio_write(kvm->opaque,
+                                           batch->mmio[batch->first].phys_addr,
+                                          &batch->mmio[batch->first].data[0],
+                                           batch->mmio[batch->first].len);
+                       batch->first = (batch->first + 1) % KVM_MAX_BATCH;
+               }
+       }
+#endif
+
        if (r == -1) {
                r = handle_io_window(kvm);
                goto more;
@@ -983,3 +997,62 @@ int kvm_pit_in_kernel(kvm_context_t kvm)
 {
        return kvm->pit_in_kernel;
 }
+
+int kvm_init_delayed_mmio(kvm_context_t kvm)
+{
+       int r = 0;
+       kvm->delayed_mmio = 0;
+#ifdef KVM_CAP_DELAYED_MMIO
+       r = ioctl(kvm->fd, KVM_CHECK_EXTENSION, KVM_CAP_DELAYED_MMIO);
+       if (r > 0) {
+               kvm->delayed_mmio = r;
+               return 0;
+       }
+#endif
+       return r;
+}
+
+int kvm_register_delayed_mmio(kvm_context_t kvm, uint64_t addr, uint32_t size)
+{
+#ifdef KVM_CAP_DELAYED_MMIO
+       struct kvm_delayed_mmio_zone zone;
+       int r;
+
+       if (kvm->delayed_mmio) {
+
+               zone.addr = addr;
+               zone.size = size;
+
+               r = ioctl(kvm->vm_fd, KVM_REGISTER_DELAYED_MMIO, &zone);
+               if (r == -1) {
+                       perror("kvm_register_delayed_mmio_zone");
+                       return -errno;
+               }
+               return 0;
+       }
+#endif
+       return -1;
+}
+
+int kvm_unregister_delayed_mmio(kvm_context_t kvm, uint64_t addr, uint32_t 
size)
+{
+#ifdef KVM_CAP_DELAYED_MMIO
+       struct kvm_delayed_mmio_zone zone;
+       int r;
+
+       if (kvm->delayed_mmio) {
+
+               zone.addr = addr;
+               zone.size = size;
+
+               r = ioctl(kvm->vm_fd, KVM_UNREGISTER_DELAYED_MMIO, &zone);
+               if (r == -1) {
+                       perror("kvm_unregister_delayed_mmio_zone");
+                       return -errno;
+               }
+               return 0;
+       }
+#endif
+       return -1;
+}
+
diff --git a/libkvm/libkvm.h b/libkvm/libkvm.h
index 63183b8..dfb615a 100644
--- a/libkvm/libkvm.h
+++ b/libkvm/libkvm.h
@@ -457,6 +457,8 @@ int kvm_get_dirty_pages_range(kvm_context_t kvm, unsigned 
long phys_addr,
                              unsigned long end_addr, void *buf, void*opaque,
                              int (*cb)(unsigned long start, unsigned long len,
                                        void*bitmap, void *opaque));
+int kvm_register_delayed_mmio(kvm_context_t kvm, uint64_t addr, uint32_t size);
+int kvm_unregister_delayed_mmio(kvm_context_t kvm, uint64_t addr, uint32_t 
size);
 
 /*!
  * \brief Create a memory alias
-- 
1.5.2.4

--
To unsubscribe from this list: send the line "unsubscribe kvm" in
the body of a message to [EMAIL PROTECTED]
More majordomo info at  http://vger.kernel.org/majordomo-info.html

Reply via email to