From 01a9c03c39debe843aea7f4df18274f18d8c6974 Mon Sep 17 00:00:00 2001 From: Paolo Bonzini Date: Tue, 29 Apr 2014 16:05:53 +0200 Subject: MAINTAINERS: Add myself as Memory API maintainer I'm not including Avi since he has already removed himself from the KVM entry. I'm not going to commit my patches without review. Acked-by: Edgar E. Iglesias Signed-off-by: Paolo Bonzini --- MAINTAINERS | 10 ++++++++++ 1 file changed, 10 insertions(+) diff --git a/MAINTAINERS b/MAINTAINERS index 51a6f51842..d1a340559d 100644 --- a/MAINTAINERS +++ b/MAINTAINERS @@ -726,6 +726,16 @@ S: Odd Fixes F: gdbstub* F: gdb-xml/ +Memory API +M: Paolo Bonzini +S: Supported +F: include/exec/ioport.h +F: ioport.c +F: include/exec/memory.h +F: memory.c +F: include/exec/memory-internal.h +F: exec.c + SPICE M: Gerd Hoffmann S: Supported -- cgit v1.2.3 From 20cfe8810d08c99e3fc37be2a5a3355a3a51d208 Mon Sep 17 00:00:00 2001 From: Hu Tao Date: Wed, 2 Apr 2014 15:13:26 +0800 Subject: exec: introduce qemu_ram_unset_idstr() to unset RAMBlock idstr Signed-off-by: Hu Tao Signed-off-by: Paolo Bonzini --- exec.c | 26 +++++++++++++++++++++----- include/exec/cpu-common.h | 1 + 2 files changed, 22 insertions(+), 5 deletions(-) diff --git a/exec.c b/exec.c index 4e179a6f66..6ce989a912 100644 --- a/exec.c +++ b/exec.c @@ -1201,17 +1201,24 @@ static void qemu_ram_setup_dump(void *addr, ram_addr_t size) } } -void qemu_ram_set_idstr(ram_addr_t addr, const char *name, DeviceState *dev) +static RAMBlock *find_ram_block(ram_addr_t addr) { - RAMBlock *new_block, *block; + RAMBlock *block; - new_block = NULL; QTAILQ_FOREACH(block, &ram_list.blocks, next) { if (block->offset == addr) { - new_block = block; - break; + return block; } } + + return NULL; +} + +void qemu_ram_set_idstr(ram_addr_t addr, const char *name, DeviceState *dev) +{ + RAMBlock *new_block = find_ram_block(addr); + RAMBlock *block; + assert(new_block); assert(!new_block->idstr[0]); @@ -1236,6 +1243,15 @@ void qemu_ram_set_idstr(ram_addr_t addr, const char *name, DeviceState *dev) qemu_mutex_unlock_ramlist(); } +void qemu_ram_unset_idstr(ram_addr_t addr) +{ + RAMBlock *block = find_ram_block(addr); + + if (block) { + memset(block->idstr, 0, sizeof(block->idstr)); + } +} + static int memory_try_enable_merging(void *addr, size_t len) { if (!qemu_opt_get_bool(qemu_get_machine_opts(), "mem-merge", true)) { diff --git a/include/exec/cpu-common.h b/include/exec/cpu-common.h index a21b65a893..89ec6404cf 100644 --- a/include/exec/cpu-common.h +++ b/include/exec/cpu-common.h @@ -54,6 +54,7 @@ void qemu_ram_remap(ram_addr_t addr, ram_addr_t length); /* This should not be used by devices. */ MemoryRegion *qemu_ram_addr_from_host(void *ptr, ram_addr_t *ram_addr); void qemu_ram_set_idstr(ram_addr_t addr, const char *name, DeviceState *dev); +void qemu_ram_unset_idstr(ram_addr_t addr); void cpu_physical_memory_rw(hwaddr addr, uint8_t *buf, int len, int is_write); -- cgit v1.2.3 From b0e56e0b63f350691b52d3e75e89bb64143fbeff Mon Sep 17 00:00:00 2001 From: Hu Tao Date: Wed, 2 Apr 2014 15:13:27 +0800 Subject: unset RAMBlock idstr when unregister MemoryRegion Signed-off-by: Hu Tao Signed-off-by: Paolo Bonzini --- savevm.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/savevm.c b/savevm.c index da8aa2428d..7b2c410ea1 100644 --- a/savevm.c +++ b/savevm.c @@ -1209,7 +1209,7 @@ void vmstate_register_ram(MemoryRegion *mr, DeviceState *dev) void vmstate_unregister_ram(MemoryRegion *mr, DeviceState *dev) { - /* Nothing do to while the implementation is in RAMBlock */ + qemu_ram_unset_idstr(memory_region_get_ram_addr(mr) & TARGET_PAGE_MASK); } void vmstate_register_ram_global(MemoryRegion *mr) -- cgit v1.2.3 From 4dc56152237f61694fa42675a78ffd14a509df98 Mon Sep 17 00:00:00 2001 From: Gonglei Date: Thu, 8 May 2014 11:47:32 +0800 Subject: memory: Don't update all memory region when ioeventfd changed memory mappings don't rely on ioeventfds, there is no need to destroy and rebuild them when manipulating ioeventfds, otherwise it scarifies performance. according to testing result, each ioeventfd deleing needs about 5ms, within which memory mapping rebuilding needs about 4ms. With many Nics and vmchannel in a VM doing migrating, there can be many ioeventfds deleting which increasing downtime remarkably. Signed-off-by: Gonglei Signed-off-by: Herongguang Signed-off-by: Paolo Bonzini --- memory.c | 33 +++++++++++++++++++++++---------- 1 file changed, 23 insertions(+), 10 deletions(-) diff --git a/memory.c b/memory.c index 678661e2bb..829d56db37 100644 --- a/memory.c +++ b/memory.c @@ -28,6 +28,7 @@ static unsigned memory_region_transaction_depth; static bool memory_region_update_pending; +static bool ioeventfd_update_pending; static bool global_dirty_log = false; /* flat_view_mutex is taken around reading as->current_map; the critical @@ -786,22 +787,34 @@ void memory_region_transaction_begin(void) ++memory_region_transaction_depth; } +static void memory_region_clear_pending(void) +{ + memory_region_update_pending = false; + ioeventfd_update_pending = false; +} + void memory_region_transaction_commit(void) { AddressSpace *as; assert(memory_region_transaction_depth); --memory_region_transaction_depth; - if (!memory_region_transaction_depth && memory_region_update_pending) { - memory_region_update_pending = false; - MEMORY_LISTENER_CALL_GLOBAL(begin, Forward); + if (!memory_region_transaction_depth) { + if (memory_region_update_pending) { + MEMORY_LISTENER_CALL_GLOBAL(begin, Forward); - QTAILQ_FOREACH(as, &address_spaces, address_spaces_link) { - address_space_update_topology(as); - } + QTAILQ_FOREACH(as, &address_spaces, address_spaces_link) { + address_space_update_topology(as); + } - MEMORY_LISTENER_CALL_GLOBAL(commit, Forward); - } + MEMORY_LISTENER_CALL_GLOBAL(commit, Forward); + } else if (ioeventfd_update_pending) { + QTAILQ_FOREACH(as, &address_spaces, address_spaces_link) { + address_space_update_ioeventfds(as); + } + } + memory_region_clear_pending(); + } } static void memory_region_destructor_none(MemoryRegion *mr) @@ -1373,7 +1386,7 @@ void memory_region_add_eventfd(MemoryRegion *mr, memmove(&mr->ioeventfds[i+1], &mr->ioeventfds[i], sizeof(*mr->ioeventfds) * (mr->ioeventfd_nb-1 - i)); mr->ioeventfds[i] = mrfd; - memory_region_update_pending |= mr->enabled; + ioeventfd_update_pending |= mr->enabled; memory_region_transaction_commit(); } @@ -1406,7 +1419,7 @@ void memory_region_del_eventfd(MemoryRegion *mr, --mr->ioeventfd_nb; mr->ioeventfds = g_realloc(mr->ioeventfds, sizeof(*mr->ioeventfds)*mr->ioeventfd_nb + 1); - memory_region_update_pending |= mr->enabled; + ioeventfd_update_pending |= mr->enabled; memory_region_transaction_commit(); } -- cgit v1.2.3 From 3fb5bf5730b90c08d5d1c027900efae210d9b326 Mon Sep 17 00:00:00 2001 From: Peter Crosthwaite Date: Mon, 12 May 2014 01:13:47 -0700 Subject: memory: Simplify mr_add_subregion() if-else This if else is not needed. The previous call to memory_region_add (whether _overlap or not) will always set priority and may_overlap to desired values. And its not possible to get here without having called memory_region_add_subregion due to the null guard on parent. So we can just directly call memory_region_add_subregion_common. Signed-off-by: Peter Crosthwaite Signed-off-by: Paolo Bonzini --- memory.c | 8 +------- 1 file changed, 1 insertion(+), 7 deletions(-) diff --git a/memory.c b/memory.c index 829d56db37..3811bd16f2 100644 --- a/memory.c +++ b/memory.c @@ -1514,8 +1514,6 @@ void memory_region_set_enabled(MemoryRegion *mr, bool enabled) void memory_region_set_address(MemoryRegion *mr, hwaddr addr) { MemoryRegion *parent = mr->parent; - int priority = mr->priority; - bool may_overlap = mr->may_overlap; if (addr == mr->addr || !parent) { mr->addr = addr; @@ -1525,11 +1523,7 @@ void memory_region_set_address(MemoryRegion *mr, hwaddr addr) memory_region_transaction_begin(); memory_region_ref(mr); memory_region_del_subregion(parent, mr); - if (may_overlap) { - memory_region_add_subregion_overlap(parent, addr, mr, priority); - } else { - memory_region_add_subregion(parent, addr, mr); - } + memory_region_add_subregion_common(parent, addr, mr); memory_region_unref(mr); memory_region_transaction_commit(); } -- cgit v1.2.3 From a656e22f0993ca1d84cabf47a33e99f27acc3a28 Mon Sep 17 00:00:00 2001 From: Peter Crosthwaite Date: Mon, 2 Jun 2014 19:08:44 -0700 Subject: exec: dummy_section: Pass address space through. Rather than use the global singleton. Signed-off-by: Peter Crosthwaite Signed-off-by: Paolo Bonzini --- exec.c | 14 ++++++++------ 1 file changed, 8 insertions(+), 6 deletions(-) diff --git a/exec.c b/exec.c index 6ce989a912..c3fbbb3fb8 100644 --- a/exec.c +++ b/exec.c @@ -1776,10 +1776,12 @@ static subpage_t *subpage_init(AddressSpace *as, hwaddr base) return mmio; } -static uint16_t dummy_section(PhysPageMap *map, MemoryRegion *mr) +static uint16_t dummy_section(PhysPageMap *map, AddressSpace *as, + MemoryRegion *mr) { + assert(as); MemoryRegionSection section = { - .address_space = &address_space_memory, + .address_space = as, .mr = mr, .offset_within_address_space = 0, .offset_within_region = 0, @@ -1811,13 +1813,13 @@ static void mem_begin(MemoryListener *listener) AddressSpaceDispatch *d = g_new0(AddressSpaceDispatch, 1); uint16_t n; - n = dummy_section(&d->map, &io_mem_unassigned); + n = dummy_section(&d->map, as, &io_mem_unassigned); assert(n == PHYS_SECTION_UNASSIGNED); - n = dummy_section(&d->map, &io_mem_notdirty); + n = dummy_section(&d->map, as, &io_mem_notdirty); assert(n == PHYS_SECTION_NOTDIRTY); - n = dummy_section(&d->map, &io_mem_rom); + n = dummy_section(&d->map, as, &io_mem_rom); assert(n == PHYS_SECTION_ROM); - n = dummy_section(&d->map, &io_mem_watch); + n = dummy_section(&d->map, as, &io_mem_watch); assert(n == PHYS_SECTION_WATCH); d->phys_map = (PhysPageEntry) { .ptr = PHYS_MAP_NODE_NIL, .skip = 1 }; -- cgit v1.2.3 From c9299e2fe789b085f463b2e4232507f5e77f50b4 Mon Sep 17 00:00:00 2001 From: Sergey Fedorov Date: Tue, 10 Jun 2014 13:10:28 +0400 Subject: qtest: fix qtest_clock_warp() for no deadline case Use dedicated qemu_soonest_timeout() instead of MIN(). Signed-off-by: Sergey Fedorov Signed-off-by: Paolo Bonzini --- cpus.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/cpus.c b/cpus.c index dd7ac13621..af06dc0ae6 100644 --- a/cpus.c +++ b/cpus.c @@ -347,7 +347,7 @@ void qtest_clock_warp(int64_t dest) assert(qtest_enabled()); while (clock < dest) { int64_t deadline = qemu_clock_deadline_ns_all(QEMU_CLOCK_VIRTUAL); - int64_t warp = MIN(dest - clock, deadline); + int64_t warp = qemu_soonest_timeout(dest - clock, deadline); seqlock_write_lock(&timers_state.vm_clock_seqlock); qemu_icount_bias += warp; seqlock_write_unlock(&timers_state.vm_clock_seqlock); -- cgit v1.2.3 From 0598701a4947ddbc19391e008cf753f8f22f3c25 Mon Sep 17 00:00:00 2001 From: Peter Crosthwaite Date: Thu, 5 Jun 2014 23:14:44 -0700 Subject: memory: MemoryRegion: factor out subregion add functionality Split off the core looping code that actually adds subregions into it's own fn. This prepares support for Memory Region qomification where setting the MR address or parent via QOM will back onto this more minimal function. Signed-off-by: Peter Crosthwaite [Rename new function. - Paolo] Signed-off-by: Paolo Bonzini --- memory.c | 18 ++++++++++++------ 1 file changed, 12 insertions(+), 6 deletions(-) diff --git a/memory.c b/memory.c index 3811bd16f2..15f63e8b99 100644 --- a/memory.c +++ b/memory.c @@ -1423,18 +1423,15 @@ void memory_region_del_eventfd(MemoryRegion *mr, memory_region_transaction_commit(); } -static void memory_region_add_subregion_common(MemoryRegion *mr, - hwaddr offset, - MemoryRegion *subregion) +static void memory_region_update_parent_subregions(MemoryRegion *subregion) { + hwaddr offset = subregion->addr; + MemoryRegion *mr = subregion->parent; MemoryRegion *other; memory_region_transaction_begin(); - assert(!subregion->parent); memory_region_ref(subregion); - subregion->parent = mr; - subregion->addr = offset; QTAILQ_FOREACH(other, &mr->subregions, subregions_link) { if (subregion->may_overlap || other->may_overlap) { continue; @@ -1468,6 +1465,15 @@ done: memory_region_transaction_commit(); } +static void memory_region_add_subregion_common(MemoryRegion *mr, + hwaddr offset, + MemoryRegion *subregion) +{ + assert(!subregion->parent); + subregion->parent = mr; + subregion->addr = offset; + memory_region_update_parent_subregions(subregion); +} void memory_region_add_subregion(MemoryRegion *mr, hwaddr offset, -- cgit v1.2.3 From 67891b8a85cd8238b8c55ef438b87146ff3646aa Mon Sep 17 00:00:00 2001 From: Peter Crosthwaite Date: Thu, 5 Jun 2014 23:15:18 -0700 Subject: memory: MemoryRegion: factor out memory region re-adder memory_region_set_address is mostly just a function that deletes and re-adds a memory region. Factor this generic functionality out into a re-usable function. This prepares support for further QOMification of MemoryRegion. Signed-off-by: Peter Crosthwaite Signed-off-by: Paolo Bonzini --- memory.c | 26 ++++++++++++++++---------- 1 file changed, 16 insertions(+), 10 deletions(-) diff --git a/memory.c b/memory.c index 15f63e8b99..06a4af7aa7 100644 --- a/memory.c +++ b/memory.c @@ -1517,21 +1517,27 @@ void memory_region_set_enabled(MemoryRegion *mr, bool enabled) memory_region_transaction_commit(); } -void memory_region_set_address(MemoryRegion *mr, hwaddr addr) +static void memory_region_readd_subregion(MemoryRegion *mr) { MemoryRegion *parent = mr->parent; - if (addr == mr->addr || !parent) { - mr->addr = addr; - return; + if (parent) { + memory_region_transaction_begin(); + memory_region_ref(mr); + memory_region_del_subregion(parent, mr); + mr->parent = parent; + memory_region_update_parent_subregions(mr); + memory_region_unref(mr); + memory_region_transaction_commit(); } +} - memory_region_transaction_begin(); - memory_region_ref(mr); - memory_region_del_subregion(parent, mr); - memory_region_add_subregion_common(parent, addr, mr); - memory_region_unref(mr); - memory_region_transaction_commit(); +void memory_region_set_address(MemoryRegion *mr, hwaddr addr) +{ + if (addr != mr->addr) { + mr->addr = addr; + memory_region_readd_subregion(mr); + } } void memory_region_set_alias_offset(MemoryRegion *mr, hwaddr offset) -- cgit v1.2.3 From feca4ac18b7e0df7cdc6e791a7e98cc303feb890 Mon Sep 17 00:00:00 2001 From: Paolo Bonzini Date: Wed, 11 Jun 2014 11:18:09 +0200 Subject: memory: MemoryRegion: rename parent to container Avoid confusion with the QOM parent. Reviewed-by: Peter Crosthwaite Signed-off-by: Paolo Bonzini --- include/exec/memory.h | 20 ++++++++++---------- memory.c | 40 ++++++++++++++++++++-------------------- 2 files changed, 30 insertions(+), 30 deletions(-) diff --git a/include/exec/memory.h b/include/exec/memory.h index 1d55ad94a4..549ae734e6 100644 --- a/include/exec/memory.h +++ b/include/exec/memory.h @@ -135,7 +135,7 @@ struct MemoryRegion { const MemoryRegionIOMMUOps *iommu_ops; void *opaque; struct Object *owner; - MemoryRegion *parent; + MemoryRegion *container; Int128 size; hwaddr addr; void (*destructor)(MemoryRegion *mr); @@ -815,11 +815,11 @@ void memory_region_set_enabled(MemoryRegion *mr, bool enabled); /* * memory_region_set_address: dynamically update the address of a region * - * Dynamically updates the address of a region, relative to its parent. + * Dynamically updates the address of a region, relative to its container. * May be used on regions are currently part of a memory hierarchy. * * @mr: the region to be updated - * @addr: new address, relative to parent region + * @addr: new address, relative to container region */ void memory_region_set_address(MemoryRegion *mr, hwaddr addr); @@ -836,16 +836,16 @@ void memory_region_set_alias_offset(MemoryRegion *mr, hwaddr offset); /** - * memory_region_present: checks if an address relative to a @parent - * translates into #MemoryRegion within @parent + * memory_region_present: checks if an address relative to a @container + * translates into #MemoryRegion within @container * - * Answer whether a #MemoryRegion within @parent covers the address + * Answer whether a #MemoryRegion within @container covers the address * @addr. * - * @parent: a #MemoryRegion within which @addr is a relative address - * @addr: the area within @parent to be searched + * @container: a #MemoryRegion within which @addr is a relative address + * @addr: the area within @container to be searched */ -bool memory_region_present(MemoryRegion *parent, hwaddr addr); +bool memory_region_present(MemoryRegion *container, hwaddr addr); /** * memory_region_find: translate an address/size relative to a @@ -866,7 +866,7 @@ bool memory_region_present(MemoryRegion *parent, hwaddr addr); * Similarly, the .@offset_within_address_space is relative to the * address space that contains both regions, the passed and the * returned one. However, in the special case where the @mr argument - * has no parent (and thus is the root of the address space), the + * has no container (and thus is the root of the address space), the * following will hold: * .@offset_within_address_space >= @addr * .@offset_within_address_space + .@size <= @addr + @size diff --git a/memory.c b/memory.c index 06a4af7aa7..85798b0299 100644 --- a/memory.c +++ b/memory.c @@ -485,8 +485,8 @@ static AddressSpace *memory_region_to_address_space(MemoryRegion *mr) { AddressSpace *as; - while (mr->parent) { - mr = mr->parent; + while (mr->container) { + mr = mr->container; } QTAILQ_FOREACH(as, &address_spaces, address_spaces_link) { if (mr == as->root) { @@ -850,7 +850,7 @@ void memory_region_init(MemoryRegion *mr, mr->opaque = NULL; mr->owner = owner; mr->iommu_ops = NULL; - mr->parent = NULL; + mr->container = NULL; mr->size = int128_make64(size); if (size == UINT64_MAX) { mr->size = int128_2_64(); @@ -1423,10 +1423,10 @@ void memory_region_del_eventfd(MemoryRegion *mr, memory_region_transaction_commit(); } -static void memory_region_update_parent_subregions(MemoryRegion *subregion) +static void memory_region_update_container_subregions(MemoryRegion *subregion) { hwaddr offset = subregion->addr; - MemoryRegion *mr = subregion->parent; + MemoryRegion *mr = subregion->container; MemoryRegion *other; memory_region_transaction_begin(); @@ -1469,10 +1469,10 @@ static void memory_region_add_subregion_common(MemoryRegion *mr, hwaddr offset, MemoryRegion *subregion) { - assert(!subregion->parent); - subregion->parent = mr; + assert(!subregion->container); + subregion->container = mr; subregion->addr = offset; - memory_region_update_parent_subregions(subregion); + memory_region_update_container_subregions(subregion); } void memory_region_add_subregion(MemoryRegion *mr, @@ -1498,8 +1498,8 @@ void memory_region_del_subregion(MemoryRegion *mr, MemoryRegion *subregion) { memory_region_transaction_begin(); - assert(subregion->parent == mr); - subregion->parent = NULL; + assert(subregion->container == mr); + subregion->container = NULL; QTAILQ_REMOVE(&mr->subregions, subregion, subregions_link); memory_region_unref(subregion); memory_region_update_pending |= mr->enabled && subregion->enabled; @@ -1519,14 +1519,14 @@ void memory_region_set_enabled(MemoryRegion *mr, bool enabled) static void memory_region_readd_subregion(MemoryRegion *mr) { - MemoryRegion *parent = mr->parent; + MemoryRegion *container = mr->container; - if (parent) { + if (container) { memory_region_transaction_begin(); memory_region_ref(mr); - memory_region_del_subregion(parent, mr); - mr->parent = parent; - memory_region_update_parent_subregions(mr); + memory_region_del_subregion(container, mr); + mr->container = container; + memory_region_update_container_subregions(mr); memory_region_unref(mr); memory_region_transaction_commit(); } @@ -1578,10 +1578,10 @@ static FlatRange *flatview_lookup(FlatView *view, AddrRange addr) sizeof(FlatRange), cmp_flatrange_addr); } -bool memory_region_present(MemoryRegion *parent, hwaddr addr) +bool memory_region_present(MemoryRegion *container, hwaddr addr) { - MemoryRegion *mr = memory_region_find(parent, addr, 1).mr; - if (!mr || (mr == parent)) { + MemoryRegion *mr = memory_region_find(container, addr, 1).mr; + if (!mr || (mr == container)) { return false; } memory_region_unref(mr); @@ -1599,8 +1599,8 @@ MemoryRegionSection memory_region_find(MemoryRegion *mr, FlatRange *fr; addr += mr->addr; - for (root = mr; root->parent; ) { - root = root->parent; + for (root = mr; root->container; ) { + root = root->container; addr += root->addr; } -- cgit v1.2.3 From ab5b3db5d711b290d63e954dc64647dd51cef962 Mon Sep 17 00:00:00 2001 From: Fam Zheng Date: Fri, 13 Jun 2014 14:34:41 +0800 Subject: memory: Don't call memory_region_update_coalesced_range if nothing changed With huge number of PCI devices in the system (for example, 200 virtio-blk-pci), this unconditional call can slow down emulation of irrelevant PCI operations drastically, such as a BAR update on a device that has no coalescing region. So avoid it. Signed-off-by: Fam Zheng Signed-off-by: Paolo Bonzini --- memory.c | 7 ++++++- 1 file changed, 6 insertions(+), 1 deletion(-) diff --git a/memory.c b/memory.c index 85798b0299..4895e25376 100644 --- a/memory.c +++ b/memory.c @@ -1332,6 +1332,7 @@ void memory_region_add_coalescing(MemoryRegion *mr, void memory_region_clear_coalescing(MemoryRegion *mr) { CoalescedMemoryRange *cmr; + bool updated = false; qemu_flush_coalesced_mmio_buffer(); mr->flush_coalesced_mmio = false; @@ -1340,8 +1341,12 @@ void memory_region_clear_coalescing(MemoryRegion *mr) cmr = QTAILQ_FIRST(&mr->coalesced); QTAILQ_REMOVE(&mr->coalesced, cmr, link); g_free(cmr); + updated = true; + } + + if (updated) { + memory_region_update_coalesced_range(mr); } - memory_region_update_coalesced_range(mr); } void memory_region_set_flush_coalesced(MemoryRegion *mr) -- cgit v1.2.3