From 7762c2c1e02e44fdc473cbe75105faba08b906cc Mon Sep 17 00:00:00 2001 From: Avi Kivity Date: Thu, 20 Sep 2012 16:02:51 +0300 Subject: memory: rename 'exec-obsolete.h' exec-obsolete.h used to hold pre-memory-API functions that were used from device code prior to the transition to the memory API. Now that the transition is complete, the name no longer describes the file. The functions still need to be merged better into the memory core, but there's no danger of anyone using them. Reviewed-by: Anthony Liguori Signed-off-by: Avi Kivity --- exec.c | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) (limited to 'exec.c') diff --git a/exec.c b/exec.c index 7899042ce9..eb0ec93f9a 100644 --- a/exec.c +++ b/exec.c @@ -59,8 +59,7 @@ #include "cputlb.h" -#define WANT_EXEC_OBSOLETE -#include "exec-obsolete.h" +#include "memory-internal.h" //#define DEBUG_TB_INVALIDATE //#define DEBUG_FLUSH -- cgit 1.4.1 From 9a2c913b77b54f650d60680d14b995bacbc63e50 Mon Sep 17 00:00:00 2001 From: Avi Kivity Date: Tue, 2 Oct 2012 16:42:23 +0200 Subject: memory: drop no-op MemoryListener callbacks Removes quite a bit of useless code. Signed-off-by: Avi Kivity --- exec.c | 96 ------------------------------------------------------------------ 1 file changed, 96 deletions(-) (limited to 'exec.c') diff --git a/exec.c b/exec.c index eb0ec93f9a..6558728d09 100644 --- a/exec.c +++ b/exec.c @@ -3194,32 +3194,12 @@ static void core_region_add(MemoryListener *listener, cpu_register_physical_memory_log(section, section->readonly); } -static void core_region_del(MemoryListener *listener, - MemoryRegionSection *section) -{ -} - static void core_region_nop(MemoryListener *listener, MemoryRegionSection *section) { cpu_register_physical_memory_log(section, section->readonly); } -static void core_log_start(MemoryListener *listener, - MemoryRegionSection *section) -{ -} - -static void core_log_stop(MemoryListener *listener, - MemoryRegionSection *section) -{ -} - -static void core_log_sync(MemoryListener *listener, - MemoryRegionSection *section) -{ -} - static void core_log_global_start(MemoryListener *listener) { cpu_physical_memory_set_dirty_tracking(1); @@ -3230,26 +3210,6 @@ static void core_log_global_stop(MemoryListener *listener) cpu_physical_memory_set_dirty_tracking(0); } -static void core_eventfd_add(MemoryListener *listener, - MemoryRegionSection *section, - bool match_data, uint64_t data, EventNotifier *e) -{ -} - -static void core_eventfd_del(MemoryListener *listener, - MemoryRegionSection *section, - bool match_data, uint64_t data, EventNotifier *e) -{ -} - -static void io_begin(MemoryListener *listener) -{ -} - -static void io_commit(MemoryListener *listener) -{ -} - static void io_region_add(MemoryListener *listener, MemoryRegionSection *section) { @@ -3268,75 +3228,19 @@ static void io_region_del(MemoryListener *listener, isa_unassign_ioport(section->offset_within_address_space, section->size); } -static void io_region_nop(MemoryListener *listener, - MemoryRegionSection *section) -{ -} - -static void io_log_start(MemoryListener *listener, - MemoryRegionSection *section) -{ -} - -static void io_log_stop(MemoryListener *listener, - MemoryRegionSection *section) -{ -} - -static void io_log_sync(MemoryListener *listener, - MemoryRegionSection *section) -{ -} - -static void io_log_global_start(MemoryListener *listener) -{ -} - -static void io_log_global_stop(MemoryListener *listener) -{ -} - -static void io_eventfd_add(MemoryListener *listener, - MemoryRegionSection *section, - bool match_data, uint64_t data, EventNotifier *e) -{ -} - -static void io_eventfd_del(MemoryListener *listener, - MemoryRegionSection *section, - bool match_data, uint64_t data, EventNotifier *e) -{ -} - static MemoryListener core_memory_listener = { .begin = core_begin, .commit = core_commit, .region_add = core_region_add, - .region_del = core_region_del, .region_nop = core_region_nop, - .log_start = core_log_start, - .log_stop = core_log_stop, - .log_sync = core_log_sync, .log_global_start = core_log_global_start, .log_global_stop = core_log_global_stop, - .eventfd_add = core_eventfd_add, - .eventfd_del = core_eventfd_del, .priority = 0, }; static MemoryListener io_memory_listener = { - .begin = io_begin, - .commit = io_commit, .region_add = io_region_add, .region_del = io_region_del, - .region_nop = io_region_nop, - .log_start = io_log_start, - .log_stop = io_log_stop, - .log_sync = io_log_sync, - .log_global_start = io_log_global_start, - .log_global_stop = io_log_global_stop, - .eventfd_add = io_eventfd_add, - .eventfd_del = io_eventfd_del, .priority = 0, }; -- 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 'exec.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 2673a5da25ea9005e562c20a18cf469ed4f21060 Mon Sep 17 00:00:00 2001 From: Avi Kivity Date: Tue, 2 Oct 2012 18:49:28 +0200 Subject: memory: move address_space_memory and address_space_io out of memory core With this change, memory.c no longer knows anything about special address spaces, so it is prepared for AddressSpace based DMA. Reviewed-by: Anthony Liguori Signed-off-by: Avi Kivity --- exec-memory.h | 6 ------ exec.c | 9 +++++++-- memory.c | 16 ---------------- 3 files changed, 7 insertions(+), 24 deletions(-) (limited to 'exec.c') diff --git a/exec-memory.h b/exec-memory.h index 1cd92eec71..6707e40b2f 100644 --- a/exec-memory.h +++ b/exec-memory.h @@ -33,12 +33,6 @@ MemoryRegion *get_system_memory(void); */ MemoryRegion *get_system_io(void); -/* Set the root memory region. This region is the system memory map. */ -void set_system_memory_map(MemoryRegion *mr); - -/* Set the I/O memory region. This region is the I/O memory map. */ -void set_system_io_map(MemoryRegion *mr); - #endif #endif diff --git a/exec.c b/exec.c index 5d5d9e33c9..dfc0a784f3 100644 --- a/exec.c +++ b/exec.c @@ -116,6 +116,9 @@ 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; + MemoryRegion io_mem_ram, io_mem_rom, io_mem_unassigned, io_mem_notdirty; static MemoryRegion io_mem_subpage_ram; @@ -3235,11 +3238,13 @@ static void memory_map_init(void) { system_memory = g_malloc(sizeof(*system_memory)); memory_region_init(system_memory, "system", INT64_MAX); - set_system_memory_map(system_memory); + address_space_init(&address_space_memory, system_memory); + address_space_memory.name = "memory"; system_io = g_malloc(sizeof(*system_io)); memory_region_init(system_io, "io", 65536); - set_system_io_map(system_io); + 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); diff --git a/memory.c b/memory.c index d829f67419..49a6ecc6c8 100644 --- a/memory.c +++ b/memory.c @@ -364,8 +364,6 @@ static void access_with_adjusted_size(target_phys_addr_t addr, } } -static AddressSpace address_space_memory; - static const MemoryRegionPortio *find_portio(MemoryRegion *mr, uint64_t offset, unsigned width, bool write) { @@ -454,8 +452,6 @@ const IORangeOps memory_region_iorange_ops = { .destructor = memory_region_iorange_destructor, }; -static AddressSpace address_space_io; - static AddressSpace *memory_region_to_address_space(MemoryRegion *mr) { AddressSpace *as; @@ -1545,18 +1541,6 @@ void address_space_init(AddressSpace *as, MemoryRegion *root) memory_region_transaction_commit(); } -void set_system_memory_map(MemoryRegion *mr) -{ - address_space_init(&address_space_memory, mr); - address_space_memory.name = "memory"; -} - -void set_system_io_map(MemoryRegion *mr) -{ - address_space_init(&address_space_io, mr); - address_space_io.name = "I/O"; -} - uint64_t io_mem_read(MemoryRegion *mr, target_phys_addr_t addr, unsigned size) { return memory_region_dispatch_read(mr, addr, size); -- cgit 1.4.1 From 1d71148eace669827ba15101819b54b20fcca616 Mon Sep 17 00:00:00 2001 From: Avi Kivity Date: Tue, 2 Oct 2012 18:54:45 +0200 Subject: memory: move tcg flush into a tcg memory listener We plan to make the core listener listen to all address spaces; this will cause many more flushes than necessary. Prepare for that by moving the flush into a tcg-specific listener. Later we can avoid registering the listener if tcg is disabled. Signed-off-by: Avi Kivity --- exec.c | 8 ++++++-- 1 file changed, 6 insertions(+), 2 deletions(-) (limited to 'exec.c') diff --git a/exec.c b/exec.c index dfc0a784f3..6a7ba0cea6 100644 --- a/exec.c +++ b/exec.c @@ -3166,7 +3166,7 @@ static void core_begin(MemoryListener *listener) phys_section_watch = dummy_section(&io_mem_watch); } -static void core_commit(MemoryListener *listener) +static void tcg_commit(MemoryListener *listener) { CPUArchState *env; @@ -3220,7 +3220,6 @@ static void io_region_del(MemoryListener *listener, static MemoryListener core_memory_listener = { .begin = core_begin, - .commit = core_commit, .region_add = core_region_add, .region_nop = core_region_nop, .log_global_start = core_log_global_start, @@ -3234,6 +3233,10 @@ static MemoryListener io_memory_listener = { .priority = 0, }; +static MemoryListener tcg_memory_listener = { + .commit = tcg_commit, +}; + static void memory_map_init(void) { system_memory = g_malloc(sizeof(*system_memory)); @@ -3248,6 +3251,7 @@ static void memory_map_init(void) memory_listener_register(&core_memory_listener, system_memory); memory_listener_register(&io_memory_listener, system_io); + memory_listener_register(&tcg_memory_listener, system_memory); } MemoryRegion *get_system_memory(void) -- 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 'exec.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 From ac1970fbe8ad5a70174f462109ac0f6c7bf1bc43 Mon Sep 17 00:00:00 2001 From: Avi Kivity Date: Wed, 3 Oct 2012 16:22:53 +0200 Subject: memory: per-AddressSpace dispatch Currently we use a global radix tree to dispatch memory access. This only works with a single address space; to support multiple address spaces we make the radix tree a member of AddressSpace (via an intermediate structure AddressSpaceDispatch to avoid exposing too many internals). A side effect is that address_space_io also gains a dispatch table. When we remove all the pre-memory-API I/O registrations, we can use that for dispatching I/O and get rid of the original I/O dispatch. Signed-off-by: Avi Kivity --- cputlb.c | 3 +- cputlb.h | 3 +- exec.c | 174 +++++++++++++++++++++++++++++++++--------------------- memory-internal.h | 22 ++++++- memory.c | 1 + memory.h | 62 +++++++++++++++++++ 6 files changed, 194 insertions(+), 71 deletions(-) (limited to 'exec.c') diff --git a/cputlb.c b/cputlb.c index 0627f32e35..9027557604 100644 --- a/cputlb.c +++ b/cputlb.c @@ -21,6 +21,7 @@ #include "cpu.h" #include "exec-all.h" #include "memory.h" +#include "exec-memory.h" #include "cputlb.h" @@ -251,7 +252,7 @@ void tlb_set_page(CPUArchState *env, target_ulong vaddr, if (size != TARGET_PAGE_SIZE) { tlb_add_large_page(env, vaddr, size); } - section = phys_page_find(paddr >> TARGET_PAGE_BITS); + section = phys_page_find(address_space_memory.dispatch, paddr >> TARGET_PAGE_BITS); #if defined(DEBUG_TLB) printf("tlb_set_page: vaddr=" TARGET_FMT_lx " paddr=0x" TARGET_FMT_plx " prot=%x idx=%d pd=0x%08lx\n", diff --git a/cputlb.h b/cputlb.h index 2dc2c96cd8..d537b7740f 100644 --- a/cputlb.h +++ b/cputlb.h @@ -26,7 +26,8 @@ void tlb_unprotect_code_phys(CPUArchState *env, ram_addr_t ram_addr, target_ulong vaddr); void tlb_reset_dirty_range(CPUTLBEntry *tlb_entry, uintptr_t start, uintptr_t length); -MemoryRegionSection *phys_page_find(target_phys_addr_t index); +MemoryRegionSection *phys_page_find(struct AddressSpaceDispatch *d, + target_phys_addr_t index); void cpu_tlb_reset_dirty_all(ram_addr_t start1, ram_addr_t length); void tlb_set_dirty(CPUArchState *env, target_ulong vaddr); extern int tlb_flush_count; diff --git a/exec.c b/exec.c index e732b5285e..bfc4acc206 100644 --- a/exec.c +++ b/exec.c @@ -187,7 +187,6 @@ uintptr_t qemu_host_page_mask; static void *l1_map[V_L1_SIZE]; #if !defined(CONFIG_USER_ONLY) -typedef struct PhysPageEntry PhysPageEntry; static MemoryRegionSection *phys_sections; static unsigned phys_sections_nb, phys_sections_nb_alloc; @@ -196,22 +195,12 @@ static uint16_t phys_section_notdirty; static uint16_t phys_section_rom; static uint16_t phys_section_watch; -struct PhysPageEntry { - uint16_t is_leaf : 1; - /* index into phys_sections (is_leaf) or phys_map_nodes (!is_leaf) */ - uint16_t ptr : 15; -}; - /* Simple allocator for PhysPageEntry nodes */ static PhysPageEntry (*phys_map_nodes)[L2_SIZE]; static unsigned phys_map_nodes_nb, phys_map_nodes_nb_alloc; #define PHYS_MAP_NODE_NIL (((uint16_t)~0) >> 1) -/* This is a multi-level map on the physical address space. - The bottom level has pointers to MemoryRegionSections. */ -static PhysPageEntry phys_map = { .ptr = PHYS_MAP_NODE_NIL, .is_leaf = 0 }; - static void io_mem_init(void); static void memory_map_init(void); @@ -459,18 +448,19 @@ static void phys_page_set_level(PhysPageEntry *lp, target_phys_addr_t *index, } } -static void phys_page_set(target_phys_addr_t index, target_phys_addr_t nb, +static void phys_page_set(AddressSpaceDispatch *d, + target_phys_addr_t index, target_phys_addr_t nb, uint16_t leaf) { /* Wildly overreserve - it doesn't matter much. */ phys_map_node_reserve(3 * P_L2_LEVELS); - phys_page_set_level(&phys_map, &index, &nb, leaf, P_L2_LEVELS - 1); + phys_page_set_level(&d->phys_map, &index, &nb, leaf, P_L2_LEVELS - 1); } -MemoryRegionSection *phys_page_find(target_phys_addr_t index) +MemoryRegionSection *phys_page_find(AddressSpaceDispatch *d, target_phys_addr_t index) { - PhysPageEntry lp = phys_map; + PhysPageEntry lp = d->phys_map; PhysPageEntry *p; int i; uint16_t s_index = phys_section_unassigned; @@ -1472,7 +1462,7 @@ void tb_invalidate_phys_addr(target_phys_addr_t addr) ram_addr_t ram_addr; MemoryRegionSection *section; - section = phys_page_find(addr >> TARGET_PAGE_BITS); + section = phys_page_find(address_space_memory.dispatch, addr >> TARGET_PAGE_BITS); if (!(memory_region_is_ram(section->mr) || (section->mr->rom_device && section->mr->readable))) { return; @@ -2210,9 +2200,9 @@ static void destroy_l2_mapping(PhysPageEntry *lp, unsigned level) lp->ptr = PHYS_MAP_NODE_NIL; } -static void destroy_all_mappings(void) +static void destroy_all_mappings(AddressSpaceDispatch *d) { - destroy_l2_mapping(&phys_map, P_L2_LEVELS - 1); + destroy_l2_mapping(&d->phys_map, P_L2_LEVELS - 1); phys_map_nodes_reset(); } @@ -2232,12 +2222,12 @@ static void phys_sections_clear(void) phys_sections_nb = 0; } -static void register_subpage(MemoryRegionSection *section) +static void register_subpage(AddressSpaceDispatch *d, MemoryRegionSection *section) { subpage_t *subpage; target_phys_addr_t base = section->offset_within_address_space & TARGET_PAGE_MASK; - MemoryRegionSection *existing = phys_page_find(base >> TARGET_PAGE_BITS); + MemoryRegionSection *existing = phys_page_find(d, base >> TARGET_PAGE_BITS); MemoryRegionSection subsection = { .offset_within_address_space = base, .size = TARGET_PAGE_SIZE, @@ -2249,7 +2239,7 @@ static void register_subpage(MemoryRegionSection *section) if (!(existing->mr->subpage)) { subpage = subpage_init(base); subsection.mr = &subpage->iomem; - phys_page_set(base >> TARGET_PAGE_BITS, 1, + phys_page_set(d, base >> TARGET_PAGE_BITS, 1, phys_section_add(&subsection)); } else { subpage = container_of(existing->mr, subpage_t, iomem); @@ -2260,7 +2250,7 @@ static void register_subpage(MemoryRegionSection *section) } -static void register_multipage(MemoryRegionSection *section) +static void register_multipage(AddressSpaceDispatch *d, MemoryRegionSection *section) { target_phys_addr_t start_addr = section->offset_within_address_space; ram_addr_t size = section->size; @@ -2270,13 +2260,13 @@ static void register_multipage(MemoryRegionSection *section) assert(size); addr = start_addr; - phys_page_set(addr >> TARGET_PAGE_BITS, size >> TARGET_PAGE_BITS, + phys_page_set(d, addr >> TARGET_PAGE_BITS, size >> TARGET_PAGE_BITS, section_index); } -void cpu_register_physical_memory_log(MemoryRegionSection *section, - bool readonly) +static void mem_add(MemoryListener *listener, MemoryRegionSection *section) { + AddressSpaceDispatch *d = container_of(listener, AddressSpaceDispatch, listener); MemoryRegionSection now = *section, remain = *section; if ((now.offset_within_address_space & ~TARGET_PAGE_MASK) @@ -2284,7 +2274,7 @@ void cpu_register_physical_memory_log(MemoryRegionSection *section, now.size = MIN(TARGET_PAGE_ALIGN(now.offset_within_address_space) - now.offset_within_address_space, now.size); - register_subpage(&now); + register_subpage(d, &now); remain.size -= now.size; remain.offset_within_address_space += now.size; remain.offset_within_region += now.size; @@ -2293,10 +2283,10 @@ void cpu_register_physical_memory_log(MemoryRegionSection *section, now = remain; if (remain.offset_within_region & ~TARGET_PAGE_MASK) { now.size = TARGET_PAGE_SIZE; - register_subpage(&now); + register_subpage(d, &now); } else { now.size &= TARGET_PAGE_MASK; - register_multipage(&now); + register_multipage(d, &now); } remain.size -= now.size; remain.offset_within_address_space += now.size; @@ -2304,7 +2294,7 @@ void cpu_register_physical_memory_log(MemoryRegionSection *section, } now = remain; if (now.size) { - register_subpage(&now); + register_subpage(d, &now); } } @@ -3155,11 +3145,17 @@ static void io_mem_init(void) "watch", UINT64_MAX); } +static void mem_begin(MemoryListener *listener) +{ + AddressSpaceDispatch *d = container_of(listener, AddressSpaceDispatch, listener); + + destroy_all_mappings(d); + d->phys_map.ptr = PHYS_MAP_NODE_NIL; +} + static void core_begin(MemoryListener *listener) { - destroy_all_mappings(); phys_sections_clear(); - phys_map.ptr = PHYS_MAP_NODE_NIL; phys_section_unassigned = dummy_section(&io_mem_unassigned); phys_section_notdirty = dummy_section(&io_mem_notdirty); phys_section_rom = dummy_section(&io_mem_rom); @@ -3178,18 +3174,6 @@ static void tcg_commit(MemoryListener *listener) } } -static void core_region_add(MemoryListener *listener, - MemoryRegionSection *section) -{ - cpu_register_physical_memory_log(section, section->readonly); -} - -static void core_region_nop(MemoryListener *listener, - MemoryRegionSection *section) -{ - cpu_register_physical_memory_log(section, section->readonly); -} - static void core_log_global_start(MemoryListener *listener) { cpu_physical_memory_set_dirty_tracking(1); @@ -3220,11 +3204,9 @@ static void io_region_del(MemoryListener *listener, static MemoryListener core_memory_listener = { .begin = core_begin, - .region_add = core_region_add, - .region_nop = core_region_nop, .log_global_start = core_log_global_start, .log_global_stop = core_log_global_stop, - .priority = 0, + .priority = 1, }; static MemoryListener io_memory_listener = { @@ -3237,6 +3219,21 @@ static MemoryListener tcg_memory_listener = { .commit = tcg_commit, }; +void address_space_init_dispatch(AddressSpace *as) +{ + AddressSpaceDispatch *d = g_new(AddressSpaceDispatch, 1); + + d->phys_map = (PhysPageEntry) { .ptr = PHYS_MAP_NODE_NIL, .is_leaf = 0 }; + d->listener = (MemoryListener) { + .begin = mem_begin, + .region_add = mem_add, + .region_nop = mem_add, + .priority = 0, + }; + as->dispatch = d; + memory_listener_register(&d->listener, as); +} + static void memory_map_init(void) { system_memory = g_malloc(sizeof(*system_memory)); @@ -3321,9 +3318,10 @@ static void invalidate_and_set_dirty(target_phys_addr_t addr, xen_modified_memory(addr, length); } -void cpu_physical_memory_rw(target_phys_addr_t addr, uint8_t *buf, - int len, int is_write) +void address_space_rw(AddressSpace *as, target_phys_addr_t addr, uint8_t *buf, + int len, bool is_write) { + AddressSpaceDispatch *d = as->dispatch; int l; uint8_t *ptr; uint32_t val; @@ -3335,7 +3333,7 @@ void cpu_physical_memory_rw(target_phys_addr_t addr, uint8_t *buf, l = (page + TARGET_PAGE_SIZE) - addr; if (l > len) l = len; - section = phys_page_find(page >> TARGET_PAGE_BITS); + section = phys_page_find(d, page >> TARGET_PAGE_BITS); if (is_write) { if (!memory_region_is_ram(section->mr)) { @@ -3406,10 +3404,36 @@ void cpu_physical_memory_rw(target_phys_addr_t addr, uint8_t *buf, } } +void address_space_write(AddressSpace *as, target_phys_addr_t addr, + const uint8_t *buf, int len) +{ + address_space_rw(as, addr, (uint8_t *)buf, len, true); +} + +/** + * address_space_read: read from an address space. + * + * @as: #AddressSpace to be accessed + * @addr: address within that address space + * @buf: buffer with the data transferred + */ +void address_space_read(AddressSpace *as, target_phys_addr_t addr, uint8_t *buf, int len) +{ + address_space_rw(as, addr, buf, len, false); +} + + +void cpu_physical_memory_rw(target_phys_addr_t addr, uint8_t *buf, + int len, int is_write) +{ + return address_space_rw(&address_space_memory, addr, buf, len, is_write); +} + /* used for ROM loading : can write in RAM and ROM */ void cpu_physical_memory_write_rom(target_phys_addr_t addr, const uint8_t *buf, int len) { + AddressSpaceDispatch *d = address_space_memory.dispatch; int l; uint8_t *ptr; target_phys_addr_t page; @@ -3420,7 +3444,7 @@ void cpu_physical_memory_write_rom(target_phys_addr_t addr, l = (page + TARGET_PAGE_SIZE) - addr; if (l > len) l = len; - section = phys_page_find(page >> TARGET_PAGE_BITS); + section = phys_page_find(d, page >> TARGET_PAGE_BITS); if (!(memory_region_is_ram(section->mr) || memory_region_is_romd(section->mr))) { @@ -3494,10 +3518,12 @@ static void cpu_notify_map_clients(void) * Use cpu_register_map_client() to know when retrying the map operation is * likely to succeed. */ -void *cpu_physical_memory_map(target_phys_addr_t addr, - target_phys_addr_t *plen, - int is_write) +void *address_space_map(AddressSpace *as, + target_phys_addr_t addr, + target_phys_addr_t *plen, + bool is_write) { + AddressSpaceDispatch *d = as->dispatch; target_phys_addr_t len = *plen; target_phys_addr_t todo = 0; int l; @@ -3512,7 +3538,7 @@ void *cpu_physical_memory_map(target_phys_addr_t addr, l = (page + TARGET_PAGE_SIZE) - addr; if (l > len) l = len; - section = phys_page_find(page >> TARGET_PAGE_BITS); + section = phys_page_find(d, page >> TARGET_PAGE_BITS); if (!(memory_region_is_ram(section->mr) && !section->readonly)) { if (todo || bounce.buffer) { @@ -3522,7 +3548,7 @@ void *cpu_physical_memory_map(target_phys_addr_t addr, bounce.addr = addr; bounce.len = l; if (!is_write) { - cpu_physical_memory_read(addr, bounce.buffer, l); + address_space_read(as, addr, bounce.buffer, l); } *plen = l; @@ -3543,12 +3569,12 @@ void *cpu_physical_memory_map(target_phys_addr_t addr, return ret; } -/* Unmaps a memory region previously mapped by cpu_physical_memory_map(). +/* Unmaps a memory region previously mapped by address_space_map(). * Will also mark the memory as dirty if is_write == 1. access_len gives * the amount of memory that was actually read or written by the caller. */ -void cpu_physical_memory_unmap(void *buffer, target_phys_addr_t len, - int is_write, target_phys_addr_t access_len) +void address_space_unmap(AddressSpace *as, void *buffer, target_phys_addr_t len, + int is_write, target_phys_addr_t access_len) { if (buffer != bounce.buffer) { if (is_write) { @@ -3569,13 +3595,26 @@ void cpu_physical_memory_unmap(void *buffer, target_phys_addr_t len, return; } if (is_write) { - cpu_physical_memory_write(bounce.addr, bounce.buffer, access_len); + address_space_write(as, bounce.addr, bounce.buffer, access_len); } qemu_vfree(bounce.buffer); bounce.buffer = NULL; cpu_notify_map_clients(); } +void *cpu_physical_memory_map(target_phys_addr_t addr, + target_phys_addr_t *plen, + int is_write) +{ + return address_space_map(&address_space_memory, addr, plen, is_write); +} + +void cpu_physical_memory_unmap(void *buffer, target_phys_addr_t len, + int is_write, target_phys_addr_t access_len) +{ + return address_space_unmap(&address_space_memory, buffer, len, is_write, access_len); +} + /* warning: addr must be aligned */ static inline uint32_t ldl_phys_internal(target_phys_addr_t addr, enum device_endian endian) @@ -3584,7 +3623,7 @@ static inline uint32_t ldl_phys_internal(target_phys_addr_t addr, uint32_t val; MemoryRegionSection *section; - section = phys_page_find(addr >> TARGET_PAGE_BITS); + section = phys_page_find(address_space_memory.dispatch, addr >> TARGET_PAGE_BITS); if (!(memory_region_is_ram(section->mr) || memory_region_is_romd(section->mr))) { @@ -3643,7 +3682,7 @@ static inline uint64_t ldq_phys_internal(target_phys_addr_t addr, uint64_t val; MemoryRegionSection *section; - section = phys_page_find(addr >> TARGET_PAGE_BITS); + section = phys_page_find(address_space_memory.dispatch, addr >> TARGET_PAGE_BITS); if (!(memory_region_is_ram(section->mr) || memory_region_is_romd(section->mr))) { @@ -3710,7 +3749,7 @@ static inline uint32_t lduw_phys_internal(target_phys_addr_t addr, uint64_t val; MemoryRegionSection *section; - section = phys_page_find(addr >> TARGET_PAGE_BITS); + section = phys_page_find(address_space_memory.dispatch, addr >> TARGET_PAGE_BITS); if (!(memory_region_is_ram(section->mr) || memory_region_is_romd(section->mr))) { @@ -3769,7 +3808,7 @@ void stl_phys_notdirty(target_phys_addr_t addr, uint32_t val) uint8_t *ptr; MemoryRegionSection *section; - section = phys_page_find(addr >> TARGET_PAGE_BITS); + section = phys_page_find(address_space_memory.dispatch, addr >> TARGET_PAGE_BITS); if (!memory_region_is_ram(section->mr) || section->readonly) { addr = memory_region_section_addr(section, addr); @@ -3801,7 +3840,7 @@ void stq_phys_notdirty(target_phys_addr_t addr, uint64_t val) uint8_t *ptr; MemoryRegionSection *section; - section = phys_page_find(addr >> TARGET_PAGE_BITS); + section = phys_page_find(address_space_memory.dispatch, addr >> TARGET_PAGE_BITS); if (!memory_region_is_ram(section->mr) || section->readonly) { addr = memory_region_section_addr(section, addr); @@ -3830,7 +3869,7 @@ static inline void stl_phys_internal(target_phys_addr_t addr, uint32_t val, uint8_t *ptr; MemoryRegionSection *section; - section = phys_page_find(addr >> TARGET_PAGE_BITS); + section = phys_page_find(address_space_memory.dispatch, addr >> TARGET_PAGE_BITS); if (!memory_region_is_ram(section->mr) || section->readonly) { addr = memory_region_section_addr(section, addr); @@ -3897,7 +3936,7 @@ static inline void stw_phys_internal(target_phys_addr_t addr, uint32_t val, uint8_t *ptr; MemoryRegionSection *section; - section = phys_page_find(addr >> TARGET_PAGE_BITS); + section = phys_page_find(address_space_memory.dispatch, addr >> TARGET_PAGE_BITS); if (!memory_region_is_ram(section->mr) || section->readonly) { addr = memory_region_section_addr(section, addr); @@ -4133,7 +4172,8 @@ bool cpu_physical_memory_is_io(target_phys_addr_t phys_addr) { MemoryRegionSection *section; - section = phys_page_find(phys_addr >> TARGET_PAGE_BITS); + section = phys_page_find(address_space_memory.dispatch, + phys_addr >> TARGET_PAGE_BITS); return !(memory_region_is_ram(section->mr) || memory_region_is_romd(section->mr)); diff --git a/memory-internal.h b/memory-internal.h index 43fa886264..6d8711bb1f 100644 --- a/memory-internal.h +++ b/memory-internal.h @@ -22,6 +22,26 @@ #ifndef CONFIG_USER_ONLY #include "hw/xen.h" +typedef struct PhysPageEntry PhysPageEntry; + +struct PhysPageEntry { + uint16_t is_leaf : 1; + /* index into phys_sections (is_leaf) or phys_map_nodes (!is_leaf) */ + uint16_t ptr : 15; +}; + +typedef struct AddressSpaceDispatch AddressSpaceDispatch; + +struct AddressSpaceDispatch { + /* This is a multi-level map on the physical address space. + * The bottom level has pointers to MemoryRegionSections. + */ + PhysPageEntry phys_map; + MemoryListener listener; +}; + +void address_space_init_dispatch(AddressSpace *as); + ram_addr_t qemu_ram_alloc_from_ptr(ram_addr_t size, void *host, MemoryRegion *mr); ram_addr_t qemu_ram_alloc(ram_addr_t size, MemoryRegion *mr); @@ -30,8 +50,6 @@ void qemu_ram_free_from_ptr(ram_addr_t addr); struct MemoryRegion; struct MemoryRegionSection; -void cpu_register_physical_memory_log(struct MemoryRegionSection *section, - bool readonly); void qemu_register_coalesced_mmio(target_phys_addr_t addr, ram_addr_t size); void qemu_unregister_coalesced_mmio(target_phys_addr_t addr, ram_addr_t size); diff --git a/memory.c b/memory.c index 0cf0177f43..13be84849c 100644 --- a/memory.c +++ b/memory.c @@ -1539,6 +1539,7 @@ void address_space_init(AddressSpace *as, MemoryRegion *root) QTAILQ_INSERT_TAIL(&address_spaces, as, address_spaces_link); as->name = NULL; memory_region_transaction_commit(); + address_space_init_dispatch(as); } uint64_t io_mem_read(MemoryRegion *mr, target_phys_addr_t addr, unsigned size) diff --git a/memory.h b/memory.h index f5a13a4db6..d36c2baa23 100644 --- a/memory.h +++ b/memory.h @@ -169,6 +169,7 @@ struct AddressSpace { struct FlatView *current_map; int ioeventfd_nb; struct MemoryRegionIoeventfd *ioeventfds; + struct AddressSpaceDispatch *dispatch; QTAILQ_ENTRY(AddressSpace) address_spaces_link; }; @@ -803,6 +804,67 @@ void mtree_info(fprintf_function mon_printf, void *f); */ void address_space_init(AddressSpace *as, MemoryRegion *root); +/** + * address_space_rw: read from or write to an address space. + * + * @as: #AddressSpace to be accessed + * @addr: address within that address space + * @buf: buffer with the data transferred + * @is_write: indicates the transfer direction + */ +void address_space_rw(AddressSpace *as, target_phys_addr_t addr, uint8_t *buf, + int len, bool is_write); + +/** + * address_space_write: write to address space. + * + * @as: #AddressSpace to be accessed + * @addr: address within that address space + * @buf: buffer with the data transferred + */ +void address_space_write(AddressSpace *as, target_phys_addr_t addr, + const uint8_t *buf, int len); + +/** + * address_space_read: read from an address space. + * + * @as: #AddressSpace to be accessed + * @addr: address within that address space + * @buf: buffer with the data transferred + */ +void address_space_read(AddressSpace *as, target_phys_addr_t addr, uint8_t *buf, int len); + +/* address_space_map: map a physical memory region into a host virtual address + * + * May map a subset of the requested range, given by and returned in @plen. + * May return %NULL if resources needed to perform the mapping are exhausted. + * Use only for reads OR writes - not for read-modify-write operations. + * Use cpu_register_map_client() to know when retrying the map operation is + * likely to succeed. + * + * @as: #AddressSpace to be accessed + * @addr: address within that address space + * @plen: pointer to length of buffer; updated on return + * @is_write: indicates the transfer direction + */ +void *address_space_map(AddressSpace *as, target_phys_addr_t addr, + target_phys_addr_t *plen, bool is_write); + +/* address_space_unmap: Unmaps a memory region previously mapped by address_space_map() + * + * Will also mark the memory as dirty if @is_write == %true. @access_len gives + * the amount of memory that was actually read or written by the caller. + * + * @as: #AddressSpace used + * @addr: address within that address space + * @len: buffer length as returned by address_space_map() + * @access_len: amount of data actually transferred + * @is_write: indicates the transfer direction + */ +void address_space_unmap(AddressSpace *as, void *buffer, target_phys_addr_t len, + int is_write, target_phys_addr_t access_len); + + #endif #endif -- cgit 1.4.1 From 83f3c251422b0724044f976a7ff26b2e8a47c374 Mon Sep 17 00:00:00 2001 From: Avi Kivity Date: Sun, 7 Oct 2012 12:59:55 +0200 Subject: memory: add address_space_destroy() Since address spaces can be created dynamically by device hotplug, they can also be destroyed dynamically. Signed-off-by: Avi Kivity --- exec.c | 10 ++++++++++ memory-internal.h | 1 + memory.c | 18 ++++++++++++++++-- memory.h | 12 ++++++++++++ 4 files changed, 39 insertions(+), 2 deletions(-) (limited to 'exec.c') diff --git a/exec.c b/exec.c index bfc4acc206..17e8ba21d4 100644 --- a/exec.c +++ b/exec.c @@ -3234,6 +3234,16 @@ void address_space_init_dispatch(AddressSpace *as) memory_listener_register(&d->listener, as); } +void address_space_destroy_dispatch(AddressSpace *as) +{ + AddressSpaceDispatch *d = as->dispatch; + + memory_listener_unregister(&d->listener); + destroy_l2_mapping(&d->phys_map, P_L2_LEVELS - 1); + g_free(d); + as->dispatch = NULL; +} + static void memory_map_init(void) { system_memory = g_malloc(sizeof(*system_memory)); diff --git a/memory-internal.h b/memory-internal.h index 6d8711bb1f..4d33cc9530 100644 --- a/memory-internal.h +++ b/memory-internal.h @@ -41,6 +41,7 @@ struct AddressSpaceDispatch { }; void address_space_init_dispatch(AddressSpace *as); +void address_space_destroy_dispatch(AddressSpace *as); ram_addr_t qemu_ram_alloc_from_ptr(ram_addr_t size, void *host, MemoryRegion *mr); diff --git a/memory.c b/memory.c index 13be84849c..2f68d67c21 100644 --- a/memory.c +++ b/memory.c @@ -564,8 +564,10 @@ static FlatView generate_memory_topology(MemoryRegion *mr) flatview_init(&view); - render_memory_region(&view, mr, int128_zero(), - addrrange_make(int128_zero(), int128_2_64()), false); + if (mr) { + render_memory_region(&view, mr, int128_zero(), + addrrange_make(int128_zero(), int128_2_64()), false); + } flatview_simplify(&view); return view; @@ -1542,6 +1544,18 @@ void address_space_init(AddressSpace *as, MemoryRegion *root) address_space_init_dispatch(as); } +void address_space_destroy(AddressSpace *as) +{ + /* Flush out anything from MemoryListeners listening in on this */ + memory_region_transaction_begin(); + as->root = NULL; + memory_region_transaction_commit(); + QTAILQ_REMOVE(&address_spaces, as, address_spaces_link); + address_space_destroy_dispatch(as); + flatview_destroy(as->current_map); + g_free(as->current_map); +} + uint64_t io_mem_read(MemoryRegion *mr, target_phys_addr_t addr, unsigned size) { return memory_region_dispatch_read(mr, addr, size); diff --git a/memory.h b/memory.h index d36c2baa23..79393f1a76 100644 --- a/memory.h +++ b/memory.h @@ -804,6 +804,18 @@ void mtree_info(fprintf_function mon_printf, void *f); */ void address_space_init(AddressSpace *as, MemoryRegion *root); + +/** + * address_space_destroy: destroy an address space + * + * Releases all resources associated with an address space. After an address space + * is destroyed, its root memory region (given by address_space_init()) may be destroyed + * as well. + * + * @as: address space to be destroyed + */ +void address_space_destroy(AddressSpace *as); + /** * address_space_rw: read from or write to an address space. * -- cgit 1.4.1