[PATCH v2 00/21] migration: Improve error reporting
Hello, The motivation behind these changes is to improve error reporting to the upper management layer (libvirt) with a more detailed error, this to let it decide, depending on the reported error, whether to try migration again later. It would be useful in cases where migration fails due to lack of HW resources on the host. For instance, some adapters can only initiate a limited number of simultaneous dirty tracking requests and this imposes a limit on the the number of VMs that can be migrated simultaneously. We are not quite ready for such a mechanism but what we can do first is to cleanup the error reporting in the early save_setup sequence. This is what the following changes propose, by adding an Error** argument to various handlers and propagating it to the core migration subsystem. Thanks, C. Changes in v2: - Removed v1 patches addressing the return-path thread termination as they are now superseded by : https://lore.kernel.org/qemu-devel/20240226203122.22894-1-faro...@suse.de/ - Documentation updates of handlers - Removed call to PRECOPY_NOTIFY_SETUP notifiers in case of errors - Modified routines taking an Error** argument to return a bool when possible and made adjustments in callers. - new MEMORY_LISTENER_CALL_LOG_GLOBAL macro for .log_global*() handlers - Handled SETUP state when migration terminates - Modified memory_get_xlat_addr() to take an Error** argument - Various refinements on error handling Cédric Le Goater (21): migration: Report error when shutdown fails migration: Remove SaveStateHandler and LoadStateHandler typedefs migration: Add documentation for SaveVMHandlers migration: Do not call PRECOPY_NOTIFY_SETUP notifiers in case of error migration: Add Error** argument to qemu_savevm_state_setup() migration: Add Error** argument to .save_setup() handler migration: Add Error** argument to .load_setup() handler memory: Add Error** argument to .log_global*() handlers memory: Add Error** argument to the global_dirty_log routines migration: Modify ram_init_bitmaps() to report dirty tracking errors migration: Fix migration termination vfio: Add Error** argument to .set_dirty_page_tracking() handler vfio: Add Error** argument to vfio_devices_dma_logging_start() vfio: Add Error** argument to vfio_devices_dma_logging_stop() vfio: Use new Error** argument in vfio_save_setup() vfio: Add Error** argument to .vfio_save_config() handler vfio: Reverse test on vfio_get_dirty_bitmap() memory: Add Error** argument to memory_get_xlat_addr() vfio: Add Error** argument to .get_dirty_bitmap() handler vfio: Also trace event failures in vfio_save_complete_precopy() vfio: Extend vfio_set_migration_error() with Error* argument include/exec/memory.h | 40 +++- include/hw/vfio/vfio-common.h | 29 ++- include/hw/vfio/vfio-container-base.h | 35 +++- include/migration/register.h | 267 +++--- include/qemu/typedefs.h | 2 - migration/savevm.h| 2 +- hw/i386/xen/xen-hvm.c | 10 +- hw/ppc/spapr.c| 2 +- hw/s390x/s390-stattrib.c | 2 +- hw/vfio/common.c | 160 +-- hw/vfio/container-base.c | 9 +- hw/vfio/container.c | 19 +- hw/vfio/migration.c | 89 ++--- hw/vfio/pci.c | 5 +- hw/virtio/vhost-vdpa.c| 5 +- hw/virtio/vhost.c | 6 +- migration/block-dirty-bitmap.c| 2 +- migration/block.c | 2 +- migration/dirtyrate.c | 21 +- migration/migration.c | 24 ++- migration/qemu-file.c | 5 +- migration/ram.c | 48 - migration/savevm.c| 28 +-- system/memory.c | 95 +++-- system/physmem.c | 5 +- 25 files changed, 699 insertions(+), 213 deletions(-) -- 2.43.2
Re: [PATCH v5 3/4] hw: Set virtio-iommu aw-bits default value on pc_q35 and arm virt
Hello Eric, On 2/15/24 09:42, Eric Auger wrote: Currently the default input range can extend to 64 bits. On x86, when the virtio-iommu protects vfio devices, the physical iommu may support only 39 bits. Let's set the default to 39, as done for the intel-iommu. On ARM we set 48b as a default (matching SMMUv3 SMMU_IDR5.VAX == 0). We use hw_compat_8_2 to handle the compatibility for machines before 9.0 which used to have a virtio-iommu default input range of 64 bits. Of course if aw-bits is set from the command line, the default is overriden. Signed-off-by: Eric Auger Reviewed-by: Zhenzhong Duan Tested-by: Yanghang Liu We need a property fixup for pseries also: $ build/ppc64-softmmu/qemu-system-ppc64 -M pseries -device virtio-iommu-pci,addr=04.0 qemu-system-ppc64: -device virtio-iommu-pci,addr=04.0: aw-bits must be within [32,64] Thanks, C. --- v3 -> v4: - update the qos test to relax the check on the max input IOVA v2 -> v3: - collected Zhenzhong's R-b - use _abort instead of NULL error handle on object_property_get_uint() call (Cédric) - use VTD_HOST_AW_39BIT (Cédric) v1 -> v2: - set aw-bits to 48b on ARM - use hw_compat_8_2 to handle the compat for older machines which used 64b as a default --- hw/arm/virt.c | 6 ++ hw/core/machine.c | 5 - hw/i386/pc.c| 6 ++ hw/virtio/virtio-iommu.c| 2 +- tests/qtest/virtio-iommu-test.c | 2 +- 5 files changed, 18 insertions(+), 3 deletions(-) diff --git a/hw/arm/virt.c b/hw/arm/virt.c index 368c2a415a..0994f2a560 100644 --- a/hw/arm/virt.c +++ b/hw/arm/virt.c @@ -2716,10 +2716,16 @@ static void virt_machine_device_pre_plug_cb(HotplugHandler *hotplug_dev, } else if (object_dynamic_cast(OBJECT(dev), TYPE_VIRTIO_MD_PCI)) { virtio_md_pci_pre_plug(VIRTIO_MD_PCI(dev), MACHINE(hotplug_dev), errp); } else if (object_dynamic_cast(OBJECT(dev), TYPE_VIRTIO_IOMMU_PCI)) { +uint8_t aw_bits = object_property_get_uint(OBJECT(dev), + "aw-bits", _abort); hwaddr db_start = 0, db_end = 0; QList *reserved_regions; char *resv_prop_str; +if (!aw_bits) { +qdev_prop_set_uint8(dev, "aw-bits", 48); +} + if (vms->iommu != VIRT_IOMMU_NONE) { error_setg(errp, "virt machine does not support multiple IOMMUs"); return; diff --git a/hw/core/machine.c b/hw/core/machine.c index fb5afdcae4..70ac96954c 100644 --- a/hw/core/machine.c +++ b/hw/core/machine.c @@ -30,9 +30,12 @@ #include "exec/confidential-guest-support.h" #include "hw/virtio/virtio-pci.h" #include "hw/virtio/virtio-net.h" +#include "hw/virtio/virtio-iommu.h" #include "audio/audio.h" -GlobalProperty hw_compat_8_2[] = {}; +GlobalProperty hw_compat_8_2[] = { +{ TYPE_VIRTIO_IOMMU_PCI, "aw-bits", "64" }, +}; const size_t hw_compat_8_2_len = G_N_ELEMENTS(hw_compat_8_2); GlobalProperty hw_compat_8_1[] = { diff --git a/hw/i386/pc.c b/hw/i386/pc.c index 196827531a..ee2d379c90 100644 --- a/hw/i386/pc.c +++ b/hw/i386/pc.c @@ -1456,6 +1456,8 @@ static void pc_machine_device_pre_plug_cb(HotplugHandler *hotplug_dev, } else if (object_dynamic_cast(OBJECT(dev), TYPE_VIRTIO_MD_PCI)) { virtio_md_pci_pre_plug(VIRTIO_MD_PCI(dev), MACHINE(hotplug_dev), errp); } else if (object_dynamic_cast(OBJECT(dev), TYPE_VIRTIO_IOMMU_PCI)) { +uint8_t aw_bits = object_property_get_uint(OBJECT(dev), + "aw-bits", _abort); /* Declare the APIC range as the reserved MSI region */ char *resv_prop_str = g_strdup_printf("0xfee0:0xfeef:%d", VIRTIO_IOMMU_RESV_MEM_T_MSI); @@ -1464,6 +1466,10 @@ static void pc_machine_device_pre_plug_cb(HotplugHandler *hotplug_dev, qlist_append_str(reserved_regions, resv_prop_str); qdev_prop_set_array(dev, "reserved-regions", reserved_regions); +if (!aw_bits) { +qdev_prop_set_uint8(dev, "aw-bits", VTD_HOST_AW_39BIT); +} + g_free(resv_prop_str); } diff --git a/hw/virtio/virtio-iommu.c b/hw/virtio/virtio-iommu.c index 8b541de850..2ec5ef3cd1 100644 --- a/hw/virtio/virtio-iommu.c +++ b/hw/virtio/virtio-iommu.c @@ -1526,7 +1526,7 @@ static Property virtio_iommu_properties[] = { DEFINE_PROP_LINK("primary-bus", VirtIOIOMMU, primary_bus, TYPE_PCI_BUS, PCIBus *), DEFINE_PROP_BOOL("boot-bypass", VirtIOIOMMU, boot_bypass, true), -DEFINE_PROP_UINT8("aw-bits", VirtIOIOMMU, aw_bits, 64), +DEFINE_PROP_UINT8("aw-bits", VirtIOIOMMU, aw_bits, 0), DEFINE_PROP_END_OF_LIST(), }; diff --git a/tests/qtest/virtio-iommu-test.c b/tests/qtest/virtio-iommu-test.c index 068e7a9e6c..0f36381acb 100644 --- a/tests/qtest/virtio-iommu-test.c +++ b/tests/qtest/virtio-iommu-test.c @@ -34,7 +34,7 @@
[PATCH v2 09/21] memory: Add Error** argument to the global_dirty_log routines
Now that the log_global*() handlers take an Error** parameter and return a bool, do the same for memory_global_dirty_log_start() and memory_global_dirty_log_stop(). The error is reported in the callers for now and it will be propagated in the call stack in the next changes. To be noted a functional change in ram_init_bitmaps(), if the dirty pages logger fails to start, there is no need to synchronize the dirty pages bitmaps. colo_incoming_start_dirty_log() could be modified in a similar way. Cc: Stefano Stabellini Cc: Anthony Perard Cc: Paul Durrant Cc: Michael S. Tsirkin Cc: Paolo Bonzini Cc: David Hildenbrand Cc: Hyman Huang Signed-off-by: Cédric Le Goater --- include/exec/memory.h | 10 -- hw/i386/xen/xen-hvm.c | 4 ++-- migration/dirtyrate.c | 21 + migration/ram.c | 34 ++ system/memory.c | 30 -- 5 files changed, 69 insertions(+), 30 deletions(-) diff --git a/include/exec/memory.h b/include/exec/memory.h index 4bc146c5ebdd377cd14a4e462f32cc945db5a0a8..8b019465ab13ce85c03075c80865a0865ea1feed 100644 --- a/include/exec/memory.h +++ b/include/exec/memory.h @@ -2576,15 +2576,21 @@ void memory_listener_unregister(MemoryListener *listener); * memory_global_dirty_log_start: begin dirty logging for all regions * * @flags: purpose of starting dirty log, migration or dirty rate + * @errp: pointer to Error*, to store an error if it happens. + * + * Return: true on success, else false setting @errp with error. */ -void memory_global_dirty_log_start(unsigned int flags); +bool memory_global_dirty_log_start(unsigned int flags, Error **errp); /** * memory_global_dirty_log_stop: end dirty logging for all regions * * @flags: purpose of stopping dirty log, migration or dirty rate + * @errp: pointer to Error*, to store an error if it happens. + * + * Return: true on success, else false setting @errp with error. */ -void memory_global_dirty_log_stop(unsigned int flags); +bool memory_global_dirty_log_stop(unsigned int flags, Error **errp); void mtree_info(bool flatview, bool dispatch_tree, bool owner, bool disabled); diff --git a/hw/i386/xen/xen-hvm.c b/hw/i386/xen/xen-hvm.c index 925a207b494b4eed52d5f360b554f18ac8a9806d..286269b47572d90e57df5ff44835bb5f8e16c7ad 100644 --- a/hw/i386/xen/xen-hvm.c +++ b/hw/i386/xen/xen-hvm.c @@ -655,9 +655,9 @@ void xen_hvm_modified_memory(ram_addr_t start, ram_addr_t length) void qmp_xen_set_global_dirty_log(bool enable, Error **errp) { if (enable) { -memory_global_dirty_log_start(GLOBAL_DIRTY_MIGRATION); +memory_global_dirty_log_start(GLOBAL_DIRTY_MIGRATION, errp); } else { -memory_global_dirty_log_stop(GLOBAL_DIRTY_MIGRATION); +memory_global_dirty_log_stop(GLOBAL_DIRTY_MIGRATION, errp); } } diff --git a/migration/dirtyrate.c b/migration/dirtyrate.c index 1d2e85746fb7b10eb7f149976970f9a92125af8a..34f6d803ff5f4e6ccf2e06aaaed65a336c4be469 100644 --- a/migration/dirtyrate.c +++ b/migration/dirtyrate.c @@ -90,11 +90,17 @@ static int64_t do_calculate_dirtyrate(DirtyPageRecord dirty_pages, void global_dirty_log_change(unsigned int flag, bool start) { +Error *local_err = NULL; +bool ret; + bql_lock(); if (start) { -memory_global_dirty_log_start(flag); +ret = memory_global_dirty_log_start(flag, _err); } else { -memory_global_dirty_log_stop(flag); +ret = memory_global_dirty_log_stop(flag, _err); +} +if (!ret) { +error_report_err(local_err); } bql_unlock(); } @@ -106,10 +112,14 @@ void global_dirty_log_change(unsigned int flag, bool start) */ static void global_dirty_log_sync(unsigned int flag, bool one_shot) { +Error *local_err = NULL; + bql_lock(); memory_global_dirty_log_sync(false); if (one_shot) { -memory_global_dirty_log_stop(flag); +if (!memory_global_dirty_log_stop(flag, _err)) { +error_report_err(local_err); +} } bql_unlock(); } @@ -608,9 +618,12 @@ static void calculate_dirtyrate_dirty_bitmap(struct DirtyRateConfig config) { int64_t start_time; DirtyPageRecord dirty_pages; +Error *local_err = NULL; bql_lock(); -memory_global_dirty_log_start(GLOBAL_DIRTY_DIRTY_RATE); +if (!memory_global_dirty_log_start(GLOBAL_DIRTY_DIRTY_RATE, _err)) { +error_report_err(local_err); +} /* * 1'round of log sync may return all 1 bits with diff --git a/migration/ram.c b/migration/ram.c index d648134133fc22cd91c7b2064198a90287ee733d..9fb1875aad73b2fa009199bdfa8960339df7287d 100644 --- a/migration/ram.c +++ b/migration/ram.c @@ -2391,6 +2391,7 @@ static void ram_save_cleanup(void *opaque) { RAMState **rsp = opaque; RAMBlock *block; +Error *local_err = NULL; /* We don't use dirty log with background snapshots */ if (!migrate_background_snapshot()) { @@ -2403,7 +2404,10 @@ static
[PATCH v2 07/21] migration: Add Error** argument to .load_setup() handler
This will be useful to report errors at a higher level, mostly in VFIO today. Reviewed-by: Philippe Mathieu-Daudé Signed-off-by: Cédric Le Goater --- include/migration/register.h | 3 ++- hw/vfio/migration.c | 2 +- migration/ram.c | 3 ++- migration/savevm.c | 10 ++ 4 files changed, 11 insertions(+), 7 deletions(-) diff --git a/include/migration/register.h b/include/migration/register.h index 96eae9dba2970552c379c732393e3ab6ef578a58..2cfc167f717de8e08c1ca8accdc3011c03eb1554 100644 --- a/include/migration/register.h +++ b/include/migration/register.h @@ -231,10 +231,11 @@ typedef struct SaveVMHandlers { * * @f: QEMUFile where to receive the data * @opaque: data pointer passed to register_savevm_live() + * @errp: pointer to Error*, to store an error if it happens. * * Returns zero to indicate success and negative for error */ -int (*load_setup)(QEMUFile *f, void *opaque); +int (*load_setup)(QEMUFile *f, void *opaque, Error **errp); /** * @load_cleanup diff --git a/hw/vfio/migration.c b/hw/vfio/migration.c index 8bcb4bc73cd5ba5338e3ffa4d907d0e6bfbb9485..2dfbe671f6f45aa530c7341177bb532d8292cecd 100644 --- a/hw/vfio/migration.c +++ b/hw/vfio/migration.c @@ -580,7 +580,7 @@ static void vfio_save_state(QEMUFile *f, void *opaque) } } -static int vfio_load_setup(QEMUFile *f, void *opaque) +static int vfio_load_setup(QEMUFile *f, void *opaque, Error **errp) { VFIODevice *vbasedev = opaque; diff --git a/migration/ram.c b/migration/ram.c index 745482899e18c86b73261b683c1bec04039a76d2..d648134133fc22cd91c7b2064198a90287ee733d 100644 --- a/migration/ram.c +++ b/migration/ram.c @@ -3498,8 +3498,9 @@ void colo_release_ram_cache(void) * * @f: QEMUFile where to receive the data * @opaque: RAMState pointer + * @errp: pointer to Error*, to store an error if it happens. */ -static int ram_load_setup(QEMUFile *f, void *opaque) +static int ram_load_setup(QEMUFile *f, void *opaque, Error **errp) { xbzrle_load_setup(); ramblock_recv_map_init(); diff --git a/migration/savevm.c b/migration/savevm.c index b5b3b51bad94dc4c04ae22cd687ba111299339aa..a4ef41d3ff5b471a1cd4166c2dc5813e44ea3a5a 100644 --- a/migration/savevm.c +++ b/migration/savevm.c @@ -2741,7 +2741,7 @@ static void qemu_loadvm_state_switchover_ack_needed(MigrationIncomingState *mis) trace_loadvm_state_switchover_ack_needed(mis->switchover_ack_pending_num); } -static int qemu_loadvm_state_setup(QEMUFile *f) +static int qemu_loadvm_state_setup(QEMUFile *f, Error **errp) { SaveStateEntry *se; int ret; @@ -2757,10 +2757,11 @@ static int qemu_loadvm_state_setup(QEMUFile *f) } } -ret = se->ops->load_setup(f, se->opaque); +ret = se->ops->load_setup(f, se->opaque, errp); if (ret < 0) { +error_prepend(errp, "Load state of device %s failed: ", + se->idstr); qemu_file_set_error(f, ret); -error_report("Load state of device %s failed", se->idstr); return ret; } } @@ -2941,7 +2942,8 @@ int qemu_loadvm_state(QEMUFile *f) return ret; } -if (qemu_loadvm_state_setup(f) != 0) { +if (qemu_loadvm_state_setup(f, _err) != 0) { +error_report_err(local_err); return -EINVAL; } -- 2.43.2
[PATCH v2 01/21] migration: Report error when shutdown fails
This will help detect issues regarding I/O channels usage. Reviewed-by: Philippe Mathieu-Daudé Reviewed-by: Peter Xu Signed-off-by: Cédric Le Goater --- migration/qemu-file.c | 5 - 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/migration/qemu-file.c b/migration/qemu-file.c index 94231ff2955c80b3d0fab11a40510d34c334a826..b69e0c62e2fcf21d346a3687df7eebee23791fdc 100644 --- a/migration/qemu-file.c +++ b/migration/qemu-file.c @@ -62,6 +62,8 @@ struct QEMUFile { */ int qemu_file_shutdown(QEMUFile *f) { +Error *err = NULL; + /* * We must set qemufile error before the real shutdown(), otherwise * there can be a race window where we thought IO all went though @@ -90,7 +92,8 @@ int qemu_file_shutdown(QEMUFile *f) return -ENOSYS; } -if (qio_channel_shutdown(f->ioc, QIO_CHANNEL_SHUTDOWN_BOTH, NULL) < 0) { +if (qio_channel_shutdown(f->ioc, QIO_CHANNEL_SHUTDOWN_BOTH, ) < 0) { +error_report_err(err); return -EIO; } -- 2.43.2
[PATCH v2 18/21] memory: Add Error** argument to memory_get_xlat_addr()
Let the callers do the reporting. This will be useful in vfio_iommu_map_dirty_notify(). Cc: Michael S. Tsirkin Cc: Paolo Bonzini Cc: David Hildenbrand Signed-off-by: Cédric Le Goater --- include/exec/memory.h | 15 ++- hw/vfio/common.c | 13 + hw/virtio/vhost-vdpa.c | 5 - system/memory.c| 10 +- 4 files changed, 32 insertions(+), 11 deletions(-) diff --git a/include/exec/memory.h b/include/exec/memory.h index 8b019465ab13ce85c03075c80865a0865ea1feed..baca989023415b69be3b4b4e7a622f983182314b 100644 --- a/include/exec/memory.h +++ b/include/exec/memory.h @@ -771,9 +771,22 @@ void ram_discard_manager_register_listener(RamDiscardManager *rdm, void ram_discard_manager_unregister_listener(RamDiscardManager *rdm, RamDiscardListener *rdl); +/** + * memory_get_xlat_addr: Extract addresses from a TLB entry + * + * @iotlb: pointer to an #IOMMUTLBEntry + * @vaddr: virtual addressf + * @ram_addr: RAM address + * @read_only: indicates if writes are allowed + * @mr_has_discard_manager: indicates memory is controlled by a + * RamDiscardManager + * @errp: pointer to Error*, to store an error if it happens. + * + * Return: true on success, else false setting @errp with error. + */ bool memory_get_xlat_addr(IOMMUTLBEntry *iotlb, void **vaddr, ram_addr_t *ram_addr, bool *read_only, - bool *mr_has_discard_manager); + bool *mr_has_discard_manager, Error **errp); typedef struct CoalescedMemoryRange CoalescedMemoryRange; typedef struct MemoryRegionIoeventfd MemoryRegionIoeventfd; diff --git a/hw/vfio/common.c b/hw/vfio/common.c index e51757e7d747c60b67deb966bb29b946a511b328..43f37447e3692ffa97788b02f83b81b44aaf301a 100644 --- a/hw/vfio/common.c +++ b/hw/vfio/common.c @@ -262,12 +262,13 @@ static bool vfio_listener_skipped_section(MemoryRegionSection *section) /* Called with rcu_read_lock held. */ static bool vfio_get_xlat_addr(IOMMUTLBEntry *iotlb, void **vaddr, - ram_addr_t *ram_addr, bool *read_only) + ram_addr_t *ram_addr, bool *read_only, + Error **errp) { bool ret, mr_has_discard_manager; ret = memory_get_xlat_addr(iotlb, vaddr, ram_addr, read_only, - _has_discard_manager); + _has_discard_manager, errp); if (ret && mr_has_discard_manager) { /* * Malicious VMs might trigger discarding of IOMMU-mapped memory. The @@ -297,6 +298,7 @@ static void vfio_iommu_map_notify(IOMMUNotifier *n, IOMMUTLBEntry *iotlb) hwaddr iova = iotlb->iova + giommu->iommu_offset; void *vaddr; int ret; +Error *local_err = NULL; trace_vfio_iommu_map_notify(iotlb->perm == IOMMU_NONE ? "UNMAP" : "MAP", iova, iova + iotlb->addr_mask); @@ -313,7 +315,8 @@ static void vfio_iommu_map_notify(IOMMUNotifier *n, IOMMUTLBEntry *iotlb) if ((iotlb->perm & IOMMU_RW) != IOMMU_NONE) { bool read_only; -if (!vfio_get_xlat_addr(iotlb, , NULL, _only)) { +if (!vfio_get_xlat_addr(iotlb, , NULL, _only, _err)) { +error_report_err(local_err); goto out; } /* @@ -1226,6 +1229,7 @@ static void vfio_iommu_map_dirty_notify(IOMMUNotifier *n, IOMMUTLBEntry *iotlb) VFIOContainerBase *bcontainer = giommu->bcontainer; hwaddr iova = iotlb->iova + giommu->iommu_offset; ram_addr_t translated_addr; +Error *local_err = NULL; int ret = -EINVAL; trace_vfio_iommu_map_dirty_notify(iova, iova + iotlb->addr_mask); @@ -1237,7 +1241,8 @@ static void vfio_iommu_map_dirty_notify(IOMMUNotifier *n, IOMMUTLBEntry *iotlb) } rcu_read_lock(); -if (!vfio_get_xlat_addr(iotlb, NULL, _addr, NULL)) { +if (!vfio_get_xlat_addr(iotlb, NULL, _addr, NULL, _err)) { +error_report_err(local_err); goto out_lock; } diff --git a/hw/virtio/vhost-vdpa.c b/hw/virtio/vhost-vdpa.c index ddae494ca8e8154ce03b88bc781fe9f1e639aceb..a6f06266cfc798b20b98001fa97ce771722175ec 100644 --- a/hw/virtio/vhost-vdpa.c +++ b/hw/virtio/vhost-vdpa.c @@ -203,6 +203,7 @@ static void vhost_vdpa_iommu_map_notify(IOMMUNotifier *n, IOMMUTLBEntry *iotlb) void *vaddr; int ret; Int128 llend; +Error *local_err = NULL; if (iotlb->target_as != _space_memory) { error_report("Wrong target AS \"%s\", only system memory is allowed", @@ -222,7 +223,9 @@ static void vhost_vdpa_iommu_map_notify(IOMMUNotifier *n, IOMMUTLBEntry *iotlb) if ((iotlb->perm & IOMMU_RW) != IOMMU_NONE) { bool read_only; -if (!memory_get_xlat_addr(iotlb, , NULL, _only, NULL)) { +if (!memory_get_xlat_addr(iotlb, , NUL
[PATCH v2 15/21] vfio: Use new Error** argument in vfio_save_setup()
Add an Error** argument to vfio_migration_set_state() and adjust callers, including vfio_save_setup(). The error will be propagated up to qemu_savevm_state_setup() where the save_setup() handler is executed. Modify vfio_vmstate_change_prepare() and vfio_vmstate_change() to store a reported error under the migration stream if a migration is in progress. Signed-off-by: Cédric Le Goater --- hw/vfio/migration.c | 64 ++--- 1 file changed, 43 insertions(+), 21 deletions(-) diff --git a/hw/vfio/migration.c b/hw/vfio/migration.c index 2dfbe671f6f45aa530c7341177bb532d8292cecd..8bdc68c66516710c52443135284262580825e0b8 100644 --- a/hw/vfio/migration.c +++ b/hw/vfio/migration.c @@ -84,7 +84,8 @@ static const char *mig_state_to_str(enum vfio_device_mig_state state) static int vfio_migration_set_state(VFIODevice *vbasedev, enum vfio_device_mig_state new_state, -enum vfio_device_mig_state recover_state) +enum vfio_device_mig_state recover_state, +Error **errp) { VFIOMigration *migration = vbasedev->migration; uint64_t buf[DIV_ROUND_UP(sizeof(struct vfio_device_feature) + @@ -104,15 +105,15 @@ static int vfio_migration_set_state(VFIODevice *vbasedev, ret = -errno; if (recover_state == VFIO_DEVICE_STATE_ERROR) { -error_report("%s: Failed setting device state to %s, err: %s. " - "Recover state is ERROR. Resetting device", - vbasedev->name, mig_state_to_str(new_state), - strerror(errno)); +error_setg(errp, "%s: Failed setting device state to %s, err: %s. " + "Recover state is ERROR. Resetting device", + vbasedev->name, mig_state_to_str(new_state), + strerror(errno)); goto reset_device; } -error_report( +error_setg(errp, "%s: Failed setting device state to %s, err: %s. Setting device in recover state %s", vbasedev->name, mig_state_to_str(new_state), strerror(errno), mig_state_to_str(recover_state)); @@ -120,7 +121,7 @@ static int vfio_migration_set_state(VFIODevice *vbasedev, mig_state->device_state = recover_state; if (ioctl(vbasedev->fd, VFIO_DEVICE_FEATURE, feature)) { ret = -errno; -error_report( +error_setg(errp, "%s: Failed setting device in recover state, err: %s. Resetting device", vbasedev->name, strerror(errno)); @@ -139,7 +140,7 @@ static int vfio_migration_set_state(VFIODevice *vbasedev, * This can happen if the device is asynchronously reset and * terminates a data transfer. */ -error_report("%s: data_fd out of sync", vbasedev->name); +error_setg(errp, "%s: data_fd out of sync", vbasedev->name); close(mig_state->data_fd); return -EBADF; @@ -170,10 +171,11 @@ reset_device: */ static int vfio_migration_set_state_or_reset(VFIODevice *vbasedev, - enum vfio_device_mig_state new_state) + enum vfio_device_mig_state new_state, + Error **errp) { return vfio_migration_set_state(vbasedev, new_state, -VFIO_DEVICE_STATE_ERROR); +VFIO_DEVICE_STATE_ERROR, errp); } static int vfio_load_buffer(QEMUFile *f, VFIODevice *vbasedev, @@ -391,8 +393,8 @@ static int vfio_save_setup(QEMUFile *f, void *opaque, Error **errp) stop_copy_size); migration->data_buffer = g_try_malloc0(migration->data_buffer_size); if (!migration->data_buffer) { -error_report("%s: Failed to allocate migration data buffer", - vbasedev->name); +error_setg(errp, "%s: Failed to allocate migration data buffer", + vbasedev->name); return -ENOMEM; } @@ -402,7 +404,7 @@ static int vfio_save_setup(QEMUFile *f, void *opaque, Error **errp) switch (migration->device_state) { case VFIO_DEVICE_STATE_RUNNING: ret = vfio_migration_set_state(vbasedev, VFIO_DEVICE_STATE_PRE_COPY, - VFIO_DEVICE_STATE_RUNNING); + VFIO_DEVICE_STATE_RUNNING, errp); if (ret) { return ret; } @@ -429,13 +431,20 @@ static void vfio_save_cleanup(void *opaque) { VFIODevice *vbasedev = opaque; VFIOMigration *migration
[PATCH v2 17/21] vfio: Reverse test on vfio_get_dirty_bitmap()
It will simplify the changes coming after. Signed-off-by: Cédric Le Goater --- hw/vfio/common.c | 22 +- 1 file changed, 13 insertions(+), 9 deletions(-) diff --git a/hw/vfio/common.c b/hw/vfio/common.c index 706e915a3ba5f8520deb3753d9bb450a986f207a..e51757e7d747c60b67deb966bb29b946a511b328 100644 --- a/hw/vfio/common.c +++ b/hw/vfio/common.c @@ -1237,16 +1237,20 @@ static void vfio_iommu_map_dirty_notify(IOMMUNotifier *n, IOMMUTLBEntry *iotlb) } rcu_read_lock(); -if (vfio_get_xlat_addr(iotlb, NULL, _addr, NULL)) { -ret = vfio_get_dirty_bitmap(bcontainer, iova, iotlb->addr_mask + 1, -translated_addr); -if (ret) { -error_report("vfio_iommu_map_dirty_notify(%p, 0x%"HWADDR_PRIx", " - "0x%"HWADDR_PRIx") = %d (%s)", - bcontainer, iova, iotlb->addr_mask + 1, ret, - strerror(-ret)); -} +if (!vfio_get_xlat_addr(iotlb, NULL, _addr, NULL)) { +goto out_lock; } + +ret = vfio_get_dirty_bitmap(bcontainer, iova, iotlb->addr_mask + 1, +translated_addr); +if (ret) { +error_report("vfio_iommu_map_dirty_notify(%p, 0x%"HWADDR_PRIx", " + "0x%"HWADDR_PRIx") = %d (%s)", + bcontainer, iova, iotlb->addr_mask + 1, ret, + strerror(-ret)); +} + +out_lock: rcu_read_unlock(); out: -- 2.43.2
[PATCH v2 14/21] vfio: Add Error** argument to vfio_devices_dma_logging_stop()
This improves error reporting in the log_global_stop() VFIO handler. Reviewed-by: Philippe Mathieu-Daudé Signed-off-by: Cédric Le Goater --- hw/vfio/common.c | 19 ++- 1 file changed, 14 insertions(+), 5 deletions(-) diff --git a/hw/vfio/common.c b/hw/vfio/common.c index a2d26cd08cb132d2b27c388bd75db3d9b8128407..706e915a3ba5f8520deb3753d9bb450a986f207a 100644 --- a/hw/vfio/common.c +++ b/hw/vfio/common.c @@ -938,12 +938,14 @@ static void vfio_dirty_tracking_init(VFIOContainerBase *bcontainer, memory_listener_unregister(); } -static void vfio_devices_dma_logging_stop(VFIOContainerBase *bcontainer) +static int vfio_devices_dma_logging_stop(VFIOContainerBase *bcontainer, + Error **errp) { uint64_t buf[DIV_ROUND_UP(sizeof(struct vfio_device_feature), sizeof(uint64_t))] = {}; struct vfio_device_feature *feature = (struct vfio_device_feature *)buf; VFIODevice *vbasedev; +int ret = 0; feature->argsz = sizeof(buf); feature->flags = VFIO_DEVICE_FEATURE_SET | @@ -955,11 +957,17 @@ static void vfio_devices_dma_logging_stop(VFIOContainerBase *bcontainer) } if (ioctl(vbasedev->fd, VFIO_DEVICE_FEATURE, feature)) { -warn_report("%s: Failed to stop DMA logging, err %d (%s)", -vbasedev->name, -errno, strerror(errno)); +/* Keep first error */ +if (!ret) { +ret = -errno; +error_setg(errp, "%s: Failed to stop DMA logging, err %d (%s)", + vbasedev->name, -errno, strerror(errno)); +} } vbasedev->dirty_tracking = false; } + +return ret; } static struct vfio_device_feature * @@ -1068,7 +1076,8 @@ static int vfio_devices_dma_logging_start(VFIOContainerBase *bcontainer, out: if (ret) { -vfio_devices_dma_logging_stop(bcontainer); +/* Ignore the potential errors when doing rollback */ +vfio_devices_dma_logging_stop(bcontainer, NULL); } vfio_device_feature_dma_logging_start_destroy(feature); @@ -1103,7 +1112,7 @@ static bool vfio_listener_log_global_stop(MemoryListener *listener, int ret = 0; if (vfio_devices_all_device_dirty_tracking(bcontainer)) { -vfio_devices_dma_logging_stop(bcontainer); +ret = vfio_devices_dma_logging_stop(bcontainer, errp); } else { ret = vfio_container_set_dirty_page_tracking(bcontainer, false, errp); } -- 2.43.2
[PATCH v2 02/21] migration: Remove SaveStateHandler and LoadStateHandler typedefs
They are only used once. Signed-off-by: Cédric Le Goater --- include/migration/register.h | 4 ++-- include/qemu/typedefs.h | 2 -- 2 files changed, 2 insertions(+), 4 deletions(-) diff --git a/include/migration/register.h b/include/migration/register.h index 9ab1f79512c605f0c88a45b560c57486fa054441..2e6a7d766e62f64940086b7b511249c9ff21fa62 100644 --- a/include/migration/register.h +++ b/include/migration/register.h @@ -18,7 +18,7 @@ typedef struct SaveVMHandlers { /* This runs inside the BQL. */ -SaveStateHandler *save_state; +void (*save_state)(QEMUFile *f, void *opaque); /* * save_prepare is called early, even before migration starts, and can be @@ -71,7 +71,7 @@ typedef struct SaveVMHandlers { /* This calculate the exact remaining data to transfer */ void (*state_pending_exact)(void *opaque, uint64_t *must_precopy, uint64_t *can_postcopy); -LoadStateHandler *load_state; +int (*load_state)(QEMUFile *f, void *opaque, int version_id); int (*load_setup)(QEMUFile *f, void *opaque); int (*load_cleanup)(void *opaque); /* Called when postcopy migration wants to resume from failure */ diff --git a/include/qemu/typedefs.h b/include/qemu/typedefs.h index d7c703b4ae9c91d9638111bcaafc656686e1dbb8..5fcba1c1b467826d4f7b6bd287690d33cdc48acf 100644 --- a/include/qemu/typedefs.h +++ b/include/qemu/typedefs.h @@ -150,8 +150,6 @@ typedef struct IRQState *qemu_irq; /* * Function types */ -typedef void SaveStateHandler(QEMUFile *f, void *opaque); -typedef int LoadStateHandler(QEMUFile *f, void *opaque, int version_id); typedef void (*qemu_irq_handler)(void *opaque, int n, int level); #endif /* QEMU_TYPEDEFS_H */ -- 2.43.2
[PATCH v2 13/21] vfio: Add Error** argument to vfio_devices_dma_logging_start()
This allows to update the Error argument of the VFIO log_global_start() handler. Errors detected when device level logging is started will be propagated up to qemu_savevm_state_setup() when the ram save_setup() handler is executed. The vfio_set_migration_error() call becomes redundant. Remove it. Reviewed-by: Philippe Mathieu-Daudé Signed-off-by: Cédric Le Goater --- hw/vfio/common.c | 21 + 1 file changed, 9 insertions(+), 12 deletions(-) diff --git a/hw/vfio/common.c b/hw/vfio/common.c index 560f4bc38499f7f4a3bc84ef7e4184fd6dc89935..a2d26cd08cb132d2b27c388bd75db3d9b8128407 100644 --- a/hw/vfio/common.c +++ b/hw/vfio/common.c @@ -1036,7 +1036,8 @@ static void vfio_device_feature_dma_logging_start_destroy( g_free(feature); } -static int vfio_devices_dma_logging_start(VFIOContainerBase *bcontainer) +static int vfio_devices_dma_logging_start(VFIOContainerBase *bcontainer, + Error **errp) { struct vfio_device_feature *feature; VFIODirtyRanges ranges; @@ -1058,8 +1059,8 @@ static int vfio_devices_dma_logging_start(VFIOContainerBase *bcontainer) ret = ioctl(vbasedev->fd, VFIO_DEVICE_FEATURE, feature); if (ret) { ret = -errno; -error_report("%s: Failed to start DMA logging, err %d (%s)", - vbasedev->name, ret, strerror(errno)); +error_setg(errp, "%s: Failed to start DMA logging, err %d (%s)", + vbasedev->name, ret, strerror(errno)); goto out; } vbasedev->dirty_tracking = true; @@ -1083,15 +1084,13 @@ static bool vfio_listener_log_global_start(MemoryListener *listener, int ret; if (vfio_devices_all_device_dirty_tracking(bcontainer)) { -ret = vfio_devices_dma_logging_start(bcontainer); +ret = vfio_devices_dma_logging_start(bcontainer, errp); } else { -ret = vfio_container_set_dirty_page_tracking(bcontainer, true, NULL); +ret = vfio_container_set_dirty_page_tracking(bcontainer, true, errp); } if (ret) { -error_report("vfio: Could not start dirty page tracking, err: %d (%s)", - ret, strerror(-ret)); -vfio_set_migration_error(ret); +error_prepend(errp, "vfio: Could not start dirty page tracking - "); } return !!ret; } @@ -1106,13 +1105,11 @@ static bool vfio_listener_log_global_stop(MemoryListener *listener, if (vfio_devices_all_device_dirty_tracking(bcontainer)) { vfio_devices_dma_logging_stop(bcontainer); } else { -ret = vfio_container_set_dirty_page_tracking(bcontainer, false, NULL); +ret = vfio_container_set_dirty_page_tracking(bcontainer, false, errp); } if (ret) { -error_report("vfio: Could not stop dirty page tracking, err: %d (%s)", - ret, strerror(-ret)); -vfio_set_migration_error(ret); +error_prepend(errp, "vfio: Could not stop dirty page tracking - "); } return !!ret; } -- 2.43.2
Re: [PATCH 2/2] ppc/pnv: Fix pervasive topology calculation for P10
Hello Caleb, On 2/27/24 15:48, Caleb Schlossin wrote: Pervasive topology(PIR) calculation for core, thread ID was wrong for big cores (SMT8). Fixing for P10. Based on: <20240123195005.8965-1-cal...@linux.vnet.ibm.com> Signed-off-by: Caleb Schlossin Since the initial patch [1] is not merged yet, you can simply send a v2 with the update. There is still some time before soft freeze [2]. The Subject of this patch [PATCH 2/2] seems to refer to a series. Is there a patch 1/2 ? Thanks, C. [1] https://lore.kernel.org/all/20240123195005.8965-1-cal...@linux.vnet.ibm.com/ [2] https://wiki.qemu.org/Planning/9.0 --- hw/ppc/pnv.c | 15 +-- 1 file changed, 13 insertions(+), 2 deletions(-) diff --git a/hw/ppc/pnv.c b/hw/ppc/pnv.c index 2f53883916..aa5aba60b4 100644 --- a/hw/ppc/pnv.c +++ b/hw/ppc/pnv.c @@ -1068,12 +1068,23 @@ static uint32_t pnv_chip_pir_p9(PnvChip *chip, uint32_t core_id, } } +/* + *0:48 Reserved - Read as zeroes + * 49:52 Node ID + * 53:55 Chip ID + * 56 Reserved - Read as zero + * 57:59 Quad ID + * 60 Core Chiplet Pair ID + * 61:63 Thread/Core Chiplet ID t0-t2 + * + * We only care about the lower bits. uint32_t is fine for the moment. + */ static uint32_t pnv_chip_pir_p10(PnvChip *chip, uint32_t core_id, uint32_t thread_id) { if (chip->nr_threads == 8) { -return (chip->chip_id << 8) | ((thread_id & 1) << 2) | (core_id << 3) | - (thread_id >> 1); +return (chip->chip_id << 8) | ((core_id / 4) << 4) | + ((core_id % 2) << 3) | thread_id; } else { return (chip->chip_id << 8) | (core_id << 2) | thread_id; }
[PULL 0/2] aspeed queue
The following changes since commit 1b330dafcdc34315f6837ff3af34dbb4b3106373: Merge tag 'edk2-stable202402-20240226-pull-request' of https://gitlab.com/kraxel/qemu into staging (2024-02-26 21:28:11 +) are available in the Git repository at: https://github.com/legoater/qemu/ tags/pull-aspeed-20240227 for you to fetch changes up to db052d0eafe86c336d512dba99a1ec7c5c553f63: aspeed: fix hardcode boot address 0 (2024-02-27 13:47:05 +0100) aspeed queue: * Add support for UART0, in preparation of AST2700 models Jamin Lin (2): aspeed: introduce a new UART0 device name aspeed: fix hardcode boot address 0 include/hw/arm/aspeed_soc.h | 19 +-- hw/arm/aspeed.c | 17 +++-- hw/arm/aspeed_ast10x0.c | 1 + hw/arm/aspeed_ast2400.c | 6 -- hw/arm/aspeed_ast2600.c | 3 ++- hw/arm/aspeed_soc_common.c | 6 -- 6 files changed, 39 insertions(+), 13 deletions(-)
[PULL 1/2] aspeed: introduce a new UART0 device name
From: Jamin Lin The Aspeed datasheet refers to the UART controllers as UART1 - UART13 for the ast10x0, ast2600, ast2500 and ast2400 SoCs and the Aspeed ast2700 introduces an UART0 and the UART controllers as UART0 - UART12. To keep the naming in the QEMU models in sync with the datasheet, let's introduce a new UART0 device name and do the required adjustements. Signed-off-by: Troy Lee Signed-off-by: Jamin Lin Reviewed-by: Cédric Le Goater [ clg: - Kept original assert() in aspeed_soc_uart_set_chr() - Fixed 'i' range in connect_serial_hds_to_uarts() loop ] Signed-off-by: Cédric Le Goater --- include/hw/arm/aspeed_soc.h | 17 + hw/arm/aspeed.c | 13 - hw/arm/aspeed_ast10x0.c | 1 + hw/arm/aspeed_ast2400.c | 2 ++ hw/arm/aspeed_ast2600.c | 1 + hw/arm/aspeed_soc_common.c | 6 -- 6 files changed, 33 insertions(+), 7 deletions(-) diff --git a/include/hw/arm/aspeed_soc.h b/include/hw/arm/aspeed_soc.h index 9d0af84a8cff..e1a023be538b 100644 --- a/include/hw/arm/aspeed_soc.h +++ b/include/hw/arm/aspeed_soc.h @@ -140,6 +140,7 @@ struct AspeedSoCClass { int wdts_num; int macs_num; int uarts_num; +int uarts_base; const int *irqmap; const hwaddr *memmap; uint32_t num_cpus; @@ -151,6 +152,7 @@ const char *aspeed_soc_cpu_type(AspeedSoCClass *sc); enum { ASPEED_DEV_SPI_BOOT, ASPEED_DEV_IOMEM, +ASPEED_DEV_UART0, ASPEED_DEV_UART1, ASPEED_DEV_UART2, ASPEED_DEV_UART3, @@ -235,4 +237,19 @@ void aspeed_mmio_map_unimplemented(AspeedSoCState *s, SysBusDevice *dev, void aspeed_board_init_flashes(AspeedSMCState *s, const char *flashtype, unsigned int count, int unit0); +static inline int aspeed_uart_index(int uart_dev) +{ +return uart_dev - ASPEED_DEV_UART0; +} + +static inline int aspeed_uart_first(AspeedSoCClass *sc) +{ +return aspeed_uart_index(sc->uarts_base); +} + +static inline int aspeed_uart_last(AspeedSoCClass *sc) +{ +return aspeed_uart_first(sc) + sc->uarts_num - 1; +} + #endif /* ASPEED_SOC_H */ diff --git a/hw/arm/aspeed.c b/hw/arm/aspeed.c index 09b1e823ba1c..0af96afa16a6 100644 --- a/hw/arm/aspeed.c +++ b/hw/arm/aspeed.c @@ -342,7 +342,7 @@ static void connect_serial_hds_to_uarts(AspeedMachineState *bmc) int uart_chosen = bmc->uart_chosen ? bmc->uart_chosen : amc->uart_default; aspeed_soc_uart_set_chr(s, uart_chosen, serial_hd(0)); -for (int i = 1, uart = ASPEED_DEV_UART1; i < sc->uarts_num; i++, uart++) { +for (int i = 1, uart = sc->uarts_base; i < sc->uarts_num; i++, uart++) { if (uart == uart_chosen) { continue; } @@ -1094,7 +1094,7 @@ static char *aspeed_get_bmc_console(Object *obj, Error **errp) AspeedMachineClass *amc = ASPEED_MACHINE_GET_CLASS(bmc); int uart_chosen = bmc->uart_chosen ? bmc->uart_chosen : amc->uart_default; -return g_strdup_printf("uart%d", uart_chosen - ASPEED_DEV_UART1 + 1); +return g_strdup_printf("uart%d", aspeed_uart_index(uart_chosen)); } static void aspeed_set_bmc_console(Object *obj, const char *value, Error **errp) @@ -1103,6 +1103,8 @@ static void aspeed_set_bmc_console(Object *obj, const char *value, Error **errp) AspeedMachineClass *amc = ASPEED_MACHINE_GET_CLASS(bmc); AspeedSoCClass *sc = ASPEED_SOC_CLASS(object_class_by_name(amc->soc_name)); int val; +int uart_first = aspeed_uart_first(sc); +int uart_last = aspeed_uart_last(sc); if (sscanf(value, "uart%u", ) != 1) { error_setg(errp, "Bad value for \"uart\" property"); @@ -1110,11 +1112,12 @@ static void aspeed_set_bmc_console(Object *obj, const char *value, Error **errp) } /* The number of UART depends on the SoC */ -if (val < 1 || val > sc->uarts_num) { -error_setg(errp, "\"uart\" should be in range [1 - %d]", sc->uarts_num); +if (val < uart_first || val > uart_last) { +error_setg(errp, "\"uart\" should be in range [%d - %d]", + uart_first, uart_last); return; } -bmc->uart_chosen = ASPEED_DEV_UART1 + val - 1; +bmc->uart_chosen = val + ASPEED_DEV_UART0; } static void aspeed_machine_class_props_init(ObjectClass *oc) diff --git a/hw/arm/aspeed_ast10x0.c b/hw/arm/aspeed_ast10x0.c index c3b5116a6a9d..2634e0f6544e 100644 --- a/hw/arm/aspeed_ast10x0.c +++ b/hw/arm/aspeed_ast10x0.c @@ -436,6 +436,7 @@ static void aspeed_soc_ast1030_class_init(ObjectClass *klass, void *data) sc->wdts_num = 4; sc->macs_num = 1; sc->uarts_num = 13; +sc->uarts_base = ASPEED_DEV_UART1; sc->irqmap = aspeed_soc_ast1030_irqmap; sc->memmap = aspeed_soc_ast1030_memmap; sc->num_cpus = 1; diff --git a/hw/arm/aspeed_ast2400.c b/hw/arm/aspeed_ast2400.c index 8829561
[PULL 2/2] aspeed: fix hardcode boot address 0
From: Jamin Lin In the previous design of ASPEED SOCs QEMU model, it set the boot address at "0" which was the hardcode setting for ast10x0, ast2600, ast2500 and ast2400. According to the design of ast2700, it has a bootmcu(riscv-32) which is used for executing SPL and initialize DRAM and copy u-boot image from SPI/Flash to DRAM at address 0x4 at SPL boot stage. Then, CPUs(cortex-a35) execute u-boot, kernel and rofs. Currently, qemu not support emulate two CPU architectures at the same machine. Therefore, qemu will only support to emulate CPU(cortex-a35) side for ast2700 and the boot address is "0x4 ". Fixed hardcode boot address "0" for future models using a different mapping address. Signed-off-by: Troy Lee Signed-off-by: Jamin Lin Reviewed-by: Cédric Le Goater Signed-off-by: Cédric Le Goater --- include/hw/arm/aspeed_soc.h | 2 -- hw/arm/aspeed.c | 4 +++- hw/arm/aspeed_ast2400.c | 4 ++-- hw/arm/aspeed_ast2600.c | 2 +- 4 files changed, 6 insertions(+), 6 deletions(-) diff --git a/include/hw/arm/aspeed_soc.h b/include/hw/arm/aspeed_soc.h index e1a023be538b..c60fac900acb 100644 --- a/include/hw/arm/aspeed_soc.h +++ b/include/hw/arm/aspeed_soc.h @@ -224,8 +224,6 @@ enum { ASPEED_DEV_FSI2, }; -#define ASPEED_SOC_SPI_BOOT_ADDR 0x0 - qemu_irq aspeed_soc_get_irq(AspeedSoCState *s, int dev); bool aspeed_soc_uart_realize(AspeedSoCState *s, Error **errp); void aspeed_soc_uart_set_chr(AspeedSoCState *s, int dev, Chardev *chr); diff --git a/hw/arm/aspeed.c b/hw/arm/aspeed.c index 0af96afa16a6..8854581ca8de 100644 --- a/hw/arm/aspeed.c +++ b/hw/arm/aspeed.c @@ -289,12 +289,14 @@ static void aspeed_install_boot_rom(AspeedMachineState *bmc, BlockBackend *blk, uint64_t rom_size) { AspeedSoCState *soc = bmc->soc; +AspeedSoCClass *sc = ASPEED_SOC_GET_CLASS(soc); memory_region_init_rom(>boot_rom, NULL, "aspeed.boot_rom", rom_size, _abort); memory_region_add_subregion_overlap(>spi_boot_container, 0, >boot_rom, 1); -write_boot_rom(blk, ASPEED_SOC_SPI_BOOT_ADDR, rom_size, _abort); +write_boot_rom(blk, sc->memmap[ASPEED_DEV_SPI_BOOT], + rom_size, _abort); } void aspeed_board_init_flashes(AspeedSMCState *s, const char *flashtype, diff --git a/hw/arm/aspeed_ast2400.c b/hw/arm/aspeed_ast2400.c index 95da85fee029..d12588620751 100644 --- a/hw/arm/aspeed_ast2400.c +++ b/hw/arm/aspeed_ast2400.c @@ -26,7 +26,7 @@ #define ASPEED_SOC_IOMEM_SIZE 0x0020 static const hwaddr aspeed_soc_ast2400_memmap[] = { -[ASPEED_DEV_SPI_BOOT] = ASPEED_SOC_SPI_BOOT_ADDR, +[ASPEED_DEV_SPI_BOOT] = 0x, [ASPEED_DEV_IOMEM] = 0x1E60, [ASPEED_DEV_FMC]= 0x1E62, [ASPEED_DEV_SPI1] = 0x1E63, @@ -61,7 +61,7 @@ static const hwaddr aspeed_soc_ast2400_memmap[] = { }; static const hwaddr aspeed_soc_ast2500_memmap[] = { -[ASPEED_DEV_SPI_BOOT] = ASPEED_SOC_SPI_BOOT_ADDR, +[ASPEED_DEV_SPI_BOOT] = 0x, [ASPEED_DEV_IOMEM] = 0x1E60, [ASPEED_DEV_FMC]= 0x1E62, [ASPEED_DEV_SPI1] = 0x1E63, diff --git a/hw/arm/aspeed_ast2600.c b/hw/arm/aspeed_ast2600.c index f74561ecdcd5..174be537709b 100644 --- a/hw/arm/aspeed_ast2600.c +++ b/hw/arm/aspeed_ast2600.c @@ -22,7 +22,7 @@ #define ASPEED_SOC_DPMCU_SIZE 0x0004 static const hwaddr aspeed_soc_ast2600_memmap[] = { -[ASPEED_DEV_SPI_BOOT] = ASPEED_SOC_SPI_BOOT_ADDR, +[ASPEED_DEV_SPI_BOOT] = 0x, [ASPEED_DEV_SRAM] = 0x1000, [ASPEED_DEV_DPMCU] = 0x1800, /* 0x1600 0x17FF : AHB BUS do LPC Bus bridge */ -- 2.43.2
Re: [PATCH V4 00/14] allow cpr-reboot for vfio
On 2/26/24 03:14, Peter Xu wrote: On Thu, Feb 22, 2024 at 12:33:42PM -0500, Steven Sistare wrote: Peter (and David if interested): these patches still need RB: migration: notifier error checking migration: stop vm for cpr migration: update cpr-reboot description migration: options incompatible with cpr These all look fine to me. Alex, these patches still need RB: vfio: register container for cpr vfio: allow cpr-reboot migration if suspended I'll need to wait for comment from either Alex/Cedric on these. Yes. It's on my list. As I asked in the other thread, afaict crp-reboot keeps changing behavior, maybe I can merge migration patches first, Go ahead. It will help me for the changes I am doing on error reporting for VFIO migration. I will rebase on top. then keep vfio patches separately merged / discussed? Sure. I always see cpr-reboot mode experimental from this regard. This makes sense to me also. Thanks, C. Please consider adding a patch to declare cpr-reboot mode experimental if that matches your expectation, until all relevant patches are merged, to make sure the ABI becomes stable. Thanks,
Re: [RFC PATCH 14/14] migration: Fix return-path thread exit
On 2/23/24 15:05, Fabiano Rosas wrote: Peter Xu writes: On Fri, Feb 16, 2024 at 02:35:26PM -0300, Fabiano Rosas wrote: Cédric Le Goater writes: Hello Fabiano On 2/14/24 21:35, Fabiano Rosas wrote: Cédric Le Goater writes: Hello Fabiano On 2/8/24 14:29, Fabiano Rosas wrote: Cédric Le Goater writes: In case of error, close_return_path_on_source() can perform a shutdown to exit the return-path thread. However, in migrate_fd_cleanup(), 'to_dst_file' is closed before calling close_return_path_on_source() and the shutdown fails, leaving the source and destination waiting for an event to occur. Hi, Cédric Are you sure this is not caused by patch 13? It happens with upstream QEMU without any patch. I might have taken that "shutdown fails" in the commit message too literaly. Anyway, I have a proposed solution: -->8-- From 729aa7b5b7f130f756d41649fdd0862bd2e90430 Mon Sep 17 00:00:00 2001 From: Fabiano Rosas Date: Wed, 14 Feb 2024 16:45:43 -0300 Subject: [PATCH] migration: Join the return path thread before releasing to_dst_file MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit The return path thread might hang at a blocking system call. Before joining the thread we might need to issue a shutdown() on the socket file descriptor to release it. To determine whether the shutdown() is necessary we look at the QEMUFile error. Make sure we only clean up the QEMUFile after the return path has been waited for. Yes. That's the important part. This fixes a hang when qemu_savevm_state_setup() produced an error that was detected by migration_detect_error(). That skips migration_completion() so close_return_path_on_source() would get stuck waiting for the RP thread to terminate. At migrate_fd_cleanup() I'm keeping the relative order of joining the migration thread and the return path just in case. That doesn't look necessary. Indeed. But I don't trust the migration code, it's full of undocumented dependencies like that. What was the reason to join the migration thread only when s->to_dst_file is valid ? I didn't find any explicit reason looking through the history. It seems we used to rely on to_dst_file before migration_thread_running was introduced. I wouldn't mind keeping that 'if' there. Let's see what Peter thinks about it. Frankly I don't have a strong opinion on current patch 14 or the new proposal, but it seems we reached a consensus. Fabiano, would you repost with a formal patch, with the proper tags? Yes, I'll post it soon. One thing I am still not sure is whether we should still have patch 13 altogether? Please see my other reply on whether it's possible to have migrate_get_error() == true but qemu_file_get_error() == false. I'll include it then. Thanks for taking over. I have included : [PATCH] migration: Join the return path thread before releasing to_dst_file in my series and dropped 13-14. I hope to send a follow up on : https://lore.kernel.org/qemu-devel/20240207133347.1115903-1-...@redhat.com/ before we reach soft freeze. It's growing quite a lot. C.
[PATCH] MAINTAINERS: Remove myself as reviewer from PPC
PPC maintainership has been a side activity for the last 2 years and it is time to let go some of it now that Nick has taken over. Signed-off-by: Cédric Le Goater --- MAINTAINERS | 3 --- 1 file changed, 3 deletions(-) diff --git a/MAINTAINERS b/MAINTAINERS index a74d73960c0a..f5a4e4745c92 100644 --- a/MAINTAINERS +++ b/MAINTAINERS @@ -316,7 +316,6 @@ F: tests/tcg/openrisc/ PowerPC TCG CPUs M: Nicholas Piggin M: Daniel Henrique Barboza -R: Cédric Le Goater L: qemu-...@nongnu.org S: Odd Fixes F: target/ppc/ @@ -468,7 +467,6 @@ F: target/mips/sysemu/ PPC KVM CPUs M: Nicholas Piggin R: Daniel Henrique Barboza -R: Cédric Le Goater S: Odd Fixes F: target/ppc/kvm.c @@ -1502,7 +1500,6 @@ F: tests/avocado/ppc_prep_40p.py sPAPR (pseries) M: Nicholas Piggin R: Daniel Henrique Barboza -R: Cédric Le Goater R: David Gibson R: Harsh Prateek Bora L: qemu-...@nongnu.org -- 2.43.0
Re: Trying to write data to i2c bus
On 2/19/24 18:14, Corey Minyard wrote: On Mon, Feb 19, 2024 at 04:53:47PM +, Paz Offer wrote: Thank you very much Corey, I am simulating an external module that wants to communicate with the board management controller (BMC). The real device will be connected to the board using i2c bus, and could initiate communication at any time, by sending bytes over the bus. And you have a simulated BMC that can do this? Or is the system running in qemu the BMC. I am not sure whether the 'Master-side' (the side the initiating communication) needs to simulate a full i2c-master device, or whether my code could 'simply' write directly to the appropriate registers of the guest OS. Are there some examples or documentation on how to implement something like this? The aspeed i2c controller is capable of having another bus master on an I2C but, but it is the only host that can currently do it. It is doable, the code is ther for multiple bus masters, but there is no device currently that does it. I assume that is coming at some point, but no documentation exists on how to do it. You can look at the git commits in hw/i2c around 37fa5ca42623 "hw/i2c: support multiple masters" for the changes that were done to support this. There is an i2c-echo device implementing an I2C slave and a test, test_arm_ast2600_evb_buildroot in tests/avocado/ machine_aspeed.py, using it on the ast2600-evb. Thanks, C.
Re: [PULL 22/49] hw/pci-host/raven.c: Mark raven_io_ops as implementing unaligned accesses
On 2/19/24 15:55, Peter Maydell wrote: On Mon, 19 Feb 2024 at 14:53, Cédric Le Goater wrote: On 2/19/24 15:49, BALATON Zoltan wrote: On Mon, 19 Feb 2024, Nicholas Piggin wrote: From: Peter Maydell The raven_io_ops MemoryRegionOps is the only one in the source tree which sets .valid.unaligned to indicate that it should support unaligned accesses and which does not also set .impl.unaligned to indicate that its read and write functions can do the unaligned handling themselves. This is a problem, because at the moment the core memory system does not implement the support for handling unaligned accesses by doing a series of aligned accesses and combining them (system/memory.c:access_with_adjusted_size() has a TODO comment noting this). Fortunately raven_io_read() and raven_io_write() will correctly deal with the case of being passed an unaligned address, so we can fix the missing unaligned access support by setting .impl.unaligned in the MemoryRegionOps struct. Fixes: 9a1839164c9c8f06 ("raven: Implement non-contiguous I/O region") Reviewed-by: Cédric Le Goater Tested-by: Cédric Le Goater Signed-off-by: Peter Maydell Signed-off-by: Nicholas Piggin Hm, this seems to be missing the actual patch. It's merged already and git knows how to handle this. Mmm, though this is the result of "rebased onto a tree that already had the commit" rather than "two merges both contain the commit", so we end up with a genuinely empty commit upstream, which is a bit odd looking, though harmless. git rebase -i db5f7f9e3ceb and dropping the first patch would cleanup the empty patch. C.
Re: [PULL 22/49] hw/pci-host/raven.c: Mark raven_io_ops as implementing unaligned accesses
On 2/19/24 15:49, BALATON Zoltan wrote: On Mon, 19 Feb 2024, Nicholas Piggin wrote: From: Peter Maydell The raven_io_ops MemoryRegionOps is the only one in the source tree which sets .valid.unaligned to indicate that it should support unaligned accesses and which does not also set .impl.unaligned to indicate that its read and write functions can do the unaligned handling themselves. This is a problem, because at the moment the core memory system does not implement the support for handling unaligned accesses by doing a series of aligned accesses and combining them (system/memory.c:access_with_adjusted_size() has a TODO comment noting this). Fortunately raven_io_read() and raven_io_write() will correctly deal with the case of being passed an unaligned address, so we can fix the missing unaligned access support by setting .impl.unaligned in the MemoryRegionOps struct. Fixes: 9a1839164c9c8f06 ("raven: Implement non-contiguous I/O region") Reviewed-by: Cédric Le Goater Tested-by: Cédric Le Goater Signed-off-by: Peter Maydell Signed-off-by: Nicholas Piggin Hm, this seems to be missing the actual patch. It's merged already and git knows how to handle this. Thanks, C.
Re: [PATCH 13/14] migration: Use migrate_has_error() in close_return_path_on_source()
On 2/14/24 17:00, Fabiano Rosas wrote: Cédric Le Goater writes: On 2/8/24 14:57, Fabiano Rosas wrote: Cédric Le Goater writes: On 2/8/24 14:07, Fabiano Rosas wrote: Cédric Le Goater writes: close_return_path_on_source() retrieves the migration error from the the QEMUFile '->to_dst_file' to know if a shutdown is required. This shutdown is required to exit the return-path thread. However, in migrate_fd_cleanup(), '->to_dst_file' is cleaned up before calling close_return_path_on_source() and the shutdown is never performed, leaving the source and destination waiting for an event to occur. Avoid relying on '->to_dst_file' and use migrate_has_error() instead. Suggested-by: Peter Xu Signed-off-by: Cédric Le Goater --- migration/migration.c | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/migration/migration.c b/migration/migration.c index d5f705ceef4c925589aa49335969672c0d761fa2..5f55af3d7624750ca416c4177781241b3e291e5d 100644 --- a/migration/migration.c +++ b/migration/migration.c @@ -2372,8 +2372,7 @@ static bool close_return_path_on_source(MigrationState *ms) * cause it to unblock if it's stuck waiting for the destination. */ WITH_QEMU_LOCK_GUARD(>qemu_file_lock) { -if (ms->to_dst_file && ms->rp_state.from_dst_file && -qemu_file_get_error(ms->to_dst_file)) { +if (migrate_has_error(ms) && ms->rp_state.from_dst_file) { qemu_file_shutdown(ms->rp_state.from_dst_file); } } Hm, maybe Peter can help defend this, but this assumes that every function that takes an 'f' and sets the file error also sets migrate_set_error(). I'm not sure we have determined that, have we? How could we check all the code path ? I agree it is difficult when looking at the code :/ It would help if the thing wasn't called 'f' for the most part of the code to begin with. Whenever there's a file error at to_dst_file there's the chance that the rp_state.from_dst_file got stuck. So we cannot ignore the file error. Would it work if we checked it earlier during cleanup as you did previously and then set the migration error? Do you mean doing something similar to what is done in source_return_path_thread() ? if (qemu_file_get_error(s->to_dst_file)) { qemu_file_get_error_obj(s->to_dst_file, ); if (err) { migrate_set_error(ms, err); error_free(err); ... Yes. That would be safer I think. Yes, something like that. I wish we could make that return path cleanup more deterministic, but currently it's just: "if something hangs, call shutdown()". We don't have a way to detect a hang, we just look at the file error and hope it works. A crucial aspect here is that calling qemu_file_shutdown() itself sets the file error. So there's not even a guarantee that an error is actually an error. Nevertheless, I am struggling to understand how qemu_file_set_error() and migrate_set_error() fit together. I was expecting some kind of synchronization routine but there isn't it seems. Are they completely orthogonal ? when should we use these routines and when not ? We're trying to phase out the QEMUFile usage altogether. One thing that is getting in the way is this dependency on the qemu_file_*_error functions. OK. the other changes, which add an Error** argument to various handlers, reduce the use of qemu_file_*_error routines in VFIO. While we're not there yet, a good pattern is to find a qemu_file_set|get_error() pair and replace it with migrate_set|has_error(). OK. I will keep that in mind for the other changes. Thanks, C. Unfortunately the return path does not fit in this, because we don't have a matching qemu_file_set_error, it could be anywhere. As I said above, we're using that error as a heuristic for: "a recvmsg() might be hanging". My initial goal was to modify some of the memory handlers (log_global*) and migration handlers to propagate errors at the QMP level and them report to the management layer. This is growing in something bigger and currently, I don't find a good approach to the problem. The last two patches of this series try to fix the return-path thread termination. Let's keep that for after. I'll try to figure that out. I see you provided a reproducer. Thanks, C.
Re: [RFC PATCH 14/14] migration: Fix return-path thread exit
Hello Fabiano On 2/14/24 21:35, Fabiano Rosas wrote: Cédric Le Goater writes: Hello Fabiano On 2/8/24 14:29, Fabiano Rosas wrote: Cédric Le Goater writes: In case of error, close_return_path_on_source() can perform a shutdown to exit the return-path thread. However, in migrate_fd_cleanup(), 'to_dst_file' is closed before calling close_return_path_on_source() and the shutdown fails, leaving the source and destination waiting for an event to occur. Hi, Cédric Are you sure this is not caused by patch 13? It happens with upstream QEMU without any patch. I might have taken that "shutdown fails" in the commit message too literaly. Anyway, I have a proposed solution: -->8-- From 729aa7b5b7f130f756d41649fdd0862bd2e90430 Mon Sep 17 00:00:00 2001 From: Fabiano Rosas Date: Wed, 14 Feb 2024 16:45:43 -0300 Subject: [PATCH] migration: Join the return path thread before releasing to_dst_file MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit The return path thread might hang at a blocking system call. Before joining the thread we might need to issue a shutdown() on the socket file descriptor to release it. To determine whether the shutdown() is necessary we look at the QEMUFile error. Make sure we only clean up the QEMUFile after the return path has been waited for. Yes. That's the important part. This fixes a hang when qemu_savevm_state_setup() produced an error that was detected by migration_detect_error(). That skips migration_completion() so close_return_path_on_source() would get stuck waiting for the RP thread to terminate. At migrate_fd_cleanup() I'm keeping the relative order of joining the migration thread and the return path just in case. That doesn't look necessary. What was the reason to join the migration thread only when s->to_dst_file is valid ? Reported-by: Cédric Le Goater Signed-off-by: Fabiano Rosas LGTM, it fixes the hang when an error is detected, the migration is aborted and the VM resumes execution. FWIW, Tested-by: Cédric Le Goater It requires more thorough testing though. Thanks, C. --- migration/migration.c | 36 1 file changed, 16 insertions(+), 20 deletions(-) diff --git a/migration/migration.c b/migration/migration.c index ab21de2cad..f0b70e8a9d 100644 --- a/migration/migration.c +++ b/migration/migration.c @@ -1326,17 +1326,19 @@ static void migrate_fd_cleanup(MigrationState *s) qemu_savevm_state_cleanup(); +bql_unlock(); +if (s->migration_thread_running) { +qemu_thread_join(>thread); +s->migration_thread_running = false; +} +bql_lock(); + +close_return_path_on_source(s); + if (s->to_dst_file) { QEMUFile *tmp; trace_migrate_fd_cleanup(); -bql_unlock(); -if (s->migration_thread_running) { -qemu_thread_join(>thread); -s->migration_thread_running = false; -} -bql_lock(); - multifd_send_shutdown(); qemu_mutex_lock(>qemu_file_lock); tmp = s->to_dst_file; @@ -1350,12 +1352,6 @@ static void migrate_fd_cleanup(MigrationState *s) qemu_fclose(tmp); } -/* - * We already cleaned up to_dst_file, so errors from the return - * path might be due to that, ignore them. - */ -close_return_path_on_source(s); - assert(!migration_is_active(s)); if (s->state == MIGRATION_STATUS_CANCELLING) { @@ -2874,6 +2870,13 @@ static MigThrError postcopy_pause(MigrationState *s) while (true) { QEMUFile *file; +/* + * We're already pausing, so ignore any errors on the return + * path and just wait for the thread to finish. It will be + * re-created when we resume. + */ +close_return_path_on_source(s); + /* * Current channel is possibly broken. Release it. Note that this is * guaranteed even without lock because to_dst_file should only be @@ -2893,13 +2896,6 @@ static MigThrError postcopy_pause(MigrationState *s) qemu_file_shutdown(file); qemu_fclose(file); -/* - * We're already pausing, so ignore any errors on the return - * path and just wait for the thread to finish. It will be - * re-created when we resume. - */ -close_return_path_on_source(s); - migrate_set_state(>state, s->state, MIGRATION_STATUS_POSTCOPY_PAUSED);
Re: [PATCH 11/14] vfio: Extend vfio_set_migration_error() with Error* argument
Hello Avihai, On 2/12/24 10:35, Avihai Horon wrote: Hi Cedric, On 07/02/2024 15:33, Cédric Le Goater wrote: External email: Use caution opening links or attachments vfio_set_migration_error() sets the 'return' error on the migration stream if a migration is in progress. To improve error reporting, add a new Error* argument to also set the Error object on the migration stream. Signed-off-by: Cédric Le Goater --- hw/vfio/common.c | 50 +--- 1 file changed, 30 insertions(+), 20 deletions(-) diff --git a/hw/vfio/common.c b/hw/vfio/common.c index 82173b039c47150f5edd05d329192c5b9c8a9a0f..afe8b6bd294fd5904f394a5db48aae3fd718b14e 100644 --- a/hw/vfio/common.c +++ b/hw/vfio/common.c @@ -148,16 +148,18 @@ bool vfio_viommu_preset(VFIODevice *vbasedev) return vbasedev->bcontainer->space->as != _space_memory; } -static void vfio_set_migration_error(int err) +static void vfio_set_migration_error(int ret, Error *err) { MigrationState *ms = migrate_get_current(); if (migration_is_setup_or_active(ms->state)) { WITH_QEMU_LOCK_GUARD(>qemu_file_lock) { if (ms->to_dst_file) { - qemu_file_set_error(ms->to_dst_file, err); + qemu_file_set_error_obj(ms->to_dst_file, ret, err); } } + } else { + error_report_err(err); } } @@ -296,15 +298,17 @@ static void vfio_iommu_map_notify(IOMMUNotifier *n, IOMMUTLBEntry *iotlb) VFIOContainerBase *bcontainer = giommu->bcontainer; hwaddr iova = iotlb->iova + giommu->iommu_offset; void *vaddr; + Error *local_err = NULL; int ret; trace_vfio_iommu_map_notify(iotlb->perm == IOMMU_NONE ? "UNMAP" : "MAP", iova, iova + iotlb->addr_mask); if (iotlb->target_as != _space_memory) { - error_report("Wrong target AS \"%s\", only system memory is allowed", - iotlb->target_as->name ? iotlb->target_as->name : "none"); - vfio_set_migration_error(-EINVAL); + error_setg(_err, + "Wrong target AS \"%s\", only system memory is allowed", + iotlb->target_as->name ? iotlb->target_as->name : "none"); + vfio_set_migration_error(-EINVAL, local_err); return; } @@ -336,11 +340,12 @@ static void vfio_iommu_map_notify(IOMMUNotifier *n, IOMMUTLBEntry *iotlb) ret = vfio_container_dma_unmap(bcontainer, iova, iotlb->addr_mask + 1, iotlb); if (ret) { - error_report("vfio_container_dma_unmap(%p, 0x%"HWADDR_PRIx", " - "0x%"HWADDR_PRIx") = %d (%s)", - bcontainer, iova, - iotlb->addr_mask + 1, ret, strerror(-ret)); - vfio_set_migration_error(ret); + error_setg(_err, + "vfio_container_dma_unmap(%p, 0x%"HWADDR_PRIx", " + "0x%"HWADDR_PRIx") = %d (%s)", + bcontainer, iova, + iotlb->addr_mask + 1, ret, strerror(-ret)); + vfio_set_migration_error(ret, local_err); } } out: @@ -1224,13 +1229,15 @@ static void vfio_iommu_map_dirty_notify(IOMMUNotifier *n, IOMMUTLBEntry *iotlb) VFIOContainerBase *bcontainer = giommu->bcontainer; hwaddr iova = iotlb->iova + giommu->iommu_offset; ram_addr_t translated_addr; + Error *local_err = NULL; int ret = -EINVAL; trace_vfio_iommu_map_dirty_notify(iova, iova + iotlb->addr_mask); if (iotlb->target_as != _space_memory) { - error_report("Wrong target AS \"%s\", only system memory is allowed", - iotlb->target_as->name ? iotlb->target_as->name : "none"); + error_setg(_err, + "Wrong target AS \"%s\", only system memory is allowed", + iotlb->target_as->name ? iotlb->target_as->name : "none"); goto out; } @@ -1239,17 +1246,18 @@ static void vfio_iommu_map_dirty_notify(IOMMUNotifier *n, IOMMUTLBEntry *iotlb) ret = vfio_get_dirty_bitmap(bcontainer, iova, iotlb->addr_mask + 1, translated_addr); If vfio_get_xlat_addr() above (it's not shown here) returns false, we will pass a NULL local_err to vfio_set_migration_error() and it may de-reference NULL ptr in error_report_err(). Ah yes. Thanks for spotting this. Should we refactor vfio_get_xlat_addr() to get errp, I think we should add an Error** parameter to vfio_get_xlat_addr() and memory_get_xlat_addr(). It shoul
Re: [PATCH 05/21] hw/ppc/pnv_bmc: Use qdev_new() instead of QOM API
On 2/16/24 12:02, Philippe Mathieu-Daudé wrote: Prefer QDev API for QDev objects, avoid the underlying QOM layer. Signed-off-by: Philippe Mathieu-Daudé Reviewed-by: Cédric Le Goater Thanks, C. --- hw/ppc/pnv_bmc.c | 10 +- 1 file changed, 5 insertions(+), 5 deletions(-) diff --git a/hw/ppc/pnv_bmc.c b/hw/ppc/pnv_bmc.c index 99f1e8d7f9..0c1274df21 100644 --- a/hw/ppc/pnv_bmc.c +++ b/hw/ppc/pnv_bmc.c @@ -269,13 +269,13 @@ void pnv_bmc_set_pnor(IPMIBmc *bmc, PnvPnor *pnor) */ IPMIBmc *pnv_bmc_create(PnvPnor *pnor) { -Object *obj; +DeviceState *dev; -obj = object_new(TYPE_IPMI_BMC_SIMULATOR); -qdev_realize(DEVICE(obj), NULL, _fatal); -pnv_bmc_set_pnor(IPMI_BMC(obj), pnor); +dev = qdev_new(TYPE_IPMI_BMC_SIMULATOR); +qdev_realize(dev, NULL, _fatal); +pnv_bmc_set_pnor(IPMI_BMC(dev), pnor); -return IPMI_BMC(obj); +return IPMI_BMC(dev); } typedef struct ForeachArgs {
Re: [PATCH 5/6] hw/vfio/common: Use RCU_READ macros
On 2/16/24 09:49, Philippe Mathieu-Daudé wrote: On 24/1/24 15:09, Philippe Mathieu-Daudé wrote: On 24/1/24 10:25, Manos Pitsidianakis wrote: On Wed, 24 Jan 2024 09:42, Philippe Mathieu-Daudé wrote: Replace the manual rcu_read_(un)lock calls by the *RCU_READ_LOCK_GUARD macros (See commit ef46ae67ba "docs/style: call out the use of GUARD macros"). Signed-off-by: Philippe Mathieu-Daudé --- hw/vfio/common.c | 34 -- 1 file changed, 16 insertions(+), 18 deletions(-) diff --git a/hw/vfio/common.c b/hw/vfio/common.c index 4aa86f563c..09878a3603 100644 --- a/hw/vfio/common.c +++ b/hw/vfio/common.c @@ -308,13 +308,13 @@ static void vfio_iommu_map_notify(IOMMUNotifier *n, IOMMUTLBEntry *iotlb) return; } - rcu_read_lock(); + RCU_READ_LOCK_GUARD(); if ((iotlb->perm & IOMMU_RW) != IOMMU_NONE) { bool read_only; if (!vfio_get_xlat_addr(iotlb, , NULL, _only)) { - goto out; + return; Since this is the only early return, we could alternatively do: - if (!vfio_get_xlat_addr(iotlb, , NULL, _only)) { + if (vfio_get_xlat_addr(iotlb, , NULL, _only)) { remove the goto/return, and wrap the rest of the codeflow in this if's brackets. And then we could use WITH_RCU_READ_LOCK_GUARD instead. That'd increase the code indentation however. If the maintainer agrees with the style & code churn, I don't mind respining. Alex, Cédric, any preference? my choice would be to keep the 'goto' statement and protect the vfio_get_xlat_addr() call with : +WITH_RCU_READ_LOCK_GUARD() { +if (vfio_get_xlat_addr(iotlb, NULL, _addr, NULL)) { +ret = vfio_get_dirty_bitmap(bcontainer, iova, +iotlb->addr_mask + 1, +translated_addr); +if (ret) { +error_report("vfio_iommu_map_dirty_notify(%p," + " 0x%"HWADDR_PRIx + ", 0x%"HWADDR_PRIx") = %d (%s)", + bcontainer, iova, iotlb->addr_mask + 1, ret, + strerror(-ret)); +} +} } Thanks, C.
Re: [PATCH v3 1/2] aspeed: introduce a new UART0 device name
On 2/15/24 08:59, Jamin Lin wrote: The Aspeed datasheet refers to the UART controllers as UART1 - UART13 for the ast10x0, ast2600, ast2500 and ast2400 SoCs and the Aspeed ast2700 introduces an UART0 and the UART controllers as UART0 - UART12. To keep the naming in the QEMU models in sync with the datasheet, let's introduce a new UART0 device name and do the required adjustements. Signed-off-by: Troy Lee Signed-off-by: Jamin Lin Reviewed-by: Cédric Le Goater One comment below, --- hw/arm/aspeed.c | 13 - hw/arm/aspeed_ast10x0.c | 1 + hw/arm/aspeed_ast2400.c | 2 ++ hw/arm/aspeed_ast2600.c | 1 + hw/arm/aspeed_soc_common.c | 10 ++ include/hw/arm/aspeed_soc.h | 17 + 6 files changed, 35 insertions(+), 9 deletions(-) diff --git a/hw/arm/aspeed.c b/hw/arm/aspeed.c index 09b1e823ba..aa165d583b 100644 --- a/hw/arm/aspeed.c +++ b/hw/arm/aspeed.c @@ -342,7 +342,7 @@ static void connect_serial_hds_to_uarts(AspeedMachineState *bmc) int uart_chosen = bmc->uart_chosen ? bmc->uart_chosen : amc->uart_default; aspeed_soc_uart_set_chr(s, uart_chosen, serial_hd(0)); -for (int i = 1, uart = ASPEED_DEV_UART1; i < sc->uarts_num; i++, uart++) { +for (int i = 0, uart = sc->uarts_base; i < sc->uarts_num; i++, uart++) { if (uart == uart_chosen) { continue; } @@ -1094,7 +1094,7 @@ static char *aspeed_get_bmc_console(Object *obj, Error **errp) AspeedMachineClass *amc = ASPEED_MACHINE_GET_CLASS(bmc); int uart_chosen = bmc->uart_chosen ? bmc->uart_chosen : amc->uart_default; -return g_strdup_printf("uart%d", uart_chosen - ASPEED_DEV_UART1 + 1); +return g_strdup_printf("uart%d", aspeed_uart_index(uart_chosen)); } static void aspeed_set_bmc_console(Object *obj, const char *value, Error **errp) @@ -1103,6 +1103,8 @@ static void aspeed_set_bmc_console(Object *obj, const char *value, Error **errp) AspeedMachineClass *amc = ASPEED_MACHINE_GET_CLASS(bmc); AspeedSoCClass *sc = ASPEED_SOC_CLASS(object_class_by_name(amc->soc_name)); int val; +int uart_first = aspeed_uart_first(sc); +int uart_last = aspeed_uart_last(sc); if (sscanf(value, "uart%u", ) != 1) { error_setg(errp, "Bad value for \"uart\" property"); @@ -1110,11 +1112,12 @@ static void aspeed_set_bmc_console(Object *obj, const char *value, Error **errp) } /* The number of UART depends on the SoC */ -if (val < 1 || val > sc->uarts_num) { -error_setg(errp, "\"uart\" should be in range [1 - %d]", sc->uarts_num); +if (val < uart_first || val > uart_last) { +error_setg(errp, "\"uart\" should be in range [%d - %d]", + uart_first, uart_last); return; } -bmc->uart_chosen = ASPEED_DEV_UART1 + val - 1; +bmc->uart_chosen = val + ASPEED_DEV_UART0; } static void aspeed_machine_class_props_init(ObjectClass *oc) diff --git a/hw/arm/aspeed_ast10x0.c b/hw/arm/aspeed_ast10x0.c index c3b5116a6a..2634e0f654 100644 --- a/hw/arm/aspeed_ast10x0.c +++ b/hw/arm/aspeed_ast10x0.c @@ -436,6 +436,7 @@ static void aspeed_soc_ast1030_class_init(ObjectClass *klass, void *data) sc->wdts_num = 4; sc->macs_num = 1; sc->uarts_num = 13; +sc->uarts_base = ASPEED_DEV_UART1; sc->irqmap = aspeed_soc_ast1030_irqmap; sc->memmap = aspeed_soc_ast1030_memmap; sc->num_cpus = 1; diff --git a/hw/arm/aspeed_ast2400.c b/hw/arm/aspeed_ast2400.c index 8829561bb6..95da85fee0 100644 --- a/hw/arm/aspeed_ast2400.c +++ b/hw/arm/aspeed_ast2400.c @@ -523,6 +523,7 @@ static void aspeed_soc_ast2400_class_init(ObjectClass *oc, void *data) sc->wdts_num = 2; sc->macs_num = 2; sc->uarts_num= 5; +sc->uarts_base = ASPEED_DEV_UART1; sc->irqmap = aspeed_soc_ast2400_irqmap; sc->memmap = aspeed_soc_ast2400_memmap; sc->num_cpus = 1; @@ -551,6 +552,7 @@ static void aspeed_soc_ast2500_class_init(ObjectClass *oc, void *data) sc->wdts_num = 3; sc->macs_num = 2; sc->uarts_num= 5; +sc->uarts_base = ASPEED_DEV_UART1; sc->irqmap = aspeed_soc_ast2500_irqmap; sc->memmap = aspeed_soc_ast2500_memmap; sc->num_cpus = 1; diff --git a/hw/arm/aspeed_ast2600.c b/hw/arm/aspeed_ast2600.c index 4ee32ea99d..f74561ecdc 100644 --- a/hw/arm/aspeed_ast2600.c +++ b/hw/arm/aspeed_ast2600.c @@ -666,6 +666,7 @@ static void aspeed_soc_ast2600_class_init(ObjectClass *oc, void *data) sc->wdts_num = 4; sc->macs_num = 4; sc->uarts_num= 13; +sc->uarts_base = ASPEED_DEV_UART1; sc->irqmap = aspeed_soc_ast2600_irqmap;
Re: [PATCH v3 2/2] aspeed: fix hardcode boot address 0
On 2/15/24 08:59, Jamin Lin wrote: In the previous design of ASPEED SOCs QEMU model, it set the boot address at "0" which was the hardcode setting for ast10x0, ast2600, ast2500 and ast2400. According to the design of ast2700, it has a bootmcu(riscv-32) which is used for executing SPL and initialize DRAM and copy u-boot image from SPI/Flash to DRAM at address 0x4 at SPL boot stage. Then, CPUs(cortex-a35) execute u-boot, kernel and rofs. Currently, qemu not support emulate two CPU architectures at the same machine. Therefore, qemu will only support to emulate CPU(cortex-a35) side for ast2700 and the boot address is "0x4 ". Fixed hardcode boot address "0" for future models using a different mapping address. Signed-off-by: Troy Lee Signed-off-by: Jamin Lin Reviewed-by: Cédric Le Goater Thanks, C. --- hw/arm/aspeed.c | 4 +++- hw/arm/aspeed_ast2400.c | 4 ++-- hw/arm/aspeed_ast2600.c | 2 +- include/hw/arm/aspeed_soc.h | 2 -- 4 files changed, 6 insertions(+), 6 deletions(-) diff --git a/hw/arm/aspeed.c b/hw/arm/aspeed.c index aa165d583b..9fec245e4e 100644 --- a/hw/arm/aspeed.c +++ b/hw/arm/aspeed.c @@ -289,12 +289,14 @@ static void aspeed_install_boot_rom(AspeedMachineState *bmc, BlockBackend *blk, uint64_t rom_size) { AspeedSoCState *soc = bmc->soc; +AspeedSoCClass *sc = ASPEED_SOC_GET_CLASS(soc); memory_region_init_rom(>boot_rom, NULL, "aspeed.boot_rom", rom_size, _abort); memory_region_add_subregion_overlap(>spi_boot_container, 0, >boot_rom, 1); -write_boot_rom(blk, ASPEED_SOC_SPI_BOOT_ADDR, rom_size, _abort); +write_boot_rom(blk, sc->memmap[ASPEED_DEV_SPI_BOOT], + rom_size, _abort); } void aspeed_board_init_flashes(AspeedSMCState *s, const char *flashtype, diff --git a/hw/arm/aspeed_ast2400.c b/hw/arm/aspeed_ast2400.c index 95da85fee0..d125886207 100644 --- a/hw/arm/aspeed_ast2400.c +++ b/hw/arm/aspeed_ast2400.c @@ -26,7 +26,7 @@ #define ASPEED_SOC_IOMEM_SIZE 0x0020 static const hwaddr aspeed_soc_ast2400_memmap[] = { -[ASPEED_DEV_SPI_BOOT] = ASPEED_SOC_SPI_BOOT_ADDR, +[ASPEED_DEV_SPI_BOOT] = 0x, [ASPEED_DEV_IOMEM] = 0x1E60, [ASPEED_DEV_FMC]= 0x1E62, [ASPEED_DEV_SPI1] = 0x1E63, @@ -61,7 +61,7 @@ static const hwaddr aspeed_soc_ast2400_memmap[] = { }; static const hwaddr aspeed_soc_ast2500_memmap[] = { -[ASPEED_DEV_SPI_BOOT] = ASPEED_SOC_SPI_BOOT_ADDR, +[ASPEED_DEV_SPI_BOOT] = 0x, [ASPEED_DEV_IOMEM] = 0x1E60, [ASPEED_DEV_FMC]= 0x1E62, [ASPEED_DEV_SPI1] = 0x1E63, diff --git a/hw/arm/aspeed_ast2600.c b/hw/arm/aspeed_ast2600.c index f74561ecdc..174be53770 100644 --- a/hw/arm/aspeed_ast2600.c +++ b/hw/arm/aspeed_ast2600.c @@ -22,7 +22,7 @@ #define ASPEED_SOC_DPMCU_SIZE 0x0004 static const hwaddr aspeed_soc_ast2600_memmap[] = { -[ASPEED_DEV_SPI_BOOT] = ASPEED_SOC_SPI_BOOT_ADDR, +[ASPEED_DEV_SPI_BOOT] = 0x, [ASPEED_DEV_SRAM] = 0x1000, [ASPEED_DEV_DPMCU] = 0x1800, /* 0x1600 0x17FF : AHB BUS do LPC Bus bridge */ diff --git a/include/hw/arm/aspeed_soc.h b/include/hw/arm/aspeed_soc.h index e1a023be53..c60fac900a 100644 --- a/include/hw/arm/aspeed_soc.h +++ b/include/hw/arm/aspeed_soc.h @@ -224,8 +224,6 @@ enum { ASPEED_DEV_FSI2, }; -#define ASPEED_SOC_SPI_BOOT_ADDR 0x0 - qemu_irq aspeed_soc_get_irq(AspeedSoCState *s, int dev); bool aspeed_soc_uart_realize(AspeedSoCState *s, Error **errp); void aspeed_soc_uart_set_chr(AspeedSoCState *s, int dev, Chardev *chr);
Re: [PATCH RFCv2 0/8] vfio/iommufd: IOMMUFD Dirty Tracking
Hello Joao, On 2/13/24 12:59, Joao Martins wrote: On 12/02/2024 13:56, Joao Martins wrote: This small series adds support for Dirty Tracking in IOMMUFD backend. The sole reason I still made it RFC is because of the second patch, where we are implementing user-managed auto domains. In essence it is quite similar to the original IOMMUFD series where we would allocate a HWPT, until we switched later on into a IOAS attach. Patch 2 goes into more detail, but the gist is that there's two modes of using IOMMUFD and by keep using kernel managed auto domains we would end up duplicating the same flags we have in HWPT but into the VFIO IOAS attach. While it is true that just adding a flag is simpler, it also creates duplication and motivates duplicate what hwpt-alloc already has. But there's a chance I have the wrong expectation here, so any feedback welcome. The series is divided into: * Patch 1: Adds a simple helper to get device capabilities; * Patches 2 - 5: IOMMUFD backend support for dirty tracking; The workflow is relatively simple: 1) Probe device and allow dirty tracking in the HWPT 2) Toggling dirty tracking on/off 3) Read-and-clear of Dirty IOVAs The heuristics selected for (1) were to enable it *if* device supports migration but doesn't support VF dirty tracking or IOMMU dirty tracking is supported. The latter is for the hotplug case where we can add a device without a tracker and thus still support migration. The unmap case is deferred until further vIOMMU support with migration is added[3] which will then introduce the usage of IOMMU_HWPT_GET_DIRTY_BITMAP_NO_CLEAR in GET_DIRTY_BITMAP ioctl in the dma unmap bitmap flow. * Patches 6-8: Add disabling of hugepages to allow tracking at base page; avoid blocking live migration where there's no VF dirty tracker, considering that we have IOMMU dirty tracking. And allow disabling VF dirty tracker via qemu command line. This series builds on top of Zhengzhong series[0], but only requires the first 9 patches i.e. up to ("vfio/pci: Initialize host iommu device instance after attachment")[1] that are more generic IOMMUFD device plumbing, and doesn't require the nesting counterpart. I need to add that this series doesn't *need* to be based on Zhengzhong series. Though given that he is consolidating how an IOMMUFD device info is represented it felt the correct thing to do. For dirty tracking we mainly need the dev_id/iommufd available when we are going to attach, that's it. I've pushed this series version that doesn't have such dependency, let me know if you want me to pursue this version instead going forward: https://github.com/jpemartins/qemu/commits/iommufd-v5.nodeps I feel I have lost track of all the different patchsets. To recap, there is yours : * vfio/iommufd: IOMMUFD Dirty Tracking https://lore.kernel.org/qemu-devel/20240212135643.5858-1-joao.m.mart...@oracle.com/ Zhengzhong's : * [PATCH rfcv2 00/18] Check and sync host IOMMU cap/ecap with vIOMMU https://lore.kernel.org/qemu-devel/20240201072818.327930-1-zhenzhong.d...@intel.com/ Eric's : * [RFC 0/7] VIRTIO-IOMMU/VFIO: Fix host iommu geometry handling for hotplugged devices https://lore.kernel.org/qemu-devel/20240117080414.316890-1-eric.au...@redhat.com/ Steve's: * [PATCH V3 00/13] allow cpr-reboot for vfio https://lore.kernel.org/qemu-devel/1707418446-134863-1-git-send-email-steven.sist...@oracle.com/ Mine, which should be an RFC : * [PATCH 00/14] migration: Improve error reporting https://lore.kernel.org/qemu-devel/20240207133347.1115903-1-...@redhat.com/ Anything else ? Thanks, C.
Re: [PATCH v4 4/4] qemu-options.hx: Add an entry for virtio-iommu-pci and document aw-bits
On 2/13/24 19:28, Eric Auger wrote: We are missing an entry for the virtio-iommu-pci device. Add the information on which machine it is currently supported and document the new aw-bits option. Signed-off-by: Eric Auger --- qemu-options.hx | 8 1 file changed, 8 insertions(+) diff --git a/qemu-options.hx b/qemu-options.hx index 8547254dbf..6a8c970640 100644 --- a/qemu-options.hx +++ b/qemu-options.hx @@ -1172,6 +1172,14 @@ SRST Please also refer to the wiki page for general scenarios of VT-d emulation in QEMU: https://wiki.qemu.org/Features/VT-d. +``-device virtio-iommu-pci[,option=...]`` +This is only supported by ``-machine q35`` and ``-machine virt``. +It supports below options: + +``aw-bits=val`` (val between 32 and 64, default depends on machine) +This decides the address width of IOVA address space. With +q35 it defaults to 39 bits. On arm virt it defaults to 48 bits. Minor improvement : "It defaults to 39 bits on q35 machines and 48 bits on ARM virt machines." Anyhow, Reviewed-by: Cédric Le Goater Thanks, C.
Re: [PATCH] target/ppc: Fix lxv/stxv MSR facility check
On 2/13/24 09:39, Nicholas Piggin wrote: The move to decodetree flipped the inequality test for the VEC / VSX MSR facility check. This caused application crashes under Linux, where these facility unavailable interrupts are used for lazy-switching of VEC/VSX register sets. Getting the incorrect interrupt would result in wrong registers being loaded, potentially overwriting live values and/or exposing stale ones. Cc: qemu-sta...@nongnu.org Reported-by: Joel Stanley Fixes: 70426b5bb738 ("target/ppc: moved stxvx and lxvx from legacy to decodtree") Resolves: https://gitlab.com/qemu-project/qemu/-/issues/1769 Tested-by: Harsh Prateek Bora Signed-off-by: Nicholas Piggin Reviewed-by: Cédric Le Goater Tested-by: Cédric Le Goater with a RHEL9 image. Thanks, C. --- target/ppc/translate/vsx-impl.c.inc | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/target/ppc/translate/vsx-impl.c.inc b/target/ppc/translate/vsx-impl.c.inc index 6db87ab336..0266f09119 100644 --- a/target/ppc/translate/vsx-impl.c.inc +++ b/target/ppc/translate/vsx-impl.c.inc @@ -2268,7 +2268,7 @@ static bool do_lstxv(DisasContext *ctx, int ra, TCGv displ, static bool do_lstxv_D(DisasContext *ctx, arg_D *a, bool store, bool paired) { -if (paired || a->rt >= 32) { +if (paired || a->rt < 32) { REQUIRE_VSX(ctx); } else { REQUIRE_VECTOR(ctx);
Re: [PATCH 4/4] hw/arm/stellaris: Add missing QOM 'SoC' parent
On 2/13/24 16:36, Philippe Mathieu-Daudé wrote: On 1/2/24 17:46, Peter Maydell wrote: On Tue, 30 Jan 2024 at 19:03, Philippe Mathieu-Daudé wrote: QDev objects created with qdev_new() need to manually add their parent relationship with object_property_add_child(). Since we don't model the SoC, just use a QOM container. Signed-off-by: Philippe Mathieu-Daudé --- Ah, this is where the other qdev_new() calls are sorted. Reviewed-by: Peter Maydell I wonder if we should add a variant on qdev_new() that you can pass in the parent object to? Yes, this is what we discussed with Markus. In order to stop using the "/unattached" container from pre-QOM, qdev_new() must take a QOM parent. I tried to do it but hit some problem with some odd use in PPC or S390 (discussed with Cédric so likely PPC, I need to go back to it). Can you remind what this was about ? Thanks, C.
Re: [PATCH 08/14] vfio: Use new Error** argument in vfio_save_setup()
On 2/12/24 10:17, Avihai Horon wrote: Hi Cedric, On 07/02/2024 15:33, Cédric Le Goater wrote: External email: Use caution opening links or attachments Add an Error** argument to vfio_migration_set_state() and adjust callers, including vfio_save_setup(). The error will be propagated up to qemu_savevm_state_setup() where the save_setup() handler is executed. Signed-off-by: Cédric Le Goater --- hw/vfio/migration.c | 62 + 1 file changed, 40 insertions(+), 22 deletions(-) diff --git a/hw/vfio/migration.c b/hw/vfio/migration.c index 2dfbe671f6f45aa530c7341177bb532d8292cecd..2e0a79967cc97f44d9be5575c3cfe18c9f349dab 100644 --- a/hw/vfio/migration.c +++ b/hw/vfio/migration.c @@ -84,7 +84,8 @@ static const char *mig_state_to_str(enum vfio_device_mig_state state) static int vfio_migration_set_state(VFIODevice *vbasedev, enum vfio_device_mig_state new_state, - enum vfio_device_mig_state recover_state) + enum vfio_device_mig_state recover_state, + Error **errp) { VFIOMigration *migration = vbasedev->migration; uint64_t buf[DIV_ROUND_UP(sizeof(struct vfio_device_feature) + @@ -104,15 +105,15 @@ static int vfio_migration_set_state(VFIODevice *vbasedev, ret = -errno; if (recover_state == VFIO_DEVICE_STATE_ERROR) { - error_report("%s: Failed setting device state to %s, err: %s. " - "Recover state is ERROR. Resetting device", - vbasedev->name, mig_state_to_str(new_state), - strerror(errno)); + error_setg(errp, "%s: Failed setting device state to %s, err: %s. " + "Recover state is ERROR. Resetting device", + vbasedev->name, mig_state_to_str(new_state), + strerror(errno)); goto reset_device; } - error_report( + error_setg(errp, "%s: Failed setting device state to %s, err: %s. Setting device in recover state %s", vbasedev->name, mig_state_to_str(new_state), strerror(errno), mig_state_to_str(recover_state)); @@ -120,7 +121,7 @@ static int vfio_migration_set_state(VFIODevice *vbasedev, mig_state->device_state = recover_state; if (ioctl(vbasedev->fd, VFIO_DEVICE_FEATURE, feature)) { ret = -errno; - error_report( + error_setg(errp, "%s: Failed setting device in recover state, err: %s. Resetting device", vbasedev->name, strerror(errno)); I think here we will assert because errp is already set. Adding an error_append() API would be useful here I guess. yes. Otherwise, we need to move the first error_setg() below, to before we return from a successful recover state change, and construct the error message differently (e.g., provide a full error message for the recover state fail case containing also the first error). Do you have other ideas? Errors for : if (ioctl(vbasedev->fd, VFIO_DEVICE_RESET)) { should be treated as the others with and error_append() and not hw_error(). This needs a rework before any new changes. I also wonder why we have twice : migration->device_state = recover_state; It looks redundant. The ioctl VFIO_DEVICE_FEATURE should leave the state unmodified. Thanks, C.
Re: [PATCH 04/14] migration: Modify ram_init_bitmaps() to report dirty tracking errors
On 2/12/24 09:51, Avihai Horon wrote: Hi Cedric, On 07/02/2024 15:33, Cédric Le Goater wrote: External email: Use caution opening links or attachments The .save_setup() handler has now an Error** argument that we can use to propagate errors reported by the .log_global_start() handler. Do that for the RAM. qemu_savevm_state_setup() will store the error under the migration stream for later detection in the migration sequence. Signed-off-by: Cédric Le Goater --- migration/ram.c | 19 ++- 1 file changed, 10 insertions(+), 9 deletions(-) diff --git a/migration/ram.c b/migration/ram.c index d86626bb1c704b2d3497b323a702ca6ca8939a79..b87245466bb46937fd0358d0c66432bcc6280018 100644 --- a/migration/ram.c +++ b/migration/ram.c @@ -2802,19 +2802,17 @@ static void migration_bitmap_clear_discarded_pages(RAMState *rs) } } -static void ram_init_bitmaps(RAMState *rs) +static void ram_init_bitmaps(RAMState *rs, Error **errp) { - Error *local_err = NULL; - qemu_mutex_lock_ramlist(); WITH_RCU_READ_LOCK_GUARD() { ram_list_init_bitmaps(); /* We don't use dirty log with background snapshots */ if (!migrate_background_snapshot()) { - memory_global_dirty_log_start(GLOBAL_DIRTY_MIGRATION, _err); - if (local_err) { - error_report_err(local_err); + memory_global_dirty_log_start(GLOBAL_DIRTY_MIGRATION, errp); + if (*errp) { I think we should use ERRP_GUARD() or a local error here and also below at ram_init_bitmaps() (or return bool like Philippe suggested). yes. I will rework that part. Thanks, C. Thanks. + break; } migration_bitmap_sync_precopy(rs, false); } @@ -2828,7 +2826,7 @@ static void ram_init_bitmaps(RAMState *rs) migration_bitmap_clear_discarded_pages(rs); } -static int ram_init_all(RAMState **rsp) +static int ram_init_all(RAMState **rsp, Error **errp) { if (ram_state_init(rsp)) { return -1; @@ -2839,7 +2837,10 @@ static int ram_init_all(RAMState **rsp) return -1; } - ram_init_bitmaps(*rsp); + ram_init_bitmaps(*rsp, errp); + if (*errp) { + return -1; + } return 0; } @@ -2952,7 +2953,7 @@ static int ram_save_setup(QEMUFile *f, void *opaque, Error **errp) /* migration has already setup the bitmap, reuse it. */ if (!migration_in_colo_state()) { - if (ram_init_all(rsp) != 0) { + if (ram_init_all(rsp, errp) != 0) { compress_threads_save_cleanup(); return -1; } -- 2.43.0
Re: [PATCH 03/14] memory: Add Error** argument to .log_global*() handlers
On 2/12/24 09:43, Avihai Horon wrote: Hi Cedric, On 09/02/2024 12:14, Cédric Le Goater wrote: External email: Use caution opening links or attachments On 2/8/24 06:48, Peter Xu wrote: On Wed, Feb 07, 2024 at 02:33:36PM +0100, Cédric Le Goater wrote: @@ -2936,14 +2940,14 @@ void memory_global_dirty_log_start(unsigned int flags) trace_global_dirty_changed(global_dirty_tracking); if (!old_flags) { - MEMORY_LISTENER_CALL_GLOBAL(log_global_start, Forward); + MEMORY_LISTENER_CALL_GLOBAL(log_global_start, Forward, errp); memory_region_transaction_begin(); memory_region_update_pending = true; memory_region_transaction_commit(); } } -static void memory_global_dirty_log_do_stop(unsigned int flags) +static void memory_global_dirty_log_do_stop(unsigned int flags, Error **errp) { assert(flags && !(flags & (~GLOBAL_DIRTY_MASK))); assert((global_dirty_tracking & flags) == flags); @@ -2955,7 +2959,7 @@ static void memory_global_dirty_log_do_stop(unsigned int flags) memory_region_transaction_begin(); memory_region_update_pending = true; memory_region_transaction_commit(); - MEMORY_LISTENER_CALL_GLOBAL(log_global_stop, Reverse); + MEMORY_LISTENER_CALL_GLOBAL(log_global_stop, Reverse, errp); } } I'm a little bit surprised to see that MEMORY_LISTENER_CALL_GLOBAL() already allows >2 args, with the ability to conditionally pass over errp with such oneliner change; even if all callers were only using 2 args before this patch.. yes. The proposal takes the easy path. Should we change all memory listener global handlers : begin commit log_global_after_sync log_global_start log_global_stop to take an extra Error **errp argument ? I think we should distinguish begin + commit handlers from the log_global_* with a new macro. In which case, we could also change the handler to return a bool and fail at the first error in MEMORY_LISTENER_CALL_GLOBAL(...). I think we must fail at first error in any case. Otherwise, if two handlers error and call error_setg() with errp, the second handler will assert IIUC. Good point. I will respin with a new MEMORY_LISTENER_CALL_GLOBAL_ERR macro exiting the loop at first error. Thanks, C.
Re: [RFC PATCH 14/14] migration: Fix return-path thread exit
Hello Peter On 2/8/24 06:57, Peter Xu wrote: On Wed, Feb 07, 2024 at 02:33:47PM +0100, Cédric Le Goater wrote: In case of error, close_return_path_on_source() can perform a shutdown to exit the return-path thread. However, in migrate_fd_cleanup(), 'to_dst_file' is closed before calling close_return_path_on_source() and the shutdown fails, leaving the source and destination waiting for an event to occur. Close the file after calling close_return_path_on_source() so that the shutdown succeeds and the return-path thread exits. Signed-off-by: Cédric Le Goater --- This is an RFC because the correct fix implies reworking the QEMUFile construct, built on top of the QEMU I/O channel. migration/migration.c | 13 ++--- 1 file changed, 6 insertions(+), 7 deletions(-) diff --git a/migration/migration.c b/migration/migration.c index 5f55af3d7624750ca416c4177781241b3e291e5d..de329f2c553288935d824748286e79e535929b8b 100644 --- a/migration/migration.c +++ b/migration/migration.c @@ -1313,6 +1313,8 @@ void migrate_set_state(int *state, int old_state, int new_state) static void migrate_fd_cleanup(MigrationState *s) { +QEMUFile *tmp = NULL; + g_free(s->hostname); s->hostname = NULL; json_writer_free(s->vmdesc); @@ -1321,8 +1323,6 @@ static void migrate_fd_cleanup(MigrationState *s) qemu_savevm_state_cleanup(); if (s->to_dst_file) { -QEMUFile *tmp; - trace_migrate_fd_cleanup(); bql_unlock(); if (s->migration_thread_running) { @@ -1341,15 +1341,14 @@ static void migrate_fd_cleanup(MigrationState *s) * critical section won't block for long. */ migration_ioc_unregister_yank_from_file(tmp); -qemu_fclose(tmp); } -/* - * We already cleaned up to_dst_file, so errors from the return - * path might be due to that, ignore them. - */ close_return_path_on_source(s); +if (tmp) { +qemu_fclose(tmp); +} + assert(!migration_is_active(s)); if (s->state == MIGRATION_STATUS_CANCELLING) { I think this is okay to me for a short term plan. I'll see how others think, also add Dan into the loop. If so, would you please add a rich comment explaining why tmp needs to be closed later? Especially, explicit comment on the ordering requirement would be helpful: IMHO here it's an order that qemu_fclose() must happen after close_return_path_on_source(). So when others work on this code we don't easily break it without noticing. Sure. I will when we have clarified with Fabiano what is the best approach. Also please feel free to post separately on migration patches if you'd like us to merge the patches when repost. This series is a collection of multiple (related) changes : * extra Error** parameter to save_setup() migration handlers. This change has consequences on the various callers which are not fully analyzed. * similar changes for memory logging handlers. These looks more self contained and I will see if I can send then separately. * return-path thread termination and then, in background we have open questions regarding : * the QEMUfile implementation and its QIOChannel usage for migration streams * qemu_file_set_error* vs. migrate_set_error. It is confusing, at least for me. Do we have some documentation on best practices ? Thanks, C.
Re: [RFC PATCH 14/14] migration: Fix return-path thread exit
Hello Fabiano On 2/8/24 14:29, Fabiano Rosas wrote: Cédric Le Goater writes: In case of error, close_return_path_on_source() can perform a shutdown to exit the return-path thread. However, in migrate_fd_cleanup(), 'to_dst_file' is closed before calling close_return_path_on_source() and the shutdown fails, leaving the source and destination waiting for an event to occur. Hi, Cédric Are you sure this is not caused by patch 13? It happens with upstream QEMU without any patch. When vfio_listener_log_global_start() fails, it sets an error on the QEMUFile. To reproduce without a VFIO device, you can inject an error when dirty tracking is started. Something like below, @@ -2817,6 +2817,8 @@ static void ram_init_bitmaps(RAMState *r * containing all 1s to exclude any discarded pages from migration. */ migration_bitmap_clear_discarded_pages(rs); + +qemu_file_set_error(migrate_get_current()->to_dst_file, -EAGAIN); } static int ram_init_all(RAMState **rsp) Activate return-path and migrate. That 'if (ms->to_dst_file' was there to avoid this sort of thing happening. Is there some reordering possibility that I'm not spotting in the code below? I think the data dependency on to_dst_file shouldn't allow it. migrate_fd_cleanup: qemu_mutex_lock(>qemu_file_lock); tmp = s->to_dst_file; s->to_dst_file = NULL; qemu_mutex_unlock(>qemu_file_lock); ... qemu_fclose(tmp); close_return_path_on_source: WITH_QEMU_LOCK_GUARD(>qemu_file_lock) { if (ms->to_dst_file && ms->rp_state.from_dst_file && qemu_file_get_error(ms->to_dst_file)) { qemu_file_shutdown(ms->rp_state.from_dst_file); } } close_return_path_on_source() is called by migrate_fd_cleanup() in the same thread. So, when we reach the locking section ms->to_dst_file is already NULL and qemu_fclose() has been closed :/ May be I misunderstood. Please try to reproduce with the little hack above. Thanks, C. I'm thinking maybe the culprit is the close_return_path_on_source() at migration_completion(). It might be possible for it to race with the migrate_fd_cleanup_bh from migration_iteration_finish(). If that's the case, then I think that one possible fix would be to hold the BQL at migration_completion() so the BH doesn't get dispatched until we properly close the return path. Close the file after calling close_return_path_on_source() so that the shutdown succeeds and the return-path thread exits. Signed-off-by: Cédric Le Goater --- This is an RFC because the correct fix implies reworking the QEMUFile construct, built on top of the QEMU I/O channel. migration/migration.c | 13 ++--- 1 file changed, 6 insertions(+), 7 deletions(-) diff --git a/migration/migration.c b/migration/migration.c index 5f55af3d7624750ca416c4177781241b3e291e5d..de329f2c553288935d824748286e79e535929b8b 100644 --- a/migration/migration.c +++ b/migration/migration.c @@ -1313,6 +1313,8 @@ void migrate_set_state(int *state, int old_state, int new_state) static void migrate_fd_cleanup(MigrationState *s) { +QEMUFile *tmp = NULL; + g_free(s->hostname); s->hostname = NULL; json_writer_free(s->vmdesc); @@ -1321,8 +1323,6 @@ static void migrate_fd_cleanup(MigrationState *s) qemu_savevm_state_cleanup(); if (s->to_dst_file) { -QEMUFile *tmp; - trace_migrate_fd_cleanup(); bql_unlock(); if (s->migration_thread_running) { @@ -1341,15 +1341,14 @@ static void migrate_fd_cleanup(MigrationState *s) * critical section won't block for long. */ migration_ioc_unregister_yank_from_file(tmp); -qemu_fclose(tmp); } -/* - * We already cleaned up to_dst_file, so errors from the return - * path might be due to that, ignore them. - */ close_return_path_on_source(s); +if (tmp) { +qemu_fclose(tmp); +} + assert(!migration_is_active(s)); if (s->state == MIGRATION_STATUS_CANCELLING) {
Re: [PATCH 01/14] migration: Add Error** argument to .save_setup() handler
On 2/12/24 09:36, Avihai Horon wrote: Hi, Cedric On 07/02/2024 15:33, Cédric Le Goater wrote: External email: Use caution opening links or attachments The purpose is to record a potential error in the migration stream if qemu_savevm_state_setup() fails. Most of the current .save_setup() handlers can be modified to use the Error argument instead of managing their own and calling locally error_report(). The following patches will introduce such changes for VFIO first. Signed-off-by: Cédric Le Goater --- include/migration/register.h | 2 +- hw/ppc/spapr.c | 2 +- hw/s390x/s390-stattrib.c | 2 +- hw/vfio/migration.c | 2 +- migration/block-dirty-bitmap.c | 2 +- migration/block.c | 2 +- migration/ram.c | 2 +- migration/savevm.c | 4 ++-- 8 files changed, 9 insertions(+), 9 deletions(-) diff --git a/include/migration/register.h b/include/migration/register.h index 9ab1f79512c605f0c88a45b560c57486fa054441..831600a00eae4efd0464b60925d65de4d9dbcff8 100644 --- a/include/migration/register.h +++ b/include/migration/register.h @@ -25,7 +25,7 @@ typedef struct SaveVMHandlers { * used to perform early checks. */ int (*save_prepare)(void *opaque, Error **errp); - int (*save_setup)(QEMUFile *f, void *opaque); + int (*save_setup)(QEMUFile *f, void *opaque, Error **errp); void (*save_cleanup)(void *opaque); int (*save_live_complete_postcopy)(QEMUFile *f, void *opaque); int (*save_live_complete_precopy)(QEMUFile *f, void *opaque); diff --git a/hw/ppc/spapr.c b/hw/ppc/spapr.c index 0d72d286d80f0435122593555f79fae4d90acf81..a1b0aa02582ad2d68a13476c1859b18143da7bb8 100644 --- a/hw/ppc/spapr.c +++ b/hw/ppc/spapr.c @@ -2142,7 +2142,7 @@ static const VMStateDescription vmstate_spapr = { } }; -static int htab_save_setup(QEMUFile *f, void *opaque) +static int htab_save_setup(QEMUFile *f, void *opaque, Error **errp) { SpaprMachineState *spapr = opaque; diff --git a/hw/s390x/s390-stattrib.c b/hw/s390x/s390-stattrib.c index c483b62a9b5f71772639fc180bdad15ecb6711cb..c934df424a555d83d2198f5ddfc0cbe0ea98e9ec 100644 --- a/hw/s390x/s390-stattrib.c +++ b/hw/s390x/s390-stattrib.c @@ -166,7 +166,7 @@ static int cmma_load(QEMUFile *f, void *opaque, int version_id) return ret; } -static int cmma_save_setup(QEMUFile *f, void *opaque) +static int cmma_save_setup(QEMUFile *f, void *opaque, Error **errp) { S390StAttribState *sas = S390_STATTRIB(opaque); S390StAttribClass *sac = S390_STATTRIB_GET_CLASS(sas); diff --git a/hw/vfio/migration.c b/hw/vfio/migration.c index 70e6b1a709f9b67e4c9eb41033d76347275cac42..8bcb4bc73cd5ba5338e3ffa4d907d0e6bfbb9485 100644 --- a/hw/vfio/migration.c +++ b/hw/vfio/migration.c @@ -378,7 +378,7 @@ static int vfio_save_prepare(void *opaque, Error **errp) return 0; } -static int vfio_save_setup(QEMUFile *f, void *opaque) +static int vfio_save_setup(QEMUFile *f, void *opaque, Error **errp) { VFIODevice *vbasedev = opaque; VFIOMigration *migration = vbasedev->migration; diff --git a/migration/block-dirty-bitmap.c b/migration/block-dirty-bitmap.c index 2708abf3d762de774ed294d3fdb8e56690d2974c..16f84e6c57c2403a8c2d6319f4e7b6360dade28c 100644 --- a/migration/block-dirty-bitmap.c +++ b/migration/block-dirty-bitmap.c @@ -1213,7 +1213,7 @@ fail: return ret; } -static int dirty_bitmap_save_setup(QEMUFile *f, void *opaque) +static int dirty_bitmap_save_setup(QEMUFile *f, void *opaque, Error **errp) { DBMSaveState *s = &((DBMState *)opaque)->save; SaveBitmapState *dbms = NULL; diff --git a/migration/block.c b/migration/block.c index 8c6ebafacc1ffe930d1d4f19d968817b14852c69..df15319ceab66201b043f15eac1b0a7d6522b60c 100644 --- a/migration/block.c +++ b/migration/block.c @@ -708,7 +708,7 @@ static void block_migration_cleanup(void *opaque) blk_mig_unlock(); } -static int block_save_setup(QEMUFile *f, void *opaque) +static int block_save_setup(QEMUFile *f, void *opaque, Error **errp) { int ret; diff --git a/migration/ram.c b/migration/ram.c index d5b7cd5ac2f31aabf4a248b966153401c48912cf..136c237f4079f68d4e578cf1c72eec2efc815bc8 100644 --- a/migration/ram.c +++ b/migration/ram.c @@ -2931,7 +2931,7 @@ void qemu_guest_free_page_hint(void *addr, size_t len) * @f: QEMUFile where to send the data * @opaque: RAMState pointer */ -static int ram_save_setup(QEMUFile *f, void *opaque) +static int ram_save_setup(QEMUFile *f, void *opaque, Error **errp) { RAMState **rsp = opaque; RAMBlock *block; diff --git a/migration/savevm.c b/migration/savevm.c index d612c8a9020b204d5d078d5df85f0e6449c27645..f2ae799bad13e631bccf733a34c3a8fd22e8dd48 100644 --- a/migration/savevm.c +++ b/migration/savevm.c @@ -1342,10 +1342,10 @@ void qemu_savevm_state_setup(QEMUFile *f) } save_section_header(f, se, QEMU_VM_SECTION_START); - ret = se->ops->
Re: [PATCH 13/14] migration: Use migrate_has_error() in close_return_path_on_source()
On 2/8/24 14:57, Fabiano Rosas wrote: Cédric Le Goater writes: On 2/8/24 14:07, Fabiano Rosas wrote: Cédric Le Goater writes: close_return_path_on_source() retrieves the migration error from the the QEMUFile '->to_dst_file' to know if a shutdown is required. This shutdown is required to exit the return-path thread. However, in migrate_fd_cleanup(), '->to_dst_file' is cleaned up before calling close_return_path_on_source() and the shutdown is never performed, leaving the source and destination waiting for an event to occur. Avoid relying on '->to_dst_file' and use migrate_has_error() instead. Suggested-by: Peter Xu Signed-off-by: Cédric Le Goater --- migration/migration.c | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/migration/migration.c b/migration/migration.c index d5f705ceef4c925589aa49335969672c0d761fa2..5f55af3d7624750ca416c4177781241b3e291e5d 100644 --- a/migration/migration.c +++ b/migration/migration.c @@ -2372,8 +2372,7 @@ static bool close_return_path_on_source(MigrationState *ms) * cause it to unblock if it's stuck waiting for the destination. */ WITH_QEMU_LOCK_GUARD(>qemu_file_lock) { -if (ms->to_dst_file && ms->rp_state.from_dst_file && -qemu_file_get_error(ms->to_dst_file)) { +if (migrate_has_error(ms) && ms->rp_state.from_dst_file) { qemu_file_shutdown(ms->rp_state.from_dst_file); } } Hm, maybe Peter can help defend this, but this assumes that every function that takes an 'f' and sets the file error also sets migrate_set_error(). I'm not sure we have determined that, have we? How could we check all the code path ? I agree it is difficult when looking at the code :/ It would help if the thing wasn't called 'f' for the most part of the code to begin with. Whenever there's a file error at to_dst_file there's the chance that the rp_state.from_dst_file got stuck. So we cannot ignore the file error. Would it work if we checked it earlier during cleanup as you did previously and then set the migration error? Do you mean doing something similar to what is done in source_return_path_thread() ? if (qemu_file_get_error(s->to_dst_file)) { qemu_file_get_error_obj(s->to_dst_file, ); if (err) { migrate_set_error(ms, err); error_free(err); ... Yes. That would be safer I think. Nevertheless, I am struggling to understand how qemu_file_set_error() and migrate_set_error() fit together. I was expecting some kind of synchronization routine but there isn't it seems. Are they completely orthogonal ? when should we use these routines and when not ? My initial goal was to modify some of the memory handlers (log_global*) and migration handlers to propagate errors at the QMP level and them report to the management layer. This is growing in something bigger and currently, I don't find a good approach to the problem. The last two patches of this series try to fix the return-path thread termination. Let's keep that for after. Thanks, C.
Re: [PATCH v2 2/6] vfio: Avoid inspecting option QDict for rombar
On 2/12/24 09:04, Philippe Mathieu-Daudé wrote: On 10/2/24 11:24, Akihiko Odaki wrote: Use pci_rom_bar_explicitly_enabled() to determine if rombar is explicitly enabled. Signed-off-by: Akihiko Odaki --- hw/vfio/pci.c | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/hw/vfio/pci.c b/hw/vfio/pci.c index d7fe06715c4b..44178ac9355f 100644 --- a/hw/vfio/pci.c +++ b/hw/vfio/pci.c @@ -1010,7 +1010,6 @@ static void vfio_pci_size_rom(VFIOPCIDevice *vdev) { uint32_t orig, size = cpu_to_le32((uint32_t)PCI_ROM_ADDRESS_MASK); off_t offset = vdev->config_offset + PCI_ROM_ADDRESS; - DeviceState *dev = DEVICE(vdev); char *name; int fd = vdev->vbasedev.fd; @@ -1044,7 +1043,7 @@ static void vfio_pci_size_rom(VFIOPCIDevice *vdev) } if (vfio_opt_rom_in_denylist(vdev)) { - if (dev->opts && qdict_haskey(dev->opts, "rombar")) { + if (pci_rom_bar_explicitly_enabled(>pdev)) { "pdev" is considered internal field, please use the DEVICE() macro to access it. Yes. I was just looking at vfio_pci_size_rom(). There is a test at the beginning of this routine which should be changed to use DEVICE() if (vdev->pdev.romfile || !vdev->pdev.rom_bar) { /* Since pci handles romfile, just print a message and return */ if (vfio_opt_rom_in_denylist(vdev) && vdev->pdev.romfile) { ... Thanks, C.
Re: [PATCH 03/14] memory: Add Error** argument to .log_global*() handlers
On 2/8/24 06:48, Peter Xu wrote: On Wed, Feb 07, 2024 at 02:33:36PM +0100, Cédric Le Goater wrote: @@ -2936,14 +2940,14 @@ void memory_global_dirty_log_start(unsigned int flags) trace_global_dirty_changed(global_dirty_tracking); if (!old_flags) { -MEMORY_LISTENER_CALL_GLOBAL(log_global_start, Forward); +MEMORY_LISTENER_CALL_GLOBAL(log_global_start, Forward, errp); memory_region_transaction_begin(); memory_region_update_pending = true; memory_region_transaction_commit(); } } -static void memory_global_dirty_log_do_stop(unsigned int flags) +static void memory_global_dirty_log_do_stop(unsigned int flags, Error **errp) { assert(flags && !(flags & (~GLOBAL_DIRTY_MASK))); assert((global_dirty_tracking & flags) == flags); @@ -2955,7 +2959,7 @@ static void memory_global_dirty_log_do_stop(unsigned int flags) memory_region_transaction_begin(); memory_region_update_pending = true; memory_region_transaction_commit(); -MEMORY_LISTENER_CALL_GLOBAL(log_global_stop, Reverse); +MEMORY_LISTENER_CALL_GLOBAL(log_global_stop, Reverse, errp); } } I'm a little bit surprised to see that MEMORY_LISTENER_CALL_GLOBAL() already allows >2 args, with the ability to conditionally pass over errp with such oneliner change; even if all callers were only using 2 args before this patch.. yes. The proposal takes the easy path. Should we change all memory listener global handlers : begin commit log_global_after_sync log_global_start log_global_stop to take an extra Error **errp argument ? I think we should distinguish begin + commit handlers from the log_global_* with a new macro. In which case, we could also change the handler to return a bool and fail at the first error in MEMORY_LISTENER_CALL_GLOBAL(...). Thanks, C.
Re: [PATCH 02/14] migration: Add Error** argument to .load_setup() handler
On 2/8/24 05:30, Peter Xu wrote: On Wed, Feb 07, 2024 at 02:33:35PM +0100, Cédric Le Goater wrote: diff --git a/migration/ram.c b/migration/ram.c index 136c237f4079f68d4e578cf1c72eec2efc815bc8..8dac9bac2fe8b8c19e102c771a7ef6e976252906 100644 --- a/migration/ram.c +++ b/migration/ram.c @@ -3498,7 +3498,7 @@ void colo_release_ram_cache(void) * @f: QEMUFile where to receive the data * @opaque: RAMState pointer Another one may need touch up.. */ -static int ram_load_setup(QEMUFile *f, void *opaque) +static int ram_load_setup(QEMUFile *f, void *opaque, Error **errp) { xbzrle_load_setup(); ramblock_recv_map_init(); diff --git a/migration/savevm.c b/migration/savevm.c index f2ae799bad13e631bccf733a34c3a8fd22e8dd48..990f4249a26d28117ee365d8b20fc5bbca0d43d6 100644 --- a/migration/savevm.c +++ b/migration/savevm.c @@ -2737,7 +2737,7 @@ static void qemu_loadvm_state_switchover_ack_needed(MigrationIncomingState *mis) trace_loadvm_state_switchover_ack_needed(mis->switchover_ack_pending_num); } -static int qemu_loadvm_state_setup(QEMUFile *f) +static int qemu_loadvm_state_setup(QEMUFile *f, Error **errp) { SaveStateEntry *se; int ret; @@ -2753,10 +2753,11 @@ static int qemu_loadvm_state_setup(QEMUFile *f) } } -ret = se->ops->load_setup(f, se->opaque); +ret = se->ops->load_setup(f, se->opaque, errp); if (ret < 0) { +error_prepend(errp, "Load state of device %s failed: ", + se->idstr); qemu_file_set_error(f, ret); Do we also want to switch to _set_error_obj()? yes. possible. Or even use migrate_set_error() It seems so and may be even remove it completely. What we could do first is add an Errp ** argument to qemu_loadvm_state() which would improve qmp_xen_load_devices_state() and load_snapshot(). It is less obvious for process_incoming_migration_co(). (the latter may apply to previous patch too if it works)? It seems safe to use migrate_set_error for both migration_thread() and bg_migration_thread() because migration_detect_error() is called after calling qemu_savevm_state_setup(). However, qemu_savevm_state() relies only on qemu_file_get_error() and there would be a problem there I think. Thanks, C. -error_report("Load state of device %s failed", se->idstr); return ret; } } @@ -2937,7 +2938,8 @@ int qemu_loadvm_state(QEMUFile *f) return ret; } -if (qemu_loadvm_state_setup(f) != 0) { +if (qemu_loadvm_state_setup(f, _err) != 0) { +error_report_err(local_err); return -EINVAL; } -- 2.43.0
Re: [PATCH v2 2/2] aspeed: fix hardcode boot address 0
On 2/7/24 20:52, Jamin Lin wrote: In the previous design of ASPEED SOCs QEMU model, it set the boot address at "0" which was the hardcode setting for ast10x0, ast2600, ast2500 and ast2400. According to the design of ast2700, it has bootmcu which is used for executing SPL and initialize DRAM, then, CPUs(cortex-a35) execute u-boot, kernel and rofs. QEMU will only support CPU(cortex-a35) parts and the boot address is "0x4 " for ast2700. Therefore, fixed hardcode boot address 0. Signed-off-by: Troy Lee Signed-off-by: Jamin Lin I agree with Philippe that the justification could be simpler. This change is just a cleanup preparing ground for future models using a different mapping address. Reviewed-by: Cédric Le Goater Thanks, C. --- hw/arm/aspeed.c | 4 +++- hw/arm/aspeed_ast2400.c | 4 ++-- hw/arm/aspeed_ast2600.c | 2 +- include/hw/arm/aspeed_soc.h | 2 -- 4 files changed, 6 insertions(+), 6 deletions(-) diff --git a/hw/arm/aspeed.c b/hw/arm/aspeed.c index 06d863958b..39758557be 100644 --- a/hw/arm/aspeed.c +++ b/hw/arm/aspeed.c @@ -289,12 +289,14 @@ static void aspeed_install_boot_rom(AspeedMachineState *bmc, BlockBackend *blk, uint64_t rom_size) { AspeedSoCState *soc = bmc->soc; +AspeedSoCClass *sc = ASPEED_SOC_GET_CLASS(soc); memory_region_init_rom(>boot_rom, NULL, "aspeed.boot_rom", rom_size, _abort); memory_region_add_subregion_overlap(>spi_boot_container, 0, >boot_rom, 1); -write_boot_rom(blk, ASPEED_SOC_SPI_BOOT_ADDR, rom_size, _abort); +write_boot_rom(blk, sc->memmap[ASPEED_DEV_SPI_BOOT], + rom_size, _abort); } void aspeed_board_init_flashes(AspeedSMCState *s, const char *flashtype, diff --git a/hw/arm/aspeed_ast2400.c b/hw/arm/aspeed_ast2400.c index 95da85fee0..d125886207 100644 --- a/hw/arm/aspeed_ast2400.c +++ b/hw/arm/aspeed_ast2400.c @@ -26,7 +26,7 @@ #define ASPEED_SOC_IOMEM_SIZE 0x0020 static const hwaddr aspeed_soc_ast2400_memmap[] = { -[ASPEED_DEV_SPI_BOOT] = ASPEED_SOC_SPI_BOOT_ADDR, +[ASPEED_DEV_SPI_BOOT] = 0x, [ASPEED_DEV_IOMEM] = 0x1E60, [ASPEED_DEV_FMC]= 0x1E62, [ASPEED_DEV_SPI1] = 0x1E63, @@ -61,7 +61,7 @@ static const hwaddr aspeed_soc_ast2400_memmap[] = { }; static const hwaddr aspeed_soc_ast2500_memmap[] = { -[ASPEED_DEV_SPI_BOOT] = ASPEED_SOC_SPI_BOOT_ADDR, +[ASPEED_DEV_SPI_BOOT] = 0x, [ASPEED_DEV_IOMEM] = 0x1E60, [ASPEED_DEV_FMC]= 0x1E62, [ASPEED_DEV_SPI1] = 0x1E63, diff --git a/hw/arm/aspeed_ast2600.c b/hw/arm/aspeed_ast2600.c index f74561ecdc..174be53770 100644 --- a/hw/arm/aspeed_ast2600.c +++ b/hw/arm/aspeed_ast2600.c @@ -22,7 +22,7 @@ #define ASPEED_SOC_DPMCU_SIZE 0x0004 static const hwaddr aspeed_soc_ast2600_memmap[] = { -[ASPEED_DEV_SPI_BOOT] = ASPEED_SOC_SPI_BOOT_ADDR, +[ASPEED_DEV_SPI_BOOT] = 0x, [ASPEED_DEV_SRAM] = 0x1000, [ASPEED_DEV_DPMCU] = 0x1800, /* 0x1600 0x17FF : AHB BUS do LPC Bus bridge */ diff --git a/include/hw/arm/aspeed_soc.h b/include/hw/arm/aspeed_soc.h index 5ab0902da0..bf43ad8351 100644 --- a/include/hw/arm/aspeed_soc.h +++ b/include/hw/arm/aspeed_soc.h @@ -224,8 +224,6 @@ enum { ASPEED_DEV_FSI2, }; -#define ASPEED_SOC_SPI_BOOT_ADDR 0x0 - qemu_irq aspeed_soc_get_irq(AspeedSoCState *s, int dev); bool aspeed_soc_uart_realize(AspeedSoCState *s, Error **errp); void aspeed_soc_uart_set_chr(AspeedSoCState *s, int dev, Chardev *chr);
Re: [PATCH v2 1/2] aspeed: introduce a new UART0 device name
Hello Jamin, On 2/7/24 21:02, Jamin Lin via wrote: The Aspeed datasheet refers to the UART controllers as UART1 - UART13 for the ast10x0, ast2600, ast2500 and ast2400 SoCs and the Aspeed ast2700 introduces an UART0 and the UART controllers as UART0 - UART12. To keep the naming in the QEMU models in sync with the datasheet, let's introduce a new UART0 device name and do the required adjustements, etc ... Please drop the etc... Signed-off-by: Troy Lee Signed-off-by: Jamin Lin --- hw/arm/aspeed.c | 13 - hw/arm/aspeed_ast10x0.c | 1 + hw/arm/aspeed_ast2400.c | 2 ++ hw/arm/aspeed_ast2600.c | 1 + hw/arm/aspeed_soc_common.c | 14 +- include/hw/arm/aspeed_soc.h | 2 ++ 6 files changed, 23 insertions(+), 10 deletions(-) diff --git a/hw/arm/aspeed.c b/hw/arm/aspeed.c index 09b1e823ba..06d863958b 100644 --- a/hw/arm/aspeed.c +++ b/hw/arm/aspeed.c @@ -342,7 +342,7 @@ static void connect_serial_hds_to_uarts(AspeedMachineState *bmc) int uart_chosen = bmc->uart_chosen ? bmc->uart_chosen : amc->uart_default; aspeed_soc_uart_set_chr(s, uart_chosen, serial_hd(0)); -for (int i = 1, uart = ASPEED_DEV_UART1; i < sc->uarts_num; i++, uart++) { +for (int i = 0, uart = sc->uarts_base; i < sc->uarts_num; i++, uart++) { if (uart == uart_chosen) { continue; } @@ -1094,7 +1094,7 @@ static char *aspeed_get_bmc_console(Object *obj, Error **errp) AspeedMachineClass *amc = ASPEED_MACHINE_GET_CLASS(bmc); int uart_chosen = bmc->uart_chosen ? bmc->uart_chosen : amc->uart_default; -return g_strdup_printf("uart%d", uart_chosen - ASPEED_DEV_UART1 + 1); +return g_strdup_printf("uart%d", uart_chosen - ASPEED_DEV_UART0); } static void aspeed_set_bmc_console(Object *obj, const char *value, Error **errp) @@ -1103,6 +1103,8 @@ static void aspeed_set_bmc_console(Object *obj, const char *value, Error **errp) AspeedMachineClass *amc = ASPEED_MACHINE_GET_CLASS(bmc); AspeedSoCClass *sc = ASPEED_SOC_CLASS(object_class_by_name(amc->soc_name)); int val; +int start = sc->uarts_base - ASPEED_DEV_UART0; +int end = start + sc->uarts_num; To help the reader, I would introduce these helpers at the end of aspeed_soc.h : static inline int aspeed_uart_index(int uart_dev) { return uart_dev - ASPEED_DEV_UART0; } static inline int aspeed_uart_first(AspeedSoCClass *sc) { return aspeed_uart_index(sc->uarts_base); } static inline int aspeed_uart_last(AspeedSoCClass *sc) { return aspeed_uart_first(sc) + sc->uarts_num - 1; } if (sscanf(value, "uart%u", ) != 1) { error_setg(errp, "Bad value for \"uart\" property"); @@ -1110,11 +1112,12 @@ static void aspeed_set_bmc_console(Object *obj, const char *value, Error **errp) } /* The number of UART depends on the SoC */ -if (val < 1 || val > sc->uarts_num) { -error_setg(errp, "\"uart\" should be in range [1 - %d]", sc->uarts_num); +if (val < start || val >= end) { +error_setg(errp, "\"uart\" should be in range [%d - %d]", + start, end - 1); return; } -bmc->uart_chosen = ASPEED_DEV_UART1 + val - 1; +bmc->uart_chosen = val + ASPEED_DEV_UART0; } static void aspeed_machine_class_props_init(ObjectClass *oc) diff --git a/hw/arm/aspeed_ast10x0.c b/hw/arm/aspeed_ast10x0.c index c3b5116a6a..2634e0f654 100644 --- a/hw/arm/aspeed_ast10x0.c +++ b/hw/arm/aspeed_ast10x0.c @@ -436,6 +436,7 @@ static void aspeed_soc_ast1030_class_init(ObjectClass *klass, void *data) sc->wdts_num = 4; sc->macs_num = 1; sc->uarts_num = 13; +sc->uarts_base = ASPEED_DEV_UART1; sc->irqmap = aspeed_soc_ast1030_irqmap; sc->memmap = aspeed_soc_ast1030_memmap; sc->num_cpus = 1; diff --git a/hw/arm/aspeed_ast2400.c b/hw/arm/aspeed_ast2400.c index 8829561bb6..95da85fee0 100644 --- a/hw/arm/aspeed_ast2400.c +++ b/hw/arm/aspeed_ast2400.c @@ -523,6 +523,7 @@ static void aspeed_soc_ast2400_class_init(ObjectClass *oc, void *data) sc->wdts_num = 2; sc->macs_num = 2; sc->uarts_num= 5; +sc->uarts_base = ASPEED_DEV_UART1; sc->irqmap = aspeed_soc_ast2400_irqmap; sc->memmap = aspeed_soc_ast2400_memmap; sc->num_cpus = 1; @@ -551,6 +552,7 @@ static void aspeed_soc_ast2500_class_init(ObjectClass *oc, void *data) sc->wdts_num = 3; sc->macs_num = 2; sc->uarts_num= 5; +sc->uarts_base = ASPEED_DEV_UART1; sc->irqmap = aspeed_soc_ast2500_irqmap; sc->memmap = aspeed_soc_ast2500_memmap; sc->num_cpus = 1; diff --git a/hw/arm/aspeed_ast2600.c b/hw/arm/aspeed_ast2600.c index 4ee32ea99d..f74561ecdc 100644 --- a/hw/arm/aspeed_ast2600.c +++ b/hw/arm/aspeed_ast2600.c @@ -666,6 +666,7 @@ static void aspeed_soc_ast2600_class_init(ObjectClass
Re: [PATCH 08/13] hw/arm/mps3r: Initial skeleton for mps3-an536 board
+/* + * The MPS3 DDR is 3GiB, but on a 32-bit host QEMU doesn't permit + * emulation of that much guest RAM, so artificially make it smaller. + */ +#if HOST_LONG_BITS == 32 +#define MPS3_DDR_SIZE (1 * GiB) +#else +#define MPS3_DDR_SIZE (3 * GiB) +#endif Generically, can we migrate a VM started on a 32-bit host to a 64-bit one? I think it's one of those things that in theory is supposed to be possible and in practice nobody tests so it might well not work. At any rate, this is the same thing we do already in mps2-tz.c for the 2GB DRAM those boards have. We could have a common helper may be. Aspeed does: /* On 32-bit hosts, lower RAM to 1G because of the 2047 MB limit */ #if HOST_LONG_BITS == 32 #define ASPEED_RAM_SIZE(sz) MIN((sz), 1 * GiB) #else #define ASPEED_RAM_SIZE(sz) (sz) #endif Thanks, C.
Re: [PATCH 13/14] migration: Use migrate_has_error() in close_return_path_on_source()
On 2/8/24 14:07, Fabiano Rosas wrote: Cédric Le Goater writes: close_return_path_on_source() retrieves the migration error from the the QEMUFile '->to_dst_file' to know if a shutdown is required. This shutdown is required to exit the return-path thread. However, in migrate_fd_cleanup(), '->to_dst_file' is cleaned up before calling close_return_path_on_source() and the shutdown is never performed, leaving the source and destination waiting for an event to occur. Avoid relying on '->to_dst_file' and use migrate_has_error() instead. Suggested-by: Peter Xu Signed-off-by: Cédric Le Goater --- migration/migration.c | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/migration/migration.c b/migration/migration.c index d5f705ceef4c925589aa49335969672c0d761fa2..5f55af3d7624750ca416c4177781241b3e291e5d 100644 --- a/migration/migration.c +++ b/migration/migration.c @@ -2372,8 +2372,7 @@ static bool close_return_path_on_source(MigrationState *ms) * cause it to unblock if it's stuck waiting for the destination. */ WITH_QEMU_LOCK_GUARD(>qemu_file_lock) { -if (ms->to_dst_file && ms->rp_state.from_dst_file && -qemu_file_get_error(ms->to_dst_file)) { +if (migrate_has_error(ms) && ms->rp_state.from_dst_file) { qemu_file_shutdown(ms->rp_state.from_dst_file); } } Hm, maybe Peter can help defend this, but this assumes that every function that takes an 'f' and sets the file error also sets migrate_set_error(). I'm not sure we have determined that, have we? How could we check all the code path ? I agree it is difficult when looking at the code :/ Thanks, C.
Re: [PATCH 01/14] migration: Add Error** argument to .save_setup() handler
On 2/7/24 21:11, Philippe Mathieu-Daudé wrote: On 7/2/24 14:33, Cédric Le Goater wrote: The purpose is to record a potential error in the migration stream if qemu_savevm_state_setup() fails. Most of the current .save_setup() handlers can be modified to use the Error argument instead of managing their own and calling locally error_report(). The following patches will introduce such changes for VFIO first. Signed-off-by: Cédric Le Goater --- include/migration/register.h | 2 +- hw/ppc/spapr.c | 2 +- hw/s390x/s390-stattrib.c | 2 +- hw/vfio/migration.c | 2 +- migration/block-dirty-bitmap.c | 2 +- migration/block.c | 2 +- migration/ram.c | 2 +- migration/savevm.c | 4 ++-- 8 files changed, 9 insertions(+), 9 deletions(-) diff --git a/include/migration/register.h b/include/migration/register.h index 9ab1f79512c605f0c88a45b560c57486fa054441..831600a00eae4efd0464b60925d65de4d9dbcff8 100644 --- a/include/migration/register.h +++ b/include/migration/register.h @@ -25,7 +25,7 @@ typedef struct SaveVMHandlers { * used to perform early checks. */ int (*save_prepare)(void *opaque, Error **errp); - int (*save_setup)(QEMUFile *f, void *opaque); + int (*save_setup)(QEMUFile *f, void *opaque, Error **errp); Since you change this, do you mind adding a docstring describing this prototype? I can send an initial patch adding the documentation tags and then resend the same patch with the updates people will provide. I don't have the knowledge to cover all of the SaveVMHandlers struct on my own. Thanks, C. Otherwise, Reviewed-by: Philippe Mathieu-Daudé
Re: [PATCH v3 3/3] hw: Set virtio-iommu aw-bits default value on pc_q35 and arm virt
On 2/8/24 11:10, Eric Auger wrote: Currently the default input range can extend to 64 bits. On x86, when the virtio-iommu protects vfio devices, the physical iommu may support only 39 bits. Let's set the default to 39, as done for the intel-iommu. On ARM we set 48b as a default (matching SMMUv3 SMMU_IDR5.VAX == 0). We use hw_compat_8_2 to handle the compatibility for machines before 9.0 which used to have a virtio-iommu default input range of 64 bits. Of course if aw-bits is set from the command line, the default is overriden. Signed-off-by: Eric Auger Reviewed-by: Zhenzhong Duan Tested-by: Yanghang Liu Reviewed-by: Cédric Le Goater Thanks, C. --- v2 -> v3: - collected Zhenzhong's R-b - use _abort instead of NULL error handle on object_property_get_uint() call (Cédric) - use VTD_HOST_AW_39BIT (Cédric) v1 -> v2: - set aw-bits to 48b on ARM - use hw_compat_8_2 to handle the compat for older machines which used 64b as a default --- hw/arm/virt.c| 6 ++ hw/core/machine.c| 5 - hw/i386/pc.c | 6 ++ hw/virtio/virtio-iommu.c | 2 +- 4 files changed, 17 insertions(+), 2 deletions(-) diff --git a/hw/arm/virt.c b/hw/arm/virt.c index 368c2a415a..0994f2a560 100644 --- a/hw/arm/virt.c +++ b/hw/arm/virt.c @@ -2716,10 +2716,16 @@ static void virt_machine_device_pre_plug_cb(HotplugHandler *hotplug_dev, } else if (object_dynamic_cast(OBJECT(dev), TYPE_VIRTIO_MD_PCI)) { virtio_md_pci_pre_plug(VIRTIO_MD_PCI(dev), MACHINE(hotplug_dev), errp); } else if (object_dynamic_cast(OBJECT(dev), TYPE_VIRTIO_IOMMU_PCI)) { +uint8_t aw_bits = object_property_get_uint(OBJECT(dev), + "aw-bits", _abort); hwaddr db_start = 0, db_end = 0; QList *reserved_regions; char *resv_prop_str; +if (!aw_bits) { +qdev_prop_set_uint8(dev, "aw-bits", 48); +} + if (vms->iommu != VIRT_IOMMU_NONE) { error_setg(errp, "virt machine does not support multiple IOMMUs"); return; diff --git a/hw/core/machine.c b/hw/core/machine.c index fb5afdcae4..70ac96954c 100644 --- a/hw/core/machine.c +++ b/hw/core/machine.c @@ -30,9 +30,12 @@ #include "exec/confidential-guest-support.h" #include "hw/virtio/virtio-pci.h" #include "hw/virtio/virtio-net.h" +#include "hw/virtio/virtio-iommu.h" #include "audio/audio.h" -GlobalProperty hw_compat_8_2[] = {}; +GlobalProperty hw_compat_8_2[] = { +{ TYPE_VIRTIO_IOMMU_PCI, "aw-bits", "64" }, +}; const size_t hw_compat_8_2_len = G_N_ELEMENTS(hw_compat_8_2); GlobalProperty hw_compat_8_1[] = { diff --git a/hw/i386/pc.c b/hw/i386/pc.c index 196827531a..ee2d379c90 100644 --- a/hw/i386/pc.c +++ b/hw/i386/pc.c @@ -1456,6 +1456,8 @@ static void pc_machine_device_pre_plug_cb(HotplugHandler *hotplug_dev, } else if (object_dynamic_cast(OBJECT(dev), TYPE_VIRTIO_MD_PCI)) { virtio_md_pci_pre_plug(VIRTIO_MD_PCI(dev), MACHINE(hotplug_dev), errp); } else if (object_dynamic_cast(OBJECT(dev), TYPE_VIRTIO_IOMMU_PCI)) { +uint8_t aw_bits = object_property_get_uint(OBJECT(dev), + "aw-bits", _abort); /* Declare the APIC range as the reserved MSI region */ char *resv_prop_str = g_strdup_printf("0xfee0:0xfeef:%d", VIRTIO_IOMMU_RESV_MEM_T_MSI); @@ -1464,6 +1466,10 @@ static void pc_machine_device_pre_plug_cb(HotplugHandler *hotplug_dev, qlist_append_str(reserved_regions, resv_prop_str); qdev_prop_set_array(dev, "reserved-regions", reserved_regions); +if (!aw_bits) { +qdev_prop_set_uint8(dev, "aw-bits", VTD_HOST_AW_39BIT); +} + g_free(resv_prop_str); } diff --git a/hw/virtio/virtio-iommu.c b/hw/virtio/virtio-iommu.c index 7870bdbeee..c468e9b13b 100644 --- a/hw/virtio/virtio-iommu.c +++ b/hw/virtio/virtio-iommu.c @@ -1529,7 +1529,7 @@ static Property virtio_iommu_properties[] = { DEFINE_PROP_LINK("primary-bus", VirtIOIOMMU, primary_bus, TYPE_PCI_BUS, PCIBus *), DEFINE_PROP_BOOL("boot-bypass", VirtIOIOMMU, boot_bypass, true), -DEFINE_PROP_UINT8("aw-bits", VirtIOIOMMU, aw_bits, 64), +DEFINE_PROP_UINT8("aw-bits", VirtIOIOMMU, aw_bits, 0), DEFINE_PROP_END_OF_LIST(), };
[PATCH 12/14] migration: Report error when shutdown fails
This will help detect issues regarding I/O channels usage. Signed-off-by: Cédric Le Goater --- migration/qemu-file.c | 5 - 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/migration/qemu-file.c b/migration/qemu-file.c index 94231ff2955c80b3d0fab11a40510d34c334a826..b69e0c62e2fcf21d346a3687df7eebee23791fdc 100644 --- a/migration/qemu-file.c +++ b/migration/qemu-file.c @@ -62,6 +62,8 @@ struct QEMUFile { */ int qemu_file_shutdown(QEMUFile *f) { +Error *err = NULL; + /* * We must set qemufile error before the real shutdown(), otherwise * there can be a race window where we thought IO all went though @@ -90,7 +92,8 @@ int qemu_file_shutdown(QEMUFile *f) return -ENOSYS; } -if (qio_channel_shutdown(f->ioc, QIO_CHANNEL_SHUTDOWN_BOTH, NULL) < 0) { +if (qio_channel_shutdown(f->ioc, QIO_CHANNEL_SHUTDOWN_BOTH, ) < 0) { +error_report_err(err); return -EIO; } -- 2.43.0
[PATCH 08/14] vfio: Use new Error** argument in vfio_save_setup()
Add an Error** argument to vfio_migration_set_state() and adjust callers, including vfio_save_setup(). The error will be propagated up to qemu_savevm_state_setup() where the save_setup() handler is executed. Signed-off-by: Cédric Le Goater --- hw/vfio/migration.c | 62 + 1 file changed, 40 insertions(+), 22 deletions(-) diff --git a/hw/vfio/migration.c b/hw/vfio/migration.c index 2dfbe671f6f45aa530c7341177bb532d8292cecd..2e0a79967cc97f44d9be5575c3cfe18c9f349dab 100644 --- a/hw/vfio/migration.c +++ b/hw/vfio/migration.c @@ -84,7 +84,8 @@ static const char *mig_state_to_str(enum vfio_device_mig_state state) static int vfio_migration_set_state(VFIODevice *vbasedev, enum vfio_device_mig_state new_state, -enum vfio_device_mig_state recover_state) +enum vfio_device_mig_state recover_state, +Error **errp) { VFIOMigration *migration = vbasedev->migration; uint64_t buf[DIV_ROUND_UP(sizeof(struct vfio_device_feature) + @@ -104,15 +105,15 @@ static int vfio_migration_set_state(VFIODevice *vbasedev, ret = -errno; if (recover_state == VFIO_DEVICE_STATE_ERROR) { -error_report("%s: Failed setting device state to %s, err: %s. " - "Recover state is ERROR. Resetting device", - vbasedev->name, mig_state_to_str(new_state), - strerror(errno)); +error_setg(errp, "%s: Failed setting device state to %s, err: %s. " + "Recover state is ERROR. Resetting device", + vbasedev->name, mig_state_to_str(new_state), + strerror(errno)); goto reset_device; } -error_report( +error_setg(errp, "%s: Failed setting device state to %s, err: %s. Setting device in recover state %s", vbasedev->name, mig_state_to_str(new_state), strerror(errno), mig_state_to_str(recover_state)); @@ -120,7 +121,7 @@ static int vfio_migration_set_state(VFIODevice *vbasedev, mig_state->device_state = recover_state; if (ioctl(vbasedev->fd, VFIO_DEVICE_FEATURE, feature)) { ret = -errno; -error_report( +error_setg(errp, "%s: Failed setting device in recover state, err: %s. Resetting device", vbasedev->name, strerror(errno)); @@ -139,7 +140,7 @@ static int vfio_migration_set_state(VFIODevice *vbasedev, * This can happen if the device is asynchronously reset and * terminates a data transfer. */ -error_report("%s: data_fd out of sync", vbasedev->name); +error_setg(errp, "%s: data_fd out of sync", vbasedev->name); close(mig_state->data_fd); return -EBADF; @@ -170,10 +171,11 @@ reset_device: */ static int vfio_migration_set_state_or_reset(VFIODevice *vbasedev, - enum vfio_device_mig_state new_state) + enum vfio_device_mig_state new_state, + Error **errp) { return vfio_migration_set_state(vbasedev, new_state, -VFIO_DEVICE_STATE_ERROR); +VFIO_DEVICE_STATE_ERROR, errp); } static int vfio_load_buffer(QEMUFile *f, VFIODevice *vbasedev, @@ -391,8 +393,8 @@ static int vfio_save_setup(QEMUFile *f, void *opaque, Error **errp) stop_copy_size); migration->data_buffer = g_try_malloc0(migration->data_buffer_size); if (!migration->data_buffer) { -error_report("%s: Failed to allocate migration data buffer", - vbasedev->name); +error_setg(errp, "%s: Failed to allocate migration data buffer", + vbasedev->name); return -ENOMEM; } @@ -402,7 +404,7 @@ static int vfio_save_setup(QEMUFile *f, void *opaque, Error **errp) switch (migration->device_state) { case VFIO_DEVICE_STATE_RUNNING: ret = vfio_migration_set_state(vbasedev, VFIO_DEVICE_STATE_PRE_COPY, - VFIO_DEVICE_STATE_RUNNING); + VFIO_DEVICE_STATE_RUNNING, errp); if (ret) { return ret; } @@ -429,13 +431,18 @@ static void vfio_save_cleanup(void *opaque) { VFIODevice *vbasedev = opaque; VFIOMigration *migration = vbasedev->migration; +Error *local_err = NULL; /* * Changing device state from STOP_COPY to STOP can take time. Do
[PATCH 04/14] migration: Modify ram_init_bitmaps() to report dirty tracking errors
The .save_setup() handler has now an Error** argument that we can use to propagate errors reported by the .log_global_start() handler. Do that for the RAM. qemu_savevm_state_setup() will store the error under the migration stream for later detection in the migration sequence. Signed-off-by: Cédric Le Goater --- migration/ram.c | 19 ++- 1 file changed, 10 insertions(+), 9 deletions(-) diff --git a/migration/ram.c b/migration/ram.c index d86626bb1c704b2d3497b323a702ca6ca8939a79..b87245466bb46937fd0358d0c66432bcc6280018 100644 --- a/migration/ram.c +++ b/migration/ram.c @@ -2802,19 +2802,17 @@ static void migration_bitmap_clear_discarded_pages(RAMState *rs) } } -static void ram_init_bitmaps(RAMState *rs) +static void ram_init_bitmaps(RAMState *rs, Error **errp) { -Error *local_err = NULL; - qemu_mutex_lock_ramlist(); WITH_RCU_READ_LOCK_GUARD() { ram_list_init_bitmaps(); /* We don't use dirty log with background snapshots */ if (!migrate_background_snapshot()) { -memory_global_dirty_log_start(GLOBAL_DIRTY_MIGRATION, _err); -if (local_err) { -error_report_err(local_err); +memory_global_dirty_log_start(GLOBAL_DIRTY_MIGRATION, errp); +if (*errp) { +break; } migration_bitmap_sync_precopy(rs, false); } @@ -2828,7 +2826,7 @@ static void ram_init_bitmaps(RAMState *rs) migration_bitmap_clear_discarded_pages(rs); } -static int ram_init_all(RAMState **rsp) +static int ram_init_all(RAMState **rsp, Error **errp) { if (ram_state_init(rsp)) { return -1; @@ -2839,7 +2837,10 @@ static int ram_init_all(RAMState **rsp) return -1; } -ram_init_bitmaps(*rsp); +ram_init_bitmaps(*rsp, errp); +if (*errp) { +return -1; +} return 0; } @@ -2952,7 +2953,7 @@ static int ram_save_setup(QEMUFile *f, void *opaque, Error **errp) /* migration has already setup the bitmap, reuse it. */ if (!migration_in_colo_state()) { -if (ram_init_all(rsp) != 0) { +if (ram_init_all(rsp, errp) != 0) { compress_threads_save_cleanup(); return -1; } -- 2.43.0
[PATCH 05/14] vfio: Add Error** argument to .set_dirty_page_tracking() handler
We will use the Error object to improve error reporting in the .log_global*() handlers of VFIO. Signed-off-by: Cédric Le Goater --- include/hw/vfio/vfio-container-base.h | 4 ++-- hw/vfio/common.c | 4 ++-- hw/vfio/container-base.c | 4 ++-- hw/vfio/container.c | 6 +++--- 4 files changed, 9 insertions(+), 9 deletions(-) diff --git a/include/hw/vfio/vfio-container-base.h b/include/hw/vfio/vfio-container-base.h index b2813b0c117985425c842d91f011bb895955d738..f22fcb5a214be2717b42815371346401bb7fce51 100644 --- a/include/hw/vfio/vfio-container-base.h +++ b/include/hw/vfio/vfio-container-base.h @@ -81,7 +81,7 @@ int vfio_container_add_section_window(VFIOContainerBase *bcontainer, void vfio_container_del_section_window(VFIOContainerBase *bcontainer, MemoryRegionSection *section); int vfio_container_set_dirty_page_tracking(VFIOContainerBase *bcontainer, - bool start); + bool start, Error **errp); int vfio_container_query_dirty_bitmap(const VFIOContainerBase *bcontainer, VFIOBitmap *vbmap, hwaddr iova, hwaddr size); @@ -122,7 +122,7 @@ struct VFIOIOMMUClass { void (*detach_device)(VFIODevice *vbasedev); /* migration feature */ int (*set_dirty_page_tracking)(const VFIOContainerBase *bcontainer, - bool start); + bool start, Error **errp); int (*query_dirty_bitmap)(const VFIOContainerBase *bcontainer, VFIOBitmap *vbmap, hwaddr iova, hwaddr size); diff --git a/hw/vfio/common.c b/hw/vfio/common.c index 45af5c675584e1931dfba3b4f78469cc4c00014e..03f2059d903eca335b02f633b07cd35ef3dd6237 100644 --- a/hw/vfio/common.c +++ b/hw/vfio/common.c @@ -1085,7 +1085,7 @@ static void vfio_listener_log_global_start(MemoryListener *listener, if (vfio_devices_all_device_dirty_tracking(bcontainer)) { ret = vfio_devices_dma_logging_start(bcontainer); } else { -ret = vfio_container_set_dirty_page_tracking(bcontainer, true); +ret = vfio_container_set_dirty_page_tracking(bcontainer, true, NULL); } if (ret) { @@ -1105,7 +1105,7 @@ static void vfio_listener_log_global_stop(MemoryListener *listener, if (vfio_devices_all_device_dirty_tracking(bcontainer)) { vfio_devices_dma_logging_stop(bcontainer); } else { -ret = vfio_container_set_dirty_page_tracking(bcontainer, false); +ret = vfio_container_set_dirty_page_tracking(bcontainer, false, NULL); } if (ret) { diff --git a/hw/vfio/container-base.c b/hw/vfio/container-base.c index 913ae49077c4f09b7b27517c1231cfbe4befb7fb..7c0764121d24b02b6c4e66e368d7dff78a6d65aa 100644 --- a/hw/vfio/container-base.c +++ b/hw/vfio/container-base.c @@ -53,14 +53,14 @@ void vfio_container_del_section_window(VFIOContainerBase *bcontainer, } int vfio_container_set_dirty_page_tracking(VFIOContainerBase *bcontainer, - bool start) + bool start, Error **errp) { if (!bcontainer->dirty_pages_supported) { return 0; } g_assert(bcontainer->ops->set_dirty_page_tracking); -return bcontainer->ops->set_dirty_page_tracking(bcontainer, start); +return bcontainer->ops->set_dirty_page_tracking(bcontainer, start, errp); } int vfio_container_query_dirty_bitmap(const VFIOContainerBase *bcontainer, diff --git a/hw/vfio/container.c b/hw/vfio/container.c index bd25b9fbad2e717e63c2ab0e331186e5f63cef49..f772ac79b9c413c86d7e60f6dc4e6699852d5aac 100644 --- a/hw/vfio/container.c +++ b/hw/vfio/container.c @@ -210,7 +210,7 @@ static int vfio_legacy_dma_map(const VFIOContainerBase *bcontainer, hwaddr iova, static int vfio_legacy_set_dirty_page_tracking(const VFIOContainerBase *bcontainer, -bool start) +bool start, Error **errp) { const VFIOContainer *container = container_of(bcontainer, VFIOContainer, bcontainer); @@ -228,8 +228,8 @@ vfio_legacy_set_dirty_page_tracking(const VFIOContainerBase *bcontainer, ret = ioctl(container->fd, VFIO_IOMMU_DIRTY_PAGES, ); if (ret) { ret = -errno; -error_report("Failed to set dirty tracking flag 0x%x errno: %d", - dirty.flags, errno); +error_setg(errp, "Failed to set dirty tracking flag 0x%x errno: %d", + dirty.flags, errno); } return ret; -- 2.43.0
[PATCH 07/14] vfio: Add Error** argument to vfio_devices_dma_logging_stop()
This improves error reporting in the log_global_stop() VFIO handler. Signed-off-by: Cédric Le Goater --- hw/vfio/common.c | 19 ++- 1 file changed, 14 insertions(+), 5 deletions(-) diff --git a/hw/vfio/common.c b/hw/vfio/common.c index a5d53e67efaa921e89ad918390a22506c7b1ed66..82173b039c47150f5edd05d329192c5b9c8a9a0f 100644 --- a/hw/vfio/common.c +++ b/hw/vfio/common.c @@ -938,12 +938,14 @@ static void vfio_dirty_tracking_init(VFIOContainerBase *bcontainer, memory_listener_unregister(); } -static void vfio_devices_dma_logging_stop(VFIOContainerBase *bcontainer) +static int vfio_devices_dma_logging_stop(VFIOContainerBase *bcontainer, + Error **errp) { uint64_t buf[DIV_ROUND_UP(sizeof(struct vfio_device_feature), sizeof(uint64_t))] = {}; struct vfio_device_feature *feature = (struct vfio_device_feature *)buf; VFIODevice *vbasedev; +int ret = 0; feature->argsz = sizeof(buf); feature->flags = VFIO_DEVICE_FEATURE_SET | @@ -955,11 +957,17 @@ static void vfio_devices_dma_logging_stop(VFIOContainerBase *bcontainer) } if (ioctl(vbasedev->fd, VFIO_DEVICE_FEATURE, feature)) { -warn_report("%s: Failed to stop DMA logging, err %d (%s)", -vbasedev->name, -errno, strerror(errno)); +/* Keep first error */ +if (!ret) { +ret = -errno; +error_setg(errp, "%s: Failed to stop DMA logging, err %d (%s)", + vbasedev->name, -errno, strerror(errno)); +} } vbasedev->dirty_tracking = false; } + +return ret; } static struct vfio_device_feature * @@ -1068,7 +1076,8 @@ static int vfio_devices_dma_logging_start(VFIOContainerBase *bcontainer, out: if (ret) { -vfio_devices_dma_logging_stop(bcontainer); +/* Ignore the potential errors when doing rollback */ +vfio_devices_dma_logging_stop(bcontainer, NULL); } vfio_device_feature_dma_logging_start_destroy(feature); @@ -1102,7 +,7 @@ static void vfio_listener_log_global_stop(MemoryListener *listener, int ret = 0; if (vfio_devices_all_device_dirty_tracking(bcontainer)) { -vfio_devices_dma_logging_stop(bcontainer); +ret = vfio_devices_dma_logging_stop(bcontainer, errp); } else { ret = vfio_container_set_dirty_page_tracking(bcontainer, false, errp); } -- 2.43.0
[PATCH 11/14] vfio: Extend vfio_set_migration_error() with Error* argument
vfio_set_migration_error() sets the 'return' error on the migration stream if a migration is in progress. To improve error reporting, add a new Error* argument to also set the Error object on the migration stream. Signed-off-by: Cédric Le Goater --- hw/vfio/common.c | 50 +--- 1 file changed, 30 insertions(+), 20 deletions(-) diff --git a/hw/vfio/common.c b/hw/vfio/common.c index 82173b039c47150f5edd05d329192c5b9c8a9a0f..afe8b6bd294fd5904f394a5db48aae3fd718b14e 100644 --- a/hw/vfio/common.c +++ b/hw/vfio/common.c @@ -148,16 +148,18 @@ bool vfio_viommu_preset(VFIODevice *vbasedev) return vbasedev->bcontainer->space->as != _space_memory; } -static void vfio_set_migration_error(int err) +static void vfio_set_migration_error(int ret, Error *err) { MigrationState *ms = migrate_get_current(); if (migration_is_setup_or_active(ms->state)) { WITH_QEMU_LOCK_GUARD(>qemu_file_lock) { if (ms->to_dst_file) { -qemu_file_set_error(ms->to_dst_file, err); +qemu_file_set_error_obj(ms->to_dst_file, ret, err); } } +} else { +error_report_err(err); } } @@ -296,15 +298,17 @@ static void vfio_iommu_map_notify(IOMMUNotifier *n, IOMMUTLBEntry *iotlb) VFIOContainerBase *bcontainer = giommu->bcontainer; hwaddr iova = iotlb->iova + giommu->iommu_offset; void *vaddr; +Error *local_err = NULL; int ret; trace_vfio_iommu_map_notify(iotlb->perm == IOMMU_NONE ? "UNMAP" : "MAP", iova, iova + iotlb->addr_mask); if (iotlb->target_as != _space_memory) { -error_report("Wrong target AS \"%s\", only system memory is allowed", - iotlb->target_as->name ? iotlb->target_as->name : "none"); -vfio_set_migration_error(-EINVAL); +error_setg(_err, + "Wrong target AS \"%s\", only system memory is allowed", + iotlb->target_as->name ? iotlb->target_as->name : "none"); +vfio_set_migration_error(-EINVAL, local_err); return; } @@ -336,11 +340,12 @@ static void vfio_iommu_map_notify(IOMMUNotifier *n, IOMMUTLBEntry *iotlb) ret = vfio_container_dma_unmap(bcontainer, iova, iotlb->addr_mask + 1, iotlb); if (ret) { -error_report("vfio_container_dma_unmap(%p, 0x%"HWADDR_PRIx", " - "0x%"HWADDR_PRIx") = %d (%s)", - bcontainer, iova, - iotlb->addr_mask + 1, ret, strerror(-ret)); -vfio_set_migration_error(ret); +error_setg(_err, + "vfio_container_dma_unmap(%p, 0x%"HWADDR_PRIx", " + "0x%"HWADDR_PRIx") = %d (%s)", + bcontainer, iova, + iotlb->addr_mask + 1, ret, strerror(-ret)); +vfio_set_migration_error(ret, local_err); } } out: @@ -1224,13 +1229,15 @@ static void vfio_iommu_map_dirty_notify(IOMMUNotifier *n, IOMMUTLBEntry *iotlb) VFIOContainerBase *bcontainer = giommu->bcontainer; hwaddr iova = iotlb->iova + giommu->iommu_offset; ram_addr_t translated_addr; +Error *local_err = NULL; int ret = -EINVAL; trace_vfio_iommu_map_dirty_notify(iova, iova + iotlb->addr_mask); if (iotlb->target_as != _space_memory) { -error_report("Wrong target AS \"%s\", only system memory is allowed", - iotlb->target_as->name ? iotlb->target_as->name : "none"); +error_setg(_err, + "Wrong target AS \"%s\", only system memory is allowed", + iotlb->target_as->name ? iotlb->target_as->name : "none"); goto out; } @@ -1239,17 +1246,18 @@ static void vfio_iommu_map_dirty_notify(IOMMUNotifier *n, IOMMUTLBEntry *iotlb) ret = vfio_get_dirty_bitmap(bcontainer, iova, iotlb->addr_mask + 1, translated_addr); if (ret) { -error_report("vfio_iommu_map_dirty_notify(%p, 0x%"HWADDR_PRIx", " - "0x%"HWADDR_PRIx") = %d (%s)", - bcontainer, iova, iotlb->addr_mask + 1, ret, - strerror(-ret)); +error_setg(_err, + "vfio_iommu_map_dirty_notify(%p, 0x%"HWADDR_PRIx", " + "0x%"HWADDR_PRIx") = %d (%s)", + bcontainer, iova, iotlb->addr_mask + 1, ret, +
[PATCH 01/14] migration: Add Error** argument to .save_setup() handler
The purpose is to record a potential error in the migration stream if qemu_savevm_state_setup() fails. Most of the current .save_setup() handlers can be modified to use the Error argument instead of managing their own and calling locally error_report(). The following patches will introduce such changes for VFIO first. Signed-off-by: Cédric Le Goater --- include/migration/register.h | 2 +- hw/ppc/spapr.c | 2 +- hw/s390x/s390-stattrib.c | 2 +- hw/vfio/migration.c| 2 +- migration/block-dirty-bitmap.c | 2 +- migration/block.c | 2 +- migration/ram.c| 2 +- migration/savevm.c | 4 ++-- 8 files changed, 9 insertions(+), 9 deletions(-) diff --git a/include/migration/register.h b/include/migration/register.h index 9ab1f79512c605f0c88a45b560c57486fa054441..831600a00eae4efd0464b60925d65de4d9dbcff8 100644 --- a/include/migration/register.h +++ b/include/migration/register.h @@ -25,7 +25,7 @@ typedef struct SaveVMHandlers { * used to perform early checks. */ int (*save_prepare)(void *opaque, Error **errp); -int (*save_setup)(QEMUFile *f, void *opaque); +int (*save_setup)(QEMUFile *f, void *opaque, Error **errp); void (*save_cleanup)(void *opaque); int (*save_live_complete_postcopy)(QEMUFile *f, void *opaque); int (*save_live_complete_precopy)(QEMUFile *f, void *opaque); diff --git a/hw/ppc/spapr.c b/hw/ppc/spapr.c index 0d72d286d80f0435122593555f79fae4d90acf81..a1b0aa02582ad2d68a13476c1859b18143da7bb8 100644 --- a/hw/ppc/spapr.c +++ b/hw/ppc/spapr.c @@ -2142,7 +2142,7 @@ static const VMStateDescription vmstate_spapr = { } }; -static int htab_save_setup(QEMUFile *f, void *opaque) +static int htab_save_setup(QEMUFile *f, void *opaque, Error **errp) { SpaprMachineState *spapr = opaque; diff --git a/hw/s390x/s390-stattrib.c b/hw/s390x/s390-stattrib.c index c483b62a9b5f71772639fc180bdad15ecb6711cb..c934df424a555d83d2198f5ddfc0cbe0ea98e9ec 100644 --- a/hw/s390x/s390-stattrib.c +++ b/hw/s390x/s390-stattrib.c @@ -166,7 +166,7 @@ static int cmma_load(QEMUFile *f, void *opaque, int version_id) return ret; } -static int cmma_save_setup(QEMUFile *f, void *opaque) +static int cmma_save_setup(QEMUFile *f, void *opaque, Error **errp) { S390StAttribState *sas = S390_STATTRIB(opaque); S390StAttribClass *sac = S390_STATTRIB_GET_CLASS(sas); diff --git a/hw/vfio/migration.c b/hw/vfio/migration.c index 70e6b1a709f9b67e4c9eb41033d76347275cac42..8bcb4bc73cd5ba5338e3ffa4d907d0e6bfbb9485 100644 --- a/hw/vfio/migration.c +++ b/hw/vfio/migration.c @@ -378,7 +378,7 @@ static int vfio_save_prepare(void *opaque, Error **errp) return 0; } -static int vfio_save_setup(QEMUFile *f, void *opaque) +static int vfio_save_setup(QEMUFile *f, void *opaque, Error **errp) { VFIODevice *vbasedev = opaque; VFIOMigration *migration = vbasedev->migration; diff --git a/migration/block-dirty-bitmap.c b/migration/block-dirty-bitmap.c index 2708abf3d762de774ed294d3fdb8e56690d2974c..16f84e6c57c2403a8c2d6319f4e7b6360dade28c 100644 --- a/migration/block-dirty-bitmap.c +++ b/migration/block-dirty-bitmap.c @@ -1213,7 +1213,7 @@ fail: return ret; } -static int dirty_bitmap_save_setup(QEMUFile *f, void *opaque) +static int dirty_bitmap_save_setup(QEMUFile *f, void *opaque, Error **errp) { DBMSaveState *s = &((DBMState *)opaque)->save; SaveBitmapState *dbms = NULL; diff --git a/migration/block.c b/migration/block.c index 8c6ebafacc1ffe930d1d4f19d968817b14852c69..df15319ceab66201b043f15eac1b0a7d6522b60c 100644 --- a/migration/block.c +++ b/migration/block.c @@ -708,7 +708,7 @@ static void block_migration_cleanup(void *opaque) blk_mig_unlock(); } -static int block_save_setup(QEMUFile *f, void *opaque) +static int block_save_setup(QEMUFile *f, void *opaque, Error **errp) { int ret; diff --git a/migration/ram.c b/migration/ram.c index d5b7cd5ac2f31aabf4a248b966153401c48912cf..136c237f4079f68d4e578cf1c72eec2efc815bc8 100644 --- a/migration/ram.c +++ b/migration/ram.c @@ -2931,7 +2931,7 @@ void qemu_guest_free_page_hint(void *addr, size_t len) * @f: QEMUFile where to send the data * @opaque: RAMState pointer */ -static int ram_save_setup(QEMUFile *f, void *opaque) +static int ram_save_setup(QEMUFile *f, void *opaque, Error **errp) { RAMState **rsp = opaque; RAMBlock *block; diff --git a/migration/savevm.c b/migration/savevm.c index d612c8a9020b204d5d078d5df85f0e6449c27645..f2ae799bad13e631bccf733a34c3a8fd22e8dd48 100644 --- a/migration/savevm.c +++ b/migration/savevm.c @@ -1342,10 +1342,10 @@ void qemu_savevm_state_setup(QEMUFile *f) } save_section_header(f, se, QEMU_VM_SECTION_START); -ret = se->ops->save_setup(f, se->opaque); +ret = se->ops->save_setup(f, se->opaque, _err); save_section_footer(f, se); if (ret < 0) { -
[PATCH 06/14] vfio: Add Error** argument to vfio_devices_dma_logging_start()
This allows to update the Error argument of the VFIO log_global_start() handler. Errors detected when device level logging is started will be propagated up to qemu_savevm_state_setup() when the ram save_setup() handler is executed. The vfio_set_migration_error() call becomes redudant. Remove it. Signed-off-by: Cédric Le Goater --- hw/vfio/common.c | 21 + 1 file changed, 9 insertions(+), 12 deletions(-) diff --git a/hw/vfio/common.c b/hw/vfio/common.c index 03f2059d903eca335b02f633b07cd35ef3dd6237..a5d53e67efaa921e89ad918390a22506c7b1ed66 100644 --- a/hw/vfio/common.c +++ b/hw/vfio/common.c @@ -1036,7 +1036,8 @@ static void vfio_device_feature_dma_logging_start_destroy( g_free(feature); } -static int vfio_devices_dma_logging_start(VFIOContainerBase *bcontainer) +static int vfio_devices_dma_logging_start(VFIOContainerBase *bcontainer, + Error **errp) { struct vfio_device_feature *feature; VFIODirtyRanges ranges; @@ -1058,8 +1059,8 @@ static int vfio_devices_dma_logging_start(VFIOContainerBase *bcontainer) ret = ioctl(vbasedev->fd, VFIO_DEVICE_FEATURE, feature); if (ret) { ret = -errno; -error_report("%s: Failed to start DMA logging, err %d (%s)", - vbasedev->name, ret, strerror(errno)); +error_setg(errp, "%s: Failed to start DMA logging, err %d (%s)", + vbasedev->name, ret, strerror(errno)); goto out; } vbasedev->dirty_tracking = true; @@ -1083,15 +1084,13 @@ static void vfio_listener_log_global_start(MemoryListener *listener, int ret; if (vfio_devices_all_device_dirty_tracking(bcontainer)) { -ret = vfio_devices_dma_logging_start(bcontainer); +ret = vfio_devices_dma_logging_start(bcontainer, errp); } else { -ret = vfio_container_set_dirty_page_tracking(bcontainer, true, NULL); +ret = vfio_container_set_dirty_page_tracking(bcontainer, true, errp); } if (ret) { -error_report("vfio: Could not start dirty page tracking, err: %d (%s)", - ret, strerror(-ret)); -vfio_set_migration_error(ret); +error_prepend(errp, "vfio: Could not start dirty page tracking - "); } } @@ -1105,13 +1104,11 @@ static void vfio_listener_log_global_stop(MemoryListener *listener, if (vfio_devices_all_device_dirty_tracking(bcontainer)) { vfio_devices_dma_logging_stop(bcontainer); } else { -ret = vfio_container_set_dirty_page_tracking(bcontainer, false, NULL); +ret = vfio_container_set_dirty_page_tracking(bcontainer, false, errp); } if (ret) { -error_report("vfio: Could not stop dirty page tracking, err: %d (%s)", - ret, strerror(-ret)); -vfio_set_migration_error(ret); +error_prepend(errp, "vfio: Could not stop dirty page tracking - "); } } -- 2.43.0
[PATCH 13/14] migration: Use migrate_has_error() in close_return_path_on_source()
close_return_path_on_source() retrieves the migration error from the the QEMUFile '->to_dst_file' to know if a shutdown is required. This shutdown is required to exit the return-path thread. However, in migrate_fd_cleanup(), '->to_dst_file' is cleaned up before calling close_return_path_on_source() and the shutdown is never performed, leaving the source and destination waiting for an event to occur. Avoid relying on '->to_dst_file' and use migrate_has_error() instead. Suggested-by: Peter Xu Signed-off-by: Cédric Le Goater --- migration/migration.c | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/migration/migration.c b/migration/migration.c index d5f705ceef4c925589aa49335969672c0d761fa2..5f55af3d7624750ca416c4177781241b3e291e5d 100644 --- a/migration/migration.c +++ b/migration/migration.c @@ -2372,8 +2372,7 @@ static bool close_return_path_on_source(MigrationState *ms) * cause it to unblock if it's stuck waiting for the destination. */ WITH_QEMU_LOCK_GUARD(>qemu_file_lock) { -if (ms->to_dst_file && ms->rp_state.from_dst_file && -qemu_file_get_error(ms->to_dst_file)) { +if (migrate_has_error(ms) && ms->rp_state.from_dst_file) { qemu_file_shutdown(ms->rp_state.from_dst_file); } } -- 2.43.0
[PATCH 10/14] vfio: Also trace event failures in vfio_save_complete_precopy()
vfio_save_complete_precopy() currently returns before doing the trace event. Change that. Signed-off-by: Cédric Le Goater --- hw/vfio/migration.c | 3 --- 1 file changed, 3 deletions(-) diff --git a/hw/vfio/migration.c b/hw/vfio/migration.c index fb264c1ef57bbbde4306901e5449e0dfbd0ce3b7..cc5b74f9563eca25d3c7285f106ed06f1eb2f519 100644 --- a/hw/vfio/migration.c +++ b/hw/vfio/migration.c @@ -572,9 +572,6 @@ static int vfio_save_complete_precopy(QEMUFile *f, void *opaque) qemu_put_be64(f, VFIO_MIG_FLAG_END_OF_STATE); ret = qemu_file_get_error(f); -if (ret) { -return ret; -} trace_vfio_save_complete_precopy(vbasedev->name, ret); -- 2.43.0
[PATCH 09/14] vfio: Add Error** argument to .vfio_save_config() handler
Use vmstate_save_state_with_err() to improve error reporting in the callers. Signed-off-by: Cédric Le Goater --- include/hw/vfio/vfio-common.h | 2 +- hw/vfio/migration.c | 18 -- hw/vfio/pci.c | 5 +++-- 3 files changed, 16 insertions(+), 9 deletions(-) diff --git a/include/hw/vfio/vfio-common.h b/include/hw/vfio/vfio-common.h index 9b7ef7d02b5a0ad5266bcc4d06cd6874178978e4..710e0d6a880b97848af6ddc2e7968a01054fa122 100644 --- a/include/hw/vfio/vfio-common.h +++ b/include/hw/vfio/vfio-common.h @@ -133,7 +133,7 @@ struct VFIODeviceOps { int (*vfio_hot_reset_multi)(VFIODevice *vdev); void (*vfio_eoi)(VFIODevice *vdev); Object *(*vfio_get_object)(VFIODevice *vdev); -void (*vfio_save_config)(VFIODevice *vdev, QEMUFile *f); +int (*vfio_save_config)(VFIODevice *vdev, QEMUFile *f, Error **errp); int (*vfio_load_config)(VFIODevice *vdev, QEMUFile *f); }; diff --git a/hw/vfio/migration.c b/hw/vfio/migration.c index 2e0a79967cc97f44d9be5575c3cfe18c9f349dab..fb264c1ef57bbbde4306901e5449e0dfbd0ce3b7 100644 --- a/hw/vfio/migration.c +++ b/hw/vfio/migration.c @@ -190,14 +190,19 @@ static int vfio_load_buffer(QEMUFile *f, VFIODevice *vbasedev, return ret; } -static int vfio_save_device_config_state(QEMUFile *f, void *opaque) +static int vfio_save_device_config_state(QEMUFile *f, void *opaque, + Error **errp) { VFIODevice *vbasedev = opaque; +int ret = 0; qemu_put_be64(f, VFIO_MIG_FLAG_DEV_CONFIG_STATE); if (vbasedev->ops && vbasedev->ops->vfio_save_config) { -vbasedev->ops->vfio_save_config(vbasedev, f); +ret = vbasedev->ops->vfio_save_config(vbasedev, f, errp); +if (ret) { +return ret; +} } qemu_put_be64(f, VFIO_MIG_FLAG_END_OF_STATE); @@ -579,13 +584,14 @@ static int vfio_save_complete_precopy(QEMUFile *f, void *opaque) static void vfio_save_state(QEMUFile *f, void *opaque) { VFIODevice *vbasedev = opaque; +Error *local_err = NULL; int ret; -ret = vfio_save_device_config_state(f, opaque); +ret = vfio_save_device_config_state(f, opaque, _err); if (ret) { -error_report("%s: Failed to save device config space", - vbasedev->name); -qemu_file_set_error(f, ret); +error_prepend(_err, "%s: Failed to save device config space", + vbasedev->name); +qemu_file_set_error_obj(f, ret, local_err); } } diff --git a/hw/vfio/pci.c b/hw/vfio/pci.c index 4fa387f0430d62ca2ba1b5ae5b7037f8f06b33f9..99d86e1d40ef25133fc76ad6e58294b07bd20843 100644 --- a/hw/vfio/pci.c +++ b/hw/vfio/pci.c @@ -2585,11 +2585,12 @@ const VMStateDescription vmstate_vfio_pci_config = { } }; -static void vfio_pci_save_config(VFIODevice *vbasedev, QEMUFile *f) +static int vfio_pci_save_config(VFIODevice *vbasedev, QEMUFile *f, Error **errp) { VFIOPCIDevice *vdev = container_of(vbasedev, VFIOPCIDevice, vbasedev); -vmstate_save_state(f, _vfio_pci_config, vdev, NULL); +return vmstate_save_state_with_err(f, _vfio_pci_config, vdev, NULL, + errp); } static int vfio_pci_load_config(VFIODevice *vbasedev, QEMUFile *f) -- 2.43.0
[RFC PATCH 14/14] migration: Fix return-path thread exit
In case of error, close_return_path_on_source() can perform a shutdown to exit the return-path thread. However, in migrate_fd_cleanup(), 'to_dst_file' is closed before calling close_return_path_on_source() and the shutdown fails, leaving the source and destination waiting for an event to occur. Close the file after calling close_return_path_on_source() so that the shutdown succeeds and the return-path thread exits. Signed-off-by: Cédric Le Goater --- This is an RFC because the correct fix implies reworking the QEMUFile construct, built on top of the QEMU I/O channel. migration/migration.c | 13 ++--- 1 file changed, 6 insertions(+), 7 deletions(-) diff --git a/migration/migration.c b/migration/migration.c index 5f55af3d7624750ca416c4177781241b3e291e5d..de329f2c553288935d824748286e79e535929b8b 100644 --- a/migration/migration.c +++ b/migration/migration.c @@ -1313,6 +1313,8 @@ void migrate_set_state(int *state, int old_state, int new_state) static void migrate_fd_cleanup(MigrationState *s) { +QEMUFile *tmp = NULL; + g_free(s->hostname); s->hostname = NULL; json_writer_free(s->vmdesc); @@ -1321,8 +1323,6 @@ static void migrate_fd_cleanup(MigrationState *s) qemu_savevm_state_cleanup(); if (s->to_dst_file) { -QEMUFile *tmp; - trace_migrate_fd_cleanup(); bql_unlock(); if (s->migration_thread_running) { @@ -1341,15 +1341,14 @@ static void migrate_fd_cleanup(MigrationState *s) * critical section won't block for long. */ migration_ioc_unregister_yank_from_file(tmp); -qemu_fclose(tmp); } -/* - * We already cleaned up to_dst_file, so errors from the return - * path might be due to that, ignore them. - */ close_return_path_on_source(s); +if (tmp) { +qemu_fclose(tmp); +} + assert(!migration_is_active(s)); if (s->state == MIGRATION_STATUS_CANCELLING) { -- 2.43.0
[PATCH 00/14] migration: Improve error reporting
Hello, The motivation behind these changes is to improve error reporting to the upper management layer (libvirt) with a more detailed error, this to let it decide, depending on the reported error, whether to try migration again later. It would be useful in cases where migration fails due to lack of HW resources on the host. For instance, some adapters can only initiate a limited number of simultaneous dirty tracking requests and this imposes a limit on the the number of VMs that can be migrated simultaneously. We are not quite ready for such a mechanism but what we can do first is to cleanup the error reporting in the early save_setup sequence. This is what the following changes propose, by adding an Error argument to various handlers and propagating it to the core migration subsystem. The last patches try to address a related issue found on VMs with MLX5 VF assigned devices. These are one of those adapters with the HW limitation described above. If dirty tracking setup fails and return-path is in use, the return-path thread does not terminate, leaving the source and destination VMs waiting for an event to occur. The last patch is still an RFC because the correct fix is not obvious and implies reworking the QEMUFile software construct, built on top of the QEMU I/O channel. Thanks, C. [1] https://lore.kernel.org/qemu-devel/20240201184853.890471-1-...@redhat.com/ Cédric Le Goater (14): migration: Add Error** argument to .save_setup() handler migration: Add Error** argument to .load_setup() handler memory: Add Error** argument to .log_global*() handlers migration: Modify ram_init_bitmaps() to report dirty tracking errors vfio: Add Error** argument to .set_dirty_page_tracking() handler vfio: Add Error** argument to vfio_devices_dma_logging_start() vfio: Add Error** argument to vfio_devices_dma_logging_stop() vfio: Use new Error** argument in vfio_save_setup() vfio: Add Error** argument to .vfio_save_config() handler vfio: Also trace event failures in vfio_save_complete_precopy() vfio: Extend vfio_set_migration_error() with Error* argument migration: Report error when shutdown fails migration: Use migrate_has_error() in close_return_path_on_source() migration: Fix return-path thread exit include/exec/memory.h | 12 ++-- include/hw/vfio/vfio-common.h | 2 +- include/hw/vfio/vfio-container-base.h | 4 +- include/migration/register.h | 4 +- hw/i386/xen/xen-hvm.c | 8 +-- hw/ppc/spapr.c| 2 +- hw/s390x/s390-stattrib.c | 2 +- hw/vfio/common.c | 96 --- hw/vfio/container-base.c | 4 +- hw/vfio/container.c | 6 +- hw/vfio/migration.c | 87 +++- hw/vfio/pci.c | 5 +- hw/virtio/vhost.c | 4 +- migration/block-dirty-bitmap.c| 2 +- migration/block.c | 2 +- migration/dirtyrate.c | 24 +-- migration/migration.c | 16 ++--- migration/qemu-file.c | 5 +- migration/ram.c | 40 --- migration/savevm.c| 14 ++-- system/memory.c | 37 +++ 21 files changed, 236 insertions(+), 140 deletions(-) -- 2.43.0
[PATCH 03/14] memory: Add Error** argument to .log_global*() handlers
Modify memory_global_dirty_log_start() and memory_global_dirty_log_stop() to also take an Error** parameter and report the error in the callers. Aside from error reporting, there should be no functional changes. Cc: Stefano Stabellini Cc: Anthony Perard Cc: Paul Durrant Cc: Michael S. Tsirkin Cc: Paolo Bonzini Cc: David Hildenbrand Signed-off-by: Cédric Le Goater --- include/exec/memory.h | 12 hw/i386/xen/xen-hvm.c | 8 hw/vfio/common.c | 6 -- hw/virtio/vhost.c | 4 ++-- migration/dirtyrate.c | 24 migration/ram.c | 27 +++ system/memory.c | 37 + 7 files changed, 86 insertions(+), 32 deletions(-) diff --git a/include/exec/memory.h b/include/exec/memory.h index 177be23db709d8bab9cebfe6acbae57611073327..b348070dc8f17b3505196d3a92d8cfb2171b640f 100644 --- a/include/exec/memory.h +++ b/include/exec/memory.h @@ -998,8 +998,9 @@ struct MemoryListener { * active at that time. * * @listener: The #MemoryListener. + * @errp: pointer to Error*, to store an error if it happens. */ -void (*log_global_start)(MemoryListener *listener); +void (*log_global_start)(MemoryListener *listener, Error **errp); /** * @log_global_stop: @@ -1009,8 +1010,9 @@ struct MemoryListener { * the address space. * * @listener: The #MemoryListener. + * @errp: pointer to Error*, to store an error if it happens. */ -void (*log_global_stop)(MemoryListener *listener); +void (*log_global_stop)(MemoryListener *listener, Error **errp); /** * @log_global_after_sync: @@ -2567,15 +2569,17 @@ void memory_listener_unregister(MemoryListener *listener); * memory_global_dirty_log_start: begin dirty logging for all regions * * @flags: purpose of starting dirty log, migration or dirty rate + * @errp: pointer to Error*, to store an error if it happens. */ -void memory_global_dirty_log_start(unsigned int flags); +void memory_global_dirty_log_start(unsigned int flags, Error **errp); /** * memory_global_dirty_log_stop: end dirty logging for all regions * * @flags: purpose of stopping dirty log, migration or dirty rate + * @errp: pointer to Error*, to store an error if it happens. */ -void memory_global_dirty_log_stop(unsigned int flags); +void memory_global_dirty_log_stop(unsigned int flags, Error **errp); void mtree_info(bool flatview, bool dispatch_tree, bool owner, bool disabled); diff --git a/hw/i386/xen/xen-hvm.c b/hw/i386/xen/xen-hvm.c index f42621e6742552035122ea58092c91c3458338ff..d9c80416343b71311389563c7bdaa748829ada29 100644 --- a/hw/i386/xen/xen-hvm.c +++ b/hw/i386/xen/xen-hvm.c @@ -446,14 +446,14 @@ static void xen_log_sync(MemoryListener *listener, MemoryRegionSection *section) int128_get64(section->size)); } -static void xen_log_global_start(MemoryListener *listener) +static void xen_log_global_start(MemoryListener *listener, Error **errp) { if (xen_enabled()) { xen_in_migration = true; } } -static void xen_log_global_stop(MemoryListener *listener) +static void xen_log_global_stop(MemoryListener *listener, Error **errp) { xen_in_migration = false; } @@ -653,9 +653,9 @@ void xen_hvm_modified_memory(ram_addr_t start, ram_addr_t length) void qmp_xen_set_global_dirty_log(bool enable, Error **errp) { if (enable) { -memory_global_dirty_log_start(GLOBAL_DIRTY_MIGRATION); +memory_global_dirty_log_start(GLOBAL_DIRTY_MIGRATION, errp); } else { -memory_global_dirty_log_stop(GLOBAL_DIRTY_MIGRATION); +memory_global_dirty_log_stop(GLOBAL_DIRTY_MIGRATION, errp); } } diff --git a/hw/vfio/common.c b/hw/vfio/common.c index 059bfdc07a85e2eb908df828c1f42104d683e911..45af5c675584e1931dfba3b4f78469cc4c00014e 100644 --- a/hw/vfio/common.c +++ b/hw/vfio/common.c @@ -1075,7 +1075,8 @@ out: return ret; } -static void vfio_listener_log_global_start(MemoryListener *listener) +static void vfio_listener_log_global_start(MemoryListener *listener, + Error **errp) { VFIOContainerBase *bcontainer = container_of(listener, VFIOContainerBase, listener); @@ -1094,7 +1095,8 @@ static void vfio_listener_log_global_start(MemoryListener *listener) } } -static void vfio_listener_log_global_stop(MemoryListener *listener) +static void vfio_listener_log_global_stop(MemoryListener *listener, + Error **errp) { VFIOContainerBase *bcontainer = container_of(listener, VFIOContainerBase, listener); diff --git a/hw/virtio/vhost.c b/hw/virtio/vhost.c index 2c9ac794680ea9b65eba6cc22e70cf141e90aa73..970f5951cc0b2113f91a3c640e27add5752b2944 100644 --- a/hw/virtio/vhost.c +++ b/hw/virtio/vhost.c @@ -104
[PATCH 02/14] migration: Add Error** argument to .load_setup() handler
This will be useful to report errors at a higher level, mostly in VFIO today. Signed-off-by: Cédric Le Goater --- include/migration/register.h | 2 +- hw/vfio/migration.c | 2 +- migration/ram.c | 2 +- migration/savevm.c | 10 ++ 4 files changed, 9 insertions(+), 7 deletions(-) diff --git a/include/migration/register.h b/include/migration/register.h index 831600a00eae4efd0464b60925d65de4d9dbcff8..e6bc226c98b27c1fb0f9e2b56d8aff491aa14d65 100644 --- a/include/migration/register.h +++ b/include/migration/register.h @@ -72,7 +72,7 @@ typedef struct SaveVMHandlers { void (*state_pending_exact)(void *opaque, uint64_t *must_precopy, uint64_t *can_postcopy); LoadStateHandler *load_state; -int (*load_setup)(QEMUFile *f, void *opaque); +int (*load_setup)(QEMUFile *f, void *opaque, Error **errp); int (*load_cleanup)(void *opaque); /* Called when postcopy migration wants to resume from failure */ int (*resume_prepare)(MigrationState *s, void *opaque); diff --git a/hw/vfio/migration.c b/hw/vfio/migration.c index 8bcb4bc73cd5ba5338e3ffa4d907d0e6bfbb9485..2dfbe671f6f45aa530c7341177bb532d8292cecd 100644 --- a/hw/vfio/migration.c +++ b/hw/vfio/migration.c @@ -580,7 +580,7 @@ static void vfio_save_state(QEMUFile *f, void *opaque) } } -static int vfio_load_setup(QEMUFile *f, void *opaque) +static int vfio_load_setup(QEMUFile *f, void *opaque, Error **errp) { VFIODevice *vbasedev = opaque; diff --git a/migration/ram.c b/migration/ram.c index 136c237f4079f68d4e578cf1c72eec2efc815bc8..8dac9bac2fe8b8c19e102c771a7ef6e976252906 100644 --- a/migration/ram.c +++ b/migration/ram.c @@ -3498,7 +3498,7 @@ void colo_release_ram_cache(void) * @f: QEMUFile where to receive the data * @opaque: RAMState pointer */ -static int ram_load_setup(QEMUFile *f, void *opaque) +static int ram_load_setup(QEMUFile *f, void *opaque, Error **errp) { xbzrle_load_setup(); ramblock_recv_map_init(); diff --git a/migration/savevm.c b/migration/savevm.c index f2ae799bad13e631bccf733a34c3a8fd22e8dd48..990f4249a26d28117ee365d8b20fc5bbca0d43d6 100644 --- a/migration/savevm.c +++ b/migration/savevm.c @@ -2737,7 +2737,7 @@ static void qemu_loadvm_state_switchover_ack_needed(MigrationIncomingState *mis) trace_loadvm_state_switchover_ack_needed(mis->switchover_ack_pending_num); } -static int qemu_loadvm_state_setup(QEMUFile *f) +static int qemu_loadvm_state_setup(QEMUFile *f, Error **errp) { SaveStateEntry *se; int ret; @@ -2753,10 +2753,11 @@ static int qemu_loadvm_state_setup(QEMUFile *f) } } -ret = se->ops->load_setup(f, se->opaque); +ret = se->ops->load_setup(f, se->opaque, errp); if (ret < 0) { +error_prepend(errp, "Load state of device %s failed: ", + se->idstr); qemu_file_set_error(f, ret); -error_report("Load state of device %s failed", se->idstr); return ret; } } @@ -2937,7 +2938,8 @@ int qemu_loadvm_state(QEMUFile *f) return ret; } -if (qemu_loadvm_state_setup(f) != 0) { +if (qemu_loadvm_state_setup(f, _err) != 0) { +error_report_err(local_err); return -EINVAL; } -- 2.43.0
Re: [PATCH v0 1/2] aspeed: support uart controller both 0 and 1 base
Hello Jmain, On 2/5/24 10:14, Jamin Lin wrote: According to the design of ASPEED SOCS, the uart controller is 1 base for ast10x0, ast2600, ast2500 and ast2400. Please rephrase saying somehting : the Aspeed datasheet refers to the UART controllers as UART1 - UART13 for the ast10x0, ast2600, ast2500 and ast2400 SoCs and the Aspeed ast2700 introduces an UART0. To keep the naming in the QEMU models in sync with the datasheet, let's introduce a new UART0 device name and do the required adjustements, etc ... However, the uart controller is 0 base for ast2700. To support uart controller both 0 and 1 base, adds uasrt_bases parameter in AspeedSoCClass and set the default uart controller 1 base for ast10x0, astt2600, ast2500 and ast2400. From datasheet description ast2700: Base Address of UART0 = 0x14c33000 ast1030: Base Address of UART1 = 0x7e783000 ast2600: Base Address of UART1 = 0x1E78 3000 ast2500: Base Address of UART1 = 0x1E78 3000 We should also introduce ASPEED_DEV_UART0 enum. See below. Signed-off-by: Troy Lee Signed-off-by: Jamin Lin --- hw/arm/aspeed.c | 8 +--- hw/arm/aspeed_ast10x0.c | 1 + hw/arm/aspeed_ast2400.c | 2 ++ hw/arm/aspeed_ast2600.c | 1 + hw/arm/aspeed_soc_common.c | 4 ++-- include/hw/arm/aspeed_soc.h | 1 + 6 files changed, 12 insertions(+), 5 deletions(-) diff --git a/hw/arm/aspeed.c b/hw/arm/aspeed.c index 09b1e823ba..218b81298e 100644 --- a/hw/arm/aspeed.c +++ b/hw/arm/aspeed.c @@ -342,7 +342,7 @@ static void connect_serial_hds_to_uarts(AspeedMachineState *bmc) int uart_chosen = bmc->uart_chosen ? bmc->uart_chosen : amc->uart_default; aspeed_soc_uart_set_chr(s, uart_chosen, serial_hd(0)); -for (int i = 1, uart = ASPEED_DEV_UART1; i < sc->uarts_num; i++, uart++) { +for (int i = 1, uart = sc->uarts_base; i < sc->uarts_num; i++, uart++) { if (uart == uart_chosen) { continue; } @@ -1092,9 +1092,11 @@ static char *aspeed_get_bmc_console(Object *obj, Error **errp) { AspeedMachineState *bmc = ASPEED_MACHINE(obj); AspeedMachineClass *amc = ASPEED_MACHINE_GET_CLASS(bmc); +AspeedSoCClass *sc = ASPEED_SOC_CLASS(obj); + int uart_chosen = bmc->uart_chosen ? bmc->uart_chosen : amc->uart_default; -return g_strdup_printf("uart%d", uart_chosen - ASPEED_DEV_UART1 + 1); +return g_strdup_printf("uart%d", uart_chosen - sc->uarts_base + 1); Wwe didn't have a ASPEED_DEV_UART0 at the time. The calculation above should be replaced with : "uart_chosen - ASPEED_DEV_UART0" } static void aspeed_set_bmc_console(Object *obj, const char *value, Error **errp) @@ -1114,7 +1116,7 @@ static void aspeed_set_bmc_console(Object *obj, const char *value, Error **errp) error_setg(errp, "\"uart\" should be in range [1 - %d]", sc->uarts_num); The range in the reported error above needs a fix. It's not "1" anymore but "sc->uarts_base - ASPEED_DEV_UART0". Same for the test : if (val < 1 || val > sc->uarts_num) { return; } -bmc->uart_chosen = ASPEED_DEV_UART1 + val - 1; +bmc->uart_chosen = sc->uarts_base + val - 1; Should be ASPEED_DEV_UART0 + val. Thanks, C. } static void aspeed_machine_class_props_init(ObjectClass *oc) diff --git a/hw/arm/aspeed_ast10x0.c b/hw/arm/aspeed_ast10x0.c index c3b5116a6a..2634e0f654 100644 --- a/hw/arm/aspeed_ast10x0.c +++ b/hw/arm/aspeed_ast10x0.c @@ -436,6 +436,7 @@ static void aspeed_soc_ast1030_class_init(ObjectClass *klass, void *data) sc->wdts_num = 4; sc->macs_num = 1; sc->uarts_num = 13; +sc->uarts_base = ASPEED_DEV_UART1; sc->irqmap = aspeed_soc_ast1030_irqmap; sc->memmap = aspeed_soc_ast1030_memmap; sc->num_cpus = 1; diff --git a/hw/arm/aspeed_ast2400.c b/hw/arm/aspeed_ast2400.c index 8829561bb6..95da85fee0 100644 --- a/hw/arm/aspeed_ast2400.c +++ b/hw/arm/aspeed_ast2400.c @@ -523,6 +523,7 @@ static void aspeed_soc_ast2400_class_init(ObjectClass *oc, void *data) sc->wdts_num = 2; sc->macs_num = 2; sc->uarts_num= 5; +sc->uarts_base = ASPEED_DEV_UART1; sc->irqmap = aspeed_soc_ast2400_irqmap; sc->memmap = aspeed_soc_ast2400_memmap; sc->num_cpus = 1; @@ -551,6 +552,7 @@ static void aspeed_soc_ast2500_class_init(ObjectClass *oc, void *data) sc->wdts_num = 3; sc->macs_num = 2; sc->uarts_num= 5; +sc->uarts_base = ASPEED_DEV_UART1; sc->irqmap = aspeed_soc_ast2500_irqmap; sc->memmap = aspeed_soc_ast2500_memmap; sc->num_cpus = 1; diff --git a/hw/arm/aspeed_ast2600.c b/hw/arm/aspeed_ast2600.c index 4ee32ea99d..f74561ecdc 100644 --- a/hw/arm/aspeed_ast2600.c +++ b/hw/arm/aspeed_ast2600.c @@ -666,6 +666,7 @@ static void aspeed_soc_ast2600_class_init(ObjectClass *oc, void *data) sc->wdts_num = 4; sc->macs_num = 4; sc->uarts_num= 13; +sc->uarts_base =
Re: [PATCH v0 1/2] aspeed: support uart controller both 0 and 1 base
On 2/6/24 04:29, Jamin Lin wrote: -Original Message- The uart definitions on the AST2700 are different : https://github.com/AspeedTech-BMC/linux/blob/aspeed-master-v6.6/arch/arm 64/boot/dts/aspeed/aspeed-g7.dtsi serial0 = serial1 = serial2 = serial3 = serial4 = serial5 = serial6 = serial7 = serial8 = ... I think the names in the DT (and consequently in the QEMU models) follow the IP names in the datasheet. I don't think we care in QEMU, so I would be inclined to change the indexing of the device names in QEMU and start at 0, which would introduce a discrepancy for the AST2400, AST2600, AST2600 SoC. Let's see what the other maintainers have to say. Thanks, C. Hi Cedric, Did you mean to change the naming of uart device to 0 base for all ASPEED SOCs? If yes, it seems we need to do the following changes. 1. add ASPEED_DEV_UART0 in aspeed_soc.h 2. Re-defined uart memory map for ast2600, ast10x0, ast2500 and ast2400(uart0 -> ASPEED_DEV_UART0) Take ast2600 for example: static const hwaddr aspeed_soc_ast2600_memmap[] = { [ASPEED_DEV_UART1] = 0x1E783000, ---> [ASPEED_DEV_UART0] [ASPEED_DEV_UART2] = 0x1E78D000, ---> [ASPEED_DEV_UART1] [ASPEED_DEV_UART3] = 0x1E78E000, [ASPEED_DEV_UART4] = 0x1E78F000, [ASPEED_DEV_UART5] = 0x1E784000, [ASPEED_DEV_UART6] = 0x1E79, [ASPEED_DEV_UART7] = 0x1E790100, [ASPEED_DEV_UART8] = 0x1E790200, [ASPEED_DEV_UART9] = 0x1E790300, [ASPEED_DEV_UART10]= 0x1E790400, [ASPEED_DEV_UART11]= 0x1E790500, [ASPEED_DEV_UART12]= 0x1E790600, [ASPEED_DEV_UART13]= 0x1E790700, ---> [ASPEED_DEV_UART12] }; If no, could you please descript it more detail? So, I can change it and re-send this patch series. Let's keep the datasheet names. I had forgotten the reason initially and from an HW POV it makes sense to keep them in sync. I will add some more comments to the patch. By the way, I will send a new patch series to support AST2700 in two weeks. We encountered GIC issues. It seems that QEMU support GIC v3 but SPI did not support, yet. https://github.com/qemu/qemu/blob/master/hw/intc/arm_gicv3_dist.c#L383 https://github.com/AspeedTech-BMC/linux/blob/aspeed-master-v6.6/arch/arm64/boot/dts/aspeed/aspeed-g7.dtsi#L229 If you did any hacks or workarounds in the QEMU models, please keep them separate from the other patches so that we can discuss. It think that we can discuss it in a new AST2700 patch series. Sure. Thanks, C.
Re: [PATCH v0 2/2] aspeed: fix hardcode boot address 0
On 2/6/24 02:48, Jamin Lin wrote: -Original Message- From: Philippe Mathieu-Daudé Sent: Monday, February 5, 2024 9:20 PM To: Jamin Lin ; Cédric Le Goater ; Peter Maydell ; Andrew Jeffery ; Joel Stanley ; open list:ASPEED BMCs ; open list:All patches CC here Cc: Troy Lee Subject: Re: [PATCH v0 2/2] aspeed: fix hardcode boot address 0 Hi Jamin, On 5/2/24 10:14, Jamin Lin via wrote: In the previous design of QEMU model for ASPEED SOCs, it set the boot address at 0 which was the hardcode setting for ast10x0, ast2600, ast2500 and ast2400. According to the design of ast2700, it has bootmcu which is used for executing SPL and initialize DRAM, Out of curiosity, what architecture is this MCU? MCU is riscv-ibex and its architecture is riscv-32. then, CPUs(cortex-a35) execute u-boot, kernel and rofs. QEMU will only support CPU(coretax-a35) parts and the boot address is "0x4" for ast2700. OK, but I don't get how you get from here ... Our design make MCU execute SPL and copy u-boot image from SPI to DRAM at address 0x4 at SPL boot stage. However, QEMU will only support to emulate CPU sides (coretex-a35) for ast2700, The fby35 is an example of a machine with two ARM SoCs : ast1030-a1 and ast2600-a3. There is work in progress for heterogeneous QEMU machines and It might be possible to model RISC-V and ARM one day. that was why we want to change the boot address at 0x4 And use the following start command by QEMU. ./qemu-system-aarch64 -M ast2750-evb -nographic -m 8G \ -device loader,addr=0x4,file=${IMGDIR}/u-boot-nodtb.bin,force-raw=on \ -device loader,addr=$((0x4 + ${UBOOT_SIZE})),file=${IMGDIR}/u-boot.dtb,force-raw=on \ --- --- ok. Makes sense. By the way, I will send a new patch series to support ast2700 in two weeks and We set memory map for ast2700 as following. static const hwaddr aspeed_soc_ast2700_memmap[] = { [ASPEED_DEV_SPI_BOOT] = 0x4, [ASPEED_DEV_SRAM] = 0x1000, Excellent ! Thanks, C.
Re: [v0 0/2] uart base and hardcode boot address 0
On 2/5/24 10:14, Jamin Lin wrote: v0: usually we start at v1, so the next version would be a v2. Indexing again :) Thanks, C. 1. support uart controller both 0 and 1 base 2. fix hardcode boot address 0 Jamin Lin (2): aspeed: support uart controller both 0 and 1 base aspeed: fix hardcode boot address 0 hw/arm/aspeed.c | 12 hw/arm/aspeed_ast10x0.c | 1 + hw/arm/aspeed_ast2400.c | 2 ++ hw/arm/aspeed_ast2600.c | 1 + hw/arm/aspeed_soc_common.c | 4 ++-- include/hw/arm/aspeed_soc.h | 1 + 6 files changed, 15 insertions(+), 6 deletions(-)
Re: [PATCH v0 1/2] aspeed: support uart controller both 0 and 1 base
[ ... ] As you said, uart12 mapped ASPEED_DEV_UART13. The device naming will confuse users because the device name in qemu mismatch with ast2700 datasheet. That way why we want to add ASPEED_DEV_UART0 and set the memory map of AST2700 as following. static const hwaddr aspeed_soc_ast2700_memmap[] = { [ASPEED_DEV_UART0] = 0X14C33000, [ASPEED_DEV_UART1] = 0X14C33100, [ASPEED_DEV_UART2] = 0X14C33200, [ASPEED_DEV_UART3] = 0X14C33300, [ASPEED_DEV_UART4] = 0X12C1A000, [ASPEED_DEV_UART5] = 0X14C33400, [ASPEED_DEV_UART6] = 0X14C33500, [ASPEED_DEV_UART7] = 0X14C33600, [ASPEED_DEV_UART8] = 0X14C33700, [ASPEED_DEV_UART9] = 0X14C33800, [ASPEED_DEV_UART10]= 0X14C33900, [ASPEED_DEV_UART11]= 0X14C33A00, [ASPEED_DEV_UART12]= 0X14C33B00, So we would prefer to keep the QEMU IP names in sync with the datasheet, and in that case your proposal makes sense. A have a few comments that I will make on the patch. Thanks, C.
Re: [PATCH v0 1/2] aspeed: support uart controller both 0 and 1 base
On 2/5/24 11:46, Cédric Le Goater wrote: Hello Jamin, On 2/5/24 10:14, Jamin Lin wrote: According to the design of ASPEED SOCS, the uart controller is 1 base for ast10x0, ast2600, ast2500 and ast2400. However, the uart controller is 0 base for ast2700. To support uart controller both 0 and 1 base, adds uasrt_bases parameter in AspeedSoCClass and set the default uart controller 1 base for ast10x0, astt2600, ast2500 and ast2400. The board definition can set 'amc->uart_default' to choose a different default serial port for the console, or use the "bmc-console" machine option . Isn't it enough ? May be I am misunderstanding the need. To clarify, ASPEED_DEV_UART1 is in the first serial port on the boards. I think we chose to start the indexing at 1 because the Aspeed QEMU modeling began first with the UART model (console) and for simplicity, we copied the definitions of the device tree from Linux : serial0 = serial1 = serial2 = serial3 = serial4 = serial5 = The uart definitions on the AST2700 are different : https://github.com/AspeedTech-BMC/linux/blob/aspeed-master-v6.6/arch/arm64/boot/dts/aspeed/aspeed-g7.dtsi serial0 = serial1 = serial2 = serial3 = serial4 = serial5 = serial6 = serial7 = serial8 = ... I think the names in the DT (and consequently in the QEMU models) follow the IP names in the datasheet. I don't think we care in QEMU, so I would be inclined to change the indexing of the device names in QEMU and start at 0, which would introduce a discrepancy for the AST2400, AST2600, AST2600 SoC. Let's see what the other maintainers have to say. Thanks, C.
Re: [PATCH v0 2/2] aspeed: fix hardcode boot address 0
On 2/5/24 10:14, Jamin Lin wrote: In the previous design of QEMU model for ASPEED SOCs, it set the boot address at 0 which was the hardcode setting for ast10x0, ast2600, ast2500 and ast2400. According to the design of ast2700, it has bootmcu which is used for executing SPL and initialize DRAM, then, CPUs(cortex-a35) execute u-boot, kernel and rofs. QEMU will only support CPU(coretax-a35) parts and the boot address is "0x4" for ast2700. On the previous SoC, the ASPEED_DEV_SPI_BOOT region is an alias, at 0x0, to the FMC CE0 region, mapped at 0x2000. Is 0x4 (or 0x4000 ?) the address for FMC CE0 region on the ast2700 ? or an alias ? What is the cortex-a35 reset address ? It would help to also introduce a basic skeleton of the ast2700 SoC. Anyhow, this change makes sense. Could you please respin and also remove ASPEED_SOC_SPI_BOOT_ADDR. ? Thanks, C. Therefore, fixed hardcode boot address 0. Signed-off-by: Troy Lee Signed-off-by: Jamin Lin --- hw/arm/aspeed.c | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/hw/arm/aspeed.c b/hw/arm/aspeed.c index 218b81298e..82a92e8142 100644 --- a/hw/arm/aspeed.c +++ b/hw/arm/aspeed.c @@ -289,12 +289,14 @@ static void aspeed_install_boot_rom(AspeedMachineState *bmc, BlockBackend *blk, uint64_t rom_size) { AspeedSoCState *soc = bmc->soc; +AspeedSoCClass *sc = ASPEED_SOC_GET_CLASS(soc); memory_region_init_rom(>boot_rom, NULL, "aspeed.boot_rom", rom_size, _abort); memory_region_add_subregion_overlap(>spi_boot_container, 0, >boot_rom, 1); -write_boot_rom(blk, ASPEED_SOC_SPI_BOOT_ADDR, rom_size, _abort); +write_boot_rom(blk, sc->memmap[ASPEED_DEV_SPI_BOOT], + rom_size, _abort); } void aspeed_board_init_flashes(AspeedSMCState *s, const char *flashtype,
Re: [PATCH v0 1/2] aspeed: support uart controller both 0 and 1 base
Hello Jamin, On 2/5/24 10:14, Jamin Lin wrote: According to the design of ASPEED SOCS, the uart controller is 1 base for ast10x0, ast2600, ast2500 and ast2400. However, the uart controller is 0 base for ast2700. To support uart controller both 0 and 1 base, adds uasrt_bases parameter in AspeedSoCClass and set the default uart controller 1 base for ast10x0, astt2600, ast2500 and ast2400. The board definition can set 'amc->uart_default' to choose a different default serial port for the console, or use the "bmc-console" machine option . Isn't it enough ? May be I am misunderstanding the need. To clarify, ASPEED_DEV_UART1 is in the first serial port on the boards. I think we chose to start the indexing at 1 because the Aspeed QEMU modeling began first with the UART model (console) and for simplicity, we copied the definitions of the device tree from Linux : serial0 = serial1 = serial2 = serial3 = serial4 = serial5 = We replicated this indexing starting at 1 to nearly all device models : ASPEED_DEV_UART1 - 13 ASPEED_DEV_SPI1 -2 ASPEED_DEV_EHCI1 -2 ASPEED_DEV_TIMER1 - 8 ASPEED_DEV_ETH1 -4 ASPEED_DEV_MII1 - 4 ASPEED_DEV_JTAG0 - 1 <--- !! ASPEED_DEV_FSI1 - 2 I don't know what would be ASPEED_DEV_UART0 in this context. May be you could send a simplified AST2700 SoC model with definitions of a minimum address space and IRQ space ? Or you could change the indexing to start at 0 if you prefer. Just be careful with the aspeed_set/get_bmc_console routines it you choose to. Thanks, C. From datasheet description ast2700: Base Address of UART0 = 0x14c33000 ast1030: Base Address of UART1 = 0x7e783000 ast2600: Base Address of UART1 = 0x1E78 3000 ast2500: Base Address of UART1 = 0x1E78 3000 Signed-off-by: Troy Lee Signed-off-by: Jamin Lin --- hw/arm/aspeed.c | 8 +--- hw/arm/aspeed_ast10x0.c | 1 + hw/arm/aspeed_ast2400.c | 2 ++ hw/arm/aspeed_ast2600.c | 1 + hw/arm/aspeed_soc_common.c | 4 ++-- include/hw/arm/aspeed_soc.h | 1 + 6 files changed, 12 insertions(+), 5 deletions(-) diff --git a/hw/arm/aspeed.c b/hw/arm/aspeed.c index 09b1e823ba..218b81298e 100644 --- a/hw/arm/aspeed.c +++ b/hw/arm/aspeed.c @@ -342,7 +342,7 @@ static void connect_serial_hds_to_uarts(AspeedMachineState *bmc) int uart_chosen = bmc->uart_chosen ? bmc->uart_chosen : amc->uart_default; aspeed_soc_uart_set_chr(s, uart_chosen, serial_hd(0)); -for (int i = 1, uart = ASPEED_DEV_UART1; i < sc->uarts_num; i++, uart++) { +for (int i = 1, uart = sc->uarts_base; i < sc->uarts_num; i++, uart++) { if (uart == uart_chosen) { continue; } @@ -1092,9 +1092,11 @@ static char *aspeed_get_bmc_console(Object *obj, Error **errp) { AspeedMachineState *bmc = ASPEED_MACHINE(obj); AspeedMachineClass *amc = ASPEED_MACHINE_GET_CLASS(bmc); +AspeedSoCClass *sc = ASPEED_SOC_CLASS(obj); + int uart_chosen = bmc->uart_chosen ? bmc->uart_chosen : amc->uart_default; -return g_strdup_printf("uart%d", uart_chosen - ASPEED_DEV_UART1 + 1); +return g_strdup_printf("uart%d", uart_chosen - sc->uarts_base + 1); } static void aspeed_set_bmc_console(Object *obj, const char *value, Error **errp) @@ -1114,7 +1116,7 @@ static void aspeed_set_bmc_console(Object *obj, const char *value, Error **errp) error_setg(errp, "\"uart\" should be in range [1 - %d]", sc->uarts_num); return; } -bmc->uart_chosen = ASPEED_DEV_UART1 + val - 1; +bmc->uart_chosen = sc->uarts_base + val - 1; } static void aspeed_machine_class_props_init(ObjectClass *oc) diff --git a/hw/arm/aspeed_ast10x0.c b/hw/arm/aspeed_ast10x0.c index c3b5116a6a..2634e0f654 100644 --- a/hw/arm/aspeed_ast10x0.c +++ b/hw/arm/aspeed_ast10x0.c @@ -436,6 +436,7 @@ static void aspeed_soc_ast1030_class_init(ObjectClass *klass, void *data) sc->wdts_num = 4; sc->macs_num = 1; sc->uarts_num = 13; +sc->uarts_base = ASPEED_DEV_UART1; sc->irqmap = aspeed_soc_ast1030_irqmap; sc->memmap = aspeed_soc_ast1030_memmap; sc->num_cpus = 1; diff --git a/hw/arm/aspeed_ast2400.c b/hw/arm/aspeed_ast2400.c index 8829561bb6..95da85fee0 100644 --- a/hw/arm/aspeed_ast2400.c +++ b/hw/arm/aspeed_ast2400.c @@ -523,6 +523,7 @@ static void aspeed_soc_ast2400_class_init(ObjectClass *oc, void *data) sc->wdts_num = 2; sc->macs_num = 2; sc->uarts_num= 5; +sc->uarts_base = ASPEED_DEV_UART1; sc->irqmap = aspeed_soc_ast2400_irqmap; sc->memmap = aspeed_soc_ast2400_memmap; sc->num_cpus = 1; @@ -551,6 +552,7 @@ static void aspeed_soc_ast2500_class_init(ObjectClass *oc, void *data) sc->wdts_num = 3; sc->macs_num = 2; sc->uarts_num= 5; +sc->uarts_base = ASPEED_DEV_UART1; sc->irqmap = aspeed_soc_ast2500_irqmap; sc->memmap =
Re: [PATCH v2 1/3] virtio-iommu: Add an option to define the input range width
On 2/5/24 10:14, Cédric Le Goater wrote: On 2/1/24 17:32, Eric Auger wrote: aw-bits is a new option that allows to set the bit width of the input address range. This value will be used as a default for the device config input_range.end. By default it is set to 64 bits which is the current value. Signed-off-by: Eric Auger --- v1 -> v2: - Check the aw-bits value is within [32,64] --- include/hw/virtio/virtio-iommu.h | 1 + hw/virtio/virtio-iommu.c | 7 ++- 2 files changed, 7 insertions(+), 1 deletion(-) diff --git a/include/hw/virtio/virtio-iommu.h b/include/hw/virtio/virtio-iommu.h index 781ebaea8f..5fbe4677c2 100644 --- a/include/hw/virtio/virtio-iommu.h +++ b/include/hw/virtio/virtio-iommu.h @@ -66,6 +66,7 @@ struct VirtIOIOMMU { bool boot_bypass; Notifier machine_done; bool granule_frozen; + uint8_t aw_bits; }; #endif diff --git a/hw/virtio/virtio-iommu.c b/hw/virtio/virtio-iommu.c index ec2ba11d1d..7870bdbeee 100644 --- a/hw/virtio/virtio-iommu.c +++ b/hw/virtio/virtio-iommu.c @@ -1314,7 +1314,11 @@ static void virtio_iommu_device_realize(DeviceState *dev, Error **errp) */ s->config.bypass = s->boot_bypass; s->config.page_size_mask = qemu_real_host_page_mask(); - s->config.input_range.end = UINT64_MAX; + if (s->aw_bits < 32 || s->aw_bits > 64) { + error_setg(errp, "aw-bits must be within [32,64]"); + } + s->config.input_range.end = + s->aw_bits == 64 ? UINT64_MAX : BIT_ULL(s->aw_bits) - 1; This could be simplified : s->config.input_range.end = BIT_ULL(s->aw_bits) - 1; Forget that. We would need a int28. Thanks, C. Anyhow, Reviewed-by: Cédric Le Goater Thanks, C. s->config.domain_range.end = UINT32_MAX; s->config.probe_size = VIOMMU_PROBE_SIZE; @@ -1525,6 +1529,7 @@ static Property virtio_iommu_properties[] = { DEFINE_PROP_LINK("primary-bus", VirtIOIOMMU, primary_bus, TYPE_PCI_BUS, PCIBus *), DEFINE_PROP_BOOL("boot-bypass", VirtIOIOMMU, boot_bypass, true), + DEFINE_PROP_UINT8("aw-bits", VirtIOIOMMU, aw_bits, 64), DEFINE_PROP_END_OF_LIST(), };
Re: [PATCH 2/2] migration: Fix return-path thread exit
On 2/5/24 04:37, Peter Xu wrote: On Fri, Feb 02, 2024 at 12:11:09PM -0300, Fabiano Rosas wrote: Cédric Le Goater writes: On 2/2/24 15:42, Fabiano Rosas wrote: Cédric Le Goater writes: In case of error, close_return_path_on_source() can perform a shutdown to exit the return-path thread. However, in migrate_fd_cleanup(), 'to_dst_file' is closed before calling close_return_path_on_source() and the shutdown fails, leaving the source and destination waiting for an event to occur. At close_return_path_on_source, qemu_file_shutdown() and checking ms->to_dst_file are done under the qemu_file_lock, so how could migrate_fd_cleanup() have cleared the pointer but the ms->to_dst_file check have passed? This is not a locking issue, it's much simpler. migrate_fd_cleanup() clears the ms->to_dst_file pointer and closes the QEMUFile and then calls close_return_path_on_source() which then tries to use resources which are not available anymore. I'm missing something here. Which resources? I assume you're talking about this: WITH_QEMU_LOCK_GUARD(>qemu_file_lock) { if (ms->to_dst_file && ms->rp_state.from_dst_file && qemu_file_get_error(ms->to_dst_file)) { qemu_file_shutdown(ms->rp_state.from_dst_file); } } How do we get past the 'if (ms->to_dst_file)'? We don't; migrate_fd_cleanup() will release ms->to_dst_file, then call close_return_path_on_source(), found that to_dst_file==NULL and then skip the shutdown(). One other option might be that we do close_return_path_on_source() before the chunk of releasing to_dst_file. This "two qemufiles share the same ioc" issue had bitten us before IIRC, and the only concern of that workaround is we keep postponing resolution of the real issue, then we keep getting bitten by it.. Maybe we can wait a few days to see if Dan can join the conversation and if we can reach a consensus on a complete solution. Otherwise I think we can still work this around, but maybe that'll require a comment block explaining the bits after such movement. yes. The series should have been sent with an RFC. I changed PATCH 1 to use migrate_has_error() instead of qemu_file_get_error(ms->to_dst_file). I will keep PATCH 2 as it is for the time being and wait for more feedback. The prereq series adds an Error** argument to the .save_setup() and .log_global*() handlers. I should send this week. Thanks, C. Thanks,
Re: [PATCH v2 3/3] hw: Set virtio-iommu aw-bits default value on pc_q35_9.0 and arm virt
On 2/1/24 17:32, Eric Auger wrote: Currently the default input range can extend to 64 bits. On x86, when the virtio-iommu protects vfio devices, the physical iommu may support only 39 bits. Let's set the default to 39, as done for the intel-iommu. On ARM we set 48b as a default (matching SMMUv3 SMMU_IDR5.VAX == 0). We use hw_compat_8_2 to handle the compatibility for machines before 9.0 which used to have a virtio-iommu default input range of 64 bits. Of course if aw-bits is set from the command line, the default is overriden. Signed-off-by: Eric Auger --- v1 -> v2: - set aw-bits to 48b on ARM - use hw_compat_8_2 to handle the compat for older machines which used 64b as a default --- hw/arm/virt.c| 6 ++ hw/core/machine.c| 5 - hw/i386/pc.c | 6 ++ hw/virtio/virtio-iommu.c | 2 +- 4 files changed, 17 insertions(+), 2 deletions(-) diff --git a/hw/arm/virt.c b/hw/arm/virt.c index e6ead2c5c8..56539f2fc5 100644 --- a/hw/arm/virt.c +++ b/hw/arm/virt.c @@ -2718,10 +2718,16 @@ static void virt_machine_device_pre_plug_cb(HotplugHandler *hotplug_dev, } else if (object_dynamic_cast(OBJECT(dev), TYPE_VIRTIO_MD_PCI)) { virtio_md_pci_pre_plug(VIRTIO_MD_PCI(dev), MACHINE(hotplug_dev), errp); } else if (object_dynamic_cast(OBJECT(dev), TYPE_VIRTIO_IOMMU_PCI)) { +uint8_t aw_bits = object_property_get_uint(OBJECT(dev), + "aw-bits", NULL); object_property_get_uint() should not fail. Please use _abort. hwaddr db_start = 0, db_end = 0; QList *reserved_regions; char *resv_prop_str; +if (!aw_bits) { +qdev_prop_set_uint8(dev, "aw-bits", 48); +} + if (vms->iommu != VIRT_IOMMU_NONE) { error_setg(errp, "virt machine does not support multiple IOMMUs"); return; diff --git a/hw/core/machine.c b/hw/core/machine.c index fb5afdcae4..70ac96954c 100644 --- a/hw/core/machine.c +++ b/hw/core/machine.c @@ -30,9 +30,12 @@ #include "exec/confidential-guest-support.h" #include "hw/virtio/virtio-pci.h" #include "hw/virtio/virtio-net.h" +#include "hw/virtio/virtio-iommu.h" #include "audio/audio.h" -GlobalProperty hw_compat_8_2[] = {}; +GlobalProperty hw_compat_8_2[] = { +{ TYPE_VIRTIO_IOMMU_PCI, "aw-bits", "64" }, +}; const size_t hw_compat_8_2_len = G_N_ELEMENTS(hw_compat_8_2); GlobalProperty hw_compat_8_1[] = { diff --git a/hw/i386/pc.c b/hw/i386/pc.c index 803244e5cc..0e2bcb4840 100644 --- a/hw/i386/pc.c +++ b/hw/i386/pc.c @@ -1458,6 +1458,8 @@ static void pc_machine_device_pre_plug_cb(HotplugHandler *hotplug_dev, } else if (object_dynamic_cast(OBJECT(dev), TYPE_VIRTIO_MD_PCI)) { virtio_md_pci_pre_plug(VIRTIO_MD_PCI(dev), MACHINE(hotplug_dev), errp); } else if (object_dynamic_cast(OBJECT(dev), TYPE_VIRTIO_IOMMU_PCI)) { +uint8_t aw_bits = object_property_get_uint(OBJECT(dev), + "aw-bits", NULL); /* Declare the APIC range as the reserved MSI region */ char *resv_prop_str = g_strdup_printf("0xfee0:0xfeef:%d", VIRTIO_IOMMU_RESV_MEM_T_MSI); @@ -1466,6 +1468,10 @@ static void pc_machine_device_pre_plug_cb(HotplugHandler *hotplug_dev, qlist_append_str(reserved_regions, resv_prop_str); qdev_prop_set_array(dev, "reserved-regions", reserved_regions); +if (!aw_bits) { +qdev_prop_set_uint8(dev, "aw-bits", 39); May be use VTD_HOST_AW_39BIT instead of 39 ? This would make it easier to find uses of certain defaults values and would clarify that the default AW of virtio-iommu is set as intel-iommu. Thanks, C. +} + g_free(resv_prop_str); } diff --git a/hw/virtio/virtio-iommu.c b/hw/virtio/virtio-iommu.c index 7870bdbeee..c468e9b13b 100644 --- a/hw/virtio/virtio-iommu.c +++ b/hw/virtio/virtio-iommu.c @@ -1529,7 +1529,7 @@ static Property virtio_iommu_properties[] = { DEFINE_PROP_LINK("primary-bus", VirtIOIOMMU, primary_bus, TYPE_PCI_BUS, PCIBus *), DEFINE_PROP_BOOL("boot-bypass", VirtIOIOMMU, boot_bypass, true), -DEFINE_PROP_UINT8("aw-bits", VirtIOIOMMU, aw_bits, 64), +DEFINE_PROP_UINT8("aw-bits", VirtIOIOMMU, aw_bits, 0), DEFINE_PROP_END_OF_LIST(), };
Re: [PATCH v2 2/3] virtio-iommu: Trace domain range limits as unsigned int
On 2/1/24 17:32, Eric Auger wrote: Use %u format to trace domain_range limits. Signed-off-by: Eric Auger Reviewed-by: Cédric Le Goater Thanks, C. --- hw/virtio/trace-events | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/hw/virtio/trace-events b/hw/virtio/trace-events index 77905d1994..2350849fbd 100644 --- a/hw/virtio/trace-events +++ b/hw/virtio/trace-events @@ -111,7 +111,7 @@ virtio_iommu_device_reset(void) "reset!" virtio_iommu_system_reset(void) "system reset!" virtio_iommu_get_features(uint64_t features) "device supports features=0x%"PRIx64 virtio_iommu_device_status(uint8_t status) "driver status = %d" -virtio_iommu_get_config(uint64_t page_size_mask, uint64_t start, uint64_t end, uint32_t domain_start, uint32_t domain_end, uint32_t probe_size, uint8_t bypass) "page_size_mask=0x%"PRIx64" input range start=0x%"PRIx64" input range end=0x%"PRIx64" domain range start=%d domain range end=%d probe_size=0x%x bypass=0x%x" +virtio_iommu_get_config(uint64_t page_size_mask, uint64_t start, uint64_t end, uint32_t domain_start, uint32_t domain_end, uint32_t probe_size, uint8_t bypass) "page_size_mask=0x%"PRIx64" input range start=0x%"PRIx64" input range end=0x%"PRIx64" domain range start=%u domain range end=%u probe_size=0x%x bypass=0x%x" virtio_iommu_set_config(uint8_t bypass) "bypass=0x%x" virtio_iommu_attach(uint32_t domain_id, uint32_t ep_id) "domain=%d endpoint=%d" virtio_iommu_detach(uint32_t domain_id, uint32_t ep_id) "domain=%d endpoint=%d"
Re: [PATCH v2 1/3] virtio-iommu: Add an option to define the input range width
On 2/1/24 17:32, Eric Auger wrote: aw-bits is a new option that allows to set the bit width of the input address range. This value will be used as a default for the device config input_range.end. By default it is set to 64 bits which is the current value. Signed-off-by: Eric Auger --- v1 -> v2: - Check the aw-bits value is within [32,64] --- include/hw/virtio/virtio-iommu.h | 1 + hw/virtio/virtio-iommu.c | 7 ++- 2 files changed, 7 insertions(+), 1 deletion(-) diff --git a/include/hw/virtio/virtio-iommu.h b/include/hw/virtio/virtio-iommu.h index 781ebaea8f..5fbe4677c2 100644 --- a/include/hw/virtio/virtio-iommu.h +++ b/include/hw/virtio/virtio-iommu.h @@ -66,6 +66,7 @@ struct VirtIOIOMMU { bool boot_bypass; Notifier machine_done; bool granule_frozen; +uint8_t aw_bits; }; #endif diff --git a/hw/virtio/virtio-iommu.c b/hw/virtio/virtio-iommu.c index ec2ba11d1d..7870bdbeee 100644 --- a/hw/virtio/virtio-iommu.c +++ b/hw/virtio/virtio-iommu.c @@ -1314,7 +1314,11 @@ static void virtio_iommu_device_realize(DeviceState *dev, Error **errp) */ s->config.bypass = s->boot_bypass; s->config.page_size_mask = qemu_real_host_page_mask(); -s->config.input_range.end = UINT64_MAX; +if (s->aw_bits < 32 || s->aw_bits > 64) { +error_setg(errp, "aw-bits must be within [32,64]"); +} +s->config.input_range.end = +s->aw_bits == 64 ? UINT64_MAX : BIT_ULL(s->aw_bits) - 1; This could be simplified : s->config.input_range.end = BIT_ULL(s->aw_bits) - 1; Anyhow, Reviewed-by: Cédric Le Goater Thanks, C. s->config.domain_range.end = UINT32_MAX; s->config.probe_size = VIOMMU_PROBE_SIZE; @@ -1525,6 +1529,7 @@ static Property virtio_iommu_properties[] = { DEFINE_PROP_LINK("primary-bus", VirtIOIOMMU, primary_bus, TYPE_PCI_BUS, PCIBus *), DEFINE_PROP_BOOL("boot-bypass", VirtIOIOMMU, boot_bypass, true), +DEFINE_PROP_UINT8("aw-bits", VirtIOIOMMU, aw_bits, 64), DEFINE_PROP_END_OF_LIST(), };
Re: [PATCH 2/2] migration: Fix return-path thread exit
On 2/2/24 15:42, Fabiano Rosas wrote: Cédric Le Goater writes: In case of error, close_return_path_on_source() can perform a shutdown to exit the return-path thread. However, in migrate_fd_cleanup(), 'to_dst_file' is closed before calling close_return_path_on_source() and the shutdown fails, leaving the source and destination waiting for an event to occur. At close_return_path_on_source, qemu_file_shutdown() and checking ms->to_dst_file are done under the qemu_file_lock, so how could migrate_fd_cleanup() have cleared the pointer but the ms->to_dst_file check have passed? This is not a locking issue, it's much simpler. migrate_fd_cleanup() clears the ms->to_dst_file pointer and closes the QEMUFile and then calls close_return_path_on_source() which then tries to use resources which are not available anymore. Thanks, C. Close the file after calling close_return_path_on_source() so that the shutdown succeeds and the return-path thread exits. Signed-off-by: Cédric Le Goater --- migration/migration.c | 12 +--- 1 file changed, 5 insertions(+), 7 deletions(-) diff --git a/migration/migration.c b/migration/migration.c index 2c3362235c7651c11d581f3c3639571f1f9636ef..1e0b6acaedc272e8ce26ad40be2c42177f5fd14e 100644 --- a/migration/migration.c +++ b/migration/migration.c @@ -1314,6 +1314,7 @@ void migrate_set_state(int *state, int old_state, int new_state) static void migrate_fd_cleanup(MigrationState *s) { int file_error = 0; +QEMUFile *tmp = NULL; g_free(s->hostname); s->hostname = NULL; @@ -1323,8 +1324,6 @@ static void migrate_fd_cleanup(MigrationState *s) qemu_savevm_state_cleanup(); if (s->to_dst_file) { -QEMUFile *tmp; - trace_migrate_fd_cleanup(); bql_unlock(); if (s->migration_thread_running) { @@ -1344,15 +1343,14 @@ static void migrate_fd_cleanup(MigrationState *s) * critical section won't block for long. */ migration_ioc_unregister_yank_from_file(tmp); -qemu_fclose(tmp); } -/* - * We already cleaned up to_dst_file, so errors from the return - * path might be due to that, ignore them. - */ close_return_path_on_source(s, file_error); +if (tmp) { +qemu_fclose(tmp); +} + assert(!migration_is_active(s)); if (s->state == MIGRATION_STATUS_CANCELLING) {
Re: [PATCH 1/2] migration: Add a file_error argument to close_return_path_on_source()
On 2/2/24 15:30, Fabiano Rosas wrote: Cédric Le Goater writes: close_return_path_on_source() retrieves the migration error from the the QEMUFile '->to_dst_file' to know if a shutdown is required to exit the return-path thread. However, in migrate_fd_cleanup(), '->to_dst_file' is cleaned up before calling close_return_path_on_source() and the shutdown is never performed, leaving the source and destination waiting for an event to occur. Isn't this just missing qemu_file_shutdown() at migrate_fd_cleanup? if (s->to_dst_file) { ... migration_ioc_unregister_yank_from_file(tmp); + qemu_file_shutdown(tmp); qemu_fclose(tmp); } That would make the return-path thread exit indeed. It should not be necessary when there are no errors though and this is done outside of the close_return_path_on_source() helper. There could be side effects. I took into account Peter's comment and replaced the changes of PATCH 1 with : @@ -2372,8 +2372,7 @@ static bool close_return_path_on_source( * cause it to unblock if it's stuck waiting for the destination. */ WITH_QEMU_LOCK_GUARD(>qemu_file_lock) { -if (ms->to_dst_file && ms->rp_state.from_dst_file && -qemu_file_get_error(ms->to_dst_file)) { +if (migrate_has_error(ms) && ms->rp_state.from_dst_file) { qemu_file_shutdown(ms->rp_state.from_dst_file); } } Nevertheless, we need to qemu_file_shutdown() correctly the socket for this to work and the problem seems more complex than just moving code as I did in PATCH 2. Thanks, C.
Re: [PATCH 0/2] migration: Fix return-path thread exit
Hello Peter, Today, close_return_path_on_source() can perform a shutdown to exit the return-path thread if an error occured. However, migrate_fd_cleanup() does cleanups too early and the shutdown in close_return_path_on_source() fails, leaving the source and destination waiting for an event to occur. This little series tries to fix that. Comments welcome ! One thing I do agree is that relying on qemu_file_get_error(to_dst_file) in close_return_path_on_source() is weird: IMHO we have better way to detect "whether the migration has error" now, which is migrate_has_error(). ok. migrate_has_error() looks safe to use in that case. It works fine with all the prereq VFIO cleanups (that I didn't send yet) and errors in the setup of dirty tracking are reported correctly to the migration core subsystem. For this specific issue, I think one long standing issue that might be relevant is we have two QEMUFile (from_dst_file, to_dst_file) that share the same QIOChannel now. Logically the two QEMUFile should be able to be managed separately, say, close() of to_dst_file shouldn't affect the other. However I don't think it's the case now, as qemu_fclose(to_dst_file) will do qio_channel_close() already, which means there will be a side effect to the other QEMUFile that its backing IOC is already closed. Is this the issue we're facing? Yes. The socket is closed before calling close_return_path_on_source() and ms->rp_state.from_dst_file becomes invalid, the shutdown silently fails (we should maybe report error in qemu_file_shutdown()) and the return-path thread does not exits. IOW, the close() of to_dst_file will not properly kick the other thread who is blocked at reading from_dst_file, while the shutdown() will kick it out? Yes, that's how I understand the comment : /* * If this is a normal exit then the destination will send a SHUT * and the rp_thread will exit, however if there's an error we * need to cause it to exit. shutdown(2), if we have it, will * cause it to unblock if it's stuck waiting for the destination. */ If so, not sure whether we can somehow relay the real qio_channel_close() to until the last user releases it? IOW, conditionally close() the channel> in qio_channel_finalize(), if the channel is still open? Would that make sense? It's the first time that I look at this code :/ I can't tell. Here is the closing section : qemu_mutex_unlock(>qemu_file_lock); /* * Close the file handle without the lock to make sure the * critical section won't block for long. */ migration_ioc_unregister_yank_from_file(tmp); qemu_fclose(tmp); } Thanks, C.
[PATCH 2/2] migration: Fix return-path thread exit
In case of error, close_return_path_on_source() can perform a shutdown to exit the return-path thread. However, in migrate_fd_cleanup(), 'to_dst_file' is closed before calling close_return_path_on_source() and the shutdown fails, leaving the source and destination waiting for an event to occur. Close the file after calling close_return_path_on_source() so that the shutdown succeeds and the return-path thread exits. Signed-off-by: Cédric Le Goater --- migration/migration.c | 12 +--- 1 file changed, 5 insertions(+), 7 deletions(-) diff --git a/migration/migration.c b/migration/migration.c index 2c3362235c7651c11d581f3c3639571f1f9636ef..1e0b6acaedc272e8ce26ad40be2c42177f5fd14e 100644 --- a/migration/migration.c +++ b/migration/migration.c @@ -1314,6 +1314,7 @@ void migrate_set_state(int *state, int old_state, int new_state) static void migrate_fd_cleanup(MigrationState *s) { int file_error = 0; +QEMUFile *tmp = NULL; g_free(s->hostname); s->hostname = NULL; @@ -1323,8 +1324,6 @@ static void migrate_fd_cleanup(MigrationState *s) qemu_savevm_state_cleanup(); if (s->to_dst_file) { -QEMUFile *tmp; - trace_migrate_fd_cleanup(); bql_unlock(); if (s->migration_thread_running) { @@ -1344,15 +1343,14 @@ static void migrate_fd_cleanup(MigrationState *s) * critical section won't block for long. */ migration_ioc_unregister_yank_from_file(tmp); -qemu_fclose(tmp); } -/* - * We already cleaned up to_dst_file, so errors from the return - * path might be due to that, ignore them. - */ close_return_path_on_source(s, file_error); +if (tmp) { +qemu_fclose(tmp); +} + assert(!migration_is_active(s)); if (s->state == MIGRATION_STATUS_CANCELLING) { -- 2.43.0
[PATCH 1/2] migration: Add a file_error argument to close_return_path_on_source()
close_return_path_on_source() retrieves the migration error from the the QEMUFile '->to_dst_file' to know if a shutdown is required to exit the return-path thread. However, in migrate_fd_cleanup(), '->to_dst_file' is cleaned up before calling close_return_path_on_source() and the shutdown is never performed, leaving the source and destination waiting for an event to occur. Cache the file error in a temporary variable and pass it to close_return_path_on_source() to avoid relying on '->to_dst_file'. Signed-off-by: Cédric Le Goater --- migration/migration.c | 21 + 1 file changed, 13 insertions(+), 8 deletions(-) diff --git a/migration/migration.c b/migration/migration.c index d5f705ceef4c925589aa49335969672c0d761fa2..2c3362235c7651c11d581f3c3639571f1f9636ef 100644 --- a/migration/migration.c +++ b/migration/migration.c @@ -100,7 +100,7 @@ static int migration_maybe_pause(MigrationState *s, int *current_active_state, int new_state); static void migrate_fd_cancel(MigrationState *s); -static bool close_return_path_on_source(MigrationState *s); +static bool close_return_path_on_source(MigrationState *s, int eror); static void migration_downtime_start(MigrationState *s) { @@ -1313,6 +1313,8 @@ void migrate_set_state(int *state, int old_state, int new_state) static void migrate_fd_cleanup(MigrationState *s) { +int file_error = 0; + g_free(s->hostname); s->hostname = NULL; json_writer_free(s->vmdesc); @@ -1333,6 +1335,7 @@ static void migrate_fd_cleanup(MigrationState *s) multifd_save_cleanup(); qemu_mutex_lock(>qemu_file_lock); +file_error = qemu_file_get_error(s->to_dst_file); tmp = s->to_dst_file; s->to_dst_file = NULL; qemu_mutex_unlock(>qemu_file_lock); @@ -1348,7 +1351,7 @@ static void migrate_fd_cleanup(MigrationState *s) * We already cleaned up to_dst_file, so errors from the return * path might be due to that, ignore them. */ -close_return_path_on_source(s); +close_return_path_on_source(s, file_error); assert(!migration_is_active(s)); @@ -2357,7 +2360,7 @@ static int open_return_path_on_source(MigrationState *ms) } /* Return true if error detected, or false otherwise */ -static bool close_return_path_on_source(MigrationState *ms) +static bool close_return_path_on_source(MigrationState *ms, int file_error) { if (!ms->rp_state.rp_thread_created) { return false; @@ -2372,8 +2375,7 @@ static bool close_return_path_on_source(MigrationState *ms) * cause it to unblock if it's stuck waiting for the destination. */ WITH_QEMU_LOCK_GUARD(>qemu_file_lock) { -if (ms->to_dst_file && ms->rp_state.from_dst_file && -qemu_file_get_error(ms->to_dst_file)) { +if (file_error && ms->rp_state.from_dst_file) { qemu_file_shutdown(ms->rp_state.from_dst_file); } } @@ -2707,6 +2709,7 @@ static void migration_completion(MigrationState *s) { int ret = 0; int current_active_state = s->state; +int file_error = qemu_file_get_error(s->to_dst_file); if (s->state == MIGRATION_STATUS_ACTIVE) { ret = migration_completion_precopy(s, _active_state); @@ -2720,11 +2723,11 @@ static void migration_completion(MigrationState *s) goto fail; } -if (close_return_path_on_source(s)) { +if (close_return_path_on_source(s, file_error)) { goto fail; } -if (qemu_file_get_error(s->to_dst_file)) { +if (file_error) { trace_migration_completion_file_err(); goto fail; } @@ -2861,6 +2864,7 @@ static MigThrError postcopy_pause(MigrationState *s) while (true) { QEMUFile *file; +int file_error; /* * Current channel is possibly broken. Release it. Note that this is @@ -2874,6 +2878,7 @@ static MigThrError postcopy_pause(MigrationState *s) assert(s->to_dst_file); migration_ioc_unregister_yank_from_file(s->to_dst_file); qemu_mutex_lock(>qemu_file_lock); +file_error = qemu_file_get_error(s->to_dst_file); file = s->to_dst_file; s->to_dst_file = NULL; qemu_mutex_unlock(>qemu_file_lock); @@ -2886,7 +2891,7 @@ static MigThrError postcopy_pause(MigrationState *s) * path and just wait for the thread to finish. It will be * re-created when we resume. */ -close_return_path_on_source(s); +close_return_path_on_source(s, file_error); migrate_set_state(>state, s->state, MIGRATION_STATUS_POSTCOPY_PAUSED); -- 2.43.0
[PATCH 0/2] migration: Fix return-path thread exit
Hello, Today, close_return_path_on_source() can perform a shutdown to exit the return-path thread if an error occured. However, migrate_fd_cleanup() does cleanups too early and the shutdown in close_return_path_on_source() fails, leaving the source and destination waiting for an event to occur. This little series tries to fix that. Comments welcome ! Thanks, C. Cédric Le Goater (2): migration: Add a file_error argument to close_return_path_on_source() migration: Fix return-path thread exit migration/migration.c | 33 ++--- 1 file changed, 18 insertions(+), 15 deletions(-) -- 2.43.0
Re: [PATCH v4 22/47] hw/arm/aspeed: use qemu_configure_nic_device()
On 1/26/24 18:24, David Woodhouse wrote: From: David Woodhouse Signed-off-by: David Woodhouse Acked-by: Cédric Le Goater and Reviewed-by: Cédric Le Goater Thanks, C. --- hw/arm/aspeed.c | 9 - 1 file changed, 4 insertions(+), 5 deletions(-) diff --git a/hw/arm/aspeed.c b/hw/arm/aspeed.c index cc59176563..bed5e4f40b 100644 --- a/hw/arm/aspeed.c +++ b/hw/arm/aspeed.c @@ -356,7 +356,6 @@ static void aspeed_machine_init(MachineState *machine) AspeedMachineClass *amc = ASPEED_MACHINE_GET_CLASS(machine); AspeedSoCClass *sc; int i; -NICInfo *nd = _table[0]; bmc->soc = ASPEED_SOC(object_new(amc->soc_name)); object_property_add_child(OBJECT(machine), "soc", OBJECT(bmc->soc)); @@ -371,10 +370,10 @@ static void aspeed_machine_init(MachineState *machine) _fatal); for (i = 0; i < sc->macs_num; i++) { -if ((amc->macs_mask & (1 << i)) && nd->used) { -qemu_check_nic_model(nd, TYPE_FTGMAC100); -qdev_set_nic_properties(DEVICE(>soc->ftgmac100[i]), nd); -nd++; +if ((amc->macs_mask & (1 << i)) && +!qemu_configure_nic_device(DEVICE(>soc->ftgmac100[i]), + true, NULL)) { +break; /* No configs left; stop asking */ } }
[PULL 06/17] hw/arm/aspeed: Check for CPU types in machine_run_board_init()
From: Philippe Mathieu-Daudé Aspeed SoCs use a single CPU type (set as AspeedSoCClass::cpu_type). Convert it to a NULL-terminated array (of a single non-NULL element). Set MachineClass::valid_cpu_types[] to use the common machine code to provide hints when the requested CPU is invalid (see commit e702cbc19e ("machine: Improve is_cpu_type_supported()"). Reviewed-by: Cédric Le Goater Reviewed-by: Richard Henderson Reviewed-by: Gavin Shan Signed-off-by: Philippe Mathieu-Daudé Signed-off-by: Cédric Le Goater --- include/hw/arm/aspeed_soc.h | 3 ++- hw/arm/aspeed.c | 1 + hw/arm/aspeed_ast10x0.c | 6 +- hw/arm/aspeed_ast2400.c | 12 ++-- hw/arm/aspeed_ast2600.c | 6 +- hw/arm/aspeed_soc_common.c | 5 - 6 files changed, 27 insertions(+), 6 deletions(-) diff --git a/include/hw/arm/aspeed_soc.h b/include/hw/arm/aspeed_soc.h index a060a5991874..0db5a41e7170 100644 --- a/include/hw/arm/aspeed_soc.h +++ b/include/hw/arm/aspeed_soc.h @@ -128,7 +128,8 @@ struct AspeedSoCClass { DeviceClass parent_class; const char *name; -const char *cpu_type; +/** valid_cpu_types: NULL terminated array of a single CPU type. */ +const char * const *valid_cpu_types; uint32_t silicon_rev; uint64_t sram_size; uint64_t secsram_size; diff --git a/hw/arm/aspeed.c b/hw/arm/aspeed.c index d2d490a6d142..fc8355cdce14 100644 --- a/hw/arm/aspeed.c +++ b/hw/arm/aspeed.c @@ -1149,6 +1149,7 @@ static void aspeed_machine_class_init_cpus_defaults(MachineClass *mc) mc->default_cpus = sc->num_cpus; mc->min_cpus = sc->num_cpus; mc->max_cpus = sc->num_cpus; +mc->valid_cpu_types = sc->valid_cpu_types; } static void aspeed_machine_class_init(ObjectClass *oc, void *data) diff --git a/hw/arm/aspeed_ast10x0.c b/hw/arm/aspeed_ast10x0.c index dca601a3f9b6..c3b5116a6a9d 100644 --- a/hw/arm/aspeed_ast10x0.c +++ b/hw/arm/aspeed_ast10x0.c @@ -417,13 +417,17 @@ static void aspeed_soc_ast1030_realize(DeviceState *dev_soc, Error **errp) static void aspeed_soc_ast1030_class_init(ObjectClass *klass, void *data) { +static const char * const valid_cpu_types[] = { +ARM_CPU_TYPE_NAME("cortex-m4"), /* TODO cortex-m4f */ +NULL +}; DeviceClass *dc = DEVICE_CLASS(klass); AspeedSoCClass *sc = ASPEED_SOC_CLASS(dc); dc->realize = aspeed_soc_ast1030_realize; sc->name = "ast1030-a1"; -sc->cpu_type = ARM_CPU_TYPE_NAME("cortex-m4"); /* TODO cortex-m4f */ +sc->valid_cpu_types = valid_cpu_types; sc->silicon_rev = AST1030_A1_SILICON_REV; sc->sram_size = 0xc; sc->secsram_size = 0x4; /* 256 * KiB */ diff --git a/hw/arm/aspeed_ast2400.c b/hw/arm/aspeed_ast2400.c index 3baf95916d46..8829561bb6c2 100644 --- a/hw/arm/aspeed_ast2400.c +++ b/hw/arm/aspeed_ast2400.c @@ -503,6 +503,10 @@ static void aspeed_ast2400_soc_realize(DeviceState *dev, Error **errp) static void aspeed_soc_ast2400_class_init(ObjectClass *oc, void *data) { +static const char * const valid_cpu_types[] = { +ARM_CPU_TYPE_NAME("arm926"), +NULL +}; AspeedSoCClass *sc = ASPEED_SOC_CLASS(oc); DeviceClass *dc = DEVICE_CLASS(oc); @@ -511,7 +515,7 @@ static void aspeed_soc_ast2400_class_init(ObjectClass *oc, void *data) dc->user_creatable = false; sc->name = "ast2400-a1"; -sc->cpu_type = ARM_CPU_TYPE_NAME("arm926"); +sc->valid_cpu_types = valid_cpu_types; sc->silicon_rev = AST2400_A1_SILICON_REV; sc->sram_size= 0x8000; sc->spis_num = 1; @@ -527,6 +531,10 @@ static void aspeed_soc_ast2400_class_init(ObjectClass *oc, void *data) static void aspeed_soc_ast2500_class_init(ObjectClass *oc, void *data) { +static const char * const valid_cpu_types[] = { +ARM_CPU_TYPE_NAME("arm1176"), +NULL +}; AspeedSoCClass *sc = ASPEED_SOC_CLASS(oc); DeviceClass *dc = DEVICE_CLASS(oc); @@ -535,7 +543,7 @@ static void aspeed_soc_ast2500_class_init(ObjectClass *oc, void *data) dc->user_creatable = false; sc->name = "ast2500-a1"; -sc->cpu_type = ARM_CPU_TYPE_NAME("arm1176"); +sc->valid_cpu_types = valid_cpu_types; sc->silicon_rev = AST2500_A1_SILICON_REV; sc->sram_size= 0x9000; sc->spis_num = 2; diff --git a/hw/arm/aspeed_ast2600.c b/hw/arm/aspeed_ast2600.c index b264433cf095..46baba0e4195 100644 --- a/hw/arm/aspeed_ast2600.c +++ b/hw/arm/aspeed_ast2600.c @@ -629,13 +629,17 @@ static void aspeed_soc_ast2600_realize(DeviceState *dev, Error **errp) static void aspeed_soc_ast2600_class_init(ObjectClass *oc, void *data) { +static const char * const valid_cpu_types[] = { +ARM_CPU_TYPE_NAME("cortex-a7"), +NULL +}; DeviceClass *dc = DEVI
[PULL 11/17] hw/fsi: Introduce IBM's cfam
From: Ninad Palsule This is a part of patchset where IBM's Flexible Service Interface is introduced. The Common FRU Access Macro (CFAM), an address space containing various "engines" that drive accesses on busses internal and external to the POWER chip. Examples include the SBEFIFO and I2C masters. The engines hang off of an internal Local Bus (LBUS) which is described by the CFAM configuration block. Signed-off-by: Andrew Jeffery Signed-off-by: Ninad Palsule Reviewed-by: Cédric Le Goater [ clg: - moved object FSIScratchPad under FSICFAMState - moved FSIScratchPad code under cfam.c - introduced fsi_cfam_instance_init() - reworked fsi_cfam_realize() ] Signed-off-by: Cédric Le Goater --- include/hw/fsi/cfam.h | 34 + hw/fsi/cfam.c | 168 ++ hw/fsi/meson.build| 2 +- hw/fsi/trace-events | 5 ++ 4 files changed, 208 insertions(+), 1 deletion(-) create mode 100644 include/hw/fsi/cfam.h create mode 100644 hw/fsi/cfam.c diff --git a/include/hw/fsi/cfam.h b/include/hw/fsi/cfam.h new file mode 100644 index ..7abc3b287bef --- /dev/null +++ b/include/hw/fsi/cfam.h @@ -0,0 +1,34 @@ +/* + * SPDX-License-Identifier: GPL-2.0-or-later + * Copyright (C) 2024 IBM Corp. + * + * IBM Common FRU Access Macro + */ +#ifndef FSI_CFAM_H +#define FSI_CFAM_H + +#include "exec/memory.h" + +#include "hw/fsi/fsi.h" +#include "hw/fsi/lbus.h" + +#define TYPE_FSI_CFAM "cfam" +#define FSI_CFAM(obj) OBJECT_CHECK(FSICFAMState, (obj), TYPE_FSI_CFAM) + +/* P9-ism */ +#define CFAM_CONFIG_NR_REGS 0x28 + +typedef struct FSICFAMState { +/* < private > */ +FSISlaveState parent; + +/* CFAM config address space */ +MemoryRegion config_iomem; + +MemoryRegion mr; + +FSILBus lbus; +FSIScratchPad scratchpad; +} FSICFAMState; + +#endif /* FSI_CFAM_H */ diff --git a/hw/fsi/cfam.c b/hw/fsi/cfam.c new file mode 100644 index ..c62f0f78dee5 --- /dev/null +++ b/hw/fsi/cfam.c @@ -0,0 +1,168 @@ +/* + * SPDX-License-Identifier: GPL-2.0-or-later + * Copyright (C) 2024 IBM Corp. + * + * IBM Common FRU Access Macro + */ + +#include "qemu/osdep.h" +#include "qemu/units.h" + +#include "qapi/error.h" +#include "trace.h" + +#include "hw/fsi/cfam.h" +#include "hw/fsi/fsi.h" + +#include "hw/qdev-properties.h" + +#define ENGINE_CONFIG_NEXTBIT(31) +#define ENGINE_CONFIG_TYPE_PEEK (0x02 << 4) +#define ENGINE_CONFIG_TYPE_FSI(0x03 << 4) +#define ENGINE_CONFIG_TYPE_SCRATCHPAD (0x06 << 4) + +/* Valid, slots, version, type, crc */ +#define CFAM_CONFIG_REG(__VER, __TYPE, __CRC) \ +(ENGINE_CONFIG_NEXT | \ + 0x0001 | \ + (__VER) | \ + (__TYPE) | \ + (__CRC)) + +#define TO_REG(x) ((x) >> 2) + +#define CFAM_CONFIG_CHIP_IDTO_REG(0x00) +#define CFAM_CONFIG_PEEK_STATUSTO_REG(0x04) +#define CFAM_CONFIG_CHIP_ID_P9 0xc0022d15 +#define CFAM_CONFIG_CHIP_ID_BREAK 0xc0de + +static uint64_t fsi_cfam_config_read(void *opaque, hwaddr addr, unsigned size) +{ +trace_fsi_cfam_config_read(addr, size); + +switch (addr) { +case 0x00: +return CFAM_CONFIG_CHIP_ID_P9; +case 0x04: +return CFAM_CONFIG_REG(0x1000, ENGINE_CONFIG_TYPE_PEEK, 0xc); +case 0x08: +return CFAM_CONFIG_REG(0x5000, ENGINE_CONFIG_TYPE_FSI, 0xa); +case 0xc: +return CFAM_CONFIG_REG(0x1000, ENGINE_CONFIG_TYPE_SCRATCHPAD, 0x7); +default: +/* + * The config table contains different engines from 0xc onwards. + * The scratch pad is already added at address 0xc. We need to add + * future engines from address 0x10 onwards. Returning 0 as engine + * is not implemented. + */ +return 0; +} +} + +static void fsi_cfam_config_write(void *opaque, hwaddr addr, uint64_t data, + unsigned size) +{ +FSICFAMState *cfam = FSI_CFAM(opaque); + +trace_fsi_cfam_config_write(addr, size, data); + +switch (TO_REG(addr)) { +case CFAM_CONFIG_CHIP_ID: +case CFAM_CONFIG_PEEK_STATUS: +if (data == CFAM_CONFIG_CHIP_ID_BREAK) { +bus_cold_reset(BUS(>lbus)); +} +break; +default: +trace_fsi_cfam_config_write_noaddr(addr, size, data); +} +} + +static const struct MemoryRegionOps cfam_config_ops = { +.read = fsi_cfam_config_read, +.write = fsi_cfam_config_write, +.valid.max_access_size = 4, +.valid.min_access_size = 4, +.impl.max_access_size = 4, +.impl.min_access_size = 4, +.endianness = DEVICE_BIG_ENDIAN, +}; + +static uint64_t fsi_cfam_unimplemented_read(void *opaque, hwaddr addr, +unsign
[PULL 14/17] hw/arm: Hook up FSI module in AST2600
From: Ninad Palsule This patchset introduces IBM's Flexible Service Interface(FSI). Time for some fun with inter-processor buses. FSI allows a service processor access to the internal buses of a host POWER processor to perform configuration or debugging. FSI has long existed in POWER processes and so comes with some baggage, including how it has been integrated into the ASPEED SoC. Working backwards from the POWER processor, the fundamental pieces of interest for the implementation are: 1. The Common FRU Access Macro (CFAM), an address space containing various "engines" that drive accesses on buses internal and external to the POWER chip. Examples include the SBEFIFO and I2C masters. The engines hang off of an internal Local Bus (LBUS) which is described by the CFAM configuration block. 2. The FSI slave: The slave is the terminal point of the FSI bus for FSI symbols addressed to it. Slaves can be cascaded off of one another. The slave's configuration registers appear in address space of the CFAM to which it is attached. 3. The FSI master: A controller in the platform service processor (e.g. BMC) driving CFAM engine accesses into the POWER chip. At the hardware level FSI is a bit-based protocol supporting synchronous and DMA-driven accesses of engines in a CFAM. 4. The On-Chip Peripheral Bus (OPB): A low-speed bus typically found in POWER processors. This now makes an appearance in the ASPEED SoC due to tight integration of the FSI master IP with the OPB, mainly the existence of an MMIO-mapping of the CFAM address straight onto a sub-region of the OPB address space. 5. An APB-to-OPB bridge enabling access to the OPB from the ARM core in the AST2600. Hardware limitations prevent the OPB from being directly mapped into APB, so all accesses are indirect through the bridge. The implementation appears as following in the qemu device tree: (qemu) info qtree bus: main-system-bus type System ... dev: aspeed.apb2opb, id "" gpio-out "sysbus-irq" 1 mmio 1e79b000/1000 bus: opb.1 type opb dev: fsi.master, id "" bus: fsi.bus.1 type fsi.bus dev: cfam.config, id "" dev: cfam, id "" bus: fsi.lbus.1 type lbus dev: scratchpad, id "" address = 0 (0x0) bus: opb.0 type opb dev: fsi.master, id "" bus: fsi.bus.0 type fsi.bus dev: cfam.config, id "" dev: cfam, id "" bus: fsi.lbus.0 type lbus dev: scratchpad, id "" address = 0 (0x0) The LBUS is modelled to maintain the qdev bus hierarchy and to take advantage of the object model to automatically generate the CFAM configuration block. The configuration block presents engines in the order they are attached to the CFAM's LBUS. Engine implementations should subclass the LBusDevice and set the 'config' member of LBusDeviceClass to match the engine's type. CFAM designs offer a lot of flexibility, for instance it is possible for a CFAM to be simultaneously driven from multiple FSI links. The modeling is not so complete; it's assumed that each CFAM is attached to a single FSI slave (as a consequence the CFAM subclasses the FSI slave). As for FSI, its symbols and wire-protocol are not modelled at all. This is not necessary to get FSI off the ground thanks to the mapping of the CFAM address space onto the OPB address space - the models follow this directly and map the CFAM memory region into the OPB's memory region. Future work includes supporting more advanced accesses that drive the FSI master directly rather than indirectly via the CFAM mapping, which will require implementing the FSI state machine and methods for each of the FSI symbols on the slave. Further down the track we can also look at supporting the bitbanged SoftFSI drivers in Linux by extending the FSI slave model to resolve sequences of GPIO IRQs into FSI symbols, and calling the associated symbol method on the slave to map the access onto the CFAM. Testing: Tested by reading cfam config address 0 on rainier machine type. root@p10bmc:~# pdbg -a getcfam 0x0 p0: 0x0 = 0xc0022d15 Signed-off-by: Andrew Jeffery Signed-off-by: Ninad Palsule Reviewed-by: Philippe Mathieu-Daudé Reviewed-by: Cédric Le Goater Signed-off-by: Cédric Le Goater --- include/hw/arm/aspeed_soc.h | 4 hw/arm/aspeed_ast2600.c | 19 +++ 2 files changed, 23 insertions(+) diff --git a/include/hw/arm/aspeed_soc.h b/include/hw/arm/aspeed_soc.h index 0db5a41e7170..9d0af84a8cff 100644 --- a/include/hw/arm/aspeed_soc.h +++ b/include/hw/arm/aspeed_soc.h @@ -36,6 +36,7 @@ #include "hw/
[PULL 16/17] hw/fsi: Added FSI documentation
From: Ninad Palsule Documentation for IBM FSI model. Signed-off-by: Ninad Palsule Reviewed-by: Cédric Le Goater [ clg : - Removed source file list - Fixed aspeed machine reference ] Signed-off-by: Cédric Le Goater --- docs/specs/fsi.rst | 122 +++ docs/specs/index.rst | 1 + 2 files changed, 123 insertions(+) create mode 100644 docs/specs/fsi.rst diff --git a/docs/specs/fsi.rst b/docs/specs/fsi.rst new file mode 100644 index ..af8782253152 --- /dev/null +++ b/docs/specs/fsi.rst @@ -0,0 +1,122 @@ +== +IBM's Flexible Service Interface (FSI) +== + +The QEMU FSI emulation implements hardware interfaces between ASPEED SOC, FSI +master/slave and the end engine. + +FSI is a point-to-point two wire interface which is capable of supporting +distances of up to 4 meters. FSI interfaces have been used successfully for +many years in IBM servers to attach IBM Flexible Support Processors(FSP) to +CPUs and IBM ASICs. + +FSI allows a service processor access to the internal buses of a host POWER +processor to perform configuration or debugging. FSI has long existed in POWER +processes and so comes with some baggage, including how it has been integrated +into the ASPEED SoC. + +Working backwards from the POWER processor, the fundamental pieces of interest +for the implementation are: (see the `FSI specification`_ for more details) + +1. The Common FRU Access Macro (CFAM), an address space containing various + "engines" that drive accesses on buses internal and external to the POWER + chip. Examples include the SBEFIFO and I2C masters. The engines hang off of + an internal Local Bus (LBUS) which is described by the CFAM configuration + block. + +2. The FSI slave: The slave is the terminal point of the FSI bus for FSI + symbols addressed to it. Slaves can be cascaded off of one another. The + slave's configuration registers appear in address space of the CFAM to + which it is attached. + +3. The FSI master: A controller in the platform service processor (e.g. BMC) + driving CFAM engine accesses into the POWER chip. At the hardware level + FSI is a bit-based protocol supporting synchronous and DMA-driven accesses + of engines in a CFAM. + +4. The On-Chip Peripheral Bus (OPB): A low-speed bus typically found in POWER + processors. This now makes an appearance in the ASPEED SoC due to tight + integration of the FSI master IP with the OPB, mainly the existence of an + MMIO-mapping of the CFAM address straight onto a sub-region of the OPB + address space. + +5. An APB-to-OPB bridge enabling access to the OPB from the ARM core in the + AST2600. Hardware limitations prevent the OPB from being directly mapped + into APB, so all accesses are indirect through the bridge. + +The LBUS is modelled to maintain the qdev bus hierarchy and to take advantages +of the object model to automatically generate the CFAM configuration block. +The configuration block presents engines in the order they are attached to the +CFAM's LBUS. Engine implementations should subclass the LBusDevice and set the +'config' member of LBusDeviceClass to match the engine's type. + +CFAM designs offer a lot of flexibility, for instance it is possible for a +CFAM to be simultaneously driven from multiple FSI links. The modeling is not +so complete; it's assumed that each CFAM is attached to a single FSI slave (as +a consequence the CFAM subclasses the FSI slave). + +As for FSI, its symbols and wire-protocol are not modelled at all. This is not +necessary to get FSI off the ground thanks to the mapping of the CFAM address +space onto the OPB address space - the models follow this directly and map the +CFAM memory region into the OPB's memory region. + +The following commands start the ``rainier-bmc`` machine with built-in FSI +model. There are no model specific arguments. Please check this document to +learn more about Aspeed ``rainier-bmc`` machine: (:doc:`../../system/arm/aspeed`) + +.. code-block:: console + + qemu-system-arm -M rainier-bmc -nographic \ + -kernel fitImage-linux.bin \ + -dtb aspeed-bmc-ibm-rainier.dtb \ + -initrd obmc-phosphor-initramfs.rootfs.cpio.xz \ + -drive file=obmc-phosphor-image.rootfs.wic.qcow2,if=sd,index=2 \ + -append "rootwait console=ttyS4,115200n8 root=PARTLABEL=rofs-a" + +The implementation appears as following in the qemu device tree: + +.. code-block:: console + + (qemu) info qtree + bus: main-system-bus +type System +... +dev: aspeed.apb2opb, id "" + gpio-out "sysbus-irq" 1 + mmio 1e79b000/1000 + bus: opb.1 +type opb +dev: fsi.master, id "" + bus: fsi.bus.1 +type fsi.bus +dev: cfam.config, id "" +dev: cfam, id "" + bus: lbus.1 +type lbus +
[PULL 07/17] hw/fsi: Introduce IBM's Local bus
From: Ninad Palsule This is a part of patchset where IBM's Flexible Service Interface is introduced. The LBUS is modelled to maintain mapped memory for the devices. The memory is mapped after CFAM config, peek table and FSI slave registers. Signed-off-by: Andrew Jeffery Signed-off-by: Ninad Palsule Reviewed-by: Cédric Le Goater [ clg: - removed lbus_add_device() bc unused - removed lbus_create_device() bc used only once - removed "address" property - updated meson.build to build fsi dir - included an empty hw/fsi/trace-events ] Signed-off-by: Cédric Le Goater --- meson.build | 1 + hw/fsi/trace.h| 1 + include/hw/fsi/lbus.h | 32 hw/fsi/lbus.c | 43 +++ hw/Kconfig| 1 + hw/fsi/Kconfig| 2 ++ hw/fsi/meson.build| 1 + hw/fsi/trace-events | 0 hw/meson.build| 1 + 9 files changed, 82 insertions(+) create mode 100644 hw/fsi/trace.h create mode 100644 include/hw/fsi/lbus.h create mode 100644 hw/fsi/lbus.c create mode 100644 hw/fsi/Kconfig create mode 100644 hw/fsi/meson.build create mode 100644 hw/fsi/trace-events diff --git a/meson.build b/meson.build index 5ffa8c97166d..b5d6dc94a837 100644 --- a/meson.build +++ b/meson.build @@ -3289,6 +3289,7 @@ if have_system 'hw/char', 'hw/display', 'hw/dma', +'hw/fsi', 'hw/hyperv', 'hw/i2c', 'hw/i386', diff --git a/hw/fsi/trace.h b/hw/fsi/trace.h new file mode 100644 index ..ee67c7fb04da --- /dev/null +++ b/hw/fsi/trace.h @@ -0,0 +1 @@ +#include "trace/trace-hw_fsi.h" diff --git a/include/hw/fsi/lbus.h b/include/hw/fsi/lbus.h new file mode 100644 index ..e8a22e22a8fa --- /dev/null +++ b/include/hw/fsi/lbus.h @@ -0,0 +1,32 @@ +/* + * SPDX-License-Identifier: GPL-2.0-or-later + * Copyright (C) 2024 IBM Corp. + * + * IBM Local bus and connected device structures. + */ +#ifndef FSI_LBUS_H +#define FSI_LBUS_H + +#include "hw/qdev-core.h" +#include "qemu/units.h" +#include "exec/memory.h" + +#define TYPE_FSI_LBUS_DEVICE "fsi.lbus.device" +OBJECT_DECLARE_SIMPLE_TYPE(FSILBusDevice, FSI_LBUS_DEVICE) + +typedef struct FSILBusDevice { +DeviceState parent; + +MemoryRegion iomem; +} FSILBusDevice; + +#define TYPE_FSI_LBUS "fsi.lbus" +OBJECT_DECLARE_SIMPLE_TYPE(FSILBus, FSI_LBUS) + +typedef struct FSILBus { +BusState bus; + +MemoryRegion mr; +} FSILBus; + +#endif /* FSI_LBUS_H */ diff --git a/hw/fsi/lbus.c b/hw/fsi/lbus.c new file mode 100644 index ..44d2319087a8 --- /dev/null +++ b/hw/fsi/lbus.c @@ -0,0 +1,43 @@ +/* + * SPDX-License-Identifier: GPL-2.0-or-later + * Copyright (C) 2024 IBM Corp. + * + * IBM Local bus where FSI slaves are connected + */ + +#include "qemu/osdep.h" +#include "qapi/error.h" +#include "hw/fsi/lbus.h" + +#include "hw/qdev-properties.h" + +#include "trace.h" + +static void fsi_lbus_init(Object *o) +{ +FSILBus *lbus = FSI_LBUS(o); + +memory_region_init(>mr, OBJECT(lbus), TYPE_FSI_LBUS, 1 * MiB); +} + +static const TypeInfo fsi_lbus_info = { +.name = TYPE_FSI_LBUS, +.parent = TYPE_BUS, +.instance_init = fsi_lbus_init, +.instance_size = sizeof(FSILBus), +}; + +static const TypeInfo fsi_lbus_device_type_info = { +.name = TYPE_FSI_LBUS_DEVICE, +.parent = TYPE_DEVICE, +.instance_size = sizeof(FSILBusDevice), +.abstract = true, +}; + +static void fsi_lbus_register_types(void) +{ +type_register_static(_lbus_info); +type_register_static(_lbus_device_type_info); +} + +type_init(fsi_lbus_register_types); diff --git a/hw/Kconfig b/hw/Kconfig index 9ca7b38c31f1..2c00936c28e8 100644 --- a/hw/Kconfig +++ b/hw/Kconfig @@ -9,6 +9,7 @@ source core/Kconfig source cxl/Kconfig source display/Kconfig source dma/Kconfig +source fsi/Kconfig source gpio/Kconfig source hyperv/Kconfig source i2c/Kconfig diff --git a/hw/fsi/Kconfig b/hw/fsi/Kconfig new file mode 100644 index ..9c34a418d700 --- /dev/null +++ b/hw/fsi/Kconfig @@ -0,0 +1,2 @@ +config FSI +bool diff --git a/hw/fsi/meson.build b/hw/fsi/meson.build new file mode 100644 index ..93ba19dd0411 --- /dev/null +++ b/hw/fsi/meson.build @@ -0,0 +1 @@ +system_ss.add(when: 'CONFIG_FSI', if_true: files('lbus.c')) diff --git a/hw/fsi/trace-events b/hw/fsi/trace-events new file mode 100644 index ..e69de29bb2d1 diff --git a/hw/meson.build b/hw/meson.build index f01fac4617c9..463d70268304 100644 --- a/hw/meson.build +++ b/hw/meson.build @@ -44,6 +44,7 @@ subdir('virtio') subdir('watchdog') subdir('xen') subdir('xenpv') +subdir('fsi') subdir('alpha') subdir('arm') -- 2.43.0
[PULL 10/17] hw/fsi: Introduce IBM's fsi-slave model
From: Ninad Palsule This is a part of patchset where IBM's Flexible Service Interface is introduced. The FSI slave: The slave is the terminal point of the FSI bus for FSI symbols addressed to it. Slaves can be cascaded off of one another. The slave's configuration registers appear in address space of the CFAM to which it is attached. Signed-off-by: Andrew Jeffery Signed-off-by: Ninad Palsule Reviewed-by: Cédric Le Goater Signed-off-by: Cédric Le Goater --- include/hw/fsi/fsi.h | 18 ++ hw/fsi/fsi.c | 84 ++-- hw/fsi/trace-events | 2 ++ 3 files changed, 102 insertions(+), 2 deletions(-) diff --git a/include/hw/fsi/fsi.h b/include/hw/fsi/fsi.h index 50e8f5c888f1..e00f6ef078c8 100644 --- a/include/hw/fsi/fsi.h +++ b/include/hw/fsi/fsi.h @@ -7,7 +7,13 @@ #ifndef FSI_FSI_H #define FSI_FSI_H +#include "exec/memory.h" #include "hw/qdev-core.h" +#include "hw/fsi/lbus.h" +#include "qemu/bitops.h" + +/* Bitwise operations at the word level. */ +#define BE_GENMASK(hb, lb) MAKE_64BIT_MASK((lb), ((hb) - (lb) + 1)) #define TYPE_FSI_BUS "fsi.bus" OBJECT_DECLARE_SIMPLE_TYPE(FSIBus, FSI_BUS) @@ -16,4 +22,16 @@ typedef struct FSIBus { BusState bus; } FSIBus; +#define TYPE_FSI_SLAVE "fsi.slave" +OBJECT_DECLARE_SIMPLE_TYPE(FSISlaveState, FSI_SLAVE) + +#define FSI_SLAVE_CONTROL_NR_REGS ((0x40 >> 2) + 1) + +typedef struct FSISlaveState { +DeviceState parent; + +MemoryRegion iomem; +uint32_t regs[FSI_SLAVE_CONTROL_NR_REGS]; +} FSISlaveState; + #endif /* FSI_FSI_H */ diff --git a/hw/fsi/fsi.c b/hw/fsi/fsi.c index 60cb03f7a24e..9a5f4e616f16 100644 --- a/hw/fsi/fsi.c +++ b/hw/fsi/fsi.c @@ -5,18 +5,98 @@ * IBM Flexible Service Interface */ #include "qemu/osdep.h" +#include "qapi/error.h" +#include "qemu/log.h" +#include "trace.h" #include "hw/fsi/fsi.h" +#define TO_REG(x) ((x) >> 2) + static const TypeInfo fsi_bus_info = { .name = TYPE_FSI_BUS, .parent = TYPE_BUS, .instance_size = sizeof(FSIBus), }; -static void fsi_bus_register_types(void) +static uint64_t fsi_slave_read(void *opaque, hwaddr addr, unsigned size) +{ +FSISlaveState *s = FSI_SLAVE(opaque); +int reg = TO_REG(addr); + +trace_fsi_slave_read(addr, size); + +if (reg >= FSI_SLAVE_CONTROL_NR_REGS) { +qemu_log_mask(LOG_GUEST_ERROR, + "%s: Out of bounds read: 0x%"HWADDR_PRIx" for %u\n", + __func__, addr, size); +return 0; +} + +return s->regs[reg]; +} + +static void fsi_slave_write(void *opaque, hwaddr addr, uint64_t data, + unsigned size) +{ +FSISlaveState *s = FSI_SLAVE(opaque); +int reg = TO_REG(addr); + +trace_fsi_slave_write(addr, size, data); + +if (reg >= FSI_SLAVE_CONTROL_NR_REGS) { +qemu_log_mask(LOG_GUEST_ERROR, + "%s: Out of bounds write: 0x%"HWADDR_PRIx" for %u\n", + __func__, addr, size); +return; +} + +s->regs[reg] = data; +} + +static const struct MemoryRegionOps fsi_slave_ops = { +.read = fsi_slave_read, +.write = fsi_slave_write, +.endianness = DEVICE_BIG_ENDIAN, +}; + +static void fsi_slave_reset(DeviceState *dev) +{ +FSISlaveState *s = FSI_SLAVE(dev); + +/* Initialize registers */ +memset(s->regs, 0, sizeof(s->regs)); +} + +static void fsi_slave_init(Object *o) +{ +FSISlaveState *s = FSI_SLAVE(o); + +memory_region_init_io(>iomem, OBJECT(s), _slave_ops, + s, TYPE_FSI_SLAVE, 0x400); +} + +static void fsi_slave_class_init(ObjectClass *klass, void *data) +{ +DeviceClass *dc = DEVICE_CLASS(klass); + +dc->bus_type = TYPE_FSI_BUS; +dc->desc = "FSI Slave"; +dc->reset = fsi_slave_reset; +} + +static const TypeInfo fsi_slave_info = { +.name = TYPE_FSI_SLAVE, +.parent = TYPE_DEVICE, +.instance_init = fsi_slave_init, +.instance_size = sizeof(FSISlaveState), +.class_init = fsi_slave_class_init, +}; + +static void fsi_register_types(void) { type_register_static(_bus_info); +type_register_static(_slave_info); } -type_init(fsi_bus_register_types); +type_init(fsi_register_types); diff --git a/hw/fsi/trace-events b/hw/fsi/trace-events index c5753e27910a..8f29adb7df92 100644 --- a/hw/fsi/trace-events +++ b/hw/fsi/trace-events @@ -1,2 +1,4 @@ fsi_scratchpad_read(uint64_t addr, uint32_t size) "@0x%" PRIx64 " size=%d" fsi_scratchpad_write(uint64_t addr, uint32_t size, uint64_t data) "@0x%" PRIx64 " size=%d value=0x%"PRIx64 +fsi_slave_read(uint64_t addr, uint32_t size) "@0x%" PRIx64 " size=%d" +fsi_slave_write(uint64_t addr, uint32_t size, uint64_t data) "@0x%" PRIx64 " size=%d value=0x%"PRIx64 -- 2.43.0
[PULL 13/17] hw/fsi: Aspeed APB2OPB & On-chip peripheral bus
From: Ninad Palsule This is a part of patchset where IBM's Flexible Service Interface is introduced. An APB-to-OPB bridge enabling access to the OPB from the ARM core in the AST2600. Hardware limitations prevent the OPB from being directly mapped into APB, so all accesses are indirect through the bridge. The On-Chip Peripheral Bus (OPB): A low-speed bus typically found in POWER processors. This now makes an appearance in the ASPEED SoC due to tight integration of the FSI master IP with the OPB, mainly the existence of an MMIO-mapping of the CFAM address straight onto a sub-region of the OPB address space. Signed-off-by: Andrew Jeffery Signed-off-by: Ninad Palsule Reviewed-by: Cédric Le Goater [ clg: - moved FSIMasterState under AspeedAPB2OPBState - modified fsi_opb_fsi_master_address() and fsi_opb_opb2fsi_address() - instroduced fsi_aspeed_apb2opb_init() - reworked fsi_aspeed_apb2opb_realize() - removed FSIMasterState object and fsi_opb_realize() - simplified OPBus - introduced fsi_aspeed_apb2opb_rw to fix endianness issue ] Signed-off-by: Cédric Le Goater --- include/hw/fsi/aspeed_apb2opb.h | 46 hw/fsi/aspeed_apb2opb.c | 367 hw/arm/Kconfig | 1 + hw/fsi/Kconfig | 5 + hw/fsi/meson.build | 1 + hw/fsi/trace-events | 2 + 6 files changed, 422 insertions(+) create mode 100644 include/hw/fsi/aspeed_apb2opb.h create mode 100644 hw/fsi/aspeed_apb2opb.c diff --git a/include/hw/fsi/aspeed_apb2opb.h b/include/hw/fsi/aspeed_apb2opb.h new file mode 100644 index ..f6a2387abf28 --- /dev/null +++ b/include/hw/fsi/aspeed_apb2opb.h @@ -0,0 +1,46 @@ +/* + * SPDX-License-Identifier: GPL-2.0-or-later + * Copyright (C) 2024 IBM Corp. + * + * ASPEED APB2OPB Bridge + * IBM On-Chip Peripheral Bus + */ +#ifndef FSI_ASPEED_APB2OPB_H +#define FSI_ASPEED_APB2OPB_H + +#include "exec/memory.h" +#include "hw/fsi/fsi-master.h" +#include "hw/sysbus.h" + +#define TYPE_FSI_OPB "fsi.opb" + +#define TYPE_OP_BUS "opb" +OBJECT_DECLARE_SIMPLE_TYPE(OPBus, OP_BUS) + +typedef struct OPBus { +BusState bus; + +MemoryRegion mr; +AddressSpace as; +} OPBus; + +#define TYPE_ASPEED_APB2OPB "aspeed.apb2opb" +OBJECT_DECLARE_SIMPLE_TYPE(AspeedAPB2OPBState, ASPEED_APB2OPB) + +#define ASPEED_APB2OPB_NR_REGS ((0xe8 >> 2) + 1) + +#define ASPEED_FSI_NUM 2 + +typedef struct AspeedAPB2OPBState { +SysBusDevice parent_obj; + +MemoryRegion iomem; + +uint32_t regs[ASPEED_APB2OPB_NR_REGS]; +qemu_irq irq; + +OPBus opb[ASPEED_FSI_NUM]; +FSIMasterState fsi[ASPEED_FSI_NUM]; +} AspeedAPB2OPBState; + +#endif /* FSI_ASPEED_APB2OPB_H */ diff --git a/hw/fsi/aspeed_apb2opb.c b/hw/fsi/aspeed_apb2opb.c new file mode 100644 index ..ea50718b6a2b --- /dev/null +++ b/hw/fsi/aspeed_apb2opb.c @@ -0,0 +1,367 @@ +/* + * SPDX-License-Identifier: GPL-2.0-or-later + * Copyright (C) 2024 IBM Corp. + * + * ASPEED APB-OPB FSI interface + * IBM On-chip Peripheral Bus + */ + +#include "qemu/osdep.h" +#include "qemu/log.h" +#include "qom/object.h" +#include "qapi/error.h" +#include "trace.h" + +#include "hw/fsi/aspeed_apb2opb.h" +#include "hw/qdev-core.h" + +#define TO_REG(x) (x >> 2) + +#define APB2OPB_VERSIONTO_REG(0x00) +#define APB2OPB_TRIGGERTO_REG(0x04) + +#define APB2OPB_CONTROLTO_REG(0x08) +#define APB2OPB_CONTROL_OFF BE_GENMASK(31, 13) + +#define APB2OPB_OPB2FSITO_REG(0x0c) +#define APB2OPB_OPB2FSI_OFF BE_GENMASK(31, 22) + +#define APB2OPB_OPB0_SEL TO_REG(0x10) +#define APB2OPB_OPB1_SEL TO_REG(0x28) +#define APB2OPB_OPB_SEL_EN BIT(0) + +#define APB2OPB_OPB0_MODE TO_REG(0x14) +#define APB2OPB_OPB1_MODE TO_REG(0x2c) +#define APB2OPB_OPB_MODE_RD BIT(0) + +#define APB2OPB_OPB0_XFER TO_REG(0x18) +#define APB2OPB_OPB1_XFER TO_REG(0x30) +#define APB2OPB_OPB_XFER_FULLBIT(1) +#define APB2OPB_OPB_XFER_HALFBIT(0) + +#define APB2OPB_OPB0_ADDR TO_REG(0x1c) +#define APB2OPB_OPB0_WRITE_DATATO_REG(0x20) + +#define APB2OPB_OPB1_ADDR TO_REG(0x34) +#define APB2OPB_OPB1_WRITE_DATA TO_REG(0x38) + +#define APB2OPB_IRQ_STSTO_REG(0x48) +#define APB2OPB_IRQ_STS_OPB1_TX_ACK BIT(17) +#define APB2OPB_IRQ_STS_OPB0_TX_ACK BIT(16) + +#define APB2OPB_OPB0_WRITE_WORD_ENDIAN TO_REG(0x4c) +#define APB2OPB_OPB0_WRITE_WORD_ENDIAN_BE 0x0011101b +#define APB2OPB_OPB0_WRITE_BYTE_ENDIAN TO_REG(0x50) +#define APB2OPB_OPB0_WRITE_BYTE_ENDIAN_BE 0x0c330f3f +#define APB2OPB_OPB1_
[PULL 09/17] hw/fsi: Introduce IBM's FSI Bus
From: Ninad Palsule This is a part of patchset where FSI bus is introduced. The FSI bus is a simple bus where FSI master is attached. Signed-off-by: Andrew Jeffery Signed-off-by: Ninad Palsule Reviewed-by: Cédric Le Goater [ clg: - removed include/hw/fsi/engine-scratchpad.h and hw/fsi/engine-scratchpad.c - dropped FSI_SCRATCHPAD - included FSIBus definition - dropped hw/fsi/trace-events changes ] Signed-off-by: Cédric Le Goater --- include/hw/fsi/fsi.h | 19 +++ hw/fsi/fsi.c | 22 ++ hw/fsi/meson.build | 2 +- 3 files changed, 42 insertions(+), 1 deletion(-) create mode 100644 include/hw/fsi/fsi.h create mode 100644 hw/fsi/fsi.c diff --git a/include/hw/fsi/fsi.h b/include/hw/fsi/fsi.h new file mode 100644 index ..50e8f5c888f1 --- /dev/null +++ b/include/hw/fsi/fsi.h @@ -0,0 +1,19 @@ +/* + * SPDX-License-Identifier: GPL-2.0-or-later + * Copyright (C) 2024 IBM Corp. + * + * IBM Flexible Service Interface + */ +#ifndef FSI_FSI_H +#define FSI_FSI_H + +#include "hw/qdev-core.h" + +#define TYPE_FSI_BUS "fsi.bus" +OBJECT_DECLARE_SIMPLE_TYPE(FSIBus, FSI_BUS) + +typedef struct FSIBus { +BusState bus; +} FSIBus; + +#endif /* FSI_FSI_H */ diff --git a/hw/fsi/fsi.c b/hw/fsi/fsi.c new file mode 100644 index ..60cb03f7a24e --- /dev/null +++ b/hw/fsi/fsi.c @@ -0,0 +1,22 @@ +/* + * SPDX-License-Identifier: GPL-2.0-or-later + * Copyright (C) 2024 IBM Corp. + * + * IBM Flexible Service Interface + */ +#include "qemu/osdep.h" + +#include "hw/fsi/fsi.h" + +static const TypeInfo fsi_bus_info = { +.name = TYPE_FSI_BUS, +.parent = TYPE_BUS, +.instance_size = sizeof(FSIBus), +}; + +static void fsi_bus_register_types(void) +{ +type_register_static(_bus_info); +} + +type_init(fsi_bus_register_types); diff --git a/hw/fsi/meson.build b/hw/fsi/meson.build index 93ba19dd0411..574f5f928903 100644 --- a/hw/fsi/meson.build +++ b/hw/fsi/meson.build @@ -1 +1 @@ -system_ss.add(when: 'CONFIG_FSI', if_true: files('lbus.c')) +system_ss.add(when: 'CONFIG_FSI', if_true: files('lbus.c','fsi.c')) -- 2.43.0
[PULL v2 00/17] aspeed queue
The following changes since commit bd2e12310b18b51aefbf834e6d54989fd175976f: Merge tag 'qga-pull-2024-01-30' of https://github.com/kostyanf14/qemu into staging (2024-01-30 15:53:46 +) are available in the Git repository at: https://github.com/legoater/qemu/ tags/pull-aspeed-20240201 for you to fetch changes up to 649b8ed20543f1b7f7e3dd8fd409092639bb345e: hw/fsi: Update MAINTAINER list (2024-02-01 08:33:18 +0100) aspeed queue: * Update of buildroot images to 2023.11 (6.6.3 kernel) * Check of the valid CPU type supported by aspeed machines * Simplified models for the IBM's FSI bus and the Aspeed controller bridge Changes since v1: - Endianness fix - Renamed test file to match other filenames - Fixed file list in MAINTAINER Cédric Le Goater (1): tests/avocado/machine_aspeed.py: Update buildroot images to 2023.11 Ninad Palsule (11): hw/fsi: Introduce IBM's Local bus hw/fsi: Introduce IBM's scratchpad device hw/fsi: Introduce IBM's FSI Bus hw/fsi: Introduce IBM's fsi-slave model hw/fsi: Introduce IBM's cfam hw/fsi: Introduce IBM's FSI master hw/fsi: Aspeed APB2OPB & On-chip peripheral bus hw/arm: Hook up FSI module in AST2600 hw/fsi: Added qtest hw/fsi: Added FSI documentation hw/fsi: Update MAINTAINER list Philippe Mathieu-Daudé (5): hw/arm/aspeed: Remove dead code hw/arm/aspeed: Set default CPU count using aspeed_soc_num_cpus() hw/arm/aspeed: Init CPU defaults in a common helper hw/arm/aspeed: Introduce aspeed_soc_cpu_type() helper hw/arm/aspeed: Check for CPU types in machine_run_board_init() MAINTAINERS | 9 + docs/specs/fsi.rst | 122 + docs/specs/index.rst| 1 + meson.build | 1 + hw/fsi/trace.h | 1 + include/hw/arm/aspeed_soc.h | 8 +- include/hw/fsi/aspeed_apb2opb.h | 46 + include/hw/fsi/cfam.h | 34 include/hw/fsi/fsi-master.h | 32 include/hw/fsi/fsi.h| 37 include/hw/fsi/lbus.h | 43 + hw/arm/aspeed.c | 70 hw/arm/aspeed_ast10x0.c | 8 +- hw/arm/aspeed_ast2400.c | 15 +- hw/arm/aspeed_ast2600.c | 28 ++- hw/arm/aspeed_soc_common.c | 8 + hw/fsi/aspeed_apb2opb.c | 367 hw/fsi/cfam.c | 168 ++ hw/fsi/fsi-master.c | 170 +++ hw/fsi/fsi.c| 102 +++ hw/fsi/lbus.c | 117 + tests/qtest/aspeed_fsi-test.c | 205 ++ hw/Kconfig | 1 + hw/arm/Kconfig | 1 + hw/fsi/Kconfig | 7 + hw/fsi/meson.build | 2 + hw/fsi/trace-events | 13 ++ hw/meson.build | 1 + tests/avocado/machine_aspeed.py | 18 +- tests/qtest/meson.build | 1 + 30 files changed, 1578 insertions(+), 58 deletions(-) create mode 100644 docs/specs/fsi.rst create mode 100644 hw/fsi/trace.h create mode 100644 include/hw/fsi/aspeed_apb2opb.h create mode 100644 include/hw/fsi/cfam.h create mode 100644 include/hw/fsi/fsi-master.h create mode 100644 include/hw/fsi/fsi.h create mode 100644 include/hw/fsi/lbus.h create mode 100644 hw/fsi/aspeed_apb2opb.c create mode 100644 hw/fsi/cfam.c create mode 100644 hw/fsi/fsi-master.c create mode 100644 hw/fsi/fsi.c create mode 100644 hw/fsi/lbus.c create mode 100644 tests/qtest/aspeed_fsi-test.c create mode 100644 hw/fsi/Kconfig create mode 100644 hw/fsi/meson.build create mode 100644 hw/fsi/trace-events
[PULL 05/17] hw/arm/aspeed: Introduce aspeed_soc_cpu_type() helper
From: Philippe Mathieu-Daudé In order to alter AspeedSoCClass::cpu_type in the next commit, introduce the aspeed_soc_cpu_type() helper to retrieve the per-SoC CPU type from AspeedSoCClass. Signed-off-by: Philippe Mathieu-Daudé Reviewed-by: Cédric Le Goater Reviewed-by: Richard Henderson Reviewed-by: Gavin Shan Signed-off-by: Cédric Le Goater --- include/hw/arm/aspeed_soc.h | 1 + hw/arm/aspeed_ast10x0.c | 2 +- hw/arm/aspeed_ast2400.c | 3 ++- hw/arm/aspeed_ast2600.c | 3 ++- hw/arm/aspeed_soc_common.c | 5 + 5 files changed, 11 insertions(+), 3 deletions(-) diff --git a/include/hw/arm/aspeed_soc.h b/include/hw/arm/aspeed_soc.h index cb832bc1ee14..a060a5991874 100644 --- a/include/hw/arm/aspeed_soc.h +++ b/include/hw/arm/aspeed_soc.h @@ -143,6 +143,7 @@ struct AspeedSoCClass { qemu_irq (*get_irq)(AspeedSoCState *s, int dev); }; +const char *aspeed_soc_cpu_type(AspeedSoCClass *sc); enum { ASPEED_DEV_SPI_BOOT, diff --git a/hw/arm/aspeed_ast10x0.c b/hw/arm/aspeed_ast10x0.c index 8becb146a8df..dca601a3f9b6 100644 --- a/hw/arm/aspeed_ast10x0.c +++ b/hw/arm/aspeed_ast10x0.c @@ -211,7 +211,7 @@ static void aspeed_soc_ast1030_realize(DeviceState *dev_soc, Error **errp) /* AST1030 CPU Core */ armv7m = DEVICE(>armv7m); qdev_prop_set_uint32(armv7m, "num-irq", 256); -qdev_prop_set_string(armv7m, "cpu-type", sc->cpu_type); +qdev_prop_set_string(armv7m, "cpu-type", aspeed_soc_cpu_type(sc)); qdev_connect_clock_in(armv7m, "cpuclk", s->sysclk); object_property_set_link(OBJECT(>armv7m), "memory", OBJECT(s->memory), _abort); diff --git a/hw/arm/aspeed_ast2400.c b/hw/arm/aspeed_ast2400.c index ad76035528fd..3baf95916d46 100644 --- a/hw/arm/aspeed_ast2400.c +++ b/hw/arm/aspeed_ast2400.c @@ -156,7 +156,8 @@ static void aspeed_ast2400_soc_init(Object *obj) } for (i = 0; i < sc->num_cpus; i++) { -object_initialize_child(obj, "cpu[*]", >cpu[i], sc->cpu_type); +object_initialize_child(obj, "cpu[*]", >cpu[i], +aspeed_soc_cpu_type(sc)); } snprintf(typename, sizeof(typename), "aspeed.scu-%s", socname); diff --git a/hw/arm/aspeed_ast2600.c b/hw/arm/aspeed_ast2600.c index 386a88d4e0f9..b264433cf095 100644 --- a/hw/arm/aspeed_ast2600.c +++ b/hw/arm/aspeed_ast2600.c @@ -158,7 +158,8 @@ static void aspeed_soc_ast2600_init(Object *obj) } for (i = 0; i < sc->num_cpus; i++) { -object_initialize_child(obj, "cpu[*]", >cpu[i], sc->cpu_type); +object_initialize_child(obj, "cpu[*]", >cpu[i], +aspeed_soc_cpu_type(sc)); } snprintf(typename, sizeof(typename), "aspeed.scu-%s", socname); diff --git a/hw/arm/aspeed_soc_common.c b/hw/arm/aspeed_soc_common.c index 828f61093bfa..36ca189ce960 100644 --- a/hw/arm/aspeed_soc_common.c +++ b/hw/arm/aspeed_soc_common.c @@ -18,6 +18,11 @@ #include "hw/char/serial.h" +const char *aspeed_soc_cpu_type(AspeedSoCClass *sc) +{ +return sc->cpu_type; +} + qemu_irq aspeed_soc_get_irq(AspeedSoCState *s, int dev) { return ASPEED_SOC_GET_CLASS(s)->get_irq(s, dev); -- 2.43.0
[PULL 17/17] hw/fsi: Update MAINTAINER list
From: Ninad Palsule Add maintainer for IBM FSI model Signed-off-by: Ninad Palsule Reviewed-by: Cédric Le Goater [ clg: - slight change in commit log - fixed file list ] Signed-off-by: Cédric Le Goater --- MAINTAINERS | 9 + 1 file changed, 9 insertions(+) diff --git a/MAINTAINERS b/MAINTAINERS index dfaca8323e91..2f9741b898e8 100644 --- a/MAINTAINERS +++ b/MAINTAINERS @@ -3585,6 +3585,15 @@ F: tests/qtest/adm1272-test.c F: tests/qtest/max34451-test.c F: tests/qtest/isl_pmbus_vr-test.c +FSI +M: Ninad Palsule +R: Cédric Le Goater +S: Maintained +F: hw/fsi/* +F: include/hw/fsi/* +F: docs/specs/fsi.rst +F: tests/qtest/aspeed_fsi-test.c + Firmware schema specifications M: Philippe Mathieu-Daudé R: Daniel P. Berrange -- 2.43.0
[PULL 15/17] hw/fsi: Added qtest
From: Ninad Palsule Added basic qtests for FSI model. Signed-off-by: Ninad Palsule Acked-by: Thomas Huth [ clg: aspeed-fsi-test.c -> aspeed_fsi-test.c to match other filenames ] Signed-off-by: Cédric Le Goater --- tests/qtest/aspeed_fsi-test.c | 205 ++ tests/qtest/meson.build | 1 + 2 files changed, 206 insertions(+) create mode 100644 tests/qtest/aspeed_fsi-test.c diff --git a/tests/qtest/aspeed_fsi-test.c b/tests/qtest/aspeed_fsi-test.c new file mode 100644 index ..b3020dd82118 --- /dev/null +++ b/tests/qtest/aspeed_fsi-test.c @@ -0,0 +1,205 @@ +/* + * QTest testcases for IBM's Flexible Service Interface (FSI) + * + * Copyright (c) 2023 IBM Corporation + * + * Authors: + * Ninad Palsule + * + * This work is licensed under the terms of the GNU GPL, version 2 or later. + * See the COPYING file in the top-level directory. + */ + +#include "qemu/osdep.h" +#include + +#include "qemu/module.h" +#include "libqtest-single.h" + +/* Registers from ast2600 specifications */ +#define ASPEED_FSI_ENGINER_TRIGGER 0x04 +#define ASPEED_FSI_OPB0_BUS_SELECT 0x10 +#define ASPEED_FSI_OPB1_BUS_SELECT 0x28 +#define ASPEED_FSI_OPB0_RW_DIRECTION 0x14 +#define ASPEED_FSI_OPB1_RW_DIRECTION 0x2c +#define ASPEED_FSI_OPB0_XFER_SIZE0x18 +#define ASPEED_FSI_OPB1_XFER_SIZE0x30 +#define ASPEED_FSI_OPB0_BUS_ADDR 0x1c +#define ASPEED_FSI_OPB1_BUS_ADDR 0x34 +#define ASPEED_FSI_INTRRUPT_CLEAR0x40 +#define ASPEED_FSI_INTRRUPT_STATUS 0x48 +#define ASPEED_FSI_OPB0_BUS_STATUS 0x80 +#define ASPEED_FSI_OPB1_BUS_STATUS 0x8c +#define ASPEED_FSI_OPB0_READ_DATA0x84 +#define ASPEED_FSI_OPB1_READ_DATA0x90 + +/* + * FSI Base addresses from the ast2600 specifications. + */ +#define AST2600_OPB_FSI0_BASE_ADDR 0x1e79b000 +#define AST2600_OPB_FSI1_BASE_ADDR 0x1e79b100 + +static uint32_t aspeed_fsi_base_addr; + +static uint32_t aspeed_fsi_readl(QTestState *s, uint32_t reg) +{ +return qtest_readl(s, aspeed_fsi_base_addr + reg); +} + +static void aspeed_fsi_writel(QTestState *s, uint32_t reg, uint32_t val) +{ +qtest_writel(s, aspeed_fsi_base_addr + reg, val); +} + +/* Setup base address and select register */ +static void test_fsi_setup(QTestState *s, uint32_t base_addr) +{ +uint32_t curval; + +aspeed_fsi_base_addr = base_addr; + +/* Set the base select register */ +if (base_addr == AST2600_OPB_FSI0_BASE_ADDR) { +/* Unselect FSI1 */ +aspeed_fsi_writel(s, ASPEED_FSI_OPB1_BUS_SELECT, 0x0); +curval = aspeed_fsi_readl(s, ASPEED_FSI_OPB1_BUS_SELECT); +g_assert_cmpuint(curval, ==, 0x0); + +/* Select FSI0 */ +aspeed_fsi_writel(s, ASPEED_FSI_OPB0_BUS_SELECT, 0x1); +curval = aspeed_fsi_readl(s, ASPEED_FSI_OPB0_BUS_SELECT); +g_assert_cmpuint(curval, ==, 0x1); +} else if (base_addr == AST2600_OPB_FSI1_BASE_ADDR) { +/* Unselect FSI0 */ +aspeed_fsi_writel(s, ASPEED_FSI_OPB0_BUS_SELECT, 0x0); +curval = aspeed_fsi_readl(s, ASPEED_FSI_OPB0_BUS_SELECT); +g_assert_cmpuint(curval, ==, 0x0); + +/* Select FSI1 */ +aspeed_fsi_writel(s, ASPEED_FSI_OPB1_BUS_SELECT, 0x1); +curval = aspeed_fsi_readl(s, ASPEED_FSI_OPB1_BUS_SELECT); +g_assert_cmpuint(curval, ==, 0x1); +} else { +g_assert_not_reached(); +} +} + +static void test_fsi_reg_change(QTestState *s, uint32_t reg, uint32_t newval) +{ +uint32_t base; +uint32_t curval; + +base = aspeed_fsi_readl(s, reg); +aspeed_fsi_writel(s, reg, newval); +curval = aspeed_fsi_readl(s, reg); +g_assert_cmpuint(curval, ==, newval); +aspeed_fsi_writel(s, reg, base); +curval = aspeed_fsi_readl(s, reg); +g_assert_cmpuint(curval, ==, base); +} + +static void test_fsi0_master_regs(const void *data) +{ +QTestState *s = (QTestState *)data; + +test_fsi_setup(s, AST2600_OPB_FSI0_BASE_ADDR); + +test_fsi_reg_change(s, ASPEED_FSI_OPB0_RW_DIRECTION, 0xF3F4F514); +test_fsi_reg_change(s, ASPEED_FSI_OPB0_XFER_SIZE, 0xF3F4F518); +test_fsi_reg_change(s, ASPEED_FSI_OPB0_BUS_ADDR, 0xF3F4F51c); +test_fsi_reg_change(s, ASPEED_FSI_INTRRUPT_CLEAR, 0xF3F4F540); +test_fsi_reg_change(s, ASPEED_FSI_INTRRUPT_STATUS, 0xF3F4F548); +test_fsi_reg_change(s, ASPEED_FSI_OPB0_BUS_STATUS, 0xF3F4F580); +test_fsi_reg_change(s, ASPEED_FSI_OPB0_READ_DATA, 0xF3F4F584); +} + +static void test_fsi1_master_regs(const void *data) +{ +QTestState *s = (QTestState *)data; + +test_fsi_setup(s, AST2600_OPB_FSI1_BASE_ADDR); + +test_fsi_reg_change(s, ASPEED_FSI_OPB1_RW_DIRECTION, 0xF3F4F514); +test_fsi_reg_change(s, ASPEED_FSI_OPB1_XFER_SIZE, 0xF3F4F518); +test_fsi_reg_change(s, ASPEED_FSI_OPB1_BUS_ADDR, 0xF3F4F51c); +test_fsi_reg_change(s, ASPEED_FSI_INTRRUPT_CLEAR, 0xF3F4F540); +test_fsi_reg_change(s, ASPEED_FSI_INTRRUPT_STATUS, 0xF3F4F548); +test_fsi_reg_change(s, ASPEE
[PULL 12/17] hw/fsi: Introduce IBM's FSI master
From: Ninad Palsule This is a part of patchset where IBM's Flexible Service Interface is introduced. This commit models the FSI master. CFAM is hanging out of FSI master which is a bus controller. The FSI master: A controller in the platform service processor (e.g. BMC) driving CFAM engine accesses into the POWER chip. At the hardware level FSI is a bit-based protocol supporting synchronous and DMA-driven accesses of engines in a CFAM. Signed-off-by: Andrew Jeffery Signed-off-by: Ninad Palsule Reviewed-by: Cédric Le Goater [ clg: - move FSICFAMState object under FSIMasterState - introduced fsi_master_init() - reworked fsi_master_realize() - dropped FSIBus definition ] Signed-off-by: Cédric Le Goater --- include/hw/fsi/fsi-master.h | 32 +++ hw/fsi/fsi-master.c | 170 hw/fsi/meson.build | 2 +- hw/fsi/trace-events | 2 + 4 files changed, 205 insertions(+), 1 deletion(-) create mode 100644 include/hw/fsi/fsi-master.h create mode 100644 hw/fsi/fsi-master.c diff --git a/include/hw/fsi/fsi-master.h b/include/hw/fsi/fsi-master.h new file mode 100644 index ..68e5f56db2ea --- /dev/null +++ b/include/hw/fsi/fsi-master.h @@ -0,0 +1,32 @@ +/* + * SPDX-License-Identifier: GPL-2.0-or-later + * Copyright (C) 2024 IBM Corp. + * + * IBM Flexible Service Interface Master + */ +#ifndef FSI_FSI_MASTER_H +#define FSI_FSI_MASTER_H + +#include "exec/memory.h" +#include "hw/qdev-core.h" +#include "hw/fsi/fsi.h" +#include "hw/fsi/cfam.h" + +#define TYPE_FSI_MASTER "fsi.master" +OBJECT_DECLARE_SIMPLE_TYPE(FSIMasterState, FSI_MASTER) + +#define FSI_MASTER_NR_REGS ((0x2e0 >> 2) + 1) + +typedef struct FSIMasterState { +DeviceState parent; +MemoryRegion iomem; +MemoryRegion opb2fsi; + +FSIBus bus; + +uint32_t regs[FSI_MASTER_NR_REGS]; +FSICFAMState cfam; +} FSIMasterState; + + +#endif /* FSI_FSI_H */ diff --git a/hw/fsi/fsi-master.c b/hw/fsi/fsi-master.c new file mode 100644 index ..a5f0598c98ed --- /dev/null +++ b/hw/fsi/fsi-master.c @@ -0,0 +1,170 @@ +/* + * SPDX-License-Identifier: GPL-2.0-or-later + * Copyright (C) 2024 IBM Corp. + * + * IBM Flexible Service Interface master + */ + +#include "qemu/osdep.h" +#include "qapi/error.h" +#include "qemu/log.h" +#include "trace.h" + +#include "hw/fsi/fsi-master.h" + +#define TYPE_OP_BUS "opb" + +#define TO_REG(x) ((x) >> 2) + +#define FSI_MENP0 TO_REG(0x010) +#define FSI_MENP32 TO_REG(0x014) +#define FSI_MSENP0 TO_REG(0x018) +#define FSI_MLEVP0 TO_REG(0x018) +#define FSI_MSENP32 TO_REG(0x01c) +#define FSI_MLEVP32 TO_REG(0x01c) +#define FSI_MCENP0 TO_REG(0x020) +#define FSI_MREFP0 TO_REG(0x020) +#define FSI_MCENP32 TO_REG(0x024) +#define FSI_MREFP32 TO_REG(0x024) + +#define FSI_MVERTO_REG(0x074) +#define FSI_MRESP0 TO_REG(0x0d0) + +#define FSI_MRESB0 TO_REG(0x1d0) +#define FSI_MRESB0_RESET_GENERAL BIT(31) +#define FSI_MRESB0_RESET_ERRORBIT(30) + +static uint64_t fsi_master_read(void *opaque, hwaddr addr, unsigned size) +{ +FSIMasterState *s = FSI_MASTER(opaque); +int reg = TO_REG(addr); + +trace_fsi_master_read(addr, size); + +if (reg >= FSI_MASTER_NR_REGS) { +qemu_log_mask(LOG_GUEST_ERROR, + "%s: Out of bounds read: 0x%"HWADDR_PRIx" for %u\n", + __func__, addr, size); +return 0; +} + +return s->regs[reg]; +} + +static void fsi_master_write(void *opaque, hwaddr addr, uint64_t data, + unsigned size) +{ +FSIMasterState *s = FSI_MASTER(opaque); +int reg = TO_REG(addr); + +trace_fsi_master_write(addr, size, data); + +if (reg >= FSI_MASTER_NR_REGS) { +qemu_log_mask(LOG_GUEST_ERROR, + "%s: Out of bounds write: %"HWADDR_PRIx" for %u\n", + __func__, addr, size); +return; +} + +switch (reg) { +case FSI_MENP0: +s->regs[FSI_MENP0] = data; +break; +case FSI_MENP32: +s->regs[FSI_MENP32] = data; +break; +case FSI_MSENP0: +s->regs[FSI_MENP0] |= data; +break; +case FSI_MSENP32: +s->regs[FSI_MENP32] |= data; +break; +case FSI_MCENP0: +s->regs[FSI_MENP0] &= ~data; +break; +case FSI_MCENP32: +s->regs[FSI_MENP32] &= ~data; +
[PULL 08/17] hw/fsi: Introduce IBM's scratchpad device
From: Ninad Palsule This is a part of patchset where IBM's Flexible Service Interface is introduced. The scratchpad provides a set of non-functional registers. The firmware is free to use them, hardware does not support any special management support. The scratchpad registers can be read or written from LBUS slave. The scratch pad is managed under FSI CFAM state. Signed-off-by: Andrew Jeffery Signed-off-by: Ninad Palsule Reviewed-by: Cédric Le Goater [ clg: - moved object FSIScratchPad under FSICFAMState - moved FSIScratchPad code under cfam.c ] Signed-off-by: Cédric Le Goater --- include/hw/fsi/lbus.h | 11 ++ hw/fsi/lbus.c | 78 +-- hw/fsi/trace-events | 2 ++ 3 files changed, 89 insertions(+), 2 deletions(-) diff --git a/include/hw/fsi/lbus.h b/include/hw/fsi/lbus.h index e8a22e22a8fa..558268c013f5 100644 --- a/include/hw/fsi/lbus.h +++ b/include/hw/fsi/lbus.h @@ -29,4 +29,15 @@ typedef struct FSILBus { MemoryRegion mr; } FSILBus; +#define TYPE_FSI_SCRATCHPAD "fsi.scratchpad" +#define SCRATCHPAD(obj) OBJECT_CHECK(FSIScratchPad, (obj), TYPE_FSI_SCRATCHPAD) + +#define FSI_SCRATCHPAD_NR_REGS 4 + +typedef struct FSIScratchPad { +FSILBusDevice parent; + +uint32_t regs[FSI_SCRATCHPAD_NR_REGS]; +} FSIScratchPad; + #endif /* FSI_LBUS_H */ diff --git a/hw/fsi/lbus.c b/hw/fsi/lbus.c index 44d2319087a8..20495f42fd99 100644 --- a/hw/fsi/lbus.c +++ b/hw/fsi/lbus.c @@ -8,11 +8,12 @@ #include "qemu/osdep.h" #include "qapi/error.h" #include "hw/fsi/lbus.h" - #include "hw/qdev-properties.h" - +#include "qemu/log.h" #include "trace.h" +#define TO_REG(offset) ((offset) >> 2) + static void fsi_lbus_init(Object *o) { FSILBus *lbus = FSI_LBUS(o); @@ -34,10 +35,83 @@ static const TypeInfo fsi_lbus_device_type_info = { .abstract = true, }; +static uint64_t fsi_scratchpad_read(void *opaque, hwaddr addr, unsigned size) +{ +FSIScratchPad *s = SCRATCHPAD(opaque); +int reg = TO_REG(addr); + +trace_fsi_scratchpad_read(addr, size); + +if (reg >= FSI_SCRATCHPAD_NR_REGS) { +qemu_log_mask(LOG_GUEST_ERROR, + "%s: Out-of-bounds read at offset 0x%" HWADDR_PRIx "\n", + __func__, addr); +return 0; +} + +return s->regs[reg]; +} + +static void fsi_scratchpad_write(void *opaque, hwaddr addr, uint64_t data, + unsigned size) +{ +FSIScratchPad *s = SCRATCHPAD(opaque); + +trace_fsi_scratchpad_write(addr, size, data); +int reg = TO_REG(addr); + +if (reg >= FSI_SCRATCHPAD_NR_REGS) { +qemu_log_mask(LOG_GUEST_ERROR, + "%s: Out-of-bounds write at offset 0x%" HWADDR_PRIx "\n", + __func__, addr); +return; +} + +s->regs[reg] = data; +} + +static const struct MemoryRegionOps scratchpad_ops = { +.read = fsi_scratchpad_read, +.write = fsi_scratchpad_write, +.endianness = DEVICE_BIG_ENDIAN, +}; + +static void fsi_scratchpad_realize(DeviceState *dev, Error **errp) +{ +FSILBusDevice *ldev = FSI_LBUS_DEVICE(dev); + +memory_region_init_io(>iomem, OBJECT(ldev), _ops, + ldev, TYPE_FSI_SCRATCHPAD, 0x400); +} + +static void fsi_scratchpad_reset(DeviceState *dev) +{ +FSIScratchPad *s = SCRATCHPAD(dev); + +memset(s->regs, 0, sizeof(s->regs)); +} + +static void fsi_scratchpad_class_init(ObjectClass *klass, void *data) +{ +DeviceClass *dc = DEVICE_CLASS(klass); + +dc->bus_type = TYPE_FSI_LBUS; +dc->realize = fsi_scratchpad_realize; +dc->reset = fsi_scratchpad_reset; +} + +static const TypeInfo fsi_scratchpad_info = { +.name = TYPE_FSI_SCRATCHPAD, +.parent = TYPE_FSI_LBUS_DEVICE, +.instance_size = sizeof(FSIScratchPad), +.class_init = fsi_scratchpad_class_init, +}; + static void fsi_lbus_register_types(void) { type_register_static(_lbus_info); type_register_static(_lbus_device_type_info); +type_register_static(_scratchpad_info); } type_init(fsi_lbus_register_types); diff --git a/hw/fsi/trace-events b/hw/fsi/trace-events index e69de29bb2d1..c5753e27910a 100644 --- a/hw/fsi/trace-events +++ b/hw/fsi/trace-events @@ -0,0 +1,2 @@ +fsi_scratchpad_read(uint64_t addr, uint32_t size) "@0x%" PRIx64 " size=%d" +fsi_scratchpad_write(uint64_t addr, uint32_t size, uint64_t data) "@0x%" PRIx64 " size=%d value=0x%"PRIx64 -- 2.43.0
[PULL 03/17] hw/arm/aspeed: Set default CPU count using aspeed_soc_num_cpus()
From: Philippe Mathieu-Daudé Since commit b7f1a0cb76 ("arm/aspeed: Compute the number of CPUs from the SoC definition") Aspeed machines use the aspeed_soc_num_cpus() helper to set the number of CPUs. Use it for the ast1030-evb (commit 356b230ed1 "aspeed/soc: Add AST1030 support") and supermicrox11-bmc (commit 40a38df55e "hw/arm/aspeed: Add board model for Supermicro X11 BMC") machines. Signed-off-by: Philippe Mathieu-Daudé Reviewed-by: Cédric Le Goater Reviewed-by: Gavin Shan Signed-off-by: Cédric Le Goater --- hw/arm/aspeed.c | 5 - 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/hw/arm/aspeed.c b/hw/arm/aspeed.c index 4bc292ff84fc..5b01a4dd28f8 100644 --- a/hw/arm/aspeed.c +++ b/hw/arm/aspeed.c @@ -1212,6 +1212,8 @@ static void aspeed_machine_supermicrox11_bmc_class_init(ObjectClass *oc, amc->macs_mask = ASPEED_MAC0_ON | ASPEED_MAC1_ON; amc->i2c_init = palmetto_bmc_i2c_init; mc->default_ram_size = 256 * MiB; +mc->default_cpus = mc->min_cpus = mc->max_cpus = +aspeed_soc_num_cpus(amc->soc_name); } static void aspeed_machine_supermicro_x11spi_bmc_class_init(ObjectClass *oc, @@ -1586,11 +1588,12 @@ static void aspeed_minibmc_machine_ast1030_evb_class_init(ObjectClass *oc, mc->init = aspeed_minibmc_machine_init; amc->i2c_init = ast1030_evb_i2c_init; mc->default_ram_size = 0; -mc->default_cpus = mc->min_cpus = mc->max_cpus = 1; amc->fmc_model = "sst25vf032b"; amc->spi_model = "sst25vf032b"; amc->num_cs = 2; amc->macs_mask = 0; +mc->default_cpus = mc->min_cpus = mc->max_cpus = +aspeed_soc_num_cpus(amc->soc_name); } static void aspeed_machine_qcom_dc_scm_v1_class_init(ObjectClass *oc, -- 2.43.0
[PULL 04/17] hw/arm/aspeed: Init CPU defaults in a common helper
From: Philippe Mathieu-Daudé Rework aspeed_soc_num_cpus() as a new init_cpus_defaults() helper to reduce code duplication. Reviewed-by: Cédric Le Goater Reviewed-by: Richard Henderson Reviewed-by: Gavin Shan Signed-off-by: Philippe Mathieu-Daudé Signed-off-by: Cédric Le Goater --- hw/arm/aspeed.c | 71 +++-- 1 file changed, 28 insertions(+), 43 deletions(-) diff --git a/hw/arm/aspeed.c b/hw/arm/aspeed.c index 5b01a4dd28f8..d2d490a6d142 100644 --- a/hw/arm/aspeed.c +++ b/hw/arm/aspeed.c @@ -1141,10 +1141,14 @@ static void aspeed_machine_class_props_init(ObjectClass *oc) "Change the SPI Flash model"); } -static int aspeed_soc_num_cpus(const char *soc_name) +static void aspeed_machine_class_init_cpus_defaults(MachineClass *mc) { - AspeedSoCClass *sc = ASPEED_SOC_CLASS(object_class_by_name(soc_name)); - return sc->num_cpus; +AspeedMachineClass *amc = ASPEED_MACHINE_CLASS(mc); +AspeedSoCClass *sc = ASPEED_SOC_CLASS(object_class_by_name(amc->soc_name)); + +mc->default_cpus = sc->num_cpus; +mc->min_cpus = sc->num_cpus; +mc->max_cpus = sc->num_cpus; } static void aspeed_machine_class_init(ObjectClass *oc, void *data) @@ -1176,8 +1180,7 @@ static void aspeed_machine_palmetto_class_init(ObjectClass *oc, void *data) amc->num_cs= 1; amc->i2c_init = palmetto_bmc_i2c_init; mc->default_ram_size = 256 * MiB; -mc->default_cpus = mc->min_cpus = mc->max_cpus = -aspeed_soc_num_cpus(amc->soc_name); +aspeed_machine_class_init_cpus_defaults(mc); }; static void aspeed_machine_quanta_q71l_class_init(ObjectClass *oc, void *data) @@ -1193,8 +1196,7 @@ static void aspeed_machine_quanta_q71l_class_init(ObjectClass *oc, void *data) amc->num_cs= 1; amc->i2c_init = quanta_q71l_bmc_i2c_init; mc->default_ram_size = 128 * MiB; -mc->default_cpus = mc->min_cpus = mc->max_cpus = -aspeed_soc_num_cpus(amc->soc_name); +aspeed_machine_class_init_cpus_defaults(mc); } static void aspeed_machine_supermicrox11_bmc_class_init(ObjectClass *oc, @@ -1212,8 +1214,7 @@ static void aspeed_machine_supermicrox11_bmc_class_init(ObjectClass *oc, amc->macs_mask = ASPEED_MAC0_ON | ASPEED_MAC1_ON; amc->i2c_init = palmetto_bmc_i2c_init; mc->default_ram_size = 256 * MiB; -mc->default_cpus = mc->min_cpus = mc->max_cpus = -aspeed_soc_num_cpus(amc->soc_name); +aspeed_machine_class_init_cpus_defaults(mc); } static void aspeed_machine_supermicro_x11spi_bmc_class_init(ObjectClass *oc, @@ -1231,8 +1232,7 @@ static void aspeed_machine_supermicro_x11spi_bmc_class_init(ObjectClass *oc, amc->macs_mask = ASPEED_MAC0_ON | ASPEED_MAC1_ON; amc->i2c_init = palmetto_bmc_i2c_init; mc->default_ram_size = 512 * MiB; -mc->default_cpus = mc->min_cpus = mc->max_cpus = -aspeed_soc_num_cpus(amc->soc_name); +aspeed_machine_class_init_cpus_defaults(mc); } static void aspeed_machine_ast2500_evb_class_init(ObjectClass *oc, void *data) @@ -1248,8 +1248,7 @@ static void aspeed_machine_ast2500_evb_class_init(ObjectClass *oc, void *data) amc->num_cs= 1; amc->i2c_init = ast2500_evb_i2c_init; mc->default_ram_size = 512 * MiB; -mc->default_cpus = mc->min_cpus = mc->max_cpus = -aspeed_soc_num_cpus(amc->soc_name); +aspeed_machine_class_init_cpus_defaults(mc); }; static void aspeed_machine_yosemitev2_class_init(ObjectClass *oc, void *data) @@ -1266,8 +1265,7 @@ static void aspeed_machine_yosemitev2_class_init(ObjectClass *oc, void *data) amc->num_cs= 2; amc->i2c_init = yosemitev2_bmc_i2c_init; mc->default_ram_size = 512 * MiB; -mc->default_cpus = mc->min_cpus = mc->max_cpus = -aspeed_soc_num_cpus(amc->soc_name); +aspeed_machine_class_init_cpus_defaults(mc); }; static void aspeed_machine_romulus_class_init(ObjectClass *oc, void *data) @@ -1283,8 +1281,7 @@ static void aspeed_machine_romulus_class_init(ObjectClass *oc, void *data) amc->num_cs= 2; amc->i2c_init = romulus_bmc_i2c_init; mc->default_ram_size = 512 * MiB; -mc->default_cpus = mc->min_cpus = mc->max_cpus = -aspeed_soc_num_cpus(amc->soc_name); +aspeed_machine_class_init_cpus_defaults(mc); }; static void aspeed_machine_tiogapass_class_init(ObjectClass *oc, void *data) @@ -1301,8 +1298,7 @@ static void aspeed_machine_tiogapass_class_init(ObjectClass *oc, void *data) amc->num_cs= 2; amc->i2c_init = tiogapass_bmc_i2c_init; mc->default_ram_size = 1 * GiB; -mc->default_cpus = mc->min_cpus = mc->max_cpus = -aspeed_soc_num_cpus(amc->soc_name); +aspeed_machine_class_init_cpus_defaul
[PULL 01/17] tests/avocado/machine_aspeed.py: Update buildroot images to 2023.11
Compared to mainline buildroot, these images have some customization : - Linux version is bumped to 6.6.3 and built with a custom config - U-Boot is switched to the one provided by OpenBMC for more support - defconfigs extra tools for dev See branch [1] for more details. There are a few changes since last update, commit ed1f5ff84209. Images all have a password now and I2C devices have been updated in the Linux ast2600-evb device tree [2]. Do the necessary adjustements. [1] https://github.com/legoater/buildroot/commits/aspeed-2023.11 [2] https://git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git/commit/?id=9deb10cf160e Signed-off-by: Cédric Le Goater --- tests/avocado/machine_aspeed.py | 18 +- 1 file changed, 9 insertions(+), 9 deletions(-) diff --git a/tests/avocado/machine_aspeed.py b/tests/avocado/machine_aspeed.py index 6fa5459a07bf..cec018142453 100644 --- a/tests/avocado/machine_aspeed.py +++ b/tests/avocado/machine_aspeed.py @@ -155,6 +155,7 @@ def do_test_arm_aspeed_buildroot_start(self, image, cpu_id, pattern='Aspeed EVB' time.sleep(0.1) exec_command(self, 'root') time.sleep(0.1) +exec_command(self, "passw0rd") def do_test_arm_aspeed_buildroot_poweroff(self): exec_command_and_wait_for_pattern(self, 'poweroff', @@ -167,14 +168,14 @@ def test_arm_ast2500_evb_buildroot(self): """ image_url = ('https://github.com/legoater/qemu-aspeed-boot/raw/master/' - 'images/ast2500-evb/buildroot-2022.11-2-g15d3648df9/flash.img') -image_hash = ('f96d11db521fe7a2787745e9e391225dc3318ee0fc07c8b799b8833dd474') + 'images/ast2500-evb/buildroot-2023.11/flash.img') +image_hash = ('c23db6160cf77d0258397eb2051162c8473a56c441417c52a91ba217186e715f') image_path = self.fetch_asset(image_url, asset_hash=image_hash, algorithm='sha256') self.vm.add_args('-device', 'tmp105,bus=aspeed.i2c.bus.3,address=0x4d,id=tmp-test'); -self.do_test_arm_aspeed_buildroot_start(image_path, '0x0') +self.do_test_arm_aspeed_buildroot_start(image_path, '0x0', 'Aspeed AST2500 EVB') exec_command_and_wait_for_pattern(self, 'echo lm75 0x4d > /sys/class/i2c-dev/i2c-3/device/new_device', @@ -195,8 +196,8 @@ def test_arm_ast2600_evb_buildroot(self): """ image_url = ('https://github.com/legoater/qemu-aspeed-boot/raw/master/' - 'images/ast2600-evb/buildroot-2022.11-2-g15d3648df9/flash.img') -image_hash = ('e598d86e5ea79671ca8b59212a326c911bc8bea728dec1a1f5390d717a28bb8b') + 'images/ast2600-evb/buildroot-2023.11/flash.img') +image_hash = ('b62808daef48b438d0728ee07662290490ecfa65987bb91294cafb1bb7ad1a68') image_path = self.fetch_asset(image_url, asset_hash=image_hash, algorithm='sha256') @@ -206,17 +207,17 @@ def test_arm_ast2600_evb_buildroot(self): 'ds1338,bus=aspeed.i2c.bus.3,address=0x32'); self.vm.add_args('-device', 'i2c-echo,bus=aspeed.i2c.bus.3,address=0x42'); -self.do_test_arm_aspeed_buildroot_start(image_path, '0xf00') +self.do_test_arm_aspeed_buildroot_start(image_path, '0xf00', 'Aspeed AST2600 EVB') exec_command_and_wait_for_pattern(self, 'echo lm75 0x4d > /sys/class/i2c-dev/i2c-3/device/new_device', 'i2c i2c-3: new_device: Instantiated device lm75 at 0x4d'); exec_command_and_wait_for_pattern(self, - 'cat /sys/class/hwmon/hwmon0/temp1_input', '0') + 'cat /sys/class/hwmon/hwmon1/temp1_input', '0') self.vm.cmd('qom-set', path='/machine/peripheral/tmp-test', property='temperature', value=18000); exec_command_and_wait_for_pattern(self, - 'cat /sys/class/hwmon/hwmon0/temp1_input', '18000') + 'cat /sys/class/hwmon/hwmon1/temp1_input', '18000') exec_command_and_wait_for_pattern(self, 'echo ds1307 0x32 > /sys/class/i2c-dev/i2c-3/device/new_device', @@ -261,7 +262,6 @@ def test_arm_ast2600_evb_buildroot_tpm(self): self.vm.add_args('-device', 'tpm-tis-i2c,tpmdev=tpm0,bus=aspeed.i2c.bus.12,address=0x2e') self.do_test_arm_aspeed_buildroot_start(image_path, '0xf00', 'Aspeed AST2600 EVB') -exec_command(self, "passw0rd") exec_command_and_wait_for_pattern(self, 'echo tpm_tis_i2c 0x2e > /sys/bus/i2c/devices/i2c-12/new_device', -- 2.43.0