From d22b096ef6e0b20810193b68a1d472f3fb8a4f9e Mon Sep 17 00:00:00 2001 From: Avi Kivity Date: Sun, 30 Sep 2012 22:21:11 +0200 Subject: kvm: use separate MemoryListeners for memory and I/O The construct if (address_space == get_system_memory()) { // memory thing } else { // io thing } fails if we have more than two address spaces. Use a separate listener for memory and I/O, and utilize MemoryListener's address space filtering to fix this. Signed-off-by: Avi Kivity --- kvm-all.c | 83 +++++++++++++++++++++++++++++++++------------------------------ 1 file changed, 44 insertions(+), 39 deletions(-) (limited to 'kvm-all.c') diff --git a/kvm-all.c b/kvm-all.c index 92a71374ed..c69e012004 100644 --- a/kvm-all.c +++ b/kvm-all.c @@ -755,9 +755,16 @@ static void kvm_log_global_stop(struct MemoryListener *listener) assert(r >= 0); } -static void kvm_mem_ioeventfd_add(MemoryRegionSection *section, - bool match_data, uint64_t data, int fd) +static void kvm_log_nop(struct MemoryListener *listener) { +} + +static void kvm_mem_ioeventfd_add(MemoryListener *listener, + MemoryRegionSection *section, + bool match_data, uint64_t data, + EventNotifier *e) +{ + int fd = event_notifier_get_fd(e); int r; assert(match_data && section->size <= 8); @@ -769,9 +776,12 @@ static void kvm_mem_ioeventfd_add(MemoryRegionSection *section, } } -static void kvm_mem_ioeventfd_del(MemoryRegionSection *section, - bool match_data, uint64_t data, int fd) +static void kvm_mem_ioeventfd_del(MemoryListener *listener, + MemoryRegionSection *section, + bool match_data, uint64_t data, + EventNotifier *e) { + int fd = event_notifier_get_fd(e); int r; r = kvm_set_ioeventfd_mmio(fd, section->offset_within_address_space, @@ -781,9 +791,12 @@ static void kvm_mem_ioeventfd_del(MemoryRegionSection *section, } } -static void kvm_io_ioeventfd_add(MemoryRegionSection *section, - bool match_data, uint64_t data, int fd) +static void kvm_io_ioeventfd_add(MemoryListener *listener, + MemoryRegionSection *section, + bool match_data, uint64_t data, + EventNotifier *e) { + int fd = event_notifier_get_fd(e); int r; assert(match_data && section->size == 2); @@ -795,10 +808,13 @@ static void kvm_io_ioeventfd_add(MemoryRegionSection *section, } } -static void kvm_io_ioeventfd_del(MemoryRegionSection *section, - bool match_data, uint64_t data, int fd) +static void kvm_io_ioeventfd_del(MemoryListener *listener, + MemoryRegionSection *section, + bool match_data, uint64_t data, + EventNotifier *e) { + int fd = event_notifier_get_fd(e); int r; r = kvm_set_ioeventfd_pio_word(fd, section->offset_within_address_space, @@ -808,34 +824,6 @@ static void kvm_io_ioeventfd_del(MemoryRegionSection *section, } } -static void kvm_eventfd_add(MemoryListener *listener, - MemoryRegionSection *section, - bool match_data, uint64_t data, - EventNotifier *e) -{ - if (section->address_space == get_system_memory()) { - kvm_mem_ioeventfd_add(section, match_data, data, - event_notifier_get_fd(e)); - } else { - kvm_io_ioeventfd_add(section, match_data, data, - event_notifier_get_fd(e)); - } -} - -static void kvm_eventfd_del(MemoryListener *listener, - MemoryRegionSection *section, - bool match_data, uint64_t data, - EventNotifier *e) -{ - if (section->address_space == get_system_memory()) { - kvm_mem_ioeventfd_del(section, match_data, data, - event_notifier_get_fd(e)); - } else { - kvm_io_ioeventfd_del(section, match_data, data, - event_notifier_get_fd(e)); - } -} - static MemoryListener kvm_memory_listener = { .begin = kvm_begin, .commit = kvm_commit, @@ -847,8 +835,24 @@ static MemoryListener kvm_memory_listener = { .log_sync = kvm_log_sync, .log_global_start = kvm_log_global_start, .log_global_stop = kvm_log_global_stop, - .eventfd_add = kvm_eventfd_add, - .eventfd_del = kvm_eventfd_del, + .eventfd_add = kvm_mem_ioeventfd_add, + .eventfd_del = kvm_mem_ioeventfd_del, + .priority = 10, +}; + +static MemoryListener kvm_io_listener = { + .begin = kvm_begin, + .commit = kvm_commit, + .region_add = kvm_region_nop, + .region_del = kvm_region_nop, + .region_nop = kvm_region_nop, + .log_start = kvm_region_nop, + .log_stop = kvm_region_nop, + .log_sync = kvm_region_nop, + .log_global_start = kvm_log_nop, + .log_global_stop = kvm_log_nop, + .eventfd_add = kvm_io_ioeventfd_add, + .eventfd_del = kvm_io_ioeventfd_del, .priority = 10, }; @@ -1401,7 +1405,8 @@ int kvm_init(void) } kvm_state = s; - memory_listener_register(&kvm_memory_listener, NULL); + memory_listener_register(&kvm_memory_listener, get_system_memory()); + memory_listener_register(&kvm_io_listener, get_system_io()); s->many_ioeventfds = kvm_check_many_ioeventfds(); -- cgit 1.4.1 From ad1ff3d99a55f559e00a11de14d91ca33a139252 Mon Sep 17 00:00:00 2001 From: Avi Kivity Date: Tue, 2 Oct 2012 16:42:23 +0200 Subject: kvm: drop no-op MemoryListener callbacks Removes quite a bit of useless code. Signed-off-by: Avi Kivity --- kvm-all.c | 30 ------------------------------ 1 file changed, 30 deletions(-) (limited to 'kvm-all.c') diff --git a/kvm-all.c b/kvm-all.c index c69e012004..46cf7e9ec4 100644 --- a/kvm-all.c +++ b/kvm-all.c @@ -703,14 +703,6 @@ static void kvm_set_phys_mem(MemoryRegionSection *section, bool add) } } -static void kvm_begin(MemoryListener *listener) -{ -} - -static void kvm_commit(MemoryListener *listener) -{ -} - static void kvm_region_add(MemoryListener *listener, MemoryRegionSection *section) { @@ -723,11 +715,6 @@ static void kvm_region_del(MemoryListener *listener, kvm_set_phys_mem(section, false); } -static void kvm_region_nop(MemoryListener *listener, - MemoryRegionSection *section) -{ -} - static void kvm_log_sync(MemoryListener *listener, MemoryRegionSection *section) { @@ -755,10 +742,6 @@ static void kvm_log_global_stop(struct MemoryListener *listener) assert(r >= 0); } -static void kvm_log_nop(struct MemoryListener *listener) -{ -} - static void kvm_mem_ioeventfd_add(MemoryListener *listener, MemoryRegionSection *section, bool match_data, uint64_t data, @@ -825,11 +808,8 @@ static void kvm_io_ioeventfd_del(MemoryListener *listener, } static MemoryListener kvm_memory_listener = { - .begin = kvm_begin, - .commit = kvm_commit, .region_add = kvm_region_add, .region_del = kvm_region_del, - .region_nop = kvm_region_nop, .log_start = kvm_log_start, .log_stop = kvm_log_stop, .log_sync = kvm_log_sync, @@ -841,16 +821,6 @@ static MemoryListener kvm_memory_listener = { }; static MemoryListener kvm_io_listener = { - .begin = kvm_begin, - .commit = kvm_commit, - .region_add = kvm_region_nop, - .region_del = kvm_region_nop, - .region_nop = kvm_region_nop, - .log_start = kvm_region_nop, - .log_stop = kvm_region_nop, - .log_sync = kvm_region_nop, - .log_global_start = kvm_log_nop, - .log_global_stop = kvm_log_nop, .eventfd_add = kvm_io_ioeventfd_add, .eventfd_del = kvm_io_ioeventfd_del, .priority = 10, -- cgit 1.4.1 From 95d2994a2f756c9c8684709421d40c45e63e4e04 Mon Sep 17 00:00:00 2001 From: Avi Kivity Date: Tue, 2 Oct 2012 18:21:54 +0200 Subject: memory: manage coalesced mmio via a MemoryListener Instead of calling a global function on coalesced mmio changes, which routes the call to kvm if enabled, add coalesced mmio hooks to MemoryListener and make kvm use that instead. The motivation is support for multiple address spaces (which means we we need to filter the call on the right address space) but the result is cleaner as well. Signed-off-by: Avi Kivity --- exec.c | 13 ------------- kvm-all.c | 20 ++++++++++---------- kvm-stub.c | 10 ---------- kvm.h | 2 -- memory.c | 17 +++++++++++++---- memory.h | 4 ++++ 6 files changed, 27 insertions(+), 39 deletions(-) (limited to 'kvm-all.c') diff --git a/exec.c b/exec.c index 6558728d09..5d5d9e33c9 100644 --- a/exec.c +++ b/exec.c @@ -2305,19 +2305,6 @@ void cpu_register_physical_memory_log(MemoryRegionSection *section, } } - -void qemu_register_coalesced_mmio(target_phys_addr_t addr, ram_addr_t size) -{ - if (kvm_enabled()) - kvm_coalesce_mmio_region(addr, size); -} - -void qemu_unregister_coalesced_mmio(target_phys_addr_t addr, ram_addr_t size) -{ - if (kvm_enabled()) - kvm_uncoalesce_mmio_region(addr, size); -} - void qemu_flush_coalesced_mmio_buffer(void) { if (kvm_enabled()) diff --git a/kvm-all.c b/kvm-all.c index 46cf7e9ec4..677dd2d99f 100644 --- a/kvm-all.c +++ b/kvm-all.c @@ -454,9 +454,10 @@ static int kvm_physical_sync_dirty_bitmap(MemoryRegionSection *section) return ret; } -int kvm_coalesce_mmio_region(target_phys_addr_t start, ram_addr_t size) +static void kvm_coalesce_mmio_region(MemoryListener *listener, + MemoryRegionSection *secion, + target_phys_addr_t start, target_phys_addr_t size) { - int ret = -ENOSYS; KVMState *s = kvm_state; if (s->coalesced_mmio) { @@ -466,15 +467,14 @@ int kvm_coalesce_mmio_region(target_phys_addr_t start, ram_addr_t size) zone.size = size; zone.pad = 0; - ret = kvm_vm_ioctl(s, KVM_REGISTER_COALESCED_MMIO, &zone); + (void)kvm_vm_ioctl(s, KVM_REGISTER_COALESCED_MMIO, &zone); } - - return ret; } -int kvm_uncoalesce_mmio_region(target_phys_addr_t start, ram_addr_t size) +static void kvm_uncoalesce_mmio_region(MemoryListener *listener, + MemoryRegionSection *secion, + target_phys_addr_t start, target_phys_addr_t size) { - int ret = -ENOSYS; KVMState *s = kvm_state; if (s->coalesced_mmio) { @@ -484,10 +484,8 @@ int kvm_uncoalesce_mmio_region(target_phys_addr_t start, ram_addr_t size) zone.size = size; zone.pad = 0; - ret = kvm_vm_ioctl(s, KVM_UNREGISTER_COALESCED_MMIO, &zone); + (void)kvm_vm_ioctl(s, KVM_UNREGISTER_COALESCED_MMIO, &zone); } - - return ret; } int kvm_check_extension(KVMState *s, unsigned int extension) @@ -817,6 +815,8 @@ static MemoryListener kvm_memory_listener = { .log_global_stop = kvm_log_global_stop, .eventfd_add = kvm_mem_ioeventfd_add, .eventfd_del = kvm_mem_ioeventfd_del, + .coalesced_mmio_add = kvm_coalesce_mmio_region, + .coalesced_mmio_del = kvm_uncoalesce_mmio_region, .priority = 10, }; diff --git a/kvm-stub.c b/kvm-stub.c index 3c52eb5bc6..a3455e2203 100644 --- a/kvm-stub.c +++ b/kvm-stub.c @@ -29,16 +29,6 @@ int kvm_init_vcpu(CPUArchState *env) return -ENOSYS; } -int kvm_coalesce_mmio_region(target_phys_addr_t start, ram_addr_t size) -{ - return -ENOSYS; -} - -int kvm_uncoalesce_mmio_region(target_phys_addr_t start, ram_addr_t size) -{ - return -ENOSYS; -} - int kvm_init(void) { return -ENOSYS; diff --git a/kvm.h b/kvm.h index dea2998fd4..eefcb492f0 100644 --- a/kvm.h +++ b/kvm.h @@ -129,8 +129,6 @@ void *kvm_vmalloc(ram_addr_t size); void *kvm_arch_vmalloc(ram_addr_t size); void kvm_setup_guest_memory(void *start, size_t size); -int kvm_coalesce_mmio_region(target_phys_addr_t start, ram_addr_t size); -int kvm_uncoalesce_mmio_region(target_phys_addr_t start, ram_addr_t size); void kvm_flush_coalesced_mmio_buffer(void); #endif diff --git a/memory.c b/memory.c index 269af3f6b0..d829f67419 100644 --- a/memory.c +++ b/memory.c @@ -1136,11 +1136,19 @@ static void memory_region_update_coalesced_range_as(MemoryRegion *mr, AddressSpa FlatRange *fr; CoalescedMemoryRange *cmr; AddrRange tmp; + MemoryRegionSection section; FOR_EACH_FLAT_RANGE(fr, as->current_map) { if (fr->mr == mr) { - qemu_unregister_coalesced_mmio(int128_get64(fr->addr.start), - int128_get64(fr->addr.size)); + section = (MemoryRegionSection) { + .address_space = as->root, + .offset_within_address_space = int128_get64(fr->addr.start), + .size = int128_get64(fr->addr.size), + }; + + MEMORY_LISTENER_CALL(coalesced_mmio_del, Reverse, §ion, + int128_get64(fr->addr.start), + int128_get64(fr->addr.size)); QTAILQ_FOREACH(cmr, &mr->coalesced, link) { tmp = addrrange_shift(cmr->addr, int128_sub(fr->addr.start, @@ -1149,8 +1157,9 @@ static void memory_region_update_coalesced_range_as(MemoryRegion *mr, AddressSpa continue; } tmp = addrrange_intersection(tmp, fr->addr); - qemu_register_coalesced_mmio(int128_get64(tmp.start), - int128_get64(tmp.size)); + MEMORY_LISTENER_CALL(coalesced_mmio_add, Forward, §ion, + int128_get64(tmp.start), + int128_get64(tmp.size)); } } } diff --git a/memory.h b/memory.h index 46bc5e1cfd..64d2b341b6 100644 --- a/memory.h +++ b/memory.h @@ -217,6 +217,10 @@ struct MemoryListener { bool match_data, uint64_t data, EventNotifier *e); void (*eventfd_del)(MemoryListener *listener, MemoryRegionSection *section, bool match_data, uint64_t data, EventNotifier *e); + void (*coalesced_mmio_add)(MemoryListener *listener, MemoryRegionSection *section, + target_phys_addr_t addr, target_phys_addr_t len); + void (*coalesced_mmio_del)(MemoryListener *listener, MemoryRegionSection *section, + target_phys_addr_t addr, target_phys_addr_t len); /* Lower = earlier (during add), later (during del) */ unsigned priority; MemoryRegion *address_space_filter; -- cgit 1.4.1 From f6790af6bcfa35fa9ea3c565a0a2aed54337aef5 Mon Sep 17 00:00:00 2001 From: Avi Kivity Date: Tue, 2 Oct 2012 20:13:51 +0200 Subject: memory: use AddressSpace for MemoryListener filtering Using the AddressSpace type reduces confusion, as you can't accidentally supply the MemoryRegion you're interested in. Reviewed-by: Anthony Liguori Signed-off-by: Avi Kivity --- exec-memory.h | 3 +++ exec.c | 10 +++++----- hw/vfio_pci.c | 3 +-- hw/vhost.c | 2 +- hw/xen_pt.c | 4 ++-- kvm-all.c | 4 ++-- memory.c | 14 +++++++------- memory.h | 6 +++--- xen-all.c | 2 +- 9 files changed, 25 insertions(+), 23 deletions(-) (limited to 'kvm-all.c') diff --git a/exec-memory.h b/exec-memory.h index 6707e40b2f..ac1d07dfe4 100644 --- a/exec-memory.h +++ b/exec-memory.h @@ -33,6 +33,9 @@ MemoryRegion *get_system_memory(void); */ MemoryRegion *get_system_io(void); +extern AddressSpace address_space_memory; +extern AddressSpace address_space_io; + #endif #endif diff --git a/exec.c b/exec.c index 6a7ba0cea6..e732b5285e 100644 --- a/exec.c +++ b/exec.c @@ -116,8 +116,8 @@ RAMList ram_list = { .blocks = QLIST_HEAD_INITIALIZER(ram_list.blocks) }; static MemoryRegion *system_memory; static MemoryRegion *system_io; -static AddressSpace address_space_io; -static AddressSpace address_space_memory; +AddressSpace address_space_io; +AddressSpace address_space_memory; MemoryRegion io_mem_ram, io_mem_rom, io_mem_unassigned, io_mem_notdirty; static MemoryRegion io_mem_subpage_ram; @@ -3249,9 +3249,9 @@ static void memory_map_init(void) address_space_init(&address_space_io, system_io); address_space_io.name = "I/O"; - memory_listener_register(&core_memory_listener, system_memory); - memory_listener_register(&io_memory_listener, system_io); - memory_listener_register(&tcg_memory_listener, system_memory); + memory_listener_register(&core_memory_listener, &address_space_memory); + memory_listener_register(&io_memory_listener, &address_space_io); + memory_listener_register(&tcg_memory_listener, &address_space_memory); } MemoryRegion *get_system_memory(void) diff --git a/hw/vfio_pci.c b/hw/vfio_pci.c index 49e11e7db3..f5db4a8567 100644 --- a/hw/vfio_pci.c +++ b/hw/vfio_pci.c @@ -1507,8 +1507,7 @@ static int vfio_connect_container(VFIOGroup *group) container->iommu_data.listener = vfio_memory_listener; container->iommu_data.release = vfio_listener_release; - memory_listener_register(&container->iommu_data.listener, - get_system_memory()); + memory_listener_register(&container->iommu_data.listener, &address_space_memory); } else { error_report("vfio: No available IOMMU models\n"); g_free(container); diff --git a/hw/vhost.c b/hw/vhost.c index 100f7659a0..0b4ac3f1df 100644 --- a/hw/vhost.c +++ b/hw/vhost.c @@ -792,7 +792,7 @@ int vhost_dev_init(struct vhost_dev *hdev, int devfd, const char *devpath, hdev->log_size = 0; hdev->log_enabled = false; hdev->started = false; - memory_listener_register(&hdev->memory_listener, get_system_memory()); + memory_listener_register(&hdev->memory_listener, &address_space_memory); hdev->force = force; return 0; fail: diff --git a/hw/xen_pt.c b/hw/xen_pt.c index d5dc11e582..d3d7c8bc3c 100644 --- a/hw/xen_pt.c +++ b/hw/xen_pt.c @@ -749,8 +749,8 @@ static int xen_pt_initfn(PCIDevice *d) } out: - memory_listener_register(&s->memory_listener, get_system_memory()); - memory_listener_register(&s->io_listener, get_system_io()); + memory_listener_register(&s->memory_listener, &address_space_memory); + memory_listener_register(&s->io_listener, &address_space_io); XEN_PT_LOG(d, "Real physical device %02x:%02x.%d registered successfuly!\n", bus, slot, func); diff --git a/kvm-all.c b/kvm-all.c index 677dd2d99f..c2c69093ec 100644 --- a/kvm-all.c +++ b/kvm-all.c @@ -1375,8 +1375,8 @@ int kvm_init(void) } kvm_state = s; - memory_listener_register(&kvm_memory_listener, get_system_memory()); - memory_listener_register(&kvm_io_listener, get_system_io()); + memory_listener_register(&kvm_memory_listener, &address_space_memory); + memory_listener_register(&kvm_io_listener, &address_space_io); s->many_ioeventfds = kvm_check_many_ioeventfds(); diff --git a/memory.c b/memory.c index 49a6ecc6c8..0cf0177f43 100644 --- a/memory.c +++ b/memory.c @@ -147,7 +147,7 @@ static bool memory_listener_match(MemoryListener *listener, #define MEMORY_LISTENER_UPDATE_REGION(fr, as, dir, callback) \ MEMORY_LISTENER_CALL(callback, dir, (&(MemoryRegionSection) { \ .mr = (fr)->mr, \ - .address_space = (as)->root, \ + .address_space = (as), \ .offset_within_region = (fr)->offset_in_region, \ .size = int128_get64((fr)->addr.size), \ .offset_within_address_space = int128_get64((fr)->addr.start), \ @@ -593,7 +593,7 @@ static void address_space_add_del_ioeventfds(AddressSpace *as, fds_new[inew]))) { fd = &fds_old[iold]; section = (MemoryRegionSection) { - .address_space = as->root, + .address_space = as, .offset_within_address_space = int128_get64(fd->addr.start), .size = int128_get64(fd->addr.size), }; @@ -606,7 +606,7 @@ static void address_space_add_del_ioeventfds(AddressSpace *as, fds_old[iold]))) { fd = &fds_new[inew]; section = (MemoryRegionSection) { - .address_space = as->root, + .address_space = as, .offset_within_address_space = int128_get64(fd->addr.start), .size = int128_get64(fd->addr.size), }; @@ -1137,7 +1137,7 @@ static void memory_region_update_coalesced_range_as(MemoryRegion *mr, AddressSpa FOR_EACH_FLAT_RANGE(fr, as->current_map) { if (fr->mr == mr) { section = (MemoryRegionSection) { - .address_space = as->root, + .address_space = as, .offset_within_address_space = int128_get64(fr->addr.start), .size = int128_get64(fr->addr.size), }; @@ -1476,7 +1476,7 @@ static void listener_add_address_space(MemoryListener *listener, FlatRange *fr; if (listener->address_space_filter - && listener->address_space_filter != as->root) { + && listener->address_space_filter != as) { return; } @@ -1489,7 +1489,7 @@ static void listener_add_address_space(MemoryListener *listener, FOR_EACH_FLAT_RANGE(fr, as->current_map) { MemoryRegionSection section = { .mr = fr->mr, - .address_space = as->root, + .address_space = as, .offset_within_region = fr->offset_in_region, .size = int128_get64(fr->addr.size), .offset_within_address_space = int128_get64(fr->addr.start), @@ -1501,7 +1501,7 @@ static void listener_add_address_space(MemoryListener *listener, } } -void memory_listener_register(MemoryListener *listener, MemoryRegion *filter) +void memory_listener_register(MemoryListener *listener, AddressSpace *filter) { MemoryListener *other = NULL; AddressSpace *as; diff --git a/memory.h b/memory.h index 64d2b341b6..f5a13a4db6 100644 --- a/memory.h +++ b/memory.h @@ -187,7 +187,7 @@ typedef struct MemoryRegionSection MemoryRegionSection; */ struct MemoryRegionSection { MemoryRegion *mr; - MemoryRegion *address_space; + AddressSpace *address_space; target_phys_addr_t offset_within_region; uint64_t size; target_phys_addr_t offset_within_address_space; @@ -223,7 +223,7 @@ struct MemoryListener { target_phys_addr_t addr, target_phys_addr_t len); /* Lower = earlier (during add), later (during del) */ unsigned priority; - MemoryRegion *address_space_filter; + AddressSpace *address_space_filter; QTAILQ_ENTRY(MemoryListener) link; }; @@ -774,7 +774,7 @@ void memory_region_transaction_commit(void); * @listener: an object containing the callbacks to be called * @filter: if non-%NULL, only regions in this address space will be observed */ -void memory_listener_register(MemoryListener *listener, MemoryRegion *filter); +void memory_listener_register(MemoryListener *listener, AddressSpace *filter); /** * memory_listener_unregister: undo the effect of memory_listener_register() diff --git a/xen-all.c b/xen-all.c index 8731e1165b..9d1e168826 100644 --- a/xen-all.c +++ b/xen-all.c @@ -1141,7 +1141,7 @@ int xen_hvm_init(void) state->memory_listener = xen_memory_listener; QLIST_INIT(&state->physmap); - memory_listener_register(&state->memory_listener, get_system_memory()); + memory_listener_register(&state->memory_listener, &address_space_memory); state->log_for_dirtybit = NULL; /* Initialize backend core & drivers */ -- cgit 1.4.1