diff --git a/memory.c b/memory.c index 5a0cc66982dc8c165a40aa8abaac1c8016339381..0acebb1f22f040649a7c055dddb33310e9179de4 100644 --- a/memory.c +++ b/memory.c @@ -1887,23 +1887,16 @@ static FlatRange *flatview_lookup(FlatView *view, AddrRange addr) sizeof(FlatRange), cmp_flatrange_addr); } -bool memory_region_present(MemoryRegion *container, hwaddr addr) -{ - MemoryRegion *mr = memory_region_find(container, addr, 1).mr; - if (!mr || (mr == container)) { - return false; - } - memory_region_unref(mr); - return true; -} - bool memory_region_is_mapped(MemoryRegion *mr) { return mr->container ? true : false; } -MemoryRegionSection memory_region_find(MemoryRegion *mr, - hwaddr addr, uint64_t size) +/* Same as memory_region_find, but it does not add a reference to the + * returned region. It must be called from an RCU critical section. + */ +static MemoryRegionSection memory_region_find_rcu(MemoryRegion *mr, + hwaddr addr, uint64_t size) { MemoryRegionSection ret = { .mr = NULL }; MemoryRegion *root; @@ -1924,11 +1917,10 @@ MemoryRegionSection memory_region_find(MemoryRegion *mr, } range = addrrange_make(int128_make64(addr), int128_make64(size)); - rcu_read_lock(); view = atomic_rcu_read(&as->current_map); fr = flatview_lookup(view, range); if (!fr) { - goto out; + return ret; } while (fr > view->ranges && addrrange_intersects(fr[-1].addr, range)) { @@ -1944,12 +1936,32 @@ 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); -out: + return ret; +} + +MemoryRegionSection memory_region_find(MemoryRegion *mr, + hwaddr addr, uint64_t size) +{ + MemoryRegionSection ret; + rcu_read_lock(); + ret = memory_region_find_rcu(mr, addr, size); + if (ret.mr) { + memory_region_ref(ret.mr); + } rcu_read_unlock(); return ret; } +bool memory_region_present(MemoryRegion *container, hwaddr addr) +{ + MemoryRegion *mr; + + rcu_read_lock(); + mr = memory_region_find_rcu(container, addr, 1).mr; + rcu_read_unlock(); + return mr && mr != container; +} + void address_space_sync_dirty_bitmap(AddressSpace *as) { FlatView *view;