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

It checks the coalesced MMIO availability with ioctl(KVM_CHECK_EXTENSION).
If KVM_CAP_COALESCED_MMIO is available, it processes the MMIO ring buffer
at the return of ioctl(KVM_RUN).
It defines kvm_register_coalesced_mmio() to register a coalesced MMIO zone, and 
kvm_unregister_coalesced_mmio() to unregister it.

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

diff --git a/libkvm/kvm-common.h b/libkvm/kvm-common.h
index a3549e2..9780fb8 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 coalesced mmio
+       int coalesced_mmio;
 };
 
 void init_slots(void);
diff --git a/libkvm/libkvm.c b/libkvm/libkvm.c
index d1e95a4..1e7bbed 100644
--- a/libkvm/libkvm.c
+++ b/libkvm/libkvm.c
@@ -879,6 +879,22 @@ again:
 
        post_kvm_run(kvm, vcpu);
 
+#if defined(KVM_CAP_COALESCED_MMIO)
+       if (kvm->coalesced_mmio) {
+               struct kvm_coalesced_mmio_ring *ring = (void *)run +
+                                               kvm->coalesced_mmio * PAGE_SIZE;
+               while (ring->first != ring->last) {
+                       kvm->callbacks->mmio_write(kvm->opaque,
+                                ring->coalesced_mmio[ring->first].phys_addr,
+                               &ring->coalesced_mmio[ring->first].data[0],
+                                ring->coalesced_mmio[ring->first].len);
+                       smp_wmb();
+                       ring->first = (ring->first + 1) %
+                                                       KVM_COALESCED_MMIO_MAX;
+               }
+       }
+#endif
+
        if (r == -1) {
                r = handle_io_window(kvm);
                goto more;
@@ -983,3 +999,62 @@ int kvm_pit_in_kernel(kvm_context_t kvm)
 {
        return kvm->pit_in_kernel;
 }
+
+int kvm_init_coalesced_mmio(kvm_context_t kvm)
+{
+       int r = 0;
+       kvm->coalesced_mmio = 0;
+#ifdef KVM_CAP_COALESCED_MMIO
+       r = ioctl(kvm->fd, KVM_CHECK_EXTENSION, KVM_CAP_COALESCED_MMIO);
+       if (r > 0) {
+               kvm->coalesced_mmio = r;
+               return 0;
+       }
+#endif
+       return r;
+}
+
+int kvm_register_coalesced_mmio(kvm_context_t kvm, uint64_t addr, uint32_t 
size)
+{
+#ifdef KVM_CAP_COALESCED_MMIO
+       struct kvm_coalesced_mmio_zone zone;
+       int r;
+
+       if (kvm->coalesced_mmio) {
+
+               zone.addr = addr;
+               zone.size = size;
+
+               r = ioctl(kvm->vm_fd, KVM_REGISTER_COALESCED_MMIO, &zone);
+               if (r == -1) {
+                       perror("kvm_register_coalesced_mmio_zone");
+                       return -errno;
+               }
+               return 0;
+       }
+#endif
+       return -ENOSYS;
+}
+
+int kvm_unregister_coalesced_mmio(kvm_context_t kvm, uint64_t addr, uint32_t 
size)
+{
+#ifdef KVM_CAP_COALESCED_MMIO
+       struct kvm_coalesced_mmio_zone zone;
+       int r;
+
+       if (kvm->coalesced_mmio) {
+
+               zone.addr = addr;
+               zone.size = size;
+
+               r = ioctl(kvm->vm_fd, KVM_UNREGISTER_COALESCED_MMIO, &zone);
+               if (r == -1) {
+                       perror("kvm_unregister_coalesced_mmio_zone");
+                       return -errno;
+               }
+               return 0;
+       }
+#endif
+       return -ENOSYS;
+}
+
diff --git a/libkvm/libkvm.h b/libkvm/libkvm.h
index 63183b8..a33e9db 100644
--- a/libkvm/libkvm.h
+++ b/libkvm/libkvm.h
@@ -457,6 +457,10 @@ 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_coalesced_mmio(kvm_context_t kvm,
+                               uint64_t addr, uint32_t size);
+int kvm_unregister_coalesced_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