X-Git-Url: https://git.proxmox.com/?a=blobdiff_plain;f=memory.c;h=9fbca52e05b4e66c2726ae5527ce99e7aae09a47;hb=248987f92cfda8305d6d44ced23e173e62a8bc0e;hp=9b73892768d9181156ad1979b8ea7457cdd2727b;hpb=8ca19bd882997b69cd9c37adabbfe8360a0a83ee;p=mirror_qemu.git diff --git a/memory.c b/memory.c index 9b73892768..9fbca52e05 100644 --- a/memory.c +++ b/memory.c @@ -39,7 +39,7 @@ static bool memory_region_update_pending; static bool ioeventfd_update_pending; static bool global_dirty_log = false; -static QTAILQ_HEAD(memory_listeners, MemoryListener) memory_listeners +static QTAILQ_HEAD(, MemoryListener) memory_listeners = QTAILQ_HEAD_INITIALIZER(memory_listeners); static QTAILQ_HEAD(, AddressSpace) address_spaces @@ -113,8 +113,7 @@ enum ListenerDirection { Forward, Reverse }; } \ break; \ case Reverse: \ - QTAILQ_FOREACH_REVERSE(_listener, &memory_listeners, \ - memory_listeners, link) { \ + QTAILQ_FOREACH_REVERSE(_listener, &memory_listeners, link) { \ if (_listener->_callback) { \ _listener->_callback(_listener, ##_args); \ } \ @@ -128,19 +127,17 @@ enum ListenerDirection { Forward, Reverse }; #define MEMORY_LISTENER_CALL(_as, _callback, _direction, _section, _args...) \ do { \ MemoryListener *_listener; \ - struct memory_listeners_as *list = &(_as)->listeners; \ \ switch (_direction) { \ case Forward: \ - QTAILQ_FOREACH(_listener, list, link_as) { \ + QTAILQ_FOREACH(_listener, &(_as)->listeners, link_as) { \ if (_listener->_callback) { \ _listener->_callback(_listener, _section, ##_args); \ } \ } \ break; \ case Reverse: \ - QTAILQ_FOREACH_REVERSE(_listener, list, memory_listeners_as, \ - link_as) { \ + QTAILQ_FOREACH_REVERSE(_listener, &(_as)->listeners, link_as) { \ if (_listener->_callback) { \ _listener->_callback(_listener, _section, ##_args); \ } \ @@ -216,6 +213,8 @@ struct FlatRange { uint8_t dirty_log_mask; bool romd_mode; bool readonly; + bool nonvolatile; + int has_coalesced_range; }; #define FOR_EACH_FLAT_RANGE(var, view) \ @@ -231,6 +230,7 @@ section_from_flat_range(FlatRange *fr, FlatView *fv) .size = fr->addr.size, .offset_within_address_space = int128_get64(fr->addr.start), .readonly = fr->readonly, + .nonvolatile = fr->nonvolatile, }; } @@ -240,7 +240,8 @@ static bool flatrange_equal(FlatRange *a, FlatRange *b) && addrrange_equal(a->addr, b->addr) && a->offset_in_region == b->offset_in_region && a->romd_mode == b->romd_mode - && a->readonly == b->readonly; + && a->readonly == b->readonly + && a->nonvolatile == b->nonvolatile; } static FlatView *flatview_new(MemoryRegion *mr_root) @@ -312,7 +313,8 @@ static bool can_merge(FlatRange *r1, FlatRange *r2) int128_make64(r2->offset_in_region)) && r1->dirty_log_mask == r2->dirty_log_mask && r1->romd_mode == r2->romd_mode - && r1->readonly == r2->readonly; + && r1->readonly == r2->readonly + && r1->nonvolatile == r2->nonvolatile; } /* Attempt to simplify a view by merging adjacent ranges */ @@ -374,6 +376,33 @@ static void adjust_endianness(MemoryRegion *mr, uint64_t *data, unsigned size) } } +static inline void memory_region_shift_read_access(uint64_t *value, + signed shift, + uint64_t mask, + uint64_t tmp) +{ + if (shift >= 0) { + *value |= (tmp & mask) << shift; + } else { + *value |= (tmp & mask) >> -shift; + } +} + +static inline uint64_t memory_region_shift_write_access(uint64_t *value, + signed shift, + uint64_t mask) +{ + uint64_t tmp; + + if (shift >= 0) { + tmp = (*value >> shift) & mask; + } else { + tmp = (*value << -shift) & mask; + } + + return tmp; +} + static hwaddr memory_region_to_absolute_addr(MemoryRegion *mr, hwaddr offset) { MemoryRegion *root; @@ -396,37 +425,11 @@ static int get_cpu_index(void) return -1; } -static MemTxResult memory_region_oldmmio_read_accessor(MemoryRegion *mr, - hwaddr addr, - uint64_t *value, - unsigned size, - unsigned shift, - uint64_t mask, - MemTxAttrs attrs) -{ - uint64_t tmp; - - tmp = mr->ops->old_mmio.read[ctz32(size)](mr->opaque, addr); - if (mr->subpage) { - trace_memory_region_subpage_read(get_cpu_index(), mr, addr, tmp, size); - } else if (mr == &io_mem_notdirty) { - /* Accesses to code which has previously been translated into a TB show - * up in the MMIO path, as accesses to the io_mem_notdirty - * MemoryRegion. */ - trace_memory_region_tb_read(get_cpu_index(), addr, tmp, size); - } else if (TRACE_MEMORY_REGION_OPS_READ_ENABLED) { - hwaddr abs_addr = memory_region_to_absolute_addr(mr, addr); - trace_memory_region_ops_read(get_cpu_index(), mr, abs_addr, tmp, size); - } - *value |= (tmp & mask) << shift; - return MEMTX_OK; -} - static MemTxResult memory_region_read_accessor(MemoryRegion *mr, hwaddr addr, uint64_t *value, unsigned size, - unsigned shift, + signed shift, uint64_t mask, MemTxAttrs attrs) { @@ -444,7 +447,7 @@ static MemTxResult memory_region_read_accessor(MemoryRegion *mr, hwaddr abs_addr = memory_region_to_absolute_addr(mr, addr); trace_memory_region_ops_read(get_cpu_index(), mr, abs_addr, tmp, size); } - *value |= (tmp & mask) << shift; + memory_region_shift_read_access(value, shift, mask, tmp); return MEMTX_OK; } @@ -452,7 +455,7 @@ static MemTxResult memory_region_read_with_attrs_accessor(MemoryRegion *mr, hwaddr addr, uint64_t *value, unsigned size, - unsigned shift, + signed shift, uint64_t mask, MemTxAttrs attrs) { @@ -471,47 +474,20 @@ static MemTxResult memory_region_read_with_attrs_accessor(MemoryRegion *mr, hwaddr abs_addr = memory_region_to_absolute_addr(mr, addr); trace_memory_region_ops_read(get_cpu_index(), mr, abs_addr, tmp, size); } - *value |= (tmp & mask) << shift; + memory_region_shift_read_access(value, shift, mask, tmp); return r; } -static MemTxResult memory_region_oldmmio_write_accessor(MemoryRegion *mr, - hwaddr addr, - uint64_t *value, - unsigned size, - unsigned shift, - uint64_t mask, - MemTxAttrs attrs) -{ - uint64_t tmp; - - tmp = (*value >> shift) & mask; - if (mr->subpage) { - trace_memory_region_subpage_write(get_cpu_index(), mr, addr, tmp, size); - } else if (mr == &io_mem_notdirty) { - /* Accesses to code which has previously been translated into a TB show - * up in the MMIO path, as accesses to the io_mem_notdirty - * MemoryRegion. */ - trace_memory_region_tb_write(get_cpu_index(), addr, tmp, size); - } else if (TRACE_MEMORY_REGION_OPS_WRITE_ENABLED) { - hwaddr abs_addr = memory_region_to_absolute_addr(mr, addr); - trace_memory_region_ops_write(get_cpu_index(), mr, abs_addr, tmp, size); - } - mr->ops->old_mmio.write[ctz32(size)](mr->opaque, addr, tmp); - return MEMTX_OK; -} - static MemTxResult memory_region_write_accessor(MemoryRegion *mr, hwaddr addr, uint64_t *value, unsigned size, - unsigned shift, + signed shift, uint64_t mask, MemTxAttrs attrs) { - uint64_t tmp; + uint64_t tmp = memory_region_shift_write_access(value, shift, mask); - tmp = (*value >> shift) & mask; if (mr->subpage) { trace_memory_region_subpage_write(get_cpu_index(), mr, addr, tmp, size); } else if (mr == &io_mem_notdirty) { @@ -531,13 +507,12 @@ static MemTxResult memory_region_write_with_attrs_accessor(MemoryRegion *mr, hwaddr addr, uint64_t *value, unsigned size, - unsigned shift, + signed shift, uint64_t mask, MemTxAttrs attrs) { - uint64_t tmp; + uint64_t tmp = memory_region_shift_write_access(value, shift, mask); - tmp = (*value >> shift) & mask; if (mr->subpage) { trace_memory_region_subpage_write(get_cpu_index(), mr, addr, tmp, size); } else if (mr == &io_mem_notdirty) { @@ -562,7 +537,7 @@ static MemTxResult access_with_adjusted_size(hwaddr addr, hwaddr addr, uint64_t *value, unsigned size, - unsigned shift, + signed shift, uint64_t mask, MemTxAttrs attrs), MemoryRegion *mr, @@ -582,7 +557,7 @@ static MemTxResult access_with_adjusted_size(hwaddr addr, /* FIXME: support unaligned access? */ access_size = MAX(MIN(size, access_size_max), access_size_min); - access_mask = -1ULL >> (64 - access_size * 8); + access_mask = MAKE_64BIT_MASK(0, access_size * 8); if (memory_region_big_endian(mr)) { for (i = 0; i < size; i += access_size) { r |= access_fn(mr, addr + i, value, access_size, @@ -619,7 +594,8 @@ static void render_memory_region(FlatView *view, MemoryRegion *mr, Int128 base, AddrRange clip, - bool readonly) + bool readonly, + bool nonvolatile) { MemoryRegion *subregion; unsigned i; @@ -635,6 +611,7 @@ static void render_memory_region(FlatView *view, int128_addto(&base, int128_make64(mr->addr)); readonly |= mr->readonly; + nonvolatile |= mr->nonvolatile; tmp = addrrange_make(base, mr->size); @@ -647,13 +624,15 @@ static void render_memory_region(FlatView *view, if (mr->alias) { int128_subfrom(&base, int128_make64(mr->alias->addr)); int128_subfrom(&base, int128_make64(mr->alias_offset)); - render_memory_region(view, mr->alias, base, clip, readonly); + render_memory_region(view, mr->alias, base, clip, + readonly, nonvolatile); return; } /* Render subregions in priority order. */ QTAILQ_FOREACH(subregion, &mr->subregions, subregions_link) { - render_memory_region(view, subregion, base, clip, readonly); + render_memory_region(view, subregion, base, clip, + readonly, nonvolatile); } if (!mr->terminates) { @@ -668,6 +647,8 @@ static void render_memory_region(FlatView *view, fr.dirty_log_mask = memory_region_get_dirty_log_mask(mr); fr.romd_mode = mr->romd_mode; fr.readonly = readonly; + fr.nonvolatile = nonvolatile; + fr.has_coalesced_range = 0; /* Render the region itself into any gaps left by the current view. */ for (i = 0; i < view->nr && int128_nz(remain); ++i) { @@ -753,7 +734,8 @@ static FlatView *generate_memory_topology(MemoryRegion *mr) if (mr) { render_memory_region(view, mr, int128_zero(), - addrrange_make(int128_zero(), int128_2_64()), false); + addrrange_make(int128_zero(), int128_2_64()), + false, false); } flatview_simplify(view); @@ -867,6 +849,49 @@ static void address_space_update_ioeventfds(AddressSpace *as) flatview_unref(view); } +static void flat_range_coalesced_io_del(FlatRange *fr, AddressSpace *as) +{ + if (!fr->has_coalesced_range) { + return; + } + + if (--fr->has_coalesced_range > 0) { + return; + } + + MEMORY_LISTENER_UPDATE_REGION(fr, as, Reverse, coalesced_io_del, + int128_get64(fr->addr.start), + int128_get64(fr->addr.size)); +} + +static void flat_range_coalesced_io_add(FlatRange *fr, AddressSpace *as) +{ + MemoryRegion *mr = fr->mr; + CoalescedMemoryRange *cmr; + AddrRange tmp; + + if (QTAILQ_EMPTY(&mr->coalesced)) { + return; + } + + if (fr->has_coalesced_range++) { + return; + } + + QTAILQ_FOREACH(cmr, &mr->coalesced, link) { + tmp = addrrange_shift(cmr->addr, + int128_sub(fr->addr.start, + int128_make64(fr->offset_in_region))); + if (!addrrange_intersects(tmp, fr->addr)) { + continue; + } + tmp = addrrange_intersection(tmp, fr->addr); + MEMORY_LISTENER_UPDATE_REGION(fr, as, Forward, coalesced_io_add, + int128_get64(tmp.start), + int128_get64(tmp.size)); + } +} + static void address_space_update_topology_pass(AddressSpace *as, const FlatView *old_view, const FlatView *new_view, @@ -899,6 +924,7 @@ static void address_space_update_topology_pass(AddressSpace *as, /* In old but not in new, or in both but attributes changed. */ if (!adding) { + flat_range_coalesced_io_del(frold, as); MEMORY_LISTENER_UPDATE_REGION(frold, as, Reverse, region_del); } @@ -927,6 +953,7 @@ static void address_space_update_topology_pass(AddressSpace *as, if (adding) { MEMORY_LISTENER_UPDATE_REGION(frnew, as, Forward, region_add); + flat_range_coalesced_io_add(frnew, as); } ++inew; @@ -1394,16 +1421,12 @@ static MemTxResult memory_region_dispatch_read1(MemoryRegion *mr, mr->ops->impl.max_access_size, memory_region_read_accessor, mr, attrs); - } else if (mr->ops->read_with_attrs) { + } else { return access_with_adjusted_size(addr, pval, size, mr->ops->impl.min_access_size, mr->ops->impl.max_access_size, memory_region_read_with_attrs_accessor, mr, attrs); - } else { - return access_with_adjusted_size(addr, pval, size, 1, 4, - memory_region_oldmmio_read_accessor, - mr, attrs); } } @@ -1475,17 +1498,13 @@ MemTxResult memory_region_dispatch_write(MemoryRegion *mr, mr->ops->impl.max_access_size, memory_region_write_accessor, mr, attrs); - } else if (mr->ops->write_with_attrs) { + } else { return access_with_adjusted_size(addr, &data, size, mr->ops->impl.min_access_size, mr->ops->impl.max_access_size, memory_region_write_with_attrs_accessor, mr, attrs); - } else { - return access_with_adjusted_size(addr, &data, size, 1, 4, - memory_region_oldmmio_write_accessor, - mr, attrs); } } @@ -1518,12 +1537,18 @@ void memory_region_init_ram_shared_nomigrate(MemoryRegion *mr, bool share, Error **errp) { + Error *err = NULL; memory_region_init(mr, owner, name, size); mr->ram = true; mr->terminates = true; mr->destructor = memory_region_destructor_ram; - mr->ram_block = qemu_ram_alloc(size, share, mr, errp); + mr->ram_block = qemu_ram_alloc(size, share, mr, &err); mr->dirty_log_mask = tcg_enabled() ? (1 << DIRTY_MEMORY_CODE) : 0; + if (err) { + mr->size = int128_zero(); + object_unparent(OBJECT(mr)); + error_propagate(errp, err); + } } void memory_region_init_resizeable_ram(MemoryRegion *mr, @@ -1536,16 +1561,22 @@ void memory_region_init_resizeable_ram(MemoryRegion *mr, void *host), Error **errp) { + Error *err = NULL; memory_region_init(mr, owner, name, size); mr->ram = true; mr->terminates = true; mr->destructor = memory_region_destructor_ram; mr->ram_block = qemu_ram_alloc_resizeable(size, max_size, resized, - mr, errp); + mr, &err); mr->dirty_log_mask = tcg_enabled() ? (1 << DIRTY_MEMORY_CODE) : 0; + if (err) { + mr->size = int128_zero(); + object_unparent(OBJECT(mr)); + error_propagate(errp, err); + } } -#ifdef __linux__ +#ifdef CONFIG_POSIX void memory_region_init_ram_from_file(MemoryRegion *mr, struct Object *owner, const char *name, @@ -1555,13 +1586,19 @@ void memory_region_init_ram_from_file(MemoryRegion *mr, const char *path, Error **errp) { + Error *err = NULL; memory_region_init(mr, owner, name, size); mr->ram = true; mr->terminates = true; mr->destructor = memory_region_destructor_ram; mr->align = align; - mr->ram_block = qemu_ram_alloc_from_file(size, mr, ram_flags, path, errp); + mr->ram_block = qemu_ram_alloc_from_file(size, mr, ram_flags, path, &err); mr->dirty_log_mask = tcg_enabled() ? (1 << DIRTY_MEMORY_CODE) : 0; + if (err) { + mr->size = int128_zero(); + object_unparent(OBJECT(mr)); + error_propagate(errp, err); + } } void memory_region_init_ram_from_fd(MemoryRegion *mr, @@ -1572,14 +1609,20 @@ void memory_region_init_ram_from_fd(MemoryRegion *mr, int fd, Error **errp) { + Error *err = NULL; memory_region_init(mr, owner, name, size); mr->ram = true; mr->terminates = true; mr->destructor = memory_region_destructor_ram; mr->ram_block = qemu_ram_alloc_from_fd(size, mr, share ? RAM_SHARED : 0, - fd, errp); + fd, &err); mr->dirty_log_mask = tcg_enabled() ? (1 << DIRTY_MEMORY_CODE) : 0; + if (err) { + mr->size = int128_zero(); + object_unparent(OBJECT(mr)); + error_propagate(errp, err); + } } #endif @@ -1606,10 +1649,17 @@ void memory_region_init_ram_device_ptr(MemoryRegion *mr, uint64_t size, void *ptr) { - memory_region_init_ram_ptr(mr, owner, name, size, ptr); + memory_region_init(mr, owner, name, size); + mr->ram = true; + mr->terminates = true; mr->ram_device = true; mr->ops = &ram_device_mem_ops; mr->opaque = mr; + mr->destructor = memory_region_destructor_ram; + mr->dirty_log_mask = tcg_enabled() ? (1 << DIRTY_MEMORY_CODE) : 0; + /* qemu_ram_alloc_from_ptr cannot fail with ptr != NULL. */ + assert(ptr != NULL); + mr->ram_block = qemu_ram_alloc_from_ptr(size, ptr, mr, &error_fatal); } void memory_region_init_alias(MemoryRegion *mr, @@ -1630,13 +1680,19 @@ void memory_region_init_rom_nomigrate(MemoryRegion *mr, uint64_t size, Error **errp) { + Error *err = NULL; memory_region_init(mr, owner, name, size); mr->ram = true; mr->readonly = true; mr->terminates = true; mr->destructor = memory_region_destructor_ram; - mr->ram_block = qemu_ram_alloc(size, false, mr, errp); + mr->ram_block = qemu_ram_alloc(size, false, mr, &err); mr->dirty_log_mask = tcg_enabled() ? (1 << DIRTY_MEMORY_CODE) : 0; + if (err) { + mr->size = int128_zero(); + object_unparent(OBJECT(mr)); + error_propagate(errp, err); + } } void memory_region_init_rom_device_nomigrate(MemoryRegion *mr, @@ -1647,6 +1703,7 @@ void memory_region_init_rom_device_nomigrate(MemoryRegion *mr, uint64_t size, Error **errp) { + Error *err = NULL; assert(ops); memory_region_init(mr, owner, name, size); mr->ops = ops; @@ -1654,7 +1711,12 @@ void memory_region_init_rom_device_nomigrate(MemoryRegion *mr, mr->terminates = true; mr->rom_device = true; mr->destructor = memory_region_destructor_ram; - mr->ram_block = qemu_ram_alloc(size, false, mr, errp); + mr->ram_block = qemu_ram_alloc(size, false, mr, &err); + if (err) { + mr->size = int128_zero(); + object_unparent(OBJECT(mr)); + error_propagate(errp, err); + } } void memory_region_init_iommu(void *_iommu_mr, @@ -2038,6 +2100,16 @@ void memory_region_set_readonly(MemoryRegion *mr, bool readonly) } } +void memory_region_set_nonvolatile(MemoryRegion *mr, bool nonvolatile) +{ + if (mr->nonvolatile != nonvolatile) { + memory_region_transaction_begin(); + mr->nonvolatile = nonvolatile; + memory_region_update_pending |= mr->enabled; + memory_region_transaction_commit(); + } +} + void memory_region_rom_device_set_romd(MemoryRegion *mr, bool romd_mode) { if (mr->romd_mode != romd_mode) { @@ -2115,34 +2187,12 @@ static void memory_region_update_coalesced_range_as(MemoryRegion *mr, AddressSpa { FlatView *view; FlatRange *fr; - CoalescedMemoryRange *cmr; - AddrRange tmp; - MemoryRegionSection section; view = address_space_get_flatview(as); FOR_EACH_FLAT_RANGE(fr, view) { if (fr->mr == mr) { - section = (MemoryRegionSection) { - .fv = view, - .offset_within_address_space = int128_get64(fr->addr.start), - .size = fr->addr.size, - }; - - MEMORY_LISTENER_CALL(as, coalesced_mmio_del, Reverse, §ion, - int128_get64(fr->addr.start), - int128_get64(fr->addr.size)); - QTAILQ_FOREACH(cmr, &mr->coalesced, link) { - tmp = addrrange_shift(cmr->addr, - int128_sub(fr->addr.start, - int128_make64(fr->offset_in_region))); - if (!addrrange_intersects(tmp, fr->addr)) { - continue; - } - tmp = addrrange_intersection(tmp, fr->addr); - MEMORY_LISTENER_CALL(as, coalesced_mmio_add, Forward, §ion, - int128_get64(tmp.start), - int128_get64(tmp.size)); - } + flat_range_coalesced_io_del(fr, as); + flat_range_coalesced_io_add(fr, as); } } flatview_unref(view); @@ -2488,6 +2538,7 @@ static MemoryRegionSection memory_region_find_rcu(MemoryRegion *mr, ret.size = range.size; ret.offset_within_address_space = int128_get64(range.start); ret.readonly = fr->readonly; + ret.nonvolatile = fr->nonvolatile; return ret; } @@ -2641,8 +2692,7 @@ void memory_listener_register(MemoryListener *listener, AddressSpace *as) listener->address_space = as; if (QTAILQ_EMPTY(&memory_listeners) - || listener->priority >= QTAILQ_LAST(&memory_listeners, - memory_listeners)->priority) { + || listener->priority >= QTAILQ_LAST(&memory_listeners)->priority) { QTAILQ_INSERT_TAIL(&memory_listeners, listener, link); } else { QTAILQ_FOREACH(other, &memory_listeners, link) { @@ -2654,8 +2704,7 @@ void memory_listener_register(MemoryListener *listener, AddressSpace *as) } if (QTAILQ_EMPTY(&as->listeners) - || listener->priority >= QTAILQ_LAST(&as->listeners, - memory_listeners)->priority) { + || listener->priority >= QTAILQ_LAST(&as->listeners)->priority) { QTAILQ_INSERT_TAIL(&as->listeners, listener, link_as); } else { QTAILQ_FOREACH(other, &as->listeners, link_as) { @@ -2745,7 +2794,7 @@ struct MemoryRegionList { QTAILQ_ENTRY(MemoryRegionList) mrqueue; }; -typedef QTAILQ_HEAD(mrqueue, MemoryRegionList) MemoryRegionListHead; +typedef QTAILQ_HEAD(, MemoryRegionList) MemoryRegionListHead; #define MR_SIZE(size) (int128_nz(size) ? (hwaddr)int128_get64( \ int128_sub((size), int128_one())) : 0) @@ -2838,10 +2887,11 @@ static void mtree_print_mr(fprintf_function mon_printf, void *f, QTAILQ_INSERT_TAIL(alias_print_queue, ml, mrqueue); } mon_printf(f, TARGET_FMT_plx "-" TARGET_FMT_plx - " (prio %d, %s): alias %s @%s " TARGET_FMT_plx + " (prio %d, %s%s): alias %s @%s " TARGET_FMT_plx "-" TARGET_FMT_plx "%s", cur_start, cur_end, mr->priority, + mr->nonvolatile ? "nv-" : "", memory_region_type((MemoryRegion *)mr), memory_region_name(mr), memory_region_name(mr->alias), @@ -2853,9 +2903,10 @@ static void mtree_print_mr(fprintf_function mon_printf, void *f, } } else { mon_printf(f, - TARGET_FMT_plx "-" TARGET_FMT_plx " (prio %d, %s): %s%s", + TARGET_FMT_plx "-" TARGET_FMT_plx " (prio %d, %s%s): %s%s", cur_start, cur_end, mr->priority, + mr->nonvolatile ? "nv-" : "", memory_region_type((MemoryRegion *)mr), memory_region_name(mr), mr->enabled ? "" : " [disabled]"); @@ -2940,19 +2991,21 @@ static void mtree_print_flatview(gpointer key, gpointer value, mr = range->mr; if (range->offset_in_region) { p(f, MTREE_INDENT TARGET_FMT_plx "-" - TARGET_FMT_plx " (prio %d, %s): %s @" TARGET_FMT_plx, + TARGET_FMT_plx " (prio %d, %s%s): %s @" TARGET_FMT_plx, int128_get64(range->addr.start), int128_get64(range->addr.start) + MR_SIZE(range->addr.size), mr->priority, + range->nonvolatile ? "nv-" : "", range->readonly ? "rom" : memory_region_type(mr), memory_region_name(mr), range->offset_in_region); } else { p(f, MTREE_INDENT TARGET_FMT_plx "-" - TARGET_FMT_plx " (prio %d, %s): %s", + TARGET_FMT_plx " (prio %d, %s%s): %s", int128_get64(range->addr.start), int128_get64(range->addr.start) + MR_SIZE(range->addr.size), mr->priority, + range->nonvolatile ? "nv-" : "", range->readonly ? "rom" : memory_region_type(mr), memory_region_name(mr)); }