diff options
Diffstat (limited to 'softmmu')
-rw-r--r-- | softmmu/dma-helpers.c | 34 | ||||
-rw-r--r-- | softmmu/memory.c | 188 |
2 files changed, 152 insertions, 70 deletions
diff --git a/softmmu/dma-helpers.c b/softmmu/dma-helpers.c index b0be156479..1c6fba6a11 100644 --- a/softmmu/dma-helpers.c +++ b/softmmu/dma-helpers.c @@ -294,49 +294,43 @@ BlockAIOCB *dma_blk_write(BlockBackend *blk, } -static MemTxResult dma_buf_rw(void *buf, int32_t len, uint64_t *residp, +static MemTxResult dma_buf_rw(void *buf, dma_addr_t len, dma_addr_t *residual, QEMUSGList *sg, DMADirection dir, MemTxAttrs attrs) { uint8_t *ptr = buf; - uint64_t resid; + dma_addr_t xresidual; int sg_cur_index; MemTxResult res = MEMTX_OK; - resid = sg->size; + xresidual = sg->size; sg_cur_index = 0; - len = MIN(len, resid); + len = MIN(len, xresidual); while (len > 0) { ScatterGatherEntry entry = sg->sg[sg_cur_index++]; - int32_t xfer = MIN(len, entry.len); + dma_addr_t xfer = MIN(len, entry.len); res |= dma_memory_rw(sg->as, entry.base, ptr, xfer, dir, attrs); ptr += xfer; len -= xfer; - resid -= xfer; + xresidual -= xfer; } - if (residp) { - *residp = resid; + if (residual) { + *residual = xresidual; } return res; } -uint64_t dma_buf_read(void *ptr, int32_t len, QEMUSGList *sg, MemTxAttrs attrs) +MemTxResult dma_buf_read(void *ptr, dma_addr_t len, dma_addr_t *residual, + QEMUSGList *sg, MemTxAttrs attrs) { - uint64_t resid; - - dma_buf_rw(ptr, len, &resid, sg, DMA_DIRECTION_FROM_DEVICE, attrs); - - return resid; + return dma_buf_rw(ptr, len, residual, sg, DMA_DIRECTION_FROM_DEVICE, attrs); } -uint64_t dma_buf_write(void *ptr, int32_t len, QEMUSGList *sg, MemTxAttrs attrs) +MemTxResult dma_buf_write(void *ptr, dma_addr_t len, dma_addr_t *residual, + QEMUSGList *sg, MemTxAttrs attrs) { - uint64_t resid; - - dma_buf_rw(ptr, len, &resid, sg, DMA_DIRECTION_TO_DEVICE, attrs); - - return resid; + return dma_buf_rw(ptr, len, residual, sg, DMA_DIRECTION_TO_DEVICE, attrs); } void dma_acct_start(BlockBackend *blk, BlockAcctCookie *cookie, diff --git a/softmmu/memory.c b/softmmu/memory.c index 7340e19ff5..678dc62f06 100644 --- a/softmmu/memory.c +++ b/softmmu/memory.c @@ -1444,6 +1444,11 @@ MemTxResult memory_region_dispatch_read(MemoryRegion *mr, unsigned size = memop_size(op); MemTxResult r; + if (mr->alias) { + return memory_region_dispatch_read(mr->alias, + mr->alias_offset + addr, + pval, op, attrs); + } if (!memory_region_access_valid(mr, addr, size, false, attrs)) { *pval = unassigned_mem_read(mr, addr, size); return MEMTX_DECODE_ERROR; @@ -1488,6 +1493,11 @@ MemTxResult memory_region_dispatch_write(MemoryRegion *mr, { unsigned size = memop_size(op); + if (mr->alias) { + return memory_region_dispatch_write(mr->alias, + mr->alias_offset + addr, + data, op, attrs); + } if (!memory_region_access_valid(mr, addr, size, true, attrs)) { unassigned_mem_write(mr, addr, data, size); return MEMTX_DECODE_ERROR; @@ -2535,8 +2545,13 @@ static void memory_region_add_subregion_common(MemoryRegion *mr, hwaddr offset, MemoryRegion *subregion) { + MemoryRegion *alias; + assert(!subregion->container); subregion->container = mr; + for (alias = subregion->alias; alias; alias = alias->alias) { + alias->mapped_via_alias++; + } subregion->addr = offset; memory_region_update_container_subregions(subregion); } @@ -2561,9 +2576,15 @@ void memory_region_add_subregion_overlap(MemoryRegion *mr, void memory_region_del_subregion(MemoryRegion *mr, MemoryRegion *subregion) { + MemoryRegion *alias; + memory_region_transaction_begin(); assert(subregion->container == mr); subregion->container = NULL; + for (alias = subregion->alias; alias; alias = alias->alias) { + alias->mapped_via_alias--; + assert(alias->mapped_via_alias >= 0); + } QTAILQ_REMOVE(&mr->subregions, subregion, subregions_link); memory_region_unref(subregion); memory_region_update_pending |= mr->enabled && subregion->enabled; @@ -2660,7 +2681,7 @@ static FlatRange *flatview_lookup(FlatView *view, AddrRange addr) bool memory_region_is_mapped(MemoryRegion *mr) { - return mr->container ? true : false; + return !!mr->container || mr->mapped_via_alias; } /* Same as memory_region_find, but it does not add a reference to the @@ -2773,6 +2794,8 @@ static VMChangeStateEntry *vmstate_change; void memory_global_dirty_log_start(unsigned int flags) { + unsigned int old_flags = global_dirty_tracking; + if (vmstate_change) { qemu_del_vm_change_state_handler(vmstate_change); vmstate_change = NULL; @@ -2781,15 +2804,14 @@ void memory_global_dirty_log_start(unsigned int flags) assert(flags && !(flags & (~GLOBAL_DIRTY_MASK))); assert(!(global_dirty_tracking & flags)); global_dirty_tracking |= flags; - trace_global_dirty_changed(global_dirty_tracking); - MEMORY_LISTENER_CALL_GLOBAL(log_global_start, Forward); - - /* Refresh DIRTY_MEMORY_MIGRATION bit. */ - memory_region_transaction_begin(); - memory_region_update_pending = true; - memory_region_transaction_commit(); + if (!old_flags) { + MEMORY_LISTENER_CALL_GLOBAL(log_global_start, Forward); + memory_region_transaction_begin(); + memory_region_update_pending = true; + memory_region_transaction_commit(); + } } static void memory_global_dirty_log_do_stop(unsigned int flags) @@ -2800,12 +2822,12 @@ static void memory_global_dirty_log_do_stop(unsigned int flags) trace_global_dirty_changed(global_dirty_tracking); - /* Refresh DIRTY_MEMORY_MIGRATION bit. */ - memory_region_transaction_begin(); - memory_region_update_pending = true; - memory_region_transaction_commit(); - - MEMORY_LISTENER_CALL_GLOBAL(log_global_stop, Reverse); + if (!global_dirty_tracking) { + memory_region_transaction_begin(); + memory_region_update_pending = true; + memory_region_transaction_commit(); + MEMORY_LISTENER_CALL_GLOBAL(log_global_stop, Reverse); + } } static void memory_vm_change_state_handler(void *opaque, bool running, @@ -3274,58 +3296,115 @@ static gboolean mtree_info_flatview_free(gpointer key, gpointer value, return true; } -void mtree_info(bool flatview, bool dispatch_tree, bool owner, bool disabled) +static void mtree_info_flatview(bool dispatch_tree, bool owner) { - MemoryRegionListHead ml_head; - MemoryRegionList *ml, *ml2; + struct FlatViewInfo fvi = { + .counter = 0, + .dispatch_tree = dispatch_tree, + .owner = owner, + }; AddressSpace *as; + FlatView *view; + GArray *fv_address_spaces; + GHashTable *views = g_hash_table_new(g_direct_hash, g_direct_equal); + AccelClass *ac = ACCEL_GET_CLASS(current_accel()); - if (flatview) { - FlatView *view; - struct FlatViewInfo fvi = { - .counter = 0, - .dispatch_tree = dispatch_tree, - .owner = owner, - }; - GArray *fv_address_spaces; - GHashTable *views = g_hash_table_new(g_direct_hash, g_direct_equal); - AccelClass *ac = ACCEL_GET_CLASS(current_accel()); - - if (ac->has_memory) { - fvi.ac = ac; + if (ac->has_memory) { + fvi.ac = ac; + } + + /* Gather all FVs in one table */ + QTAILQ_FOREACH(as, &address_spaces, address_spaces_link) { + view = address_space_get_flatview(as); + + fv_address_spaces = g_hash_table_lookup(views, view); + if (!fv_address_spaces) { + fv_address_spaces = g_array_new(false, false, sizeof(as)); + g_hash_table_insert(views, view, fv_address_spaces); } - /* Gather all FVs in one table */ - QTAILQ_FOREACH(as, &address_spaces, address_spaces_link) { - view = address_space_get_flatview(as); + g_array_append_val(fv_address_spaces, as); + } - fv_address_spaces = g_hash_table_lookup(views, view); - if (!fv_address_spaces) { - fv_address_spaces = g_array_new(false, false, sizeof(as)); - g_hash_table_insert(views, view, fv_address_spaces); - } + /* Print */ + g_hash_table_foreach(views, mtree_print_flatview, &fvi); - g_array_append_val(fv_address_spaces, as); - } + /* Free */ + g_hash_table_foreach_remove(views, mtree_info_flatview_free, 0); + g_hash_table_unref(views); +} + +struct AddressSpaceInfo { + MemoryRegionListHead *ml_head; + bool owner; + bool disabled; +}; - /* Print */ - g_hash_table_foreach(views, mtree_print_flatview, &fvi); +/* Returns negative value if a < b; zero if a = b; positive value if a > b. */ +static gint address_space_compare_name(gconstpointer a, gconstpointer b) +{ + const AddressSpace *as_a = a; + const AddressSpace *as_b = b; - /* Free */ - g_hash_table_foreach_remove(views, mtree_info_flatview_free, 0); - g_hash_table_unref(views); + return g_strcmp0(as_a->name, as_b->name); +} - return; - } +static void mtree_print_as_name(gpointer data, gpointer user_data) +{ + AddressSpace *as = data; + + qemu_printf("address-space: %s\n", as->name); +} + +static void mtree_print_as(gpointer key, gpointer value, gpointer user_data) +{ + MemoryRegion *mr = key; + GSList *as_same_root_mr_list = value; + struct AddressSpaceInfo *asi = user_data; + + g_slist_foreach(as_same_root_mr_list, mtree_print_as_name, NULL); + mtree_print_mr(mr, 1, 0, asi->ml_head, asi->owner, asi->disabled); + qemu_printf("\n"); +} + +static gboolean mtree_info_as_free(gpointer key, gpointer value, + gpointer user_data) +{ + GSList *as_same_root_mr_list = value; + + g_slist_free(as_same_root_mr_list); + + return true; +} + +static void mtree_info_as(bool dispatch_tree, bool owner, bool disabled) +{ + MemoryRegionListHead ml_head; + MemoryRegionList *ml, *ml2; + AddressSpace *as; + GHashTable *views = g_hash_table_new(g_direct_hash, g_direct_equal); + GSList *as_same_root_mr_list; + struct AddressSpaceInfo asi = { + .ml_head = &ml_head, + .owner = owner, + .disabled = disabled, + }; QTAILQ_INIT(&ml_head); QTAILQ_FOREACH(as, &address_spaces, address_spaces_link) { - qemu_printf("address-space: %s\n", as->name); - mtree_print_mr(as->root, 1, 0, &ml_head, owner, disabled); - qemu_printf("\n"); + /* Create hashtable, key=AS root MR, value = list of AS */ + as_same_root_mr_list = g_hash_table_lookup(views, as->root); + as_same_root_mr_list = g_slist_insert_sorted(as_same_root_mr_list, as, + address_space_compare_name); + g_hash_table_insert(views, as->root, as_same_root_mr_list); } + /* print address spaces */ + g_hash_table_foreach(views, mtree_print_as, &asi); + g_hash_table_foreach_remove(views, mtree_info_as_free, 0); + g_hash_table_unref(views); + /* print aliased regions */ QTAILQ_FOREACH(ml, &ml_head, mrqueue) { qemu_printf("memory-region: %s\n", memory_region_name(ml->mr)); @@ -3338,6 +3417,15 @@ void mtree_info(bool flatview, bool dispatch_tree, bool owner, bool disabled) } } +void mtree_info(bool flatview, bool dispatch_tree, bool owner, bool disabled) +{ + if (flatview) { + mtree_info_flatview(dispatch_tree, owner); + } else { + mtree_info_as(dispatch_tree, owner, disabled); + } +} + void memory_region_init_ram(MemoryRegion *mr, Object *owner, const char *name, |