This enables partitioning of PCI devices into multiple isolated
instances, each requiring a dedicated virtual NUMA node definition.
Link: https://mail.gnu.org/archive/html/qemu-arm/2024-03/msg00358.html
Signed-off-by: Andrea Righi <arighi@nvidia.com>
---
src/conf/device_conf.h | 3 +++
src/conf/domain_conf.c | 30 ++++++++++++++++++++++++++++--
src/conf/schemas/domaincommon.rng | 5 +++++
3 files changed, 36 insertions(+), 2 deletions(-)
diff --git a/src/conf/device_conf.h b/src/conf/device_conf.h
index 2d97410f6e..e570f51824 100644
--- a/src/conf/device_conf.h
+++ b/src/conf/device_conf.h
@@ -185,6 +185,9 @@ struct _virDomainDeviceInfo {
* cases we might want to prevent that from happening by
* locking the isolation group */
bool isolationGroupLocked;
+
+ /* NUMA nodeset affinity for this device */
+ virBitmap *acpiNodeset;
};
int virDeviceHostdevPCIDriverInfoParseXML(xmlNodePtr node,
diff --git a/src/conf/domain_conf.c b/src/conf/domain_conf.c
index 7766e302ec..8c0bf63925 100644
--- a/src/conf/domain_conf.c
+++ b/src/conf/domain_conf.c
@@ -5558,8 +5558,20 @@ virDomainDeviceInfoFormat(virBuffer *buf,
virBufferAddLit(buf, "/>\n");
}
- if (info->acpiIndex != 0)
- virBufferAsprintf(buf, "<acpi index='%u'/>\n", info->acpiIndex);
+ if (info->acpiIndex != 0 || info->acpiNodeset) {
+ virBufferAddLit(buf, "<acpi");
+
+ if (info->acpiIndex != 0)
+ virBufferAsprintf(buf, " index='%u'", info->acpiIndex);
+
+ if (info->acpiNodeset) {
+ g_autofree char *nodeset = virBitmapFormat(info->acpiNodeset);
+ if (nodeset)
+ virBufferAsprintf(buf, " nodeset='%s'", nodeset);
+ }
+
+ virBufferAddLit(buf, "/>\n");
+ }
if (info->type == VIR_DOMAIN_DEVICE_ADDRESS_TYPE_NONE ||
info->type == VIR_DOMAIN_DEVICE_ADDRESS_TYPE_VIRTIO_S390)
@@ -5884,9 +5896,23 @@ virDomainDeviceInfoParseXML(virDomainXMLOption *xmlopt,
}
if ((acpi = virXPathNode("./acpi", ctxt))) {
+ g_autofree char *nodeset = NULL;
+
if (virXMLPropUInt(acpi, "index", 10, VIR_XML_PROP_NONZERO,
&info->acpiIndex) < 0)
goto cleanup;
+
+ if ((nodeset = virXMLPropString(acpi, "nodeset"))) {
+ if (virBitmapParse(nodeset, &info->acpiNodeset,
+ VIR_DOMAIN_CPUMASK_LEN) < 0)
+ goto cleanup;
+
+ if (virBitmapIsAllClear(info->acpiNodeset)) {
+ virReportError(VIR_ERR_CONFIG_UNSUPPORTED,
+ _("Invalid value of 'nodeset': %1$s"), nodeset);
+ goto cleanup;
+ }
+ }
}
if ((address = virXPathNode("./address", ctxt)) &&
diff --git a/src/conf/schemas/domaincommon.rng b/src/conf/schemas/domaincommon.rng
index e369fb6e81..298afe0b7c 100644
--- a/src/conf/schemas/domaincommon.rng
+++ b/src/conf/schemas/domaincommon.rng
@@ -7454,6 +7454,11 @@
<ref name="unsignedInt"/>
</attribute>
</optional>
+ <optional>
+ <attribute name="nodeset">
+ <ref name="cpuset"/>
+ </attribute>
+ </optional>
</element>
</define>
--
2.51.0