The VFIO IOMMU Type1 kernel driver enforces a default IOMMU mapping limit of 65535, which is configurable via the 'dma_max_mappings' module parameter. When this limit is reached, QEMU issues a warning and fails the mapping operation, but allows the VM to continue running, potentially causing issues later. This scenario occurs with SEV-SNP guests, which must update all IOMMU mappings during initialization.
To address this, update vfio_ram_discard_register_listener() to accept an 'Error **' parameter and propagate the error to the caller. This change will halt the VM immediately, at init time, with the same error message. Additionally, the same behavior will be enforced at runtime. While this might be considered too brutal, the rarity of this case and the planned removal of the dma_max_mappings module parameter make it a reasonable approach. Cc: Alex Williamson <alex.william...@redhat.com> Signed-off-by: Cédric Le Goater <c...@redhat.com> --- hw/vfio/listener.c | 13 +++++++++---- 1 file changed, 9 insertions(+), 4 deletions(-) diff --git a/hw/vfio/listener.c b/hw/vfio/listener.c index 184c15e05fcb388cf0848e97e1eb283f17a50ad4..bc40ec8613c71a12b8c0dfdea497a14a446ac1fd 100644 --- a/hw/vfio/listener.c +++ b/hw/vfio/listener.c @@ -250,8 +250,9 @@ int vfio_ram_discard_notify_populate(RamDiscardListener *rdl, return 0; } -static void vfio_ram_discard_register_listener(VFIOContainerBase *bcontainer, - MemoryRegionSection *section) +static bool vfio_ram_discard_register_listener(VFIOContainerBase *bcontainer, + MemoryRegionSection *section, + Error **errp) { RamDiscardManager *rdm = memory_region_get_ram_discard_manager(section->mr); int target_page_size = qemu_target_page_size(); @@ -316,13 +317,15 @@ static void vfio_ram_discard_register_listener(VFIOContainerBase *bcontainer, if (vrdl_mappings + max_memslots - vrdl_count > bcontainer->dma_max_mappings) { - warn_report("%s: possibly running out of DMA mappings. E.g., try" + error_setg(errp, "%s: possibly running out of DMA mappings. E.g., try" " increasing the 'block-size' of virtio-mem devies." " Maximum possible DMA mappings: %d, Maximum possible" " memslots: %d", __func__, bcontainer->dma_max_mappings, max_memslots); + return false; } } + return true; } static void vfio_ram_discard_unregister_listener(VFIOContainerBase *bcontainer, @@ -576,7 +579,9 @@ void vfio_container_region_add(VFIOContainerBase *bcontainer, */ if (memory_region_has_ram_discard_manager(section->mr)) { if (!cpr_remap) { - vfio_ram_discard_register_listener(bcontainer, section); + if (!vfio_ram_discard_register_listener(bcontainer, section, &err)) { + goto fail; + } } else if (!vfio_cpr_ram_discard_replay_populated(bcontainer, section)) { error_setg(&err, -- 2.50.1