memory: add ref/unref calls
Add ref/unref calls at the following places: - places where memory regions are stashed by a listener and used outside the BQL (including in Xen or KVM). - memory_region_find callsites - creation of aliases and containers (only the aliased/contained region gets a reference to avoid loops) - around calls to del_subregion/add_subregion, where the region could disappear after the first call Signed-off-by: Paolo Bonzini <pbonzini@redhat.com>
This commit is contained in:
parent
3ce10901ca
commit
dfde4e6e1a
3
exec.c
3
exec.c
@ -763,11 +763,14 @@ static uint16_t phys_section_add(MemoryRegionSection *section)
|
||||
phys_sections_nb_alloc);
|
||||
}
|
||||
phys_sections[phys_sections_nb] = *section;
|
||||
memory_region_ref(section->mr);
|
||||
return phys_sections_nb++;
|
||||
}
|
||||
|
||||
static void phys_section_destroy(MemoryRegion *mr)
|
||||
{
|
||||
memory_region_unref(mr);
|
||||
|
||||
if (mr->subpage) {
|
||||
subpage_t *subpage = container_of(mr, subpage_t, iomem);
|
||||
memory_region_destroy(&subpage->iomem);
|
||||
|
@ -727,6 +727,7 @@ int rom_load_all(void)
|
||||
addr += rom->romsize;
|
||||
section = memory_region_find(get_system_memory(), rom->addr, 1);
|
||||
rom->isrom = int128_nz(section.size) && memory_region_is_rom(section.mr);
|
||||
memory_region_unref(section.mr);
|
||||
}
|
||||
qemu_register_reset(rom_reset, NULL);
|
||||
roms_loaded = 1;
|
||||
|
@ -1126,6 +1126,11 @@ static void fimd_update_memory_section(Exynos4210fimdState *s, unsigned win)
|
||||
/* Total number of bytes of virtual screen used by current window */
|
||||
w->fb_len = fb_mapped_len = (w->virtpage_width + w->virtpage_offsize) *
|
||||
(w->rightbot_y - w->lefttop_y + 1);
|
||||
|
||||
/* TODO: add .exit and unref the region there. Not needed yet since sysbus
|
||||
* does not support hot-unplug.
|
||||
*/
|
||||
memory_region_unref(w->mem_section.mr);
|
||||
w->mem_section = memory_region_find(sysbus_address_space(&s->busdev),
|
||||
fb_start_addr, w->fb_len);
|
||||
assert(w->mem_section.mr);
|
||||
@ -1154,6 +1159,7 @@ static void fimd_update_memory_section(Exynos4210fimdState *s, unsigned win)
|
||||
return;
|
||||
|
||||
error_return:
|
||||
memory_region_unref(w->mem_section.mr);
|
||||
w->mem_section.mr = NULL;
|
||||
w->mem_section.size = int128_zero();
|
||||
w->host_fb_addr = NULL;
|
||||
|
@ -54,11 +54,11 @@ void framebuffer_update_display(
|
||||
src_len = src_width * rows;
|
||||
|
||||
mem_section = memory_region_find(address_space, base, src_len);
|
||||
mem = mem_section.mr;
|
||||
if (int128_get64(mem_section.size) != src_len ||
|
||||
!memory_region_is_ram(mem_section.mr)) {
|
||||
return;
|
||||
goto out;
|
||||
}
|
||||
mem = mem_section.mr;
|
||||
assert(mem);
|
||||
assert(mem_section.offset_within_address_space == base);
|
||||
|
||||
@ -68,10 +68,10 @@ void framebuffer_update_display(
|
||||
but it's not really worth it as dirty flag tracking will probably
|
||||
already have failed above. */
|
||||
if (!src_base)
|
||||
return;
|
||||
goto out;
|
||||
if (src_len != src_width * rows) {
|
||||
cpu_physical_memory_unmap(src_base, src_len, 0, 0);
|
||||
return;
|
||||
goto out;
|
||||
}
|
||||
src = src_base;
|
||||
dest = surface_data(ds);
|
||||
@ -102,10 +102,12 @@ void framebuffer_update_display(
|
||||
}
|
||||
cpu_physical_memory_unmap(src_base, src_len, 0, 0);
|
||||
if (first < 0) {
|
||||
return;
|
||||
goto out;
|
||||
}
|
||||
memory_region_reset_dirty(mem, mem_section.offset_within_region, src_len,
|
||||
DIRTY_MEMORY_VGA);
|
||||
*first_row = first;
|
||||
*last_row = last;
|
||||
out:
|
||||
memory_region_unref(mem);
|
||||
}
|
||||
|
@ -605,6 +605,7 @@ static void vapic_map_rom_writable(VAPICROMState *s)
|
||||
rom_size);
|
||||
memory_region_add_subregion_overlap(as, rom_paddr, &s->rom, 1000);
|
||||
s->rom_mapped_writable = true;
|
||||
memory_region_unref(section.mr);
|
||||
}
|
||||
|
||||
static int vapic_prepare(VAPICROMState *s)
|
||||
|
@ -1969,6 +1969,7 @@ static void vfio_listener_region_add(MemoryListener *listener,
|
||||
DPRINTF("region_add %"HWADDR_PRIx" - %"HWADDR_PRIx" [%p]\n",
|
||||
iova, end - 1, vaddr);
|
||||
|
||||
memory_region_ref(section->mr);
|
||||
ret = vfio_dma_map(container, iova, end - iova, vaddr, section->readonly);
|
||||
if (ret) {
|
||||
error_report("vfio_dma_map(%p, 0x%"HWADDR_PRIx", "
|
||||
@ -2010,6 +2011,7 @@ static void vfio_listener_region_del(MemoryListener *listener,
|
||||
iova, end - 1);
|
||||
|
||||
ret = vfio_dma_unmap(container, iova, end - iova);
|
||||
memory_region_unref(section->mr);
|
||||
if (ret) {
|
||||
error_report("vfio_dma_unmap(%p, 0x%"HWADDR_PRIx", "
|
||||
"0x%"HWADDR_PRIx") = %d (%m)",
|
||||
|
@ -64,8 +64,12 @@ out:
|
||||
static void hostmem_listener_commit(MemoryListener *listener)
|
||||
{
|
||||
HostMem *hostmem = container_of(listener, HostMem, listener);
|
||||
int i;
|
||||
|
||||
qemu_mutex_lock(&hostmem->current_regions_lock);
|
||||
for (i = 0; i < hostmem->num_current_regions; i++) {
|
||||
memory_region_unref(hostmem->current_regions[i].mr);
|
||||
}
|
||||
g_free(hostmem->current_regions);
|
||||
hostmem->current_regions = hostmem->new_regions;
|
||||
hostmem->num_current_regions = hostmem->num_new_regions;
|
||||
@ -92,8 +96,11 @@ static void hostmem_append_new_region(HostMem *hostmem,
|
||||
.guest_addr = section->offset_within_address_space,
|
||||
.size = int128_get64(section->size),
|
||||
.readonly = section->readonly,
|
||||
.mr = section->mr,
|
||||
};
|
||||
hostmem->num_new_regions++;
|
||||
|
||||
memory_region_ref(section->mr);
|
||||
}
|
||||
|
||||
static void hostmem_listener_append_region(MemoryListener *listener,
|
||||
|
@ -497,6 +497,7 @@ static void vhost_region_add(MemoryListener *listener,
|
||||
dev->mem_sections = g_renew(MemoryRegionSection, dev->mem_sections,
|
||||
dev->n_mem_sections);
|
||||
dev->mem_sections[dev->n_mem_sections - 1] = *section;
|
||||
memory_region_ref(section->mr);
|
||||
vhost_set_memory(listener, section, true);
|
||||
}
|
||||
|
||||
@ -512,6 +513,7 @@ static void vhost_region_del(MemoryListener *listener,
|
||||
}
|
||||
|
||||
vhost_set_memory(listener, section, false);
|
||||
memory_region_unref(section->mr);
|
||||
for (i = 0; i < dev->n_mem_sections; ++i) {
|
||||
if (dev->mem_sections[i].offset_within_address_space
|
||||
== section->offset_within_address_space) {
|
||||
|
@ -205,6 +205,7 @@ static void virtio_balloon_handle_output(VirtIODevice *vdev, VirtQueue *vq)
|
||||
addr = section.offset_within_region;
|
||||
balloon_page(memory_region_get_ram_ptr(section.mr) + addr,
|
||||
!!(vq == s->dvq));
|
||||
memory_region_unref(section.mr);
|
||||
}
|
||||
|
||||
virtqueue_push(vq, &elem, offset);
|
||||
|
@ -606,6 +606,7 @@ static void xen_pt_region_add(MemoryListener *l, MemoryRegionSection *sec)
|
||||
XenPCIPassthroughState *s = container_of(l, XenPCIPassthroughState,
|
||||
memory_listener);
|
||||
|
||||
memory_region_ref(sec->mr);
|
||||
xen_pt_region_update(s, sec, true);
|
||||
}
|
||||
|
||||
@ -615,6 +616,7 @@ static void xen_pt_region_del(MemoryListener *l, MemoryRegionSection *sec)
|
||||
memory_listener);
|
||||
|
||||
xen_pt_region_update(s, sec, false);
|
||||
memory_region_unref(sec->mr);
|
||||
}
|
||||
|
||||
static void xen_pt_io_region_add(MemoryListener *l, MemoryRegionSection *sec)
|
||||
@ -622,6 +624,7 @@ static void xen_pt_io_region_add(MemoryListener *l, MemoryRegionSection *sec)
|
||||
XenPCIPassthroughState *s = container_of(l, XenPCIPassthroughState,
|
||||
io_listener);
|
||||
|
||||
memory_region_ref(sec->mr);
|
||||
xen_pt_region_update(s, sec, true);
|
||||
}
|
||||
|
||||
@ -631,6 +634,7 @@ static void xen_pt_io_region_del(MemoryListener *l, MemoryRegionSection *sec)
|
||||
io_listener);
|
||||
|
||||
xen_pt_region_update(s, sec, false);
|
||||
memory_region_unref(sec->mr);
|
||||
}
|
||||
|
||||
static const MemoryListener xen_pt_memory_listener = {
|
||||
|
@ -18,6 +18,7 @@
|
||||
#include "qemu/thread.h"
|
||||
|
||||
typedef struct {
|
||||
MemoryRegion *mr;
|
||||
void *host_addr;
|
||||
hwaddr guest_addr;
|
||||
uint64_t size;
|
||||
|
@ -789,6 +789,7 @@ static void kvm_set_phys_mem(MemoryRegionSection *section, bool add)
|
||||
static void kvm_region_add(MemoryListener *listener,
|
||||
MemoryRegionSection *section)
|
||||
{
|
||||
memory_region_ref(section->mr);
|
||||
kvm_set_phys_mem(section, true);
|
||||
}
|
||||
|
||||
@ -796,6 +797,7 @@ static void kvm_region_del(MemoryListener *listener,
|
||||
MemoryRegionSection *section)
|
||||
{
|
||||
kvm_set_phys_mem(section, false);
|
||||
memory_region_unref(section->mr);
|
||||
}
|
||||
|
||||
static void kvm_log_sync(MemoryListener *listener,
|
||||
|
21
memory.c
21
memory.c
@ -148,6 +148,7 @@ static bool memory_listener_match(MemoryListener *listener,
|
||||
} \
|
||||
} while (0)
|
||||
|
||||
/* No need to ref/unref .mr, the FlatRange keeps it alive. */
|
||||
#define MEMORY_LISTENER_UPDATE_REGION(fr, as, dir, callback) \
|
||||
MEMORY_LISTENER_CALL(callback, dir, (&(MemoryRegionSection) { \
|
||||
.mr = (fr)->mr, \
|
||||
@ -263,11 +264,17 @@ static void flatview_insert(FlatView *view, unsigned pos, FlatRange *range)
|
||||
memmove(view->ranges + pos + 1, view->ranges + pos,
|
||||
(view->nr - pos) * sizeof(FlatRange));
|
||||
view->ranges[pos] = *range;
|
||||
memory_region_ref(range->mr);
|
||||
++view->nr;
|
||||
}
|
||||
|
||||
static void flatview_destroy(FlatView *view)
|
||||
{
|
||||
int i;
|
||||
|
||||
for (i = 0; i < view->nr; i++) {
|
||||
memory_region_unref(view->ranges[i].mr);
|
||||
}
|
||||
g_free(view->ranges);
|
||||
}
|
||||
|
||||
@ -709,6 +716,11 @@ static void memory_region_destructor_ram(MemoryRegion *mr)
|
||||
qemu_ram_free(mr->ram_addr);
|
||||
}
|
||||
|
||||
static void memory_region_destructor_alias(MemoryRegion *mr)
|
||||
{
|
||||
memory_region_unref(mr->alias);
|
||||
}
|
||||
|
||||
static void memory_region_destructor_ram_from_ptr(MemoryRegion *mr)
|
||||
{
|
||||
qemu_ram_free_from_ptr(mr->ram_addr);
|
||||
@ -964,6 +976,8 @@ void memory_region_init_alias(MemoryRegion *mr,
|
||||
uint64_t size)
|
||||
{
|
||||
memory_region_init(mr, owner, name, size);
|
||||
memory_region_ref(orig);
|
||||
mr->destructor = memory_region_destructor_alias;
|
||||
mr->alias = orig;
|
||||
mr->alias_offset = offset;
|
||||
}
|
||||
@ -1342,6 +1356,7 @@ static void memory_region_add_subregion_common(MemoryRegion *mr,
|
||||
memory_region_transaction_begin();
|
||||
|
||||
assert(!subregion->parent);
|
||||
memory_region_ref(subregion);
|
||||
subregion->parent = mr;
|
||||
subregion->addr = offset;
|
||||
QTAILQ_FOREACH(other, &mr->subregions, subregions_link) {
|
||||
@ -1404,6 +1419,7 @@ void memory_region_del_subregion(MemoryRegion *mr,
|
||||
assert(subregion->parent == mr);
|
||||
subregion->parent = NULL;
|
||||
QTAILQ_REMOVE(&mr->subregions, subregion, subregions_link);
|
||||
memory_region_unref(subregion);
|
||||
memory_region_update_pending |= mr->enabled && subregion->enabled;
|
||||
memory_region_transaction_commit();
|
||||
}
|
||||
@ -1431,12 +1447,14 @@ 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_unref(mr);
|
||||
memory_region_transaction_commit();
|
||||
}
|
||||
|
||||
@ -1484,6 +1502,7 @@ bool memory_region_present(MemoryRegion *parent, hwaddr addr)
|
||||
if (!mr) {
|
||||
return false;
|
||||
}
|
||||
memory_region_unref(mr);
|
||||
return true;
|
||||
}
|
||||
|
||||
@ -1523,6 +1542,8 @@ MemoryRegionSection memory_region_find(MemoryRegion *mr,
|
||||
ret.size = range.size;
|
||||
ret.offset_within_address_space = int128_get64(range.start);
|
||||
ret.readonly = fr->readonly;
|
||||
memory_region_ref(ret.mr);
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
|
@ -233,6 +233,7 @@ static void kvm_arm_machine_init_done(Notifier *notifier, void *data)
|
||||
abort();
|
||||
}
|
||||
}
|
||||
memory_region_unref(kd->mr);
|
||||
g_free(kd);
|
||||
}
|
||||
}
|
||||
@ -258,6 +259,7 @@ void kvm_arm_register_device(MemoryRegion *mr, uint64_t devid)
|
||||
kd->kda.id = devid;
|
||||
kd->kda.addr = -1;
|
||||
QSLIST_INSERT_HEAD(&kvm_devices_head, kd, entries);
|
||||
memory_region_ref(kd->mr);
|
||||
}
|
||||
|
||||
bool write_kvmstate_to_list(ARMCPU *cpu)
|
||||
|
@ -845,6 +845,7 @@ hwaddr cpu_get_phys_page_debug(CPUSPARCState *env, target_ulong addr)
|
||||
}
|
||||
}
|
||||
section = memory_region_find(get_system_memory(), phys_addr, 1);
|
||||
memory_region_unref(section.mr);
|
||||
if (!int128_nz(section.size)) {
|
||||
return -1;
|
||||
}
|
||||
|
@ -459,6 +459,7 @@ static void xen_set_memory(struct MemoryListener *listener,
|
||||
static void xen_region_add(MemoryListener *listener,
|
||||
MemoryRegionSection *section)
|
||||
{
|
||||
memory_region_ref(section->mr);
|
||||
xen_set_memory(listener, section, true);
|
||||
}
|
||||
|
||||
@ -466,6 +467,7 @@ static void xen_region_del(MemoryListener *listener,
|
||||
MemoryRegionSection *section)
|
||||
{
|
||||
xen_set_memory(listener, section, false);
|
||||
memory_region_unref(section->mr);
|
||||
}
|
||||
|
||||
static void xen_sync_dirty_bitmap(XenIOState *state,
|
||||
|
Loading…
Reference in New Issue
Block a user