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