
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