Memory regions created with size UINT64_MAX are currently treated as regions of size 2**64 bytes. This patch adds full support for such regions.
Signed-off-by: Alexander Barabash <alexander_barab...@mentor.com> --- exec.c | 4 ++++ memory.c | 72 ++++++++++++++++++++++++++++++++++++++++++++------------------ 2 files changed, 55 insertions(+), 21 deletions(-) diff --git a/exec.c b/exec.c index 140eb56..8ce8ab4 100644 --- a/exec.c +++ b/exec.c @@ -789,6 +789,10 @@ static void mem_add(MemoryListener *listener, MemoryRegionSection *section) remain.size -= now.size; remain.offset_within_address_space += now.size; remain.offset_within_region += now.size; + if ((remain.size == TARGET_PAGE_SIZE - 1) && + (section->size == UINT64_MAX)) { + remain.size = TARGET_PAGE_SIZE; + } } now = remain; if (now.size) { diff --git a/memory.c b/memory.c index 1652c10..b30edc8 100644 --- a/memory.c +++ b/memory.c @@ -84,6 +84,19 @@ static AddrRange addrrange_intersection(AddrRange r1, AddrRange r2) return addrrange_make(start, int128_sub(end, start)); } +static uint64_t mr_size_get64(Int128 size) +{ + if (int128_eq(size, int128_2_64())) { + return UINT64_MAX; + } + return int128_get64(size); +} + +static uint64_t addrrange_size_get64(const AddrRange *r) +{ + return mr_size_get64(r->size); +} + enum ListenerDirection { Forward, Reverse }; static bool memory_listener_match(MemoryListener *listener, @@ -93,6 +106,18 @@ static bool memory_listener_match(MemoryListener *listener, || listener->address_space_filter == section->address_space; } +static hwaddr memory_region_get_last_addr(const MemoryRegion *mr, hwaddr base) +{ + return int128_get64(int128_sub(int128_add(int128_make64(base + mr->addr), + mr->size), int128_one())); +} + +static hwaddr memory_region_get_last_offset(const MemoryRegion *mr) +{ + return int128_get64(int128_sub(int128_add(int128_make64(mr->alias_offset), + mr->size), int128_one())); +} + #define MEMORY_LISTENER_CALL_GLOBAL(_callback, _direction, _args...) \ do { \ MemoryListener *_listener; \ @@ -150,7 +175,7 @@ static bool memory_listener_match(MemoryListener *listener, .mr = (fr)->mr, \ .address_space = (as), \ .offset_within_region = (fr)->offset_in_region, \ - .size = int128_get64((fr)->addr.size), \ + .size = flatrange_size_get64(fr), \ .offset_within_address_space = int128_get64((fr)->addr.start), \ .readonly = (fr)->readonly, \ })) @@ -204,6 +229,12 @@ static bool memory_region_ioeventfd_equal(MemoryRegionIoeventfd a, && !memory_region_ioeventfd_before(b, a); } +static +uint64_t memory_region_ioeventfd_size_get64(const MemoryRegionIoeventfd *fd) +{ + return addrrange_size_get64(&fd->addr); +} + typedef struct FlatRange FlatRange; typedef struct FlatView FlatView; @@ -240,6 +271,11 @@ static bool flatrange_equal(FlatRange *a, FlatRange *b) && a->readonly == b->readonly; } +static uint64_t flatrange_size_get64(const FlatRange *fr) +{ + return addrrange_size_get64(&fr->addr); +} + static void flatview_init(FlatView *view) { view->ranges = NULL; @@ -598,7 +634,7 @@ static void address_space_add_del_ioeventfds(AddressSpace *as, section = (MemoryRegionSection) { .address_space = as, .offset_within_address_space = int128_get64(fd->addr.start), - .size = int128_get64(fd->addr.size), + .size = memory_region_ioeventfd_size_get64(fd), }; MEMORY_LISTENER_CALL(eventfd_del, Forward, §ion, fd->match_data, fd->data, fd->e); @@ -611,7 +647,7 @@ static void address_space_add_del_ioeventfds(AddressSpace *as, section = (MemoryRegionSection) { .address_space = as, .offset_within_address_space = int128_get64(fd->addr.start), - .size = int128_get64(fd->addr.size), + .size = memory_region_ioeventfd_size_get64(fd), }; MEMORY_LISTENER_CALL(eventfd_add, Reverse, §ion, fd->match_data, fd->data, fd->e); @@ -1030,10 +1066,7 @@ void memory_region_destroy(MemoryRegion *mr) uint64_t memory_region_size(MemoryRegion *mr) { - if (int128_eq(mr->size, int128_2_64())) { - return UINT64_MAX; - } - return int128_get64(mr->size); + return mr_size_get64(mr->size); } const char *memory_region_name(MemoryRegion *mr) @@ -1163,12 +1196,12 @@ static void memory_region_update_coalesced_range_as(MemoryRegion *mr, AddressSpa section = (MemoryRegionSection) { .address_space = as, .offset_within_address_space = int128_get64(fr->addr.start), - .size = int128_get64(fr->addr.size), + .size = flatrange_size_get64(fr), }; MEMORY_LISTENER_CALL(coalesced_mmio_del, Reverse, §ion, int128_get64(fr->addr.start), - int128_get64(fr->addr.size)); + flatrange_size_get64(fr)); QTAILQ_FOREACH(cmr, &mr->coalesced, link) { tmp = addrrange_shift(cmr->addr, int128_sub(fr->addr.start, @@ -1179,7 +1212,7 @@ static void memory_region_update_coalesced_range_as(MemoryRegion *mr, AddressSpa tmp = addrrange_intersection(tmp, fr->addr); MEMORY_LISTENER_CALL(coalesced_mmio_add, Forward, §ion, int128_get64(tmp.start), - int128_get64(tmp.size)); + addrrange_size_get64(&tmp)); } } } @@ -1197,7 +1230,7 @@ static void memory_region_update_coalesced_range(MemoryRegion *mr) void memory_region_set_coalescing(MemoryRegion *mr) { memory_region_clear_coalescing(mr); - memory_region_add_coalescing(mr, 0, int128_get64(mr->size)); + memory_region_add_coalescing(mr, 0, memory_region_size(mr)); } void memory_region_add_coalescing(MemoryRegion *mr, @@ -1331,10 +1364,10 @@ static void memory_region_add_subregion_common(MemoryRegion *mr, printf("warning: subregion collision %llx/%llx (%s) " "vs %llx/%llx (%s)\n", (unsigned long long)offset, - (unsigned long long)int128_get64(subregion->size), + (unsigned long long)memory_region_size(subregion), subregion->name, (unsigned long long)other->addr, - (unsigned long long)int128_get64(other->size), + (unsigned long long)memory_region_size(other), other->name); #endif } @@ -1474,7 +1507,7 @@ MemoryRegionSection memory_region_find(MemoryRegion *address_space, 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.size = addrrange_size_get64(&range); ret.offset_within_address_space = int128_get64(range.start); ret.readonly = fr->readonly; return ret; @@ -1523,7 +1556,7 @@ static void listener_add_address_space(MemoryListener *listener, .mr = fr->mr, .address_space = as, .offset_within_region = fr->offset_in_region, - .size = int128_get64(fr->addr.size), + .size = flatrange_size_get64(fr), .offset_within_address_space = int128_get64(fr->addr.start), .readonly = fr->readonly, }; @@ -1652,8 +1685,7 @@ static void mtree_print_mr(fprintf_function mon_printf, void *f, " (prio %d, %c%c): alias %s @%s " TARGET_FMT_plx "-" TARGET_FMT_plx "\n", base + mr->addr, - base + mr->addr - + (hwaddr)int128_get64(mr->size) - 1, + memory_region_get_last_addr(mr, base), mr->priority, mr->readable ? 'R' : '-', !mr->readonly && !(mr->rom_device && mr->readable) ? 'W' @@ -1661,14 +1693,12 @@ static void mtree_print_mr(fprintf_function mon_printf, void *f, mr->name, mr->alias->name, mr->alias_offset, - mr->alias_offset - + (hwaddr)int128_get64(mr->size) - 1); + memory_region_get_last_offset(mr)); } else { mon_printf(f, TARGET_FMT_plx "-" TARGET_FMT_plx " (prio %d, %c%c): %s\n", base + mr->addr, - base + mr->addr - + (hwaddr)int128_get64(mr->size) - 1, + memory_region_get_last_addr(mr, base), mr->priority, mr->readable ? 'R' : '-', !mr->readonly && !(mr->rom_device && mr->readable) ? 'W' -- 1.7.9.5