X-Git-Url: https://repo.jachan.dev/qemu.git/blobdiff_plain/c4e9f845f6248885ff73a9e1ecb74052a1c3dcd4..156d320349df5d17e1c4fbf11fad70d2d93f5e26:/memory.c diff --git a/memory.c b/memory.c index bb2b71ee38..8141486832 100644 --- a/memory.c +++ b/memory.c @@ -15,13 +15,13 @@ #include "qemu/osdep.h" #include "qapi/error.h" -#include "qemu-common.h" #include "cpu.h" #include "exec/memory.h" #include "exec/address-spaces.h" #include "qapi/visitor.h" #include "qemu/bitops.h" #include "qemu/error-report.h" +#include "qemu/main-loop.h" #include "qemu/qemu-print.h" #include "qom/object.h" #include "trace-root.h" @@ -29,8 +29,10 @@ #include "exec/memory-internal.h" #include "exec/ram_addr.h" #include "sysemu/kvm.h" -#include "sysemu/sysemu.h" -#include "hw/qdev-properties.h" +#include "sysemu/runstate.h" +#include "sysemu/tcg.h" +#include "sysemu/accel.h" +#include "hw/boards.h" #include "migration/vmstate.h" //#define DEBUG_UNASSIGNED @@ -38,7 +40,7 @@ static unsigned memory_region_transaction_depth; static bool memory_region_update_pending; static bool ioeventfd_update_pending; -static bool global_dirty_log = false; +bool global_dirty_log; static QTAILQ_HEAD(, MemoryListener) memory_listeners = QTAILQ_HEAD_INITIALIZER(memory_listeners); @@ -321,7 +323,7 @@ static bool can_merge(FlatRange *r1, FlatRange *r2) /* Attempt to simplify a view by merging adjacent ranges */ static void flatview_simplify(FlatView *view) { - unsigned i, j; + unsigned i, j, k; i = 0; while (i < view->nr) { @@ -332,6 +334,9 @@ static void flatview_simplify(FlatView *view) ++j; } ++i; + for (k = i; k < j; k++) { + memory_region_unref(view->ranges[k].mr); + } memmove(&view->ranges[i], &view->ranges[j], (view->nr - j) * sizeof(view->ranges[j])); view->nr -= j - i; @@ -2027,14 +2032,6 @@ void memory_region_set_log(MemoryRegion *mr, bool log, unsigned client) memory_region_transaction_commit(); } -bool memory_region_get_dirty(MemoryRegion *mr, hwaddr addr, - hwaddr size, unsigned client) -{ - assert(mr->ram_block); - return cpu_physical_memory_get_dirty(memory_region_get_ram_addr(mr) + addr, - size, client); -} - void memory_region_set_dirty(MemoryRegion *mr, hwaddr addr, hwaddr size) { @@ -2072,6 +2069,57 @@ static void memory_region_sync_dirty_bitmap(MemoryRegion *mr) } } +void memory_region_clear_dirty_bitmap(MemoryRegion *mr, hwaddr start, + hwaddr len) +{ + MemoryRegionSection mrs; + MemoryListener *listener; + AddressSpace *as; + FlatView *view; + FlatRange *fr; + hwaddr sec_start, sec_end, sec_size; + + QTAILQ_FOREACH(listener, &memory_listeners, link) { + if (!listener->log_clear) { + continue; + } + as = listener->address_space; + view = address_space_get_flatview(as); + FOR_EACH_FLAT_RANGE(fr, view) { + if (!fr->dirty_log_mask || fr->mr != mr) { + /* + * Clear dirty bitmap operation only applies to those + * regions whose dirty logging is at least enabled + */ + continue; + } + + mrs = section_from_flat_range(fr, view); + + sec_start = MAX(mrs.offset_within_region, start); + sec_end = mrs.offset_within_region + int128_get64(mrs.size); + sec_end = MIN(sec_end, start + len); + + if (sec_start >= sec_end) { + /* + * If this memory region section has no intersection + * with the requested range, skip. + */ + continue; + } + + /* Valid case; shrink the section if needed */ + mrs.offset_within_address_space += + sec_start - mrs.offset_within_region; + mrs.offset_within_region = sec_start; + sec_size = sec_end - sec_start; + mrs.size = int128_make64(sec_size); + listener->log_clear(listener, &mrs); + } + flatview_unref(view); + } +} + DirtyBitmapSnapshot *memory_region_snapshot_and_clear_dirty(MemoryRegion *mr, hwaddr addr, hwaddr size, @@ -2079,8 +2127,7 @@ DirtyBitmapSnapshot *memory_region_snapshot_and_clear_dirty(MemoryRegion *mr, { assert(mr->ram_block); memory_region_sync_dirty_bitmap(mr); - return cpu_physical_memory_snapshot_and_clear_dirty( - memory_region_get_ram_addr(mr) + addr, size, client); + return cpu_physical_memory_snapshot_and_clear_dirty(mr, addr, size, client); } bool memory_region_snapshot_get_dirty(MemoryRegion *mr, DirtyBitmapSnapshot *snap, @@ -2584,7 +2631,7 @@ void memory_global_dirty_log_start(void) MEMORY_LISTENER_CALL_GLOBAL(log_global_start, Forward); - /* Refresh DIRTY_LOG_MIGRATION bit. */ + /* Refresh DIRTY_MEMORY_MIGRATION bit. */ memory_region_transaction_begin(); memory_region_update_pending = true; memory_region_transaction_commit(); @@ -2594,7 +2641,7 @@ static void memory_global_dirty_log_do_stop(void) { global_dirty_log = false; - /* Refresh DIRTY_LOG_MIGRATION bit. */ + /* Refresh DIRTY_MEMORY_MIGRATION bit. */ memory_region_transaction_begin(); memory_region_update_pending = true; memory_region_transaction_commit(); @@ -2731,6 +2778,13 @@ void memory_listener_unregister(MemoryListener *listener) listener->address_space = NULL; } +void address_space_remove_listeners(AddressSpace *as) +{ + while (!QTAILQ_EMPTY(&as->listeners)) { + memory_listener_unregister(QTAILQ_FIRST(&as->listeners)); + } +} + void address_space_init(AddressSpace *as, MemoryRegion *root, const char *name) { memory_region_ref(root); @@ -2947,6 +3001,8 @@ struct FlatViewInfo { int counter; bool dispatch_tree; bool owner; + AccelClass *ac; + const char *ac_name; }; static void mtree_print_flatview(gpointer key, gpointer value, @@ -3009,6 +3065,17 @@ static void mtree_print_flatview(gpointer key, gpointer value, if (fvi->owner) { mtree_print_mr_owner(mr); } + + if (fvi->ac) { + for (i = 0; i < fv_address_spaces->len; ++i) { + as = g_array_index(fv_address_spaces, AddressSpace*, i); + if (fvi->ac->has_memory(current_machine, as, + int128_get64(range->addr.start), + MR_SIZE(range->addr.size) + 1)) { + qemu_printf(" %s", fvi->ac_name); + } + } + } qemu_printf("\n"); range++; } @@ -3049,6 +3116,13 @@ void mtree_info(bool flatview, bool dispatch_tree, bool owner) }; GArray *fv_address_spaces; GHashTable *views = g_hash_table_new(g_direct_hash, g_direct_equal); + AccelClass *ac = ACCEL_GET_CLASS(current_machine->accelerator); + + if (ac->has_memory) { + fvi.ac = ac; + fvi.ac_name = current_machine->accel ? current_machine->accel : + object_class_get_name(OBJECT_CLASS(ac)); + } /* Gather all FVs in one table */ QTAILQ_FOREACH(as, &address_spaces, address_spaces_link) { @@ -3171,6 +3245,7 @@ void memory_region_init_rom_device(MemoryRegion *mr, static const TypeInfo memory_region_info = { .parent = TYPE_OBJECT, .name = TYPE_MEMORY_REGION, + .class_size = sizeof(MemoryRegionClass), .instance_size = sizeof(MemoryRegion), .instance_init = memory_region_initfn, .instance_finalize = memory_region_finalize,