MemoryRegionSection memory_region_find(MemoryRegion *address_space,

                                       target_phys_addr_t addr, uint64_t size)

{

    AddressSpace *as = memory_region_to_address_space(address_space);

    AddrRange range = addrrange_make(int128_make64(addr),

                                     int128_make64(size));

    FlatRange *fr = address_space_lookup(as, range);

    MemoryRegionSection ret = { .mr = NULL, .size = 0 };



    if (!fr) {

        return ret;

    }



    while (fr > as->current_map.ranges

           && addrrange_intersects(fr[-1].addr, range)) {

        --fr;

    }



    ret.mr = fr->mr;

    range = addrrange_intersection(range, fr->addr);

    ret.offset_within_region = fr->offset_in_region;

    ret.offset_within_region += int128_get64(int128_sub(range.start,

                                                        fr->addr.start));

    ret.size = int128_get64(range.size);

    ret.offset_within_address_space = int128_get64(range.start);

    ret.readonly = fr->readonly;

    return ret;

}
