From 1a59bdba4bf476c242fbf88283a71427c0160f06 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Philippe=20Mathieu-Daud=C3=A9?= Date: Sun, 16 Aug 2020 19:07:11 +0200 Subject: [PATCH 01/19] memory: Directly dispatch alias accesses on origin memory region MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Since commit 2cdfcf272d ("memory: assign MemoryRegionOps to all regions"), all newly created regions are assigned with unassigned_mem_ops (which might be then overwritten). When using aliased container regions, and there is no region mapped at address 0 in the container, the memory_region_dispatch_read() and memory_region_dispatch_write() calls incorrectly return the container unassigned_mem_ops, because the alias offset is not used. Consider the following setup: +--------------------+ < - - - - - - - - - - - + | Container | mr | (unassigned_mem) | | | | | | | | | alias_offset + + <- - - - - - +----------+---------+ | +----------------+ | | | | | MemoryRegion0 | | | | | +----------------+ | | Alias | addr1 | | MemoryRegion1 | | <~ ~ ~ ~ ~ | | <~~~~~~ | +----------------+ | | | | | +--------------------+ | | | | | | | | | +----------------+ | | | MemoryRegionX | | | +----------------+ | | | MemoryRegionY | | | +----------------+ | | | MemoryRegionZ | | | +----------------+ | +--------------------+ The memory_region_init_alias() flow is: memory_region_init_alias() -> memory_region_init() -> object_initialize(TYPE_MEMORY_REGION) -> memory_region_initfn() -> mr->ops = &unassigned_mem_ops; Later when accessing offset=addr1 via the alias, we expect to hit MemoryRegion1. The memory_region_dispatch_read() flow is: memory_region_dispatch_read(addr1) -> memory_region_access_valid(mr) <- addr1 offset is ignored -> mr->ops->valid.accepts() -> unassigned_mem_accepts() <- false <- false <- MEMTX_DECODE_ERROR The caller gets a MEMTX_DECODE_ERROR while the access is OK. Fix by dispatching aliases recursively, accessing its origin region after adding the alias offset. Signed-off-by: Philippe Mathieu-Daudé Reviewed-by: Peter Xu Message-Id: <20210418055708.820980-1-f4bug@amsat.org> --- softmmu/memory.c | 10 ++++++++++ 1 file changed, 10 insertions(+) diff --git a/softmmu/memory.c b/softmmu/memory.c index 7340e19ff5..0c463e0fe5 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; From 670c0780e7a12013f06b7702e37d8434274cc018 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Philippe=20Mathieu-Daud=C3=A9?= Date: Wed, 1 Sep 2021 17:45:48 +0200 Subject: [PATCH 02/19] memory: Split mtree_info() as mtree_info_flatview() + mtree_info_as() MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit While mtree_info() handles both ASes and flatviews cases, the two cases share basically no code. Split mtree_info() as mtree_info_flatview() + mtree_info_as() to simplify. Suggested-by: Peter Maydell Reviewed-by: David Hildenbrand Reviewed-by: Peter Xu Reviewed-by: Richard Henderson Signed-off-by: Philippe Mathieu-Daudé Message-Id: <20210904231101.1071929-2-philmd@redhat.com> Signed-off-by: Philippe Mathieu-Daudé --- softmmu/memory.c | 87 ++++++++++++++++++++++++++---------------------- 1 file changed, 48 insertions(+), 39 deletions(-) diff --git a/softmmu/memory.c b/softmmu/memory.c index 0c463e0fe5..2cb823c642 100644 --- a/softmmu/memory.c +++ b/softmmu/memory.c @@ -3284,50 +3284,50 @@ 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) +{ + 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 (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); + } + + g_array_append_val(fv_address_spaces, as); + } + + /* Print */ + g_hash_table_foreach(views, mtree_print_flatview, &fvi); + + /* Free */ + g_hash_table_foreach_remove(views, mtree_info_flatview_free, 0); + g_hash_table_unref(views); +} + +static void mtree_info_as(bool dispatch_tree, bool owner, bool disabled) { MemoryRegionListHead ml_head; MemoryRegionList *ml, *ml2; AddressSpace *as; - 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; - } - - /* 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); - } - - g_array_append_val(fv_address_spaces, as); - } - - /* Print */ - g_hash_table_foreach(views, mtree_print_flatview, &fvi); - - /* Free */ - g_hash_table_foreach_remove(views, mtree_info_flatview_free, 0); - g_hash_table_unref(views); - - return; - } - QTAILQ_INIT(&ml_head); QTAILQ_FOREACH(as, &address_spaces, address_spaces_link) { @@ -3348,6 +3348,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, From 7bdbf99aa2aac3bf483db6a08d1cea5bf1053c74 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Philippe=20Mathieu-Daud=C3=A9?= Date: Fri, 20 Aug 2021 12:34:14 +0200 Subject: [PATCH 03/19] memory: Have 'info mtree' remove duplicated Address Space information MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Per Peter Maydell [*]: 'info mtree' monitor command was designed on the assumption that there's really only one or two interesting address spaces, and with more recent developments that's just not the case any more. Similarly about how the FlatView are sorted using a GHashTable, sort the AddressSpace objects to remove the duplications (AS using the same root MemoryRegion). This drastically reduces the output of 'info mtree' on some boards. Before: $ (echo info mtree; echo q) \ | qemu-system-aarch64 -S -monitor stdio -M raspi3b \ | wc -l 423 After: $ (echo info mtree; echo q) \ | qemu-system-aarch64 -S -monitor stdio -M raspi3b \ | wc -l 106 (qemu) info mtree address-space: I/O 0000000000000000-000000000000ffff (prio 0, i/o): io address-space: cpu-memory-0 address-space: cpu-memory-1 address-space: cpu-memory-2 address-space: cpu-memory-3 address-space: cpu-secure-memory-0 address-space: cpu-secure-memory-1 address-space: cpu-secure-memory-2 address-space: cpu-secure-memory-3 address-space: memory 0000000000000000-ffffffffffffffff (prio 0, i/o): system 0000000000000000-000000003fffffff (prio 0, ram): ram 000000003f000000-000000003fffffff (prio 1, i/o): bcm2835-peripherals 000000003f003000-000000003f00301f (prio 0, i/o): bcm2835-sys-timer 000000003f004000-000000003f004fff (prio -1000, i/o): bcm2835-txp 000000003f006000-000000003f006fff (prio 0, i/o): mphi 000000003f007000-000000003f007fff (prio 0, i/o): bcm2835-dma 000000003f00b200-000000003f00b3ff (prio 0, i/o): bcm2835-ic 000000003f00b400-000000003f00b43f (prio -1000, i/o): bcm2835-sp804 000000003f00b800-000000003f00bbff (prio 0, i/o): bcm2835-mbox 000000003f100000-000000003f1001ff (prio 0, i/o): bcm2835-powermgt 000000003f101000-000000003f102fff (prio 0, i/o): bcm2835-cprman 000000003f104000-000000003f10400f (prio 0, i/o): bcm2835-rng 000000003f200000-000000003f200fff (prio 0, i/o): bcm2835_gpio 000000003f201000-000000003f201fff (prio 0, i/o): pl011 000000003f202000-000000003f202fff (prio 0, i/o): bcm2835-sdhost 000000003f203000-000000003f2030ff (prio -1000, i/o): bcm2835-i2s 000000003f204000-000000003f20401f (prio -1000, i/o): bcm2835-spi0 000000003f205000-000000003f20501f (prio -1000, i/o): bcm2835-i2c0 000000003f20f000-000000003f20f07f (prio -1000, i/o): bcm2835-otp 000000003f212000-000000003f212007 (prio 0, i/o): bcm2835-thermal 000000003f214000-000000003f2140ff (prio -1000, i/o): bcm2835-spis 000000003f215000-000000003f2150ff (prio 0, i/o): bcm2835-aux 000000003f300000-000000003f3000ff (prio 0, i/o): sdhci 000000003f600000-000000003f6000ff (prio -1000, i/o): bcm2835-smi 000000003f804000-000000003f80401f (prio -1000, i/o): bcm2835-i2c1 000000003f805000-000000003f80501f (prio -1000, i/o): bcm2835-i2c2 000000003f900000-000000003f907fff (prio -1000, i/o): bcm2835-dbus 000000003f910000-000000003f917fff (prio -1000, i/o): bcm2835-ave0 000000003f980000-000000003f990fff (prio 0, i/o): dwc2 000000003f980000-000000003f980fff (prio 0, i/o): dwc2-io 000000003f981000-000000003f990fff (prio 0, i/o): dwc2-fifo 000000003fc00000-000000003fc00fff (prio -1000, i/o): bcm2835-v3d 000000003fe00000-000000003fe000ff (prio -1000, i/o): bcm2835-sdramc 000000003fe05000-000000003fe050ff (prio 0, i/o): bcm2835-dma-chan15 0000000040000000-00000000400000ff (prio 0, i/o): bcm2836-control address-space: bcm2835-dma-memory address-space: bcm2835-fb-memory address-space: bcm2835-property-memory address-space: dwc2 0000000000000000-00000000ffffffff (prio 0, i/o): bcm2835-gpu 0000000000000000-000000003fffffff (prio 0, ram): alias bcm2835-gpu-ram-alias[*] @ram 0000000000000000-000000003fffffff 0000000040000000-000000007fffffff (prio 0, ram): alias bcm2835-gpu-ram-alias[*] @ram 0000000000000000-000000003fffffff 000000007e000000-000000007effffff (prio 1, i/o): alias bcm2835-peripherals @bcm2835-peripherals 0000000000000000-0000000000ffffff 0000000080000000-00000000bfffffff (prio 0, ram): alias bcm2835-gpu-ram-alias[*] @ram 0000000000000000-000000003fffffff 00000000c0000000-00000000ffffffff (prio 0, ram): alias bcm2835-gpu-ram-alias[*] @ram 0000000000000000-000000003fffffff address-space: bcm2835-mbox-memory 0000000000000000-000000000000008f (prio 0, i/o): bcm2835-mbox 0000000000000010-000000000000001f (prio 0, i/o): bcm2835-fb 0000000000000080-000000000000008f (prio 0, i/o): bcm2835-property memory-region: ram 0000000000000000-000000003fffffff (prio 0, ram): ram memory-region: bcm2835-peripherals 000000003f000000-000000003fffffff (prio 1, i/o): bcm2835-peripherals 000000003f003000-000000003f00301f (prio 0, i/o): bcm2835-sys-timer 000000003f004000-000000003f004fff (prio -1000, i/o): bcm2835-txp 000000003f006000-000000003f006fff (prio 0, i/o): mphi 000000003f007000-000000003f007fff (prio 0, i/o): bcm2835-dma 000000003f00b200-000000003f00b3ff (prio 0, i/o): bcm2835-ic 000000003f00b400-000000003f00b43f (prio -1000, i/o): bcm2835-sp804 000000003f00b800-000000003f00bbff (prio 0, i/o): bcm2835-mbox 000000003f100000-000000003f1001ff (prio 0, i/o): bcm2835-powermgt 000000003f101000-000000003f102fff (prio 0, i/o): bcm2835-cprman 000000003f104000-000000003f10400f (prio 0, i/o): bcm2835-rng 000000003f200000-000000003f200fff (prio 0, i/o): bcm2835_gpio 000000003f201000-000000003f201fff (prio 0, i/o): pl011 000000003f202000-000000003f202fff (prio 0, i/o): bcm2835-sdhost 000000003f203000-000000003f2030ff (prio -1000, i/o): bcm2835-i2s 000000003f204000-000000003f20401f (prio -1000, i/o): bcm2835-spi0 000000003f205000-000000003f20501f (prio -1000, i/o): bcm2835-i2c0 000000003f20f000-000000003f20f07f (prio -1000, i/o): bcm2835-otp 000000003f212000-000000003f212007 (prio 0, i/o): bcm2835-thermal 000000003f214000-000000003f2140ff (prio -1000, i/o): bcm2835-spis 000000003f215000-000000003f2150ff (prio 0, i/o): bcm2835-aux 000000003f300000-000000003f3000ff (prio 0, i/o): sdhci 000000003f600000-000000003f6000ff (prio -1000, i/o): bcm2835-smi 000000003f804000-000000003f80401f (prio -1000, i/o): bcm2835-i2c1 000000003f805000-000000003f80501f (prio -1000, i/o): bcm2835-i2c2 000000003f900000-000000003f907fff (prio -1000, i/o): bcm2835-dbus 000000003f910000-000000003f917fff (prio -1000, i/o): bcm2835-ave0 000000003f980000-000000003f990fff (prio 0, i/o): dwc2 000000003f980000-000000003f980fff (prio 0, i/o): dwc2-io 000000003f981000-000000003f990fff (prio 0, i/o): dwc2-fifo 000000003fc00000-000000003fc00fff (prio -1000, i/o): bcm2835-v3d 000000003fe00000-000000003fe000ff (prio -1000, i/o): bcm2835-sdramc 000000003fe05000-000000003fe050ff (prio 0, i/o): bcm2835-dma-chan15 (qemu) q [*] https://www.mail-archive.com/qemu-devel@nongnu.org/msg829821.html Suggested-by: Peter Maydell Reviewed-by: Peter Maydell Reviewed-by: David Hildenbrand Reviewed-by: Peter Xu Reviewed-by: Richard Henderson Signed-off-by: Philippe Mathieu-Daudé Message-Id: <20210904231101.1071929-2-philmd@redhat.com> Signed-off-by: Philippe Mathieu-Daudé --- softmmu/memory.c | 63 +++++++++++++++++++++++++++++++++++++++++++++--- 1 file changed, 60 insertions(+), 3 deletions(-) diff --git a/softmmu/memory.c b/softmmu/memory.c index 2cb823c642..5e69624f7f 100644 --- a/softmmu/memory.c +++ b/softmmu/memory.c @@ -3322,20 +3322,77 @@ static void mtree_info_flatview(bool dispatch_tree, bool owner) g_hash_table_unref(views); } +struct AddressSpaceInfo { + MemoryRegionListHead *ml_head; + bool owner; + bool disabled; +}; + +/* 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; + + return g_strcmp0(as_a->name, as_b->name); +} + +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)); From eef3a7abff8a5eab840868fffd6195d8a2a555d0 Mon Sep 17 00:00:00 2001 From: David Hildenbrand Date: Tue, 2 Nov 2021 17:43:15 +0100 Subject: [PATCH 04/19] machine: Use host_memory_backend_is_mapped() in machine_consume_memdev() MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit memory_region_is_mapped() is the wrong check, we actually want to check whether the backend is already marked mapped. For example, memory regions mapped via an alias, such as NVDIMMs, currently don't make memory_region_is_mapped() return "true". As the machine is initialized before any memory devices (and thereby before NVDIMMs are initialized), this isn't a fix but merely a cleanup. Reviewed-by: Richard Henderson Reviewed-by: Igor Mammedov Reviewed-by: Philippe Mathieu-Daudé Reviewed-by: Peter Xu Signed-off-by: David Hildenbrand Message-Id: <20211102164317.45658-2-david@redhat.com> Signed-off-by: Philippe Mathieu-Daudé --- hw/core/machine.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/hw/core/machine.c b/hw/core/machine.c index debcdc0e70..d856485cb4 100644 --- a/hw/core/machine.c +++ b/hw/core/machine.c @@ -1091,7 +1091,7 @@ MemoryRegion *machine_consume_memdev(MachineState *machine, { MemoryRegion *ret = host_memory_backend_get_memory(backend); - if (memory_region_is_mapped(ret)) { + if (host_memory_backend_is_mapped(backend)) { error_report("memory backend %s can't be used multiple times.", object_get_canonical_path_component(OBJECT(backend))); exit(EXIT_FAILURE); From 5ead62185d23caad41ef2afc80773fb384e40229 Mon Sep 17 00:00:00 2001 From: David Hildenbrand Date: Tue, 2 Nov 2021 17:43:16 +0100 Subject: [PATCH 05/19] memory: Make memory_region_is_mapped() succeed when mapped via an alias MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit memory_region_is_mapped() currently does not return "true" when a memory region is mapped via an alias. Assuming we have: alias (A0) -> alias (A1) -> region (R0) Mapping A0 would currently only make memory_region_is_mapped() succeed on A0, but not on A1 and R0. Let's fix that by adding a "mapped_via_alias" counter to memory regions and updating it accordingly when an alias gets (un)mapped. I am not aware of actual issues, this is rather a cleanup to make it consistent. Reviewed-by: Philippe Mathieu-Daudé Reviewed-by: Peter Xu Signed-off-by: David Hildenbrand Message-Id: <20211102164317.45658-3-david@redhat.com> Signed-off-by: Philippe Mathieu-Daudé --- include/exec/memory.h | 1 + softmmu/memory.c | 13 ++++++++++++- 2 files changed, 13 insertions(+), 1 deletion(-) diff --git a/include/exec/memory.h b/include/exec/memory.h index 20f1b27377..fea1a493b9 100644 --- a/include/exec/memory.h +++ b/include/exec/memory.h @@ -738,6 +738,7 @@ struct MemoryRegion { const MemoryRegionOps *ops; void *opaque; MemoryRegion *container; + int mapped_via_alias; /* Mapped via an alias, container might be NULL */ Int128 size; hwaddr addr; void (*destructor)(MemoryRegion *mr); diff --git a/softmmu/memory.c b/softmmu/memory.c index 5e69624f7f..e37a4b8ae3 100644 --- a/softmmu/memory.c +++ b/softmmu/memory.c @@ -2545,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); } @@ -2571,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; @@ -2670,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 From 455faf03df1a9beff236e3b194cad93e4b014076 Mon Sep 17 00:00:00 2001 From: David Hildenbrand Date: Tue, 2 Nov 2021 17:43:17 +0100 Subject: [PATCH 06/19] memory: Update description of memory_region_is_mapped() MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Let's update the documentation, making it clearer what the semantics of memory_region_is_mapped() actually are. Reviewed-by: Philippe Mathieu-Daudé Reviewed-by: Peter Xu Signed-off-by: David Hildenbrand Message-Id: <20211102164317.45658-4-david@redhat.com> Signed-off-by: Philippe Mathieu-Daudé --- include/exec/memory.h | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/include/exec/memory.h b/include/exec/memory.h index fea1a493b9..63be794a06 100644 --- a/include/exec/memory.h +++ b/include/exec/memory.h @@ -2297,7 +2297,8 @@ bool memory_region_present(MemoryRegion *container, hwaddr addr); /** * memory_region_is_mapped: returns true if #MemoryRegion is mapped - * into any address space. + * into another memory region, which does not necessarily imply that it is + * mapped into an address space. * * @mr: a #MemoryRegion which should be checked if it's mapped */ From 7b0538ed3a22ce30817f818449d10701fb0821f9 Mon Sep 17 00:00:00 2001 From: Peter Xu Date: Tue, 30 Nov 2021 16:00:28 +0800 Subject: [PATCH 07/19] memory: Fix incorrect calls of log_global_start/stop MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit We should only call the log_global_start/stop when the global dirty track bitmask changes from zero<->non-zero. No real issue reported for this yet probably because no immediate user to enable both dirty rate measurement and migration at the same time. However it'll be good to be prepared for it. Fixes: 63b41db4bc ("memory: make global_dirty_tracking a bitmask") Cc: qemu-stable@nongnu.org Cc: Hyman Huang Cc: Paolo Bonzini Cc: Dr. David Alan Gilbert Cc: Juan Quintela Cc: David Hildenbrand Signed-off-by: Peter Xu Reviewed-by: David Hildenbrand Message-Id: <20211130080028.6474-1-peterx@redhat.com> Signed-off-by: Philippe Mathieu-Daudé --- softmmu/memory.c | 27 ++++++++++++++------------- 1 file changed, 14 insertions(+), 13 deletions(-) diff --git a/softmmu/memory.c b/softmmu/memory.c index e37a4b8ae3..678dc62f06 100644 --- a/softmmu/memory.c +++ b/softmmu/memory.c @@ -2794,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; @@ -2802,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) @@ -2821,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, From e3ae2bbfcac6400c1eff72b5e89d093dd5758f56 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Philippe=20Mathieu-Daud=C3=A9?= Date: Tue, 11 Jan 2022 11:44:18 +0100 Subject: [PATCH 08/19] stubs: Restrict fw_cfg to system emulation MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit fw_cfg_arch_key_name() stub is only required for sysemu. Signed-off-by: Philippe Mathieu-Daudé Reviewed-by: David Hildenbrand Message-Id: <20220111184309.28637-2-f4bug@amsat.org> --- stubs/meson.build | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/stubs/meson.build b/stubs/meson.build index 71469c1d50..363f6fa785 100644 --- a/stubs/meson.build +++ b/stubs/meson.build @@ -11,7 +11,6 @@ stub_ss.add(files('icount.c')) stub_ss.add(files('dump.c')) stub_ss.add(files('error-printf.c')) stub_ss.add(files('fdset.c')) -stub_ss.add(files('fw_cfg.c')) stub_ss.add(files('gdbstub.c')) stub_ss.add(files('get-vm-name.c')) if linux_io_uring.found() @@ -51,6 +50,7 @@ if have_block stub_ss.add(files('replay-tools.c')) endif if have_system + stub_ss.add(files('fw_cfg.c')) stub_ss.add(files('semihost.c')) stub_ss.add(files('usb-dev-stub.c')) stub_ss.add(files('xen-hw-stub.c')) From 33cda58f0064fdeffe0c13bf340c63878e321f19 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Philippe=20Mathieu-Daud=C3=A9?= Date: Fri, 31 Dec 2021 12:13:57 +0100 Subject: [PATCH 09/19] hw/nvram: Restrict fw_cfg QOM interface to sysemu and tools MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit fw_cfg QOM interface is required by system emulation and qemu-storage-daemon. User-mode emulation doesn't need it. Signed-off-by: Philippe Mathieu-Daudé Signed-off-by: Philippe Mathieu-Daudé Reviewed-by: David Hildenbrand Message-Id: <20220111184309.28637-3-f4bug@amsat.org> --- hw/nvram/meson.build | 6 ++++-- 1 file changed, 4 insertions(+), 2 deletions(-) diff --git a/hw/nvram/meson.build b/hw/nvram/meson.build index 202a5466e6..f5ee9f6b88 100644 --- a/hw/nvram/meson.build +++ b/hw/nvram/meson.build @@ -1,5 +1,7 @@ -# QOM interfaces must be available anytime QOM is used. -qom_ss.add(files('fw_cfg-interface.c')) +if have_system or have_tools + # QOM interfaces must be available anytime QOM is used. + qom_ss.add(files('fw_cfg-interface.c')) +endif softmmu_ss.add(files('fw_cfg.c')) softmmu_ss.add(when: 'CONFIG_CHRP_NVRAM', if_true: files('chrp_nvram.c')) From e0431aafc48ed0bea934148fb7266dbe36ef7685 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Philippe=20Mathieu-Daud=C3=A9?= Date: Fri, 31 Dec 2021 11:10:27 +0100 Subject: [PATCH 10/19] hw/pci: Restrict pci-bus stub to sysemu MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Neither tools nor user-mode emulation require the PCI bus stub. Signed-off-by: Philippe Mathieu-Daudé Reviewed-by: Michael S. Tsirkin Reviewed-by: Richard Henderson Reviewed-by: David Hildenbrand Message-Id: <20220111184309.28637-4-f4bug@amsat.org> Signed-off-by: Philippe Mathieu-Daudé --- stubs/meson.build | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/stubs/meson.build b/stubs/meson.build index 363f6fa785..d359cbe1ad 100644 --- a/stubs/meson.build +++ b/stubs/meson.build @@ -26,7 +26,6 @@ stub_ss.add(files('migr-blocker.c')) stub_ss.add(files('module-opts.c')) stub_ss.add(files('monitor.c')) stub_ss.add(files('monitor-core.c')) -stub_ss.add(files('pci-bus.c')) stub_ss.add(files('qemu-timer-notify-cb.c')) stub_ss.add(files('qmp_memory_device.c')) stub_ss.add(files('qmp-command-available.c')) @@ -51,6 +50,7 @@ if have_block endif if have_system stub_ss.add(files('fw_cfg.c')) + stub_ss.add(files('pci-bus.c')) stub_ss.add(files('semihost.c')) stub_ss.add(files('usb-dev-stub.c')) stub_ss.add(files('xen-hw-stub.c')) From 1efc6b319cfab73176412d86fa8f3702ed30c867 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Philippe=20Mathieu-Daud=C3=A9?= Date: Fri, 31 Dec 2021 11:51:52 +0100 Subject: [PATCH 11/19] hw/pci: Document pci_dma_map() MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Signed-off-by: Philippe Mathieu-Daudé Reviewed-by: Michael S. Tsirkin Reviewed-by: Richard Henderson Message-Id: <20220111184309.28637-5-f4bug@amsat.org> Signed-off-by: Philippe Mathieu-Daudé --- include/hw/pci/pci.h | 12 ++++++++++++ 1 file changed, 12 insertions(+) diff --git a/include/hw/pci/pci.h b/include/hw/pci/pci.h index 483d5c7c72..023abc0f79 100644 --- a/include/hw/pci/pci.h +++ b/include/hw/pci/pci.h @@ -881,6 +881,18 @@ PCI_DMA_DEFINE_LDST(q_be, q_be, 64); #undef PCI_DMA_DEFINE_LDST +/** + * pci_dma_map: Map device PCI address space range into host virtual address + * @dev: #PCIDevice to be accessed + * @addr: address within that device's address space + * @plen: pointer to length of buffer; updated on return to indicate + * if only a subset of the requested range has been mapped + * @dir: indicates the transfer direction + * + * Return: A host pointer, or %NULL if the resources needed to + * perform the mapping are exhausted (in that case *@plen + * is set to zero). + */ static inline void *pci_dma_map(PCIDevice *dev, dma_addr_t addr, dma_addr_t *plen, DMADirection dir) { From fd5e451edbebecaa65d2e6fef09b9afd7eefc951 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Philippe=20Mathieu-Daud=C3=A9?= Date: Fri, 31 Dec 2021 11:18:15 +0100 Subject: [PATCH 12/19] hw/dma: Remove CONFIG_USER_ONLY check MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit DMA API should not be included in user-mode emulation. If so, build should fail. Remove the CONFIG_USER_ONLY check. Signed-off-by: Philippe Mathieu-Daudé Reviewed-by: Richard Henderson Reviewed-by: David Hildenbrand Message-Id: <20220111184309.28637-6-f4bug@amsat.org> Signed-off-by: Philippe Mathieu-Daudé --- include/sysemu/dma.h | 3 --- 1 file changed, 3 deletions(-) diff --git a/include/sysemu/dma.h b/include/sysemu/dma.h index b3faef41b2..0db2478a50 100644 --- a/include/sysemu/dma.h +++ b/include/sysemu/dma.h @@ -31,8 +31,6 @@ struct QEMUSGList { AddressSpace *as; }; -#ifndef CONFIG_USER_ONLY - /* * When an IOMMU is present, bus addresses become distinct from * CPU/memory physical addresses and may be a different size. Because @@ -288,7 +286,6 @@ void qemu_sglist_init(QEMUSGList *qsg, DeviceState *dev, int alloc_hint, AddressSpace *as); void qemu_sglist_add(QEMUSGList *qsg, dma_addr_t base, dma_addr_t len); void qemu_sglist_destroy(QEMUSGList *qsg); -#endif typedef BlockAIOCB *DMAIOFunc(int64_t offset, QEMUIOVector *iov, BlockCompletionFunc *cb, void *cb_opaque, From ce0a7982855afd873600a4180161adbfaef24cc1 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Philippe=20Mathieu-Daud=C3=A9?= Date: Fri, 31 Dec 2021 11:19:08 +0100 Subject: [PATCH 13/19] hw/rdma/rdma_utils: Rename rdma_pci_dma_map 'len' argument MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Various APIs use 'pval' naming for 'pointer to val'. rdma_pci_dma_map() uses 'plen' for 'PCI length', but since 'PCI' is already explicit in the function name, simplify and rename the argument 'len'. No logical change. Signed-off-by: Philippe Mathieu-Daudé Reviewed-by: Richard Henderson Reviewed-by: David Hildenbrand Reviewed-by: Yuval Shaia Tested-by: Yuval Shaia Message-Id: <20220111184309.28637-7-f4bug@amsat.org> Signed-off-by: Philippe Mathieu-Daudé --- hw/rdma/rdma_utils.c | 14 +++++++------- hw/rdma/rdma_utils.h | 2 +- 2 files changed, 8 insertions(+), 8 deletions(-) diff --git a/hw/rdma/rdma_utils.c b/hw/rdma/rdma_utils.c index 98df58f689..61cb8ede0f 100644 --- a/hw/rdma/rdma_utils.c +++ b/hw/rdma/rdma_utils.c @@ -17,29 +17,29 @@ #include "trace.h" #include "rdma_utils.h" -void *rdma_pci_dma_map(PCIDevice *dev, dma_addr_t addr, dma_addr_t plen) +void *rdma_pci_dma_map(PCIDevice *dev, dma_addr_t addr, dma_addr_t len) { void *p; - hwaddr len = plen; + hwaddr pci_len = len; if (!addr) { rdma_error_report("addr is NULL"); return NULL; } - p = pci_dma_map(dev, addr, &len, DMA_DIRECTION_TO_DEVICE); + p = pci_dma_map(dev, addr, &pci_len, DMA_DIRECTION_TO_DEVICE); if (!p) { rdma_error_report("pci_dma_map fail, addr=0x%"PRIx64", len=%"PRId64, - addr, len); + addr, pci_len); return NULL; } - if (len != plen) { - rdma_pci_dma_unmap(dev, p, len); + if (pci_len != len) { + rdma_pci_dma_unmap(dev, p, pci_len); return NULL; } - trace_rdma_pci_dma_map(addr, p, len); + trace_rdma_pci_dma_map(addr, p, pci_len); return p; } diff --git a/hw/rdma/rdma_utils.h b/hw/rdma/rdma_utils.h index 9fd0efd940..0c6414e7e0 100644 --- a/hw/rdma/rdma_utils.h +++ b/hw/rdma/rdma_utils.h @@ -38,7 +38,7 @@ typedef struct RdmaProtectedGSList { GSList *list; } RdmaProtectedGSList; -void *rdma_pci_dma_map(PCIDevice *dev, dma_addr_t addr, dma_addr_t plen); +void *rdma_pci_dma_map(PCIDevice *dev, dma_addr_t addr, dma_addr_t len); void rdma_pci_dma_unmap(PCIDevice *dev, void *buffer, dma_addr_t len); void rdma_protected_gqueue_init(RdmaProtectedGQueue *list); void rdma_protected_gqueue_destroy(RdmaProtectedGQueue *list); From 5f412602ded57bbdce614685eba915f6042dda1d Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Philippe=20Mathieu-Daud=C3=A9?= Date: Fri, 31 Dec 2021 11:13:34 +0100 Subject: [PATCH 14/19] hw/scsi: Rename SCSIRequest::resid as 'residual' MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit The 'resid' field is slightly confusing and could be interpreted as some ID. Rename it as 'residual' which is clearer to review. No logical change. Signed-off-by: Philippe Mathieu-Daudé Reviewed-by: Richard Henderson Reviewed-by: David Hildenbrand Message-Id: <20220111184309.28637-8-f4bug@amsat.org> Signed-off-by: Philippe Mathieu-Daudé --- hw/scsi/megasas.c | 42 +++++++++++++++++++++++++----------------- hw/scsi/scsi-bus.c | 10 +++++----- hw/scsi/scsi-disk.c | 4 ++-- include/hw/scsi/scsi.h | 4 ++-- softmmu/dma-helpers.c | 26 +++++++++++++------------- 5 files changed, 47 insertions(+), 39 deletions(-) diff --git a/hw/scsi/megasas.c b/hw/scsi/megasas.c index dc9bbdb740..cb01954937 100644 --- a/hw/scsi/megasas.c +++ b/hw/scsi/megasas.c @@ -1045,7 +1045,8 @@ static int megasas_pd_get_info_submit(SCSIDevice *sdev, int lun, uint64_t pd_size; uint16_t pd_id = ((sdev->id & 0xFF) << 8) | (lun & 0xFF); uint8_t cmdbuf[6]; - size_t len, resid; + size_t len; + size_t residual; if (!cmd->iov_buf) { cmd->iov_buf = g_malloc0(dcmd_size); @@ -1112,9 +1113,10 @@ static int megasas_pd_get_info_submit(SCSIDevice *sdev, int lun, info->connected_port_bitmap = 0x1; info->device_speed = 1; info->link_speed = 1; - resid = dma_buf_read(cmd->iov_buf, dcmd_size, &cmd->qsg, MEMTXATTRS_UNSPECIFIED); + residual = dma_buf_read(cmd->iov_buf, dcmd_size, &cmd->qsg, + MEMTXATTRS_UNSPECIFIED); g_free(cmd->iov_buf); - cmd->iov_size = dcmd_size - resid; + cmd->iov_size = dcmd_size - residual; cmd->iov_buf = NULL; return MFI_STAT_OK; } @@ -1149,7 +1151,8 @@ static int megasas_dcmd_pd_get_info(MegasasState *s, MegasasCmd *cmd) static int megasas_dcmd_ld_get_list(MegasasState *s, MegasasCmd *cmd) { struct mfi_ld_list info; - size_t dcmd_size = sizeof(info), resid; + size_t dcmd_size = sizeof(info); + size_t residual; uint32_t num_ld_disks = 0, max_ld_disks; uint64_t ld_size; BusChild *kid; @@ -1184,8 +1187,9 @@ static int megasas_dcmd_ld_get_list(MegasasState *s, MegasasCmd *cmd) info.ld_count = cpu_to_le32(num_ld_disks); trace_megasas_dcmd_ld_get_list(cmd->index, num_ld_disks, max_ld_disks); - resid = dma_buf_read(&info, dcmd_size, &cmd->qsg, MEMTXATTRS_UNSPECIFIED); - cmd->iov_size = dcmd_size - resid; + residual = dma_buf_read(&info, dcmd_size, &cmd->qsg, + MEMTXATTRS_UNSPECIFIED); + cmd->iov_size = dcmd_size - residual; return MFI_STAT_OK; } @@ -1193,7 +1197,8 @@ static int megasas_dcmd_ld_list_query(MegasasState *s, MegasasCmd *cmd) { uint16_t flags; struct mfi_ld_targetid_list info; - size_t dcmd_size = sizeof(info), resid; + size_t dcmd_size = sizeof(info); + size_t residual; uint32_t num_ld_disks = 0, max_ld_disks = s->fw_luns; BusChild *kid; @@ -1233,8 +1238,9 @@ static int megasas_dcmd_ld_list_query(MegasasState *s, MegasasCmd *cmd) info.size = dcmd_size; trace_megasas_dcmd_ld_get_list(cmd->index, num_ld_disks, max_ld_disks); - resid = dma_buf_read(&info, dcmd_size, &cmd->qsg, MEMTXATTRS_UNSPECIFIED); - cmd->iov_size = dcmd_size - resid; + residual = dma_buf_read(&info, dcmd_size, &cmd->qsg, + MEMTXATTRS_UNSPECIFIED); + cmd->iov_size = dcmd_size - residual; return MFI_STAT_OK; } @@ -1244,7 +1250,8 @@ static int megasas_ld_get_info_submit(SCSIDevice *sdev, int lun, struct mfi_ld_info *info = cmd->iov_buf; size_t dcmd_size = sizeof(struct mfi_ld_info); uint8_t cdb[6]; - ssize_t len, resid; + ssize_t len; + size_t residual; uint16_t sdev_id = ((sdev->id & 0xFF) << 8) | (lun & 0xFF); uint64_t ld_size; @@ -1283,9 +1290,10 @@ static int megasas_ld_get_info_submit(SCSIDevice *sdev, int lun, info->ld_config.span[0].num_blocks = info->size; info->ld_config.span[0].array_ref = cpu_to_le16(sdev_id); - resid = dma_buf_read(cmd->iov_buf, dcmd_size, &cmd->qsg, MEMTXATTRS_UNSPECIFIED); + residual = dma_buf_read(cmd->iov_buf, dcmd_size, &cmd->qsg, + MEMTXATTRS_UNSPECIFIED); g_free(cmd->iov_buf); - cmd->iov_size = dcmd_size - resid; + cmd->iov_size = dcmd_size - residual; cmd->iov_buf = NULL; return MFI_STAT_OK; } @@ -1617,13 +1625,13 @@ static int megasas_handle_dcmd(MegasasState *s, MegasasCmd *cmd) } static int megasas_finish_internal_dcmd(MegasasCmd *cmd, - SCSIRequest *req, size_t resid) + SCSIRequest *req, size_t residual) { int retval = MFI_STAT_OK; int lun = req->lun; trace_megasas_dcmd_internal_finish(cmd->index, cmd->dcmd_opcode, lun); - cmd->iov_size -= resid; + cmd->iov_size -= residual; switch (cmd->dcmd_opcode) { case MFI_DCMD_PD_GET_INFO: retval = megasas_pd_get_info_submit(req->dev, lun, cmd); @@ -1865,12 +1873,12 @@ static void megasas_xfer_complete(SCSIRequest *req, uint32_t len) } } -static void megasas_command_complete(SCSIRequest *req, size_t resid) +static void megasas_command_complete(SCSIRequest *req, size_t residual) { MegasasCmd *cmd = req->hba_private; uint8_t cmd_status = MFI_STAT_OK; - trace_megasas_command_complete(cmd->index, req->status, resid); + trace_megasas_command_complete(cmd->index, req->status, residual); if (req->io_canceled) { return; @@ -1880,7 +1888,7 @@ static void megasas_command_complete(SCSIRequest *req, size_t resid) /* * Internal command complete */ - cmd_status = megasas_finish_internal_dcmd(cmd, req, resid); + cmd_status = megasas_finish_internal_dcmd(cmd, req, residual); if (cmd_status == MFI_STAT_INVALID_STATUS) { return; } diff --git a/hw/scsi/scsi-bus.c b/hw/scsi/scsi-bus.c index 2b5e9dca31..3466e680ac 100644 --- a/hw/scsi/scsi-bus.c +++ b/hw/scsi/scsi-bus.c @@ -760,7 +760,7 @@ SCSIRequest *scsi_req_new(SCSIDevice *d, uint32_t tag, uint32_t lun, } req->cmd = cmd; - req->resid = req->cmd.xfer; + req->residual = req->cmd.xfer; switch (buf[0]) { case INQUIRY: @@ -1408,7 +1408,7 @@ void scsi_req_data(SCSIRequest *req, int len) trace_scsi_req_data(req->dev->id, req->lun, req->tag, len); assert(req->cmd.mode != SCSI_XFER_NONE); if (!req->sg) { - req->resid -= len; + req->residual -= len; req->bus->info->transfer_data(req, len); return; } @@ -1421,9 +1421,9 @@ void scsi_req_data(SCSIRequest *req, int len) buf = scsi_req_get_buf(req); if (req->cmd.mode == SCSI_XFER_FROM_DEV) { - req->resid = dma_buf_read(buf, len, req->sg, MEMTXATTRS_UNSPECIFIED); + req->residual = dma_buf_read(buf, len, req->sg, MEMTXATTRS_UNSPECIFIED); } else { - req->resid = dma_buf_write(buf, len, req->sg, MEMTXATTRS_UNSPECIFIED); + req->residual = dma_buf_write(buf, len, req->sg, MEMTXATTRS_UNSPECIFIED); } scsi_req_continue(req); } @@ -1512,7 +1512,7 @@ void scsi_req_complete(SCSIRequest *req, int status) scsi_req_ref(req); scsi_req_dequeue(req); - req->bus->info->complete(req, req->resid); + req->bus->info->complete(req, req->residual); /* Cancelled requests might end up being completed instead of cancelled */ notifier_list_notify(&req->cancel_notifiers, req); diff --git a/hw/scsi/scsi-disk.c b/hw/scsi/scsi-disk.c index d4914178ea..9c0dc7b946 100644 --- a/hw/scsi/scsi-disk.c +++ b/hw/scsi/scsi-disk.c @@ -420,7 +420,7 @@ static void scsi_do_read(SCSIDiskReq *r, int ret) if (r->req.sg) { dma_acct_start(s->qdev.conf.blk, &r->acct, r->req.sg, BLOCK_ACCT_READ); - r->req.resid -= r->req.sg->size; + r->req.residual -= r->req.sg->size; r->req.aiocb = dma_blk_io(blk_get_aio_context(s->qdev.conf.blk), r->req.sg, r->sector << BDRV_SECTOR_BITS, BDRV_SECTOR_SIZE, @@ -580,7 +580,7 @@ static void scsi_write_data(SCSIRequest *req) if (r->req.sg) { dma_acct_start(s->qdev.conf.blk, &r->acct, r->req.sg, BLOCK_ACCT_WRITE); - r->req.resid -= r->req.sg->size; + r->req.residual -= r->req.sg->size; r->req.aiocb = dma_blk_io(blk_get_aio_context(s->qdev.conf.blk), r->req.sg, r->sector << BDRV_SECTOR_BITS, BDRV_SECTOR_SIZE, diff --git a/include/hw/scsi/scsi.h b/include/hw/scsi/scsi.h index 2ef80af6dc..b27d133b11 100644 --- a/include/hw/scsi/scsi.h +++ b/include/hw/scsi/scsi.h @@ -30,7 +30,7 @@ struct SCSIRequest { int16_t status; int16_t host_status; void *hba_private; - size_t resid; + size_t residual; SCSICommand cmd; NotifierList cancel_notifiers; @@ -125,7 +125,7 @@ struct SCSIBusInfo { void *hba_private); void (*transfer_data)(SCSIRequest *req, uint32_t arg); void (*fail)(SCSIRequest *req); - void (*complete)(SCSIRequest *req, size_t resid); + void (*complete)(SCSIRequest *req, size_t residual); void (*cancel)(SCSIRequest *req); void (*change)(SCSIBus *bus, SCSIDevice *dev, SCSISense sense); QEMUSGList *(*get_sg_list)(SCSIRequest *req); diff --git a/softmmu/dma-helpers.c b/softmmu/dma-helpers.c index b0be156479..4563a775aa 100644 --- a/softmmu/dma-helpers.c +++ b/softmmu/dma-helpers.c @@ -294,49 +294,49 @@ 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, int32_t len, uint64_t *residual, QEMUSGList *sg, DMADirection dir, MemTxAttrs attrs) { uint8_t *ptr = buf; - uint64_t resid; + uint64_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); 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) { - uint64_t resid; + uint64_t residual; - dma_buf_rw(ptr, len, &resid, sg, DMA_DIRECTION_FROM_DEVICE, attrs); + dma_buf_rw(ptr, len, &residual, sg, DMA_DIRECTION_FROM_DEVICE, attrs); - return resid; + return residual; } uint64_t dma_buf_write(void *ptr, int32_t len, QEMUSGList *sg, MemTxAttrs attrs) { - uint64_t resid; + uint64_t residual; - dma_buf_rw(ptr, len, &resid, sg, DMA_DIRECTION_TO_DEVICE, attrs); + dma_buf_rw(ptr, len, &residual, sg, DMA_DIRECTION_TO_DEVICE, attrs); - return resid; + return residual; } void dma_acct_start(BlockBackend *blk, BlockAcctCookie *cookie, From 60791a2c27e1b8f82ff035a474b2f96f0fafa66c Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Philippe=20Mathieu-Daud=C3=A9?= Date: Tue, 4 Jan 2022 09:42:21 +0100 Subject: [PATCH 15/19] hw/dma: Fix format string issues using dma_addr_t MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Reviewed-by: Richard Henderson Reviewed-by: David Hildenbrand Signed-off-by: Philippe Mathieu-Daudé Message-Id: <20220111184309.28637-10-f4bug@amsat.org> --- hw/ide/ahci.c | 2 +- hw/rdma/trace-events | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/hw/ide/ahci.c b/hw/ide/ahci.c index 205dfdc662..6c727dd0c0 100644 --- a/hw/ide/ahci.c +++ b/hw/ide/ahci.c @@ -1159,7 +1159,7 @@ static void process_ncq_command(AHCIState *s, int port, const uint8_t *cmd_fis, ahci_populate_sglist(ad, &ncq_tfs->sglist, ncq_tfs->cmdh, size, 0); if (ncq_tfs->sglist.size < size) { - error_report("ahci: PRDT length for NCQ command (0x%zx) " + error_report("ahci: PRDT length for NCQ command (0x" DMA_ADDR_FMT ") " "is smaller than the requested size (0x%zx)", ncq_tfs->sglist.size, size); ncq_err(ncq_tfs); diff --git a/hw/rdma/trace-events b/hw/rdma/trace-events index 9accb14973..c23175120e 100644 --- a/hw/rdma/trace-events +++ b/hw/rdma/trace-events @@ -27,5 +27,5 @@ rdma_rm_alloc_qp(uint32_t rm_qpn, uint32_t backend_qpn, uint8_t qp_type) "rm_qpn rdma_rm_modify_qp(uint32_t qpn, uint32_t attr_mask, int qp_state, uint8_t sgid_idx) "qpn=0x%x, attr_mask=0x%x, qp_state=%d, sgid_idx=%d" # rdma_utils.c -rdma_pci_dma_map(uint64_t addr, void *vaddr, uint64_t len) "0x%"PRIx64" -> %p (len=%" PRId64")" +rdma_pci_dma_map(uint64_t addr, void *vaddr, uint64_t len) "0x%"PRIx64" -> %p (len=%" PRIu64")" rdma_pci_dma_unmap(void *vaddr) "%p" From 026644cf5f9fd8c27ea7f4f2fd4fea8102b30001 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Philippe=20Mathieu-Daud=C3=A9?= Date: Tue, 11 Jan 2022 11:32:22 +0100 Subject: [PATCH 16/19] hw/dma: Move ScatterGatherEntry / QEMUSGList declarations around MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit In the next commit we will use the dma_addr_t type in the QEMUSGList structure. Since currently dma_addr_t is defined after QEMUSGList, move the declarations to have dma_addr_t defined first. This is a pure code-movement patch. Suggested-by: David Hildenbrand Signed-off-by: Philippe Mathieu-Daudé Reviewed-by: David Hildenbrand Message-Id: <20220111184309.28637-10-f4bug@amsat.org> --- include/sysemu/dma.h | 22 +++++++++++----------- 1 file changed, 11 insertions(+), 11 deletions(-) diff --git a/include/sysemu/dma.h b/include/sysemu/dma.h index 0db2478a50..c992d9d5d6 100644 --- a/include/sysemu/dma.h +++ b/include/sysemu/dma.h @@ -15,22 +15,11 @@ #include "block/block.h" #include "block/accounting.h" -typedef struct ScatterGatherEntry ScatterGatherEntry; - typedef enum { DMA_DIRECTION_TO_DEVICE = 0, DMA_DIRECTION_FROM_DEVICE = 1, } DMADirection; -struct QEMUSGList { - ScatterGatherEntry *sg; - int nsg; - int nalloc; - size_t size; - DeviceState *dev; - AddressSpace *as; -}; - /* * When an IOMMU is present, bus addresses become distinct from * CPU/memory physical addresses and may be a different size. Because @@ -43,6 +32,17 @@ typedef uint64_t dma_addr_t; #define DMA_ADDR_BITS 64 #define DMA_ADDR_FMT "%" PRIx64 +typedef struct ScatterGatherEntry ScatterGatherEntry; + +struct QEMUSGList { + ScatterGatherEntry *sg; + int nsg; + int nalloc; + size_t size; + DeviceState *dev; + AddressSpace *as; +}; + static inline void dma_barrier(AddressSpace *as, DMADirection dir) { /* From bfa30f3903e0542611196b21f5832a4be5775a21 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Philippe=20Mathieu-Daud=C3=A9?= Date: Fri, 31 Dec 2021 11:33:29 +0100 Subject: [PATCH 17/19] hw/dma: Use dma_addr_t type definition when relevant MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Update the obvious places where dma_addr_t should be used (instead of uint64_t, hwaddr, size_t, int32_t types). This allows to have &dma_addr_t type portable on 32/64-bit hosts. Signed-off-by: Philippe Mathieu-Daudé Reviewed-by: David Hildenbrand Signed-off-by: Philippe Mathieu-Daudé Message-Id: <20220111184309.28637-11-f4bug@amsat.org> --- hw/nvme/ctrl.c | 2 +- hw/rdma/rdma_utils.c | 2 +- hw/scsi/megasas.c | 10 +++++----- include/sysemu/dma.h | 8 +++++--- softmmu/dma-helpers.c | 16 +++++++++------- 5 files changed, 21 insertions(+), 17 deletions(-) diff --git a/hw/nvme/ctrl.c b/hw/nvme/ctrl.c index 462f79a1f6..c3c4917611 100644 --- a/hw/nvme/ctrl.c +++ b/hw/nvme/ctrl.c @@ -1147,7 +1147,7 @@ static uint16_t nvme_tx(NvmeCtrl *n, NvmeSg *sg, uint8_t *ptr, uint32_t len, if (sg->flags & NVME_SG_DMA) { const MemTxAttrs attrs = MEMTXATTRS_UNSPECIFIED; - uint64_t residual; + dma_addr_t residual; if (dir == NVME_TX_DIRECTION_TO_DEVICE) { residual = dma_buf_write(ptr, len, &sg->qsg, attrs); diff --git a/hw/rdma/rdma_utils.c b/hw/rdma/rdma_utils.c index 61cb8ede0f..5a7ef63ad2 100644 --- a/hw/rdma/rdma_utils.c +++ b/hw/rdma/rdma_utils.c @@ -20,7 +20,7 @@ void *rdma_pci_dma_map(PCIDevice *dev, dma_addr_t addr, dma_addr_t len) { void *p; - hwaddr pci_len = len; + dma_addr_t pci_len = len; if (!addr) { rdma_error_report("addr is NULL"); diff --git a/hw/scsi/megasas.c b/hw/scsi/megasas.c index cb01954937..6c1ae6b980 100644 --- a/hw/scsi/megasas.c +++ b/hw/scsi/megasas.c @@ -1046,7 +1046,7 @@ static int megasas_pd_get_info_submit(SCSIDevice *sdev, int lun, uint16_t pd_id = ((sdev->id & 0xFF) << 8) | (lun & 0xFF); uint8_t cmdbuf[6]; size_t len; - size_t residual; + dma_addr_t residual; if (!cmd->iov_buf) { cmd->iov_buf = g_malloc0(dcmd_size); @@ -1152,7 +1152,7 @@ static int megasas_dcmd_ld_get_list(MegasasState *s, MegasasCmd *cmd) { struct mfi_ld_list info; size_t dcmd_size = sizeof(info); - size_t residual; + dma_addr_t residual; uint32_t num_ld_disks = 0, max_ld_disks; uint64_t ld_size; BusChild *kid; @@ -1198,7 +1198,7 @@ static int megasas_dcmd_ld_list_query(MegasasState *s, MegasasCmd *cmd) uint16_t flags; struct mfi_ld_targetid_list info; size_t dcmd_size = sizeof(info); - size_t residual; + dma_addr_t residual; uint32_t num_ld_disks = 0, max_ld_disks = s->fw_luns; BusChild *kid; @@ -1251,7 +1251,7 @@ static int megasas_ld_get_info_submit(SCSIDevice *sdev, int lun, size_t dcmd_size = sizeof(struct mfi_ld_info); uint8_t cdb[6]; ssize_t len; - size_t residual; + dma_addr_t residual; uint16_t sdev_id = ((sdev->id & 0xFF) << 8) | (lun & 0xFF); uint64_t ld_size; @@ -1625,7 +1625,7 @@ static int megasas_handle_dcmd(MegasasState *s, MegasasCmd *cmd) } static int megasas_finish_internal_dcmd(MegasasCmd *cmd, - SCSIRequest *req, size_t residual) + SCSIRequest *req, dma_addr_t residual) { int retval = MFI_STAT_OK; int lun = req->lun; diff --git a/include/sysemu/dma.h b/include/sysemu/dma.h index c992d9d5d6..36039c5e68 100644 --- a/include/sysemu/dma.h +++ b/include/sysemu/dma.h @@ -38,7 +38,7 @@ struct QEMUSGList { ScatterGatherEntry *sg; int nsg; int nalloc; - size_t size; + dma_addr_t size; DeviceState *dev; AddressSpace *as; }; @@ -301,8 +301,10 @@ BlockAIOCB *dma_blk_read(BlockBackend *blk, BlockAIOCB *dma_blk_write(BlockBackend *blk, QEMUSGList *sg, uint64_t offset, uint32_t align, BlockCompletionFunc *cb, void *opaque); -uint64_t dma_buf_read(void *ptr, int32_t len, QEMUSGList *sg, MemTxAttrs attrs); -uint64_t dma_buf_write(void *ptr, int32_t len, QEMUSGList *sg, MemTxAttrs attrs); +dma_addr_t dma_buf_read(void *ptr, dma_addr_t len, + QEMUSGList *sg, MemTxAttrs attrs); +dma_addr_t dma_buf_write(void *ptr, dma_addr_t len, + QEMUSGList *sg, MemTxAttrs attrs); void dma_acct_start(BlockBackend *blk, BlockAcctCookie *cookie, QEMUSGList *sg, enum BlockAcctType type); diff --git a/softmmu/dma-helpers.c b/softmmu/dma-helpers.c index 4563a775aa..916cf12ed4 100644 --- a/softmmu/dma-helpers.c +++ b/softmmu/dma-helpers.c @@ -294,12 +294,12 @@ BlockAIOCB *dma_blk_write(BlockBackend *blk, } -static MemTxResult dma_buf_rw(void *buf, int32_t len, uint64_t *residual, +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 xresidual; + dma_addr_t xresidual; int sg_cur_index; MemTxResult res = MEMTX_OK; @@ -308,7 +308,7 @@ static MemTxResult dma_buf_rw(void *buf, int32_t len, uint64_t *residual, 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; @@ -321,18 +321,20 @@ static MemTxResult dma_buf_rw(void *buf, int32_t len, uint64_t *residual, return res; } -uint64_t dma_buf_read(void *ptr, int32_t len, QEMUSGList *sg, MemTxAttrs attrs) +dma_addr_t dma_buf_read(void *ptr, dma_addr_t len, + QEMUSGList *sg, MemTxAttrs attrs) { - uint64_t residual; + dma_addr_t residual; dma_buf_rw(ptr, len, &residual, sg, DMA_DIRECTION_FROM_DEVICE, attrs); return residual; } -uint64_t dma_buf_write(void *ptr, int32_t len, QEMUSGList *sg, MemTxAttrs attrs) +dma_addr_t dma_buf_write(void *ptr, dma_addr_t len, + QEMUSGList *sg, MemTxAttrs attrs) { - uint64_t residual; + dma_addr_t residual; dma_buf_rw(ptr, len, &residual, sg, DMA_DIRECTION_TO_DEVICE, attrs); From f02b664aad8f1aaafbcdf45285f6fcab0a4bd5d0 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Philippe=20Mathieu-Daud=C3=A9?= Date: Thu, 16 Dec 2021 09:36:38 +0100 Subject: [PATCH 18/19] hw/dma: Let dma_buf_read() / dma_buf_write() propagate MemTxResult MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Since commit 292e13142d2, dma_buf_rw() returns a MemTxResult type. Do not discard it, return it to the caller. Pass the previously returned value (the QEMUSGList residual size, which was rarely used) as an optional argument. With this new API, SCSIRequest::residual might now be accessed via a pointer. Since the size_t type does not have the same size on 32 and 64-bit host architectures, convert it to a uint64_t, which is big enough to hold the residual size, and the type is constant on both 32/64-bit hosts. Update the few dma_buf_read() / dma_buf_write() callers to the new API. Reviewed-by: Klaus Jensen Signed-off-by: Philippe Mathieu-Daudé Signed-off-by: Philippe Mathieu-Daudé Acked-by: Peter Xu Message-Id: <20220117125130.131828-1-f4bug@amsat.org> --- hw/ide/ahci.c | 8 +++--- hw/nvme/ctrl.c | 4 +-- hw/scsi/megasas.c | 59 ++++++++++++++++++++++++++++++------------ hw/scsi/scsi-bus.c | 6 +++-- include/hw/scsi/scsi.h | 2 +- include/sysemu/dma.h | 4 +-- softmmu/dma-helpers.c | 16 +++--------- 7 files changed, 59 insertions(+), 40 deletions(-) diff --git a/hw/ide/ahci.c b/hw/ide/ahci.c index 6c727dd0c0..7ce001cacd 100644 --- a/hw/ide/ahci.c +++ b/hw/ide/ahci.c @@ -1384,9 +1384,9 @@ static void ahci_pio_transfer(const IDEDMA *dma) const MemTxAttrs attrs = MEMTXATTRS_UNSPECIFIED; if (is_write) { - dma_buf_write(s->data_ptr, size, &s->sg, attrs); + dma_buf_write(s->data_ptr, size, NULL, &s->sg, attrs); } else { - dma_buf_read(s->data_ptr, size, &s->sg, attrs); + dma_buf_read(s->data_ptr, size, NULL, &s->sg, attrs); } } @@ -1479,9 +1479,9 @@ static int ahci_dma_rw_buf(const IDEDMA *dma, bool is_write) } if (is_write) { - dma_buf_read(p, l, &s->sg, MEMTXATTRS_UNSPECIFIED); + dma_buf_read(p, l, NULL, &s->sg, MEMTXATTRS_UNSPECIFIED); } else { - dma_buf_write(p, l, &s->sg, MEMTXATTRS_UNSPECIFIED); + dma_buf_write(p, l, NULL, &s->sg, MEMTXATTRS_UNSPECIFIED); } /* free sglist, update byte count */ diff --git a/hw/nvme/ctrl.c b/hw/nvme/ctrl.c index c3c4917611..1f62116af9 100644 --- a/hw/nvme/ctrl.c +++ b/hw/nvme/ctrl.c @@ -1150,9 +1150,9 @@ static uint16_t nvme_tx(NvmeCtrl *n, NvmeSg *sg, uint8_t *ptr, uint32_t len, dma_addr_t residual; if (dir == NVME_TX_DIRECTION_TO_DEVICE) { - residual = dma_buf_write(ptr, len, &sg->qsg, attrs); + dma_buf_write(ptr, len, &residual, &sg->qsg, attrs); } else { - residual = dma_buf_read(ptr, len, &sg->qsg, attrs); + dma_buf_read(ptr, len, &residual, &sg->qsg, attrs); } if (unlikely(residual)) { diff --git a/hw/scsi/megasas.c b/hw/scsi/megasas.c index 6c1ae6b980..de613c8b35 100644 --- a/hw/scsi/megasas.c +++ b/hw/scsi/megasas.c @@ -750,6 +750,7 @@ static int megasas_ctrl_get_info(MegasasState *s, MegasasCmd *cmd) size_t dcmd_size = sizeof(info); BusChild *kid; int num_pd_disks = 0; + dma_addr_t residual; memset(&info, 0x0, dcmd_size); if (cmd->iov_size < dcmd_size) { @@ -860,7 +861,9 @@ static int megasas_ctrl_get_info(MegasasState *s, MegasasCmd *cmd) MFI_INFO_PDMIX_SATA | MFI_INFO_PDMIX_LD); - cmd->iov_size -= dma_buf_read(&info, dcmd_size, &cmd->qsg, MEMTXATTRS_UNSPECIFIED); + dma_buf_read(&info, dcmd_size, &residual, &cmd->qsg, + MEMTXATTRS_UNSPECIFIED); + cmd->iov_size -= residual; return MFI_STAT_OK; } @@ -868,6 +871,7 @@ static int megasas_mfc_get_defaults(MegasasState *s, MegasasCmd *cmd) { struct mfi_defaults info; size_t dcmd_size = sizeof(struct mfi_defaults); + dma_addr_t residual; memset(&info, 0x0, dcmd_size); if (cmd->iov_size < dcmd_size) { @@ -890,7 +894,9 @@ static int megasas_mfc_get_defaults(MegasasState *s, MegasasCmd *cmd) info.disable_preboot_cli = 1; info.cluster_disable = 1; - cmd->iov_size -= dma_buf_read(&info, dcmd_size, &cmd->qsg, MEMTXATTRS_UNSPECIFIED); + dma_buf_read(&info, dcmd_size, &residual, &cmd->qsg, + MEMTXATTRS_UNSPECIFIED); + cmd->iov_size -= residual; return MFI_STAT_OK; } @@ -898,6 +904,7 @@ static int megasas_dcmd_get_bios_info(MegasasState *s, MegasasCmd *cmd) { struct mfi_bios_data info; size_t dcmd_size = sizeof(info); + dma_addr_t residual; memset(&info, 0x0, dcmd_size); if (cmd->iov_size < dcmd_size) { @@ -911,7 +918,9 @@ static int megasas_dcmd_get_bios_info(MegasasState *s, MegasasCmd *cmd) info.expose_all_drives = 1; } - cmd->iov_size -= dma_buf_read(&info, dcmd_size, &cmd->qsg, MEMTXATTRS_UNSPECIFIED); + dma_buf_read(&info, dcmd_size, &residual, &cmd->qsg, + MEMTXATTRS_UNSPECIFIED); + cmd->iov_size -= residual; return MFI_STAT_OK; } @@ -919,10 +928,13 @@ static int megasas_dcmd_get_fw_time(MegasasState *s, MegasasCmd *cmd) { uint64_t fw_time; size_t dcmd_size = sizeof(fw_time); + dma_addr_t residual; fw_time = cpu_to_le64(megasas_fw_time()); - cmd->iov_size -= dma_buf_read(&fw_time, dcmd_size, &cmd->qsg, MEMTXATTRS_UNSPECIFIED); + dma_buf_read(&fw_time, dcmd_size, &residual, &cmd->qsg, + MEMTXATTRS_UNSPECIFIED); + cmd->iov_size -= residual; return MFI_STAT_OK; } @@ -942,6 +954,7 @@ static int megasas_event_info(MegasasState *s, MegasasCmd *cmd) { struct mfi_evt_log_state info; size_t dcmd_size = sizeof(info); + dma_addr_t residual; memset(&info, 0, dcmd_size); @@ -949,7 +962,9 @@ static int megasas_event_info(MegasasState *s, MegasasCmd *cmd) info.shutdown_seq_num = cpu_to_le32(s->shutdown_event); info.boot_seq_num = cpu_to_le32(s->boot_event); - cmd->iov_size -= dma_buf_read(&info, dcmd_size, &cmd->qsg, MEMTXATTRS_UNSPECIFIED); + dma_buf_read(&info, dcmd_size, &residual, &cmd->qsg, + MEMTXATTRS_UNSPECIFIED); + cmd->iov_size -= residual; return MFI_STAT_OK; } @@ -979,6 +994,7 @@ static int megasas_dcmd_pd_get_list(MegasasState *s, MegasasCmd *cmd) size_t dcmd_size = sizeof(info); BusChild *kid; uint32_t offset, dcmd_limit, num_pd_disks = 0, max_pd_disks; + dma_addr_t residual; memset(&info, 0, dcmd_size); offset = 8; @@ -1018,7 +1034,9 @@ static int megasas_dcmd_pd_get_list(MegasasState *s, MegasasCmd *cmd) info.size = cpu_to_le32(offset); info.count = cpu_to_le32(num_pd_disks); - cmd->iov_size -= dma_buf_read(&info, offset, &cmd->qsg, MEMTXATTRS_UNSPECIFIED); + dma_buf_read(&info, offset, &residual, &cmd->qsg, + MEMTXATTRS_UNSPECIFIED); + cmd->iov_size -= residual; return MFI_STAT_OK; } @@ -1113,8 +1131,9 @@ static int megasas_pd_get_info_submit(SCSIDevice *sdev, int lun, info->connected_port_bitmap = 0x1; info->device_speed = 1; info->link_speed = 1; - residual = dma_buf_read(cmd->iov_buf, dcmd_size, &cmd->qsg, - MEMTXATTRS_UNSPECIFIED); + dma_buf_read(cmd->iov_buf, dcmd_size, &residual, &cmd->qsg, + MEMTXATTRS_UNSPECIFIED); + cmd->iov_size -= residual; g_free(cmd->iov_buf); cmd->iov_size = dcmd_size - residual; cmd->iov_buf = NULL; @@ -1187,8 +1206,8 @@ static int megasas_dcmd_ld_get_list(MegasasState *s, MegasasCmd *cmd) info.ld_count = cpu_to_le32(num_ld_disks); trace_megasas_dcmd_ld_get_list(cmd->index, num_ld_disks, max_ld_disks); - residual = dma_buf_read(&info, dcmd_size, &cmd->qsg, - MEMTXATTRS_UNSPECIFIED); + dma_buf_read(&info, dcmd_size, &residual, &cmd->qsg, + MEMTXATTRS_UNSPECIFIED); cmd->iov_size = dcmd_size - residual; return MFI_STAT_OK; } @@ -1238,8 +1257,8 @@ static int megasas_dcmd_ld_list_query(MegasasState *s, MegasasCmd *cmd) info.size = dcmd_size; trace_megasas_dcmd_ld_get_list(cmd->index, num_ld_disks, max_ld_disks); - residual = dma_buf_read(&info, dcmd_size, &cmd->qsg, - MEMTXATTRS_UNSPECIFIED); + dma_buf_read(&info, dcmd_size, &residual, &cmd->qsg, + MEMTXATTRS_UNSPECIFIED); cmd->iov_size = dcmd_size - residual; return MFI_STAT_OK; } @@ -1290,8 +1309,8 @@ static int megasas_ld_get_info_submit(SCSIDevice *sdev, int lun, info->ld_config.span[0].num_blocks = info->size; info->ld_config.span[0].array_ref = cpu_to_le16(sdev_id); - residual = dma_buf_read(cmd->iov_buf, dcmd_size, &cmd->qsg, - MEMTXATTRS_UNSPECIFIED); + dma_buf_read(cmd->iov_buf, dcmd_size, &residual, &cmd->qsg, + MEMTXATTRS_UNSPECIFIED); g_free(cmd->iov_buf); cmd->iov_size = dcmd_size - residual; cmd->iov_buf = NULL; @@ -1336,6 +1355,7 @@ static int megasas_dcmd_cfg_read(MegasasState *s, MegasasCmd *cmd) struct mfi_config_data *info; int num_pd_disks = 0, array_offset, ld_offset; BusChild *kid; + dma_addr_t residual; if (cmd->iov_size > 4096) { return MFI_STAT_INVALID_PARAMETER; @@ -1410,7 +1430,9 @@ static int megasas_dcmd_cfg_read(MegasasState *s, MegasasCmd *cmd) ld_offset += sizeof(struct mfi_ld_config); } - cmd->iov_size -= dma_buf_read(data, info->size, &cmd->qsg, MEMTXATTRS_UNSPECIFIED); + dma_buf_read(data, info->size, &residual, &cmd->qsg, + MEMTXATTRS_UNSPECIFIED); + cmd->iov_size -= residual; return MFI_STAT_OK; } @@ -1418,6 +1440,7 @@ static int megasas_dcmd_get_properties(MegasasState *s, MegasasCmd *cmd) { struct mfi_ctrl_props info; size_t dcmd_size = sizeof(info); + dma_addr_t residual; memset(&info, 0x0, dcmd_size); if (cmd->iov_size < dcmd_size) { @@ -1440,7 +1463,9 @@ static int megasas_dcmd_get_properties(MegasasState *s, MegasasCmd *cmd) info.ecc_bucket_leak_rate = cpu_to_le16(1440); info.expose_encl_devices = 1; - cmd->iov_size -= dma_buf_read(&info, dcmd_size, &cmd->qsg, MEMTXATTRS_UNSPECIFIED); + dma_buf_read(&info, dcmd_size, &residual, &cmd->qsg, + MEMTXATTRS_UNSPECIFIED); + cmd->iov_size -= residual; return MFI_STAT_OK; } @@ -1485,7 +1510,7 @@ static int megasas_dcmd_set_properties(MegasasState *s, MegasasCmd *cmd) dcmd_size); return MFI_STAT_INVALID_PARAMETER; } - dma_buf_write(&info, dcmd_size, &cmd->qsg, MEMTXATTRS_UNSPECIFIED); + dma_buf_write(&info, dcmd_size, NULL, &cmd->qsg, MEMTXATTRS_UNSPECIFIED); trace_megasas_dcmd_unsupported(cmd->index, cmd->iov_size); return MFI_STAT_OK; } diff --git a/hw/scsi/scsi-bus.c b/hw/scsi/scsi-bus.c index 3466e680ac..4057e04ce8 100644 --- a/hw/scsi/scsi-bus.c +++ b/hw/scsi/scsi-bus.c @@ -1421,9 +1421,11 @@ void scsi_req_data(SCSIRequest *req, int len) buf = scsi_req_get_buf(req); if (req->cmd.mode == SCSI_XFER_FROM_DEV) { - req->residual = dma_buf_read(buf, len, req->sg, MEMTXATTRS_UNSPECIFIED); + dma_buf_read(buf, len, &req->residual, req->sg, + MEMTXATTRS_UNSPECIFIED); } else { - req->residual = dma_buf_write(buf, len, req->sg, MEMTXATTRS_UNSPECIFIED); + dma_buf_write(buf, len, &req->residual, req->sg, + MEMTXATTRS_UNSPECIFIED); } scsi_req_continue(req); } diff --git a/include/hw/scsi/scsi.h b/include/hw/scsi/scsi.h index b27d133b11..1ffb367f94 100644 --- a/include/hw/scsi/scsi.h +++ b/include/hw/scsi/scsi.h @@ -30,7 +30,7 @@ struct SCSIRequest { int16_t status; int16_t host_status; void *hba_private; - size_t residual; + uint64_t residual; SCSICommand cmd; NotifierList cancel_notifiers; diff --git a/include/sysemu/dma.h b/include/sysemu/dma.h index 36039c5e68..a1ac5bc1b5 100644 --- a/include/sysemu/dma.h +++ b/include/sysemu/dma.h @@ -301,9 +301,9 @@ BlockAIOCB *dma_blk_read(BlockBackend *blk, BlockAIOCB *dma_blk_write(BlockBackend *blk, QEMUSGList *sg, uint64_t offset, uint32_t align, BlockCompletionFunc *cb, void *opaque); -dma_addr_t dma_buf_read(void *ptr, dma_addr_t len, +MemTxResult dma_buf_read(void *ptr, dma_addr_t len, dma_addr_t *residual, QEMUSGList *sg, MemTxAttrs attrs); -dma_addr_t dma_buf_write(void *ptr, dma_addr_t len, +MemTxResult dma_buf_write(void *ptr, dma_addr_t len, dma_addr_t *residual, QEMUSGList *sg, MemTxAttrs attrs); void dma_acct_start(BlockBackend *blk, BlockAcctCookie *cookie, diff --git a/softmmu/dma-helpers.c b/softmmu/dma-helpers.c index 916cf12ed4..1c6fba6a11 100644 --- a/softmmu/dma-helpers.c +++ b/softmmu/dma-helpers.c @@ -321,24 +321,16 @@ static MemTxResult dma_buf_rw(void *buf, dma_addr_t len, dma_addr_t *residual, return res; } -dma_addr_t dma_buf_read(void *ptr, dma_addr_t len, +MemTxResult dma_buf_read(void *ptr, dma_addr_t len, dma_addr_t *residual, QEMUSGList *sg, MemTxAttrs attrs) { - dma_addr_t residual; - - dma_buf_rw(ptr, len, &residual, sg, DMA_DIRECTION_FROM_DEVICE, attrs); - - return residual; + return dma_buf_rw(ptr, len, residual, sg, DMA_DIRECTION_FROM_DEVICE, attrs); } -dma_addr_t dma_buf_write(void *ptr, dma_addr_t len, +MemTxResult dma_buf_write(void *ptr, dma_addr_t len, dma_addr_t *residual, QEMUSGList *sg, MemTxAttrs attrs) { - dma_addr_t residual; - - dma_buf_rw(ptr, len, &residual, sg, DMA_DIRECTION_TO_DEVICE, attrs); - - return residual; + return dma_buf_rw(ptr, len, residual, sg, DMA_DIRECTION_TO_DEVICE, attrs); } void dma_acct_start(BlockBackend *blk, BlockAcctCookie *cookie, From 9d696cd50442327fd71ec7309e7b0c6fee693b1d Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Alex=20Benn=C3=A9e?= Date: Mon, 10 Jan 2022 17:51:04 +0000 Subject: [PATCH 19/19] docs/devel: add some clarifying text for aliases MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit We do mention the limitation of single parenthood for memory_region_add_subregion but lets also make it clear how aliases help solve that conundrum. Signed-off-by: Alex Bennée Reviewed-by: Philippe Mathieu-Daudé Message-Id: <20220110175104.2908956-7-alex.bennee@linaro.org> Signed-off-by: Philippe Mathieu-Daudé --- docs/devel/memory.rst | 14 +++++++++----- 1 file changed, 9 insertions(+), 5 deletions(-) diff --git a/docs/devel/memory.rst b/docs/devel/memory.rst index 5dc8a12682..69c5e3f914 100644 --- a/docs/devel/memory.rst +++ b/docs/devel/memory.rst @@ -67,11 +67,15 @@ MemoryRegion): You initialize a pure container with memory_region_init(). -- alias: a subsection of another region. Aliases allow a region to be - split apart into discontiguous regions. Examples of uses are memory banks - used when the guest address space is smaller than the amount of RAM - addressed, or a memory controller that splits main memory to expose a "PCI - hole". Aliases may point to any type of region, including other aliases, +- alias: a subsection of another region. Aliases allow a region to be + split apart into discontiguous regions. Examples of uses are memory + banks used when the guest address space is smaller than the amount + of RAM addressed, or a memory controller that splits main memory to + expose a "PCI hole". You can also create aliases to avoid trying to + add the original region to multiple parents via + `memory_region_add_subregion`. + + Aliases may point to any type of region, including other aliases, but an alias may not point back to itself, directly or indirectly. You initialize these with memory_region_init_alias().