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 <arighi(a)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