On 4/2/25 10:25, Andrea Righi via Devel wrote: > Introduce apci-generic-initiator device to the domain XML. > > Example definition: > > <acpi-generic-initiator> > <alias name="gi1" /> > <pci-dev>dev0</pci-dev> > <numa-node>1</numa-node> > </acpi-generic-initiator> > > This enables partitioning of PCI resources into multiple isolated > instances, each requiring a dedicated NUMA node definition, that can be > represented by the acpi-generic-initiator object. > > Signed-off-by: Andrea Righi <ari...@nvidia.com> > --- > src/ch/ch_domain.c | 1 + > src/conf/domain_conf.c | 133 ++++++++++++++++++++++++++++++ > src/conf/domain_conf.h | 1 + > src/conf/domain_postparse.c | 1 + > src/conf/domain_validate.c | 37 +++++++++ > src/conf/schemas/domaincommon.rng | 2 +- > src/libxl/libxl_driver.c | 6 ++ > src/lxc/lxc_driver.c | 6 ++ > src/qemu/qemu_command.c | 1 + > src/qemu/qemu_domain.c | 2 + > src/qemu/qemu_domain_address.c | 4 + > src/qemu/qemu_driver.c | 3 + > src/qemu/qemu_hotplug.c | 5 ++ > src/qemu/qemu_postparse.c | 1 + > src/qemu/qemu_validate.c | 1 + > src/test/test_driver.c | 4 + > 16 files changed, 207 insertions(+), 1 deletion(-)
There's another switch() in hypervDomainAttachDeviceFlags() in src/hyperv/hyperv_driver.c that wants this new enum addition covered too. > > diff --git a/src/ch/ch_domain.c b/src/ch/ch_domain.c > index a08b18c5b9..f88ce32803 100644 > --- a/src/ch/ch_domain.c > +++ b/src/ch/ch_domain.c > @@ -162,6 +162,7 @@ chValidateDomainDeviceDef(const virDomainDeviceDef *dev, > case VIR_DOMAIN_DEVICE_CONTROLLER: > case VIR_DOMAIN_DEVICE_CHR: > case VIR_DOMAIN_DEVICE_HOSTDEV: > + case VIR_DOMAIN_DEVICE_ACPI_INITIATOR: > break; > > case VIR_DOMAIN_DEVICE_LEASE: > diff --git a/src/conf/domain_conf.c b/src/conf/domain_conf.c > index 405f0207e9..2294ad42bf 100644 > --- a/src/conf/domain_conf.c > +++ b/src/conf/domain_conf.c > @@ -342,6 +342,7 @@ VIR_ENUM_IMPL(virDomainDevice, > "audio", > "crypto", > "pstore", > + "acpiinitiator", > ); > > VIR_ENUM_IMPL(virDomainDiskDevice, > @@ -3727,6 +3728,9 @@ void virDomainDeviceDefFree(virDomainDeviceDef *def) > case VIR_DOMAIN_DEVICE_PSTORE: > virDomainPstoreDefFree(def->data.pstore); > break; > + case VIR_DOMAIN_DEVICE_ACPI_INITIATOR: > + virDomainAcpiInitiatorDefFree(def->data.acpiinitiator); > + break; > case VIR_DOMAIN_DEVICE_LAST: > case VIR_DOMAIN_DEVICE_NONE: > break; > @@ -4705,6 +4709,8 @@ virDomainDeviceGetInfo(const virDomainDeviceDef *device) > return &device->data.crypto->info; > case VIR_DOMAIN_DEVICE_PSTORE: > return &device->data.pstore->info; > + case VIR_DOMAIN_DEVICE_ACPI_INITIATOR: > + return device->data.acpiinitiator->info; > > /* The following devices do not contain virDomainDeviceInfo */ > case VIR_DOMAIN_DEVICE_LEASE: > @@ -4813,6 +4819,9 @@ virDomainDeviceSetData(virDomainDeviceDef *device, > case VIR_DOMAIN_DEVICE_PSTORE: > device->data.pstore = devicedata; > break; > + case VIR_DOMAIN_DEVICE_ACPI_INITIATOR: > + device->data.acpiinitiator = devicedata; > + break; > case VIR_DOMAIN_DEVICE_NONE: > case VIR_DOMAIN_DEVICE_LAST: > break; > @@ -5038,6 +5047,13 @@ virDomainDeviceInfoIterateFlags(virDomainDef *def, > return rc; > } > > + device.type = VIR_DOMAIN_DEVICE_ACPI_INITIATOR; > + for (i = 0; i < def->nacpiinitiator; i++) { > + device.data.acpiinitiator = def->acpiinitiator[i]; > + if ((rc = cb(def, &device, def->acpiinitiator[i]->info, opaque)) != > 0) > + return rc; > + } > + > /* If the flag below is set, make sure @cb can handle @info being NULL */ > if (iteratorFlags & DOMAIN_DEVICE_ITERATE_MISSING_INFO) { > device.type = VIR_DOMAIN_DEVICE_GRAPHICS; > @@ -5098,6 +5114,7 @@ virDomainDeviceInfoIterateFlags(virDomainDef *def, > case VIR_DOMAIN_DEVICE_AUDIO: > case VIR_DOMAIN_DEVICE_CRYPTO: > case VIR_DOMAIN_DEVICE_PSTORE: > + case VIR_DOMAIN_DEVICE_ACPI_INITIATOR: > break; > } > #endif > @@ -13685,6 +13702,65 @@ virDomainHostdevDefParseXML(virDomainXMLOption > *xmlopt, > } > > > +static virDomainAcpiInitiatorDef * > +virDomainAcpiInitiatorDefParseXML(virDomainXMLOption *xmlopt, > + xmlNodePtr node, > + xmlXPathContextPtr ctxt, > + unsigned int flags) > +{ > + virDomainAcpiInitiatorDef *def; This could be: g_autoptr(virDomainAcpiInitiatorDef) def = NULL; > + g_autofree char *tmp = NULL; > + > + VIR_XPATH_NODE_AUTORESTORE(ctxt) > + > + ctxt->node = node; > + > + def = virDomainAcpiInitiatorDefNew(); > + > + def->name = virXPathString("string(./alias/@name)", ctxt); > + if (!def->name) { > + virReportError(VIR_ERR_XML_ERROR, "%s", > + _("missing initiator name")); > + goto error; and then all these 'goto error' could be plain 'return NULL'. > + } > + > + def->pciDev = virXPathString("string(./pci-dev)", ctxt); > + if (!def->pciDev) { > + virReportError(VIR_ERR_XML_ERROR, "%s", > + _("missing initiator pci-dev")); > + goto error; > + } > + > + tmp = virXPathString("string(./numa-node)", ctxt); > + if (tmp) { > + if (virStrToLong_i((const char *)tmp, NULL, 10, &def->numaNode) < 0) > { > + virReportError(VIR_ERR_CONFIG_UNSUPPORTED, > + _("invalid value for numa-node: '%1$s'"), tmp); > + goto error; > + } > + } else { > + virReportError(VIR_ERR_XML_ERROR, "%s", > + _("missing initiator numa-node")); > + goto error; > + } > + > + if (def->info->type == VIR_DOMAIN_DEVICE_ADDRESS_TYPE_NONE) { > + if (virDomainDeviceInfoParseXML(xmlopt, node, ctxt, def->info, > + flags) < 0) { > + virReportError(VIR_ERR_XML_ERROR, "%s", > + _("failed to parse device information")); > + goto error; > + } > + } > + > + return def; > + > + error: > + virDomainAcpiInitiatorDefFree(def); > + return NULL; > +} > + > + > static virDomainRedirdevDef * > virDomainRedirdevDefParseXML(virDomainXMLOption *xmlopt, > xmlNodePtr node, > @@ -14686,6 +14762,12 @@ virDomainDeviceDefParse(const char *xmlStr, > return NULL; > } > break; > + case VIR_DOMAIN_DEVICE_ACPI_INITIATOR: > + if (!(dev->data.acpiinitiator = > virDomainAcpiInitiatorDefParseXML(xmlopt, node, > + > ctxt, flags))) { > + return NULL; > + } > + break; > case VIR_DOMAIN_DEVICE_NONE: > case VIR_DOMAIN_DEVICE_LAST: > break; > @@ -20095,6 +20177,23 @@ virDomainDefParseXML(xmlXPathContextPtr ctxt, > } > VIR_FREE(nodes); > > + /* analysis of the acpi generic initiator */ > + if ((n = virXPathNodeSet("./devices/acpi-generic-initiator", ctxt, > &nodes)) < 0) > + return NULL; > + Missing: if (n) > + def->acpiinitiator = g_new0(virDomainAcpiInitiatorDef *, n); We probably don't need to allocate any memory if n==0. Not even a dummy pointer. > + > + for (i = 0; i < n; i++) { > + virDomainAcpiInitiatorDef *acpiinitiator; > + > + acpiinitiator = virDomainAcpiInitiatorDefParseXML(xmlopt, nodes[i], > ctxt, flags); > + if (!acpiinitiator) > + return NULL; > + > + def->acpiinitiator[def->nacpiinitiator++] = acpiinitiator; > + } > + VIR_FREE(nodes); > + Michal