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