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);
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;
/* 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);
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;
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);
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);
}
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);
}
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)
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", "
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)",
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;
.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,
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);
}
}
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) {
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);
XenPCIPassthroughState *s = container_of(l, XenPCIPassthroughState,
memory_listener);
+ memory_region_ref(sec->mr);
xen_pt_region_update(s, sec, true);
}
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)
XenPCIPassthroughState *s = container_of(l, XenPCIPassthroughState,
io_listener);
+ memory_region_ref(sec->mr);
xen_pt_region_update(s, sec, true);
}
io_listener);
xen_pt_region_update(s, sec, false);
+ memory_region_unref(sec->mr);
}
static const MemoryListener xen_pt_memory_listener = {
#include "qemu/thread.h"
typedef struct {
+ MemoryRegion *mr;
void *host_addr;
hwaddr guest_addr;
uint64_t size;
static void kvm_region_add(MemoryListener *listener,
MemoryRegionSection *section)
{
+ memory_region_ref(section->mr);
kvm_set_phys_mem(section, true);
}
MemoryRegionSection *section)
{
kvm_set_phys_mem(section, false);
+ memory_region_unref(section->mr);
}
static void kvm_log_sync(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, \
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);
}
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);
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;
}
memory_region_transaction_begin();
assert(!subregion->parent);
+ memory_region_ref(subregion);
subregion->parent = mr;
subregion->addr = offset;
QTAILQ_FOREACH(other, &mr->subregions, subregions_link) {
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();
}
}
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();
}
if (!mr) {
return false;
}
+ memory_region_unref(mr);
return true;
}
ret.size = range.size;
ret.offset_within_address_space = int128_get64(range.start);
ret.readonly = fr->readonly;
+ memory_region_ref(ret.mr);
+
return ret;
}
abort();
}
}
+ memory_region_unref(kd->mr);
g_free(kd);
}
}
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)
}
}
section = memory_region_find(get_system_memory(), phys_addr, 1);
+ memory_region_unref(section.mr);
if (!int128_nz(section.size)) {
return -1;
}
static void xen_region_add(MemoryListener *listener,
MemoryRegionSection *section)
{
+ memory_region_ref(section->mr);
xen_set_memory(listener, section, true);
}
MemoryRegionSection *section)
{
xen_set_memory(listener, section, false);
+ memory_region_unref(section->mr);
}
static void xen_sync_dirty_bitmap(XenIOState *state,