On Thu, Aug 14, 2025 at 07:54:11PM -0700, Nathan Chen via Devel wrote: > Add support for parsing multiple IOMMU devices from > the VM definition when "smmuv3Dev" is the IOMMU model. > > Signed-off-by: Nathan Chen <nathanc@xxxxxxxxxx> > --- > src/conf/domain_conf.c | 153 ++++++++++++++++++++++++++---- > src/conf/domain_conf.h | 9 +- > src/conf/domain_validate.c | 32 ++++--- > src/conf/schemas/domaincommon.rng | 4 +- > src/libvirt_private.syms | 2 + > src/qemu/qemu_alias.c | 15 ++- > src/qemu/qemu_command.c | 146 ++++++++++++++-------------- > src/qemu/qemu_domain_address.c | 35 +++---- > src/qemu/qemu_driver.c | 8 +- > src/qemu/qemu_postparse.c | 11 ++- > src/qemu/qemu_validate.c | 2 +- > 11 files changed, 284 insertions(+), 133 deletions(-) > > diff --git a/src/conf/domain_conf.c b/src/conf/domain_conf.c > index dc222887d4..5ea4d6424b 100644 > --- a/src/conf/domain_conf.c > +++ b/src/conf/domain_conf.c > @@ -16446,6 +16447,112 @@ virDomainInputDefFind(const virDomainDef *def, > } > > > +bool > +virDomainIOMMUDefEquals(const virDomainIOMMUDef *a, > + const virDomainIOMMUDef *b) > +{ > + if (a->model != b->model || > + a->intremap != b->intremap || > + a->caching_mode != b->caching_mode || > + a->eim != b->eim || > + a->iotlb != b->iotlb || > + a->aw_bits != b->aw_bits || > + a->parent_idx != b->parent_idx || > + a->accel != b->accel || > + a->dma_translation != b->dma_translation) > + return false; > + > + switch (a->info.type) { > + case VIR_DOMAIN_DEVICE_ADDRESS_TYPE_PCI: > + if (a->info.addr.pci.domain != b->info.addr.pci.domain || > + a->info.addr.pci.bus != b->info.addr.pci.bus || > + a->info.addr.pci.slot != b->info.addr.pci.slot || > + a->info.addr.pci.function != b->info.addr.pci.function) { > + return false; > + } > + break; > + > + case VIR_DOMAIN_DEVICE_ADDRESS_TYPE_DRIVE: > + if (a->info.addr.drive.controller != b->info.addr.drive.controller || > + a->info.addr.drive.bus != b->info.addr.drive.bus || > + a->info.addr.drive.unit != b->info.addr.drive.unit) { > + return false; > + } > + break; > + > + case VIR_DOMAIN_DEVICE_ADDRESS_TYPE_VIRTIO_SERIAL: > + if (a->info.addr.vioserial.controller != b->info.addr.vioserial.controller || > + a->info.addr.vioserial.bus != b->info.addr.vioserial.bus || > + a->info.addr.vioserial.port != b->info.addr.vioserial.port) { > + return false; > + } > + break; > + > + case VIR_DOMAIN_DEVICE_ADDRESS_TYPE_CCID: > + if (a->info.addr.ccid.controller != b->info.addr.ccid.controller || > + a->info.addr.ccid.slot != b->info.addr.ccid.slot) { > + return false; > + } > + break; > + > + case VIR_DOMAIN_DEVICE_ADDRESS_TYPE_ISA: > + if (a->info.addr.isa.iobase != b->info.addr.isa.iobase || > + a->info.addr.isa.irq != b->info.addr.isa.irq) { > + return false; > + } > + break; > + > + case VIR_DOMAIN_DEVICE_ADDRESS_TYPE_DIMM: > + if (a->info.addr.dimm.slot != b->info.addr.dimm.slot) { > + return false; > + } > + > + if (a->info.addr.dimm.base != b->info.addr.dimm.base) { > + return false; > + } > + break; > + > + case VIR_DOMAIN_DEVICE_ADDRESS_TYPE_CCW: > + if (a->info.addr.ccw.cssid != b->info.addr.ccw.cssid || > + a->info.addr.ccw.ssid != b->info.addr.ccw.ssid || > + a->info.addr.ccw.devno != b->info.addr.ccw.devno) { > + return false; > + } > + break; > + > + case VIR_DOMAIN_DEVICE_ADDRESS_TYPE_USB: > + case VIR_DOMAIN_DEVICE_ADDRESS_TYPE_SPAPRVIO: > + case VIR_DOMAIN_DEVICE_ADDRESS_TYPE_VIRTIO_S390: > + case VIR_DOMAIN_DEVICE_ADDRESS_TYPE_VIRTIO_MMIO: > + case VIR_DOMAIN_DEVICE_ADDRESS_TYPE_NONE: > + case VIR_DOMAIN_DEVICE_ADDRESS_TYPE_UNASSIGNED: > + case VIR_DOMAIN_DEVICE_ADDRESS_TYPE_LAST: > + break; > + } > + > + if (a->info.acpiIndex != b->info.acpiIndex) { > + return false; > + } Most of this should go away if you use virDomainDeviceInfoAddressIsEqual With regards, Daniel -- |: https://berrange.com -o- https://www.flickr.com/photos/dberrange :| |: https://libvirt.org -o- https://fstop138.berrange.com :| |: https://entangle-photo.org -o- https://www.instagram.com/dberrange :|