#include "qapi/visitor.h"
#include "qemu/bitops.h"
#include "qemu/error-report.h"
+#include "qemu/qemu-print.h"
#include "qom/object.h"
#include "trace-root.h"
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
} \
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); \
} \
#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); \
} \
bool romd_mode;
bool readonly;
bool nonvolatile;
+ int has_coalesced_range;
};
#define FOR_EACH_FLAT_RANGE(var, view) \
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) {
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,
/* 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);
}
if (adding) {
MEMORY_LISTENER_UPDATE_REGION(frnew, as, Forward, region_add);
+ flat_range_coalesced_io_add(frnew, as);
}
++inew;
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,
{
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_io_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_io_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);
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) {
}
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) {
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)
#define MTREE_INDENT " "
-static void mtree_expand_owner(fprintf_function mon_printf, void *f,
- const char *label, Object *obj)
+static void mtree_expand_owner(const char *label, Object *obj)
{
DeviceState *dev = (DeviceState *) object_dynamic_cast(obj, TYPE_DEVICE);
- mon_printf(f, " %s:{%s", label, dev ? "dev" : "obj");
+ qemu_printf(" %s:{%s", label, dev ? "dev" : "obj");
if (dev && dev->id) {
- mon_printf(f, " id=%s", dev->id);
+ qemu_printf(" id=%s", dev->id);
} else {
gchar *canonical_path = object_get_canonical_path(obj);
if (canonical_path) {
- mon_printf(f, " path=%s", canonical_path);
+ qemu_printf(" path=%s", canonical_path);
g_free(canonical_path);
} else {
- mon_printf(f, " type=%s", object_get_typename(obj));
+ qemu_printf(" type=%s", object_get_typename(obj));
}
}
- mon_printf(f, "}");
+ qemu_printf("}");
}
-static void mtree_print_mr_owner(fprintf_function mon_printf, void *f,
- const MemoryRegion *mr)
+static void mtree_print_mr_owner(const MemoryRegion *mr)
{
Object *owner = mr->owner;
Object *parent = memory_region_owner((MemoryRegion *)mr);
if (!owner && !parent) {
- mon_printf(f, " orphan");
+ qemu_printf(" orphan");
return;
}
if (owner) {
- mtree_expand_owner(mon_printf, f, "owner", owner);
+ mtree_expand_owner("owner", owner);
}
if (parent && parent != owner) {
- mtree_expand_owner(mon_printf, f, "parent", parent);
+ mtree_expand_owner("parent", parent);
}
}
-static void mtree_print_mr(fprintf_function mon_printf, void *f,
- const MemoryRegion *mr, unsigned int level,
+static void mtree_print_mr(const MemoryRegion *mr, unsigned int level,
hwaddr base,
MemoryRegionListHead *alias_print_queue,
bool owner)
}
for (i = 0; i < level; i++) {
- mon_printf(f, MTREE_INDENT);
+ qemu_printf(MTREE_INDENT);
}
cur_start = base + mr->addr;
* user who is observing this.
*/
if (cur_start < base || cur_end < cur_start) {
- mon_printf(f, "[DETECTED OVERFLOW!] ");
+ qemu_printf("[DETECTED OVERFLOW!] ");
}
if (mr->alias) {
ml->mr = mr->alias;
QTAILQ_INSERT_TAIL(alias_print_queue, ml, mrqueue);
}
- mon_printf(f, TARGET_FMT_plx "-" 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),
- mr->alias_offset,
- mr->alias_offset + MR_SIZE(mr->size),
- mr->enabled ? "" : " [disabled]");
+ qemu_printf(TARGET_FMT_plx "-" 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),
+ mr->alias_offset,
+ mr->alias_offset + MR_SIZE(mr->size),
+ mr->enabled ? "" : " [disabled]");
if (owner) {
- mtree_print_mr_owner(mon_printf, f, mr);
+ mtree_print_mr_owner(mr);
}
} else {
- mon_printf(f,
- 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]");
+ qemu_printf(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]");
if (owner) {
- mtree_print_mr_owner(mon_printf, f, mr);
+ mtree_print_mr_owner(mr);
}
}
- mon_printf(f, "\n");
+ qemu_printf("\n");
QTAILQ_INIT(&submr_print_queue);
}
QTAILQ_FOREACH(ml, &submr_print_queue, mrqueue) {
- mtree_print_mr(mon_printf, f, ml->mr, level + 1, cur_start,
+ mtree_print_mr(ml->mr, level + 1, cur_start,
alias_print_queue, owner);
}
}
struct FlatViewInfo {
- fprintf_function mon_printf;
- void *f;
int counter;
bool dispatch_tree;
bool owner;
FlatView *view = key;
GArray *fv_address_spaces = value;
struct FlatViewInfo *fvi = user_data;
- fprintf_function p = fvi->mon_printf;
- void *f = fvi->f;
FlatRange *range = &view->ranges[0];
MemoryRegion *mr;
int n = view->nr;
int i;
AddressSpace *as;
- p(f, "FlatView #%d\n", fvi->counter);
+ qemu_printf("FlatView #%d\n", fvi->counter);
++fvi->counter;
for (i = 0; i < fv_address_spaces->len; ++i) {
as = g_array_index(fv_address_spaces, AddressSpace*, i);
- p(f, " AS \"%s\", root: %s", as->name, memory_region_name(as->root));
+ qemu_printf(" AS \"%s\", root: %s",
+ as->name, memory_region_name(as->root));
if (as->root->alias) {
- p(f, ", alias %s", memory_region_name(as->root->alias));
+ qemu_printf(", alias %s", memory_region_name(as->root->alias));
}
- p(f, "\n");
+ qemu_printf("\n");
}
- p(f, " Root memory region: %s\n",
+ qemu_printf(" Root memory region: %s\n",
view->root ? memory_region_name(view->root) : "(none)");
if (n <= 0) {
- p(f, MTREE_INDENT "No rendered FlatView\n\n");
+ qemu_printf(MTREE_INDENT "No rendered FlatView\n\n");
return;
}
while (n--) {
mr = range->mr;
if (range->offset_in_region) {
- p(f, MTREE_INDENT 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);
+ qemu_printf(MTREE_INDENT 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): %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));
+ qemu_printf(MTREE_INDENT TARGET_FMT_plx "-" 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));
}
if (fvi->owner) {
- mtree_print_mr_owner(p, f, mr);
+ mtree_print_mr_owner(mr);
}
- p(f, "\n");
+ qemu_printf("\n");
range++;
}
#if !defined(CONFIG_USER_ONLY)
if (fvi->dispatch_tree && view->root) {
- mtree_print_dispatch(p, f, view->dispatch, view->root);
+ mtree_print_dispatch(view->dispatch, view->root);
}
#endif
- p(f, "\n");
+ qemu_printf("\n");
}
static gboolean mtree_info_flatview_free(gpointer key, gpointer value,
return true;
}
-void mtree_info(fprintf_function mon_printf, void *f, bool flatview,
- bool dispatch_tree, bool owner)
+void mtree_info(bool flatview, bool dispatch_tree, bool owner)
{
MemoryRegionListHead ml_head;
MemoryRegionList *ml, *ml2;
if (flatview) {
FlatView *view;
struct FlatViewInfo fvi = {
- .mon_printf = mon_printf,
- .f = f,
.counter = 0,
.dispatch_tree = dispatch_tree,
.owner = owner,
QTAILQ_INIT(&ml_head);
QTAILQ_FOREACH(as, &address_spaces, address_spaces_link) {
- mon_printf(f, "address-space: %s\n", as->name);
- mtree_print_mr(mon_printf, f, as->root, 1, 0, &ml_head, owner);
- mon_printf(f, "\n");
+ qemu_printf("address-space: %s\n", as->name);
+ mtree_print_mr(as->root, 1, 0, &ml_head, owner);
+ qemu_printf("\n");
}
/* print aliased regions */
QTAILQ_FOREACH(ml, &ml_head, mrqueue) {
- mon_printf(f, "memory-region: %s\n", memory_region_name(ml->mr));
- mtree_print_mr(mon_printf, f, ml->mr, 1, 0, &ml_head, owner);
- mon_printf(f, "\n");
+ qemu_printf("memory-region: %s\n", memory_region_name(ml->mr));
+ mtree_print_mr(ml->mr, 1, 0, &ml_head, owner);
+ qemu_printf("\n");
}
QTAILQ_FOREACH_SAFE(ml, &ml_head, mrqueue, ml2) {