By analysing phys_offset, we know whether a region is an mmio region
or not. If it is, register it as so. We don't reuse the same slot
infrastructure already existant, because there is a relationship between
the slot number for kvm the kernel module, and the index in the slots vector
for libkvm. However, we can do best in the future and use only a single data 
structure
for both.

Signed-off-by: Glauber Costa <[EMAIL PROTECTED]>
---
 libkvm/libkvm.c |   70 +++++++++++++++++++++++++++++++++++++++++++++++++++---
 qemu/qemu-kvm.c |   12 ++++++++-
 2 files changed, 76 insertions(+), 6 deletions(-)

diff --git a/libkvm/libkvm.c b/libkvm/libkvm.c
index 6ebdc52..dbc1b62 100644
--- a/libkvm/libkvm.c
+++ b/libkvm/libkvm.c
@@ -64,14 +64,22 @@ struct slot_info {
        unsigned flags;
 };
 
+struct mmio_slot_info {
+    uint64_t phys_addr;
+    unsigned int len;
+};
+
 struct slot_info slots[KVM_MAX_NUM_MEM_REGIONS];
+struct mmio_slot_info mmio_slots[KVM_MAX_NUM_MEM_REGIONS];
 
 void init_slots(void)
 {
        int i;
 
-       for (i = 0; i < KVM_MAX_NUM_MEM_REGIONS; ++i)
+       for (i = 0; i < KVM_MAX_NUM_MEM_REGIONS; ++i) {
                slots[i].len = 0;
+               mmio_slots[i].len = 0;
+       }
 }
 
 int get_free_slot(kvm_context_t kvm)
@@ -101,6 +109,16 @@ int get_free_slot(kvm_context_t kvm)
        return -1;
 }
 
+int get_free_mmio_slot(kvm_context_t kvm)
+{
+
+       unsigned int i;
+       for (i = 0; i < KVM_MAX_NUM_MEM_REGIONS; ++i)
+               if (!mmio_slots[i].len)
+                       return i;
+       return -1;
+}
+
 void register_slot(int slot, unsigned long phys_addr, unsigned long len,
                   unsigned long userspace_addr, unsigned flags)
 {
@@ -151,14 +169,47 @@ int get_container_slot(uint64_t phys_addr, unsigned long 
size)
        return -1;
 }
 
+int get_container_mmio_slot(kvm_context_t kvm, uint64_t phys_addr, unsigned 
long size)
+{
+       int i;
+
+       for (i = 0; i < KVM_MAX_NUM_MEM_REGIONS ; ++i)
+               if (mmio_slots[i].len && mmio_slots[i].phys_addr <= phys_addr &&
+                   (mmio_slots[i].phys_addr + mmio_slots[i].len) >= phys_addr 
+ size)
+                       return i;
+       return -1;
+}
+
+int kvm_register_mmio_slot(kvm_context_t kvm, uint64_t phys_addr, unsigned int 
size)
+{
+       int slot = get_free_mmio_slot(kvm);
+
+       if (slot == -1)
+               goto out;
+
+#ifdef DEBUG_MEMREG
+       fprintf(stderr, "Registering mmio region %llx (%lx)\n", phys_addr, 
size);
+#endif
+       mmio_slots[slot].phys_addr = phys_addr;
+       mmio_slots[slot].len = size;
+out:
+       return slot;
+}
+
 int kvm_is_containing_region(kvm_context_t kvm, unsigned long phys_addr, 
unsigned long size)
 {
        int slot = get_container_slot(phys_addr, size);
-       if (slot == -1)
-               return 0;
-       return 1;
+
+       if (slot != -1)
+               return 1;
+       slot = get_container_mmio_slot(kvm, phys_addr, size);
+       if (slot != -1)
+               return 1;
+
+       return 0;
 }
 
+
 /* 
  * dirty pages logging control 
  */
@@ -528,6 +579,17 @@ void kvm_unregister_memory_area(kvm_context_t kvm, 
uint64_t phys_addr, unsigned
                kvm_destroy_phys_mem(kvm, phys_addr, size);
                return;
        }
+
+       slot = get_container_mmio_slot(kvm, phys_addr, size);
+       if (slot != -1) {
+#ifdef DEBUG_MEMREG
+               fprintf(stderr, "Unregistering mmio region %llx (%lx)\n", 
phys_addr, size);
+#endif
+               kvm_unregister_coalesced_mmio(kvm, phys_addr, size);
+               mmio_slots[slot].len = 0;
+       }
+
+       return;
 }
 
 static int kvm_get_map(kvm_context_t kvm, int ioctl_num, int slot, void *buf)
diff --git a/qemu/qemu-kvm.c b/qemu/qemu-kvm.c
index d9fb499..721a9dc 100644
--- a/qemu/qemu-kvm.c
+++ b/qemu/qemu-kvm.c
@@ -788,6 +788,16 @@ void kvm_cpu_register_physical_memory(target_phys_addr_t 
start_addr,
     r = kvm_is_containing_region(kvm_context, start_addr, size);
     if (r)
         return;
+
+    if (area_flags >= TLB_MMIO) {
+        r = kvm_register_mmio_slot(kvm_context, start_addr, size);
+        if (r < 0) {
+            printf("No free mmio slots\n");
+            exit(1);
+        }
+        return;
+    }
+
     r = kvm_is_intersecting_mem(kvm_context, start_addr);
     if (r) {
         printf("Ignoring intersecting memory %llx (%lx)\n", start_addr, size);
@@ -1032,11 +1042,9 @@ void kvm_mutex_lock(void)
 
 int qemu_kvm_register_coalesced_mmio(target_phys_addr_t addr, unsigned int 
size)
 {
-    return kvm_register_coalesced_mmio(kvm_context, addr, size);
 }
 
 int qemu_kvm_unregister_coalesced_mmio(target_phys_addr_t addr,
                                       unsigned int size)
 {
-    return kvm_unregister_coalesced_mmio(kvm_context, addr, size);
 }
-- 
1.5.5.1

--
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