[PATCH v4 0/8] qemu: acpi-generic-initiator support

= Overview = This patch set introduces support for acpi-generic-initiator devices, supported by QEMU [1]. The acpi-generic-initiator object is required to support Multi-Instance GPU (MIG) configurations on NVIDIA GPUs [2]. MIG enables partitioning of GPU resources into multiple isolated instances, each requiring a dedicated NUMA node definition. = Implementation = This patch set implements the libvirt counterpart to the QEMU feature, enabling users to configure acpi-generic-initiator objects within libvirt domain XML. This includes: - adding XML syntax to define acpi-generic-initiator objects, - resolving the acpi-generic-initiator definitions into the proper QEMU command-line arguments, - ensuring compatibility with existing NUMA configuration. = Example = - Domain XML: ``` ... <cpu mode='host-passthrough' check='none'> <numa> <cell id='0' cpus='0-15' memory='8388608' unit='KiB'/> <cell id='1' memory='0' unit='KiB'/> <cell id='2' memory='0' unit='KiB'/> <cell id='3' memory='0' unit='KiB'/> <cell id='4' memory='0' unit='KiB'/> <cell id='5' memory='0' unit='KiB'/> <cell id='6' memory='0' unit='KiB'/> <cell id='7' memory='0' unit='KiB'/> <cell id='8' memory='0' unit='KiB'/> </numa> </cpu> ... <devices> ... <hostdev mode='subsystem' type='pci' managed='no'> <source> <address domain='0x0009' bus='0x01' slot='0x00' function='0x0'/> </source> <address type='pci' domain='0x0000' bus='0x03' slot='0x00' function='0x0'/> </hostdev> <acpi-generic-initiator> <pci-dev>hostdev0</pci-dev> <numa-node>1</numa-node> </acpi-generic-initiator> <acpi-generic-initiator> <pci-dev>hostdev0</pci-dev> <numa-node>2</numa-node> </acpi-generic-initiator> <acpi-generic-initiator> <pci-dev>hostdev0</pci-dev> <numa-node>3</numa-node> </acpi-generic-initiator> <acpi-generic-initiator> <pci-dev>hostdev0</pci-dev> <numa-node>4</numa-node> </acpi-generic-initiator> <acpi-generic-initiator> <pci-dev>hostdev0</pci-dev> <numa-node>5</numa-node> </acpi-generic-initiator> <acpi-generic-initiator> <pci-dev>hostdev0</pci-dev> <numa-node>6</numa-node> </acpi-generic-initiator> <acpi-generic-initiator> <pci-dev>hostdev0</pci-dev> <numa-node>7</numa-node> </acpi-generic-initiator> <acpi-generic-initiator> <pci-dev>hostdev0</pci-dev> <numa-node>8</numa-node> </acpi-generic-initiator> </devices> ``` - Generated QEMU command line options: ``` ... /usr/bin/qemu-system-aarch64 \ ... -object '{"qom-type":"memory-backend-ram","id":"ram-node0","size":8589934592}' \ -numa node,nodeid=0,cpus=0-15,memdev=ram-node0 \ -numa node,nodeid=1 \ -numa node,nodeid=2 \ -numa node,nodeid=3 \ -numa node,nodeid=4 \ -numa node,nodeid=5 \ -numa node,nodeid=6 \ -numa node,nodeid=7 \ -numa node,nodeid=8 \ ... -device '{"driver":"vfio-pci","host":"0009:01:00.0","id":"hostdev0","bus":"pci.3","addr":"0x0"}' ... -object acpi-generic-initiator,id=gi0,pci-dev=hostdev0,node=1 \ -object acpi-generic-initiator,id=gi1,pci-dev=hostdev0,node=2 \ -object acpi-generic-initiator,id=gi2,pci-dev=hostdev0,node=3 \ -object acpi-generic-initiator,id=gi3,pci-dev=hostdev0,node=4 \ -object acpi-generic-initiator,id=gi4,pci-dev=hostdev0,node=5 \ -object acpi-generic-initiator,id=gi5,pci-dev=hostdev0,node=6 \ -object acpi-generic-initiator,id=gi6,pci-dev=hostdev0,node=7 \ -object acpi-generic-initiator,id=gi7,pci-dev=hostdev0,node=8 ``` = References = [1] https://lore.kernel.org/all/20231225045603.7654-2-ankita@nvidia.com/ [2] https://www.nvidia.com/en-in/technologies/multi-instance-gpu/ This patchset is also available in the following git branch: https://github.com/arighi/libvirt.git acpi-generic-initiator-v4 ChangeLog v3 -> v4: - add acpi-generic-initiator documentation - refactor virDomainAcpiInitiatorDef to use info->alias and drop the name attribute - auto-generate alias for the acpi-generic-initiator devices via qemuAssignDeviceAliases() - use g_autoptr() when possible - add a new entry to NEWS.rst ChangeLog v2 -> v3: - replaced <text/> with proper types in the XML schema - avoid mixing g_free() and VIR_FREE() - use virXMLPropString() instead of looping all XML nodes - report proper errors with virReportError() - use virBufferEscapeString() to process strings passed by the user - fix broken formatting of function headers - misc coding style fixes ChangeLog v1 -> v2: - split parser and driver changes in separate patches - introduce a new qemu capability flag - introduce test in qemuxmlconftest Andrea Righi (8): schema: Introduce acpi-generic-initiator definition conf: Introduce acpi-generic-initiator device qemu: Allow to define NUMA nodes without memory or CPUs assigned qemu: capabilies: Introduce QEMU_CAPS_ACPI_GENERIC_INITIATOR qemu: Support acpi-generic-initiator qemu: Add test case for acpi-generic-initiator docs: Document acpi-generic-initiator device NEWS: Mention new acpi-generic-initiator device NEWS.rst | 8 ++ docs/formatdomain.rst | 36 ++++++ src/ch/ch_domain.c | 1 + src/conf/domain_conf.c | 138 +++++++++++++++++++++ src/conf/domain_conf.h | 14 +++ src/conf/domain_postparse.c | 1 + src/conf/domain_validate.c | 37 ++++++ src/conf/numa_conf.c | 3 + src/conf/schemas/domaincommon.rng | 14 +++ src/conf/virconftypes.h | 2 + src/hyperv/hyperv_driver.c | 1 + src/libxl/libxl_driver.c | 6 + src/lxc/lxc_driver.c | 6 + src/qemu/qemu_alias.c | 11 ++ src/qemu/qemu_capabilities.c | 2 + src/qemu/qemu_capabilities.h | 1 + src/qemu/qemu_command.c | 49 ++++++-- 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 + tests/qemucapabilitiesdata/caps_10.0.0_aarch64.xml | 1 + .../caps_10.0.0_x86_64+amdsev.xml | 1 + tests/qemucapabilitiesdata/caps_10.0.0_x86_64.xml | 1 + tests/qemucapabilitiesdata/caps_9.0.0_x86_64.xml | 1 + tests/qemucapabilitiesdata/caps_9.1.0_riscv64.xml | 1 + tests/qemucapabilitiesdata/caps_9.1.0_x86_64.xml | 1 + .../caps_9.2.0_aarch64+hvf.xml | 1 + .../caps_9.2.0_x86_64+amdsev.xml | 1 + tests/qemucapabilitiesdata/caps_9.2.0_x86_64.xml | 1 + .../acpi-generic-initiator.x86_64-latest.args | 55 ++++++++ .../acpi-generic-initiator.x86_64-latest.xml | 94 ++++++++++++++ tests/qemuxmlconfdata/acpi-generic-initiator.xml | 94 ++++++++++++++ tests/qemuxmlconftest.c | 1 + 37 files changed, 596 insertions(+), 7 deletions(-) create mode 100644 tests/qemuxmlconfdata/acpi-generic-initiator.x86_64-latest.args create mode 100644 tests/qemuxmlconfdata/acpi-generic-initiator.x86_64-latest.xml create mode 100644 tests/qemuxmlconfdata/acpi-generic-initiator.xml

Introduce the definition of a new acpi-generic-initiator object that can be used to link a PCI device with multiple NUMA nodes. Link: https://mail.gnu.org/archive/html/qemu-arm/2024-03/msg00358.html Signed-off-by: Andrea Righi <arighi@nvidia.com> --- src/conf/domain_conf.c | 26 ++++++++++++++++++++++++++ src/conf/domain_conf.h | 13 +++++++++++++ src/conf/schemas/domaincommon.rng | 19 +++++++++++++++++++ src/conf/virconftypes.h | 2 ++ 4 files changed, 60 insertions(+) diff --git a/src/conf/domain_conf.c b/src/conf/domain_conf.c index be70ec3b96..bfa3a46941 100644 --- a/src/conf/domain_conf.c +++ b/src/conf/domain_conf.c @@ -3479,6 +3479,19 @@ virDomainHostdevDefNew(void) } +virDomainAcpiInitiatorDef * +virDomainAcpiInitiatorDefNew(void) +{ + virDomainAcpiInitiatorDef *def; + + def = g_new0(virDomainAcpiInitiatorDef, 1); + + def->info = g_new0(virDomainDeviceInfo, 1); + + return def; +} + + static virDomainTPMDef * virDomainTPMDefNew(virDomainXMLOption *xmlopt) { @@ -3539,6 +3552,19 @@ void virDomainHostdevDefFree(virDomainHostdevDef *def) g_free(def); } +void +virDomainAcpiInitiatorDefFree(virDomainAcpiInitiatorDef *def) +{ + if (!def) + return; + + g_free(def->name); + g_free(def->pciDev); + + virDomainDeviceInfoFree(def->info); + g_free(def); +} + void virDomainHubDefFree(virDomainHubDef *def) { if (!def) diff --git a/src/conf/domain_conf.h b/src/conf/domain_conf.h index 5e02c15ed5..6aa76f7ff0 100644 --- a/src/conf/domain_conf.h +++ b/src/conf/domain_conf.h @@ -122,6 +122,7 @@ struct _virDomainDeviceDef { virDomainAudioDef *audio; virDomainCryptoDef *crypto; virDomainPstoreDef *pstore; + virDomainAcpiInitiatorDef *acpiinitiator; } data; }; @@ -353,6 +354,13 @@ typedef enum { VIR_DOMAIN_STARTUP_POLICY_LAST } virDomainStartupPolicy; +struct _virDomainAcpiInitiatorDef { + char *name; + char *pciDev; + int numaNode; + virDomainDeviceInfo *info; /* Guest address */ +}; + /* basic device for direct passthrough */ struct _virDomainHostdevDef { /* If 'parentnet' is non-NULL it means this host dev was @@ -3261,6 +3269,9 @@ struct _virDomainDef { size_t ntpms; virDomainTPMDef **tpms; + size_t nacpiinitiator; + virDomainAcpiInitiatorDef **acpiinitiator; + /* Only 1 */ virDomainMemballoonDef *memballoon; virDomainNVRAMDef *nvram; @@ -3743,6 +3754,8 @@ virDomainVideoDef *virDomainVideoDefNew(virDomainXMLOption *xmlopt); void virDomainVideoDefFree(virDomainVideoDef *def); G_DEFINE_AUTOPTR_CLEANUP_FUNC(virDomainVideoDef, virDomainVideoDefFree); void virDomainVideoDefClear(virDomainVideoDef *def); +virDomainAcpiInitiatorDef *virDomainAcpiInitiatorDefNew(void); +void virDomainAcpiInitiatorDefFree(virDomainAcpiInitiatorDef *def); virDomainHostdevDef *virDomainHostdevDefNew(void); void virDomainHostdevDefFree(virDomainHostdevDef *def); void virDomainHubDefFree(virDomainHubDef *def); diff --git a/src/conf/schemas/domaincommon.rng b/src/conf/schemas/domaincommon.rng index 81afa10083..2e307e4559 100644 --- a/src/conf/schemas/domaincommon.rng +++ b/src/conf/schemas/domaincommon.rng @@ -6848,6 +6848,7 @@ <ref name="shmem"/> <ref name="memorydev"/> <ref name="crypto"/> + <ref name="acpi-generic-initiator"/> </choice> </zeroOrMore> <zeroOrMore> @@ -7703,6 +7704,24 @@ </element> </define> + <define name="acpi-generic-initiator"> + <element name="acpi-generic-initiator"> + <interleave> + <element name="alias"> + <attribute name="name"> + <ref name="objectName"/> + </attribute> + </element> + <element name="pci-dev"> + <ref name="alias"/> + </element> + <element name="numa-node"> + <ref name="unsignedInt"/> + </element> + </interleave> + </element> + </define> + <define name="crypto"> <element name="crypto"> <attribute name="model"> diff --git a/src/conf/virconftypes.h b/src/conf/virconftypes.h index c70437bc05..776a804cd3 100644 --- a/src/conf/virconftypes.h +++ b/src/conf/virconftypes.h @@ -122,6 +122,8 @@ typedef struct _virDomainHostdevCaps virDomainHostdevCaps; typedef struct _virDomainHostdevDef virDomainHostdevDef; +typedef struct _virDomainAcpiInitiatorDef virDomainAcpiInitiatorDef; + typedef struct _virDomainHostdevSubsys virDomainHostdevSubsys; typedef struct _virDomainHostdevSubsysMediatedDev virDomainHostdevSubsysMediatedDev; -- 2.49.0

On 6/8/25 22:44, Andrea Righi via Devel wrote:
Introduce the definition of a new acpi-generic-initiator object that can be used to link a PCI device with multiple NUMA nodes.
Link: https://mail.gnu.org/archive/html/qemu-arm/2024-03/msg00358.html
Signed-off-by: Andrea Righi <arighi@nvidia.com> --- src/conf/domain_conf.c | 26 ++++++++++++++++++++++++++ src/conf/domain_conf.h | 13 +++++++++++++ src/conf/schemas/domaincommon.rng | 19 +++++++++++++++++++ src/conf/virconftypes.h | 2 ++ 4 files changed, 60 insertions(+)
This could have been merged with the next patch. Especially since the next patch removes couple of lines from this patch. Michal

Introduce apci-generic-initiator device to the domain XML. Example definition: <acpi-generic-initiator> <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@nvidia.com> --- src/ch/ch_domain.c | 1 + src/conf/domain_conf.c | 122 ++++++++++++++++++++++++++++-- src/conf/domain_conf.h | 5 +- src/conf/domain_postparse.c | 1 + src/conf/domain_validate.c | 37 +++++++++ src/conf/schemas/domaincommon.rng | 7 +- src/hyperv/hyperv_driver.c | 1 + src/libxl/libxl_driver.c | 6 ++ src/lxc/lxc_driver.c | 6 ++ src/qemu/qemu_alias.c | 11 +++ 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 + 18 files changed, 205 insertions(+), 13 deletions(-) diff --git a/src/ch/ch_domain.c b/src/ch/ch_domain.c index 7231fdc49f..95d835f07f 100644 --- a/src/ch/ch_domain.c +++ b/src/ch/ch_domain.c @@ -164,6 +164,7 @@ chValidateDomainDeviceDef(const virDomainDeviceDef *dev, case VIR_DOMAIN_DEVICE_CHR: case VIR_DOMAIN_DEVICE_HOSTDEV: case VIR_DOMAIN_DEVICE_RNG: + 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 bfa3a46941..5558e6387f 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, @@ -3486,8 +3487,6 @@ virDomainAcpiInitiatorDefNew(void) def = g_new0(virDomainAcpiInitiatorDef, 1); - def->info = g_new0(virDomainDeviceInfo, 1); - return def; } @@ -3558,10 +3557,7 @@ virDomainAcpiInitiatorDefFree(virDomainAcpiInitiatorDef *def) if (!def) return; - g_free(def->name); g_free(def->pciDev); - - virDomainDeviceInfoFree(def->info); g_free(def); } @@ -3727,6 +3723,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 +4704,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 +4814,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 +5042,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 +5109,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 @@ -13674,6 +13686,49 @@ virDomainHostdevDefParseXML(virDomainXMLOption *xmlopt, } +static virDomainAcpiInitiatorDef * +virDomainAcpiInitiatorDefParseXML(virDomainXMLOption *xmlopt, + xmlNodePtr node, + xmlXPathContextPtr ctxt, + unsigned int flags) +{ + g_autoptr(virDomainAcpiInitiatorDef) def = virDomainAcpiInitiatorDefNew(); + g_autofree char *tmp = NULL; + + VIR_XPATH_NODE_AUTORESTORE(ctxt) + + ctxt->node = node; + + if (virDomainDeviceInfoParseXML(xmlopt, node, ctxt, &def->info, flags) < 0) { + virReportError(VIR_ERR_XML_ERROR, "%s", + _("failed to parse device information")); + return NULL; + } + + def->pciDev = virXPathString("string(./pci-dev)", ctxt); + if (!def->pciDev) { + virReportError(VIR_ERR_XML_ERROR, "%s", + _("missing initiator pci-dev")); + return NULL; + } + + tmp = virXPathString("string(./numa-node)", ctxt); + if (tmp) { + if (virStrToLong_i(tmp, NULL, 10, &def->numaNode) < 0) { + virReportError(VIR_ERR_CONFIG_UNSUPPORTED, + _("invalid value for numa-node: '%1$s'"), tmp); + return NULL; + } + } else { + virReportError(VIR_ERR_XML_ERROR, "%s", + _("missing initiator numa-node")); + return NULL; + } + + return g_steal_pointer(&def); +} + + static virDomainRedirdevDef * virDomainRedirdevDefParseXML(virDomainXMLOption *xmlopt, xmlNodePtr node, @@ -14675,6 +14730,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; @@ -20084,6 +20145,24 @@ virDomainDefParseXML(xmlXPathContextPtr ctxt, } VIR_FREE(nodes); + /* analysis of the acpi generic initiator */ + if ((n = virXPathNodeSet("./devices/acpi-generic-initiator", ctxt, &nodes)) < 0) + return NULL; + + if (n) + def->acpiinitiator = g_new0(virDomainAcpiInitiatorDef *, n); + + 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); + /* analysis of the user namespace mapping */ if ((n = virXPathNodeSet("./idmap/uid", ctxt, &nodes)) < 0) return NULL; @@ -21024,6 +21103,17 @@ virDomainHostdevDefCheckABIStability(virDomainHostdevDef *src, } +static bool +virDomainAcpiInitiatorDefCheckABIStability(virDomainAcpiInitiatorDef *src, + virDomainAcpiInitiatorDef *dst) +{ + if (!virDomainDeviceInfoCheckABIStability(&src->info, &dst->info)) + return false; + + return true; +} + + static bool virDomainSmartcardDefCheckABIStability(virDomainSmartcardDef *src, virDomainSmartcardDef *dst) @@ -22372,6 +22462,12 @@ virDomainDefCheckABIStabilityFlags(virDomainDef *src, goto error; } + for (i = 0; i < src->nacpiinitiator; i++) { + if (!virDomainAcpiInitiatorDefCheckABIStability(src->acpiinitiator[i], + dst->acpiinitiator[i])) + goto error; + } + if ((!src->redirfilter && dst->redirfilter) || (src->redirfilter && !dst->redirfilter)) { virReportError(VIR_ERR_CONFIG_UNSUPPORTED, @@ -22542,6 +22638,7 @@ virDomainDefCheckABIStabilityFlags(virDomainDef *src, case VIR_DOMAIN_DEVICE_AUDIO: case VIR_DOMAIN_DEVICE_CRYPTO: case VIR_DOMAIN_DEVICE_PSTORE: + case VIR_DOMAIN_DEVICE_ACPI_INITIATOR: break; } #endif @@ -28762,6 +28859,17 @@ virDomainPstoreDefFormat(virBuffer *buf, return 0; } +static void +virDomainAcpiInitiatorDefFormat(virBuffer *buf, + virDomainAcpiInitiatorDef *acpiinitiator) +{ + g_auto(virBuffer) childBuf = VIR_BUFFER_INIT_CHILD(buf); + + virBufferEscapeString(&childBuf, "<pci-dev>%s</pci-dev>\n", acpiinitiator->pciDev); + virBufferAsprintf(&childBuf, "<numa-node>%d</numa-node>\n", acpiinitiator->numaNode); + + virXMLFormatElement(buf, "acpi-generic-initiator", NULL, &childBuf); +} int virDomainDefFormatInternal(virDomainDef *def, @@ -29246,6 +29354,9 @@ virDomainDefFormatInternalSetRootName(virDomainDef *def, if (def->pstore) virDomainPstoreDefFormat(buf, def->pstore, flags); + for (n = 0; n < def->nacpiinitiator; n++) + virDomainAcpiInitiatorDefFormat(buf, def->acpiinitiator[n]); + virBufferAdjustIndent(buf, -2); virBufferAddLit(buf, "</devices>\n"); @@ -29406,6 +29517,7 @@ virDomainDeviceIsUSB(virDomainDeviceDef *dev, case VIR_DOMAIN_DEVICE_AUDIO: case VIR_DOMAIN_DEVICE_CRYPTO: case VIR_DOMAIN_DEVICE_PSTORE: + case VIR_DOMAIN_DEVICE_ACPI_INITIATOR: break; } diff --git a/src/conf/domain_conf.h b/src/conf/domain_conf.h index 6aa76f7ff0..e843e2b87a 100644 --- a/src/conf/domain_conf.h +++ b/src/conf/domain_conf.h @@ -88,6 +88,7 @@ typedef enum { VIR_DOMAIN_DEVICE_AUDIO, VIR_DOMAIN_DEVICE_CRYPTO, VIR_DOMAIN_DEVICE_PSTORE, + VIR_DOMAIN_DEVICE_ACPI_INITIATOR, VIR_DOMAIN_DEVICE_LAST } virDomainDeviceType; @@ -355,10 +356,9 @@ typedef enum { } virDomainStartupPolicy; struct _virDomainAcpiInitiatorDef { - char *name; char *pciDev; int numaNode; - virDomainDeviceInfo *info; /* Guest address */ + virDomainDeviceInfo info; }; /* basic device for direct passthrough */ @@ -3756,6 +3756,7 @@ G_DEFINE_AUTOPTR_CLEANUP_FUNC(virDomainVideoDef, virDomainVideoDefFree); void virDomainVideoDefClear(virDomainVideoDef *def); virDomainAcpiInitiatorDef *virDomainAcpiInitiatorDefNew(void); void virDomainAcpiInitiatorDefFree(virDomainAcpiInitiatorDef *def); +G_DEFINE_AUTOPTR_CLEANUP_FUNC(virDomainAcpiInitiatorDef, virDomainAcpiInitiatorDefFree); virDomainHostdevDef *virDomainHostdevDefNew(void); void virDomainHostdevDefFree(virDomainHostdevDef *def); void virDomainHubDefFree(virDomainHubDef *def); diff --git a/src/conf/domain_postparse.c b/src/conf/domain_postparse.c index bf33f29638..acdfbdc679 100644 --- a/src/conf/domain_postparse.c +++ b/src/conf/domain_postparse.c @@ -757,6 +757,7 @@ virDomainDeviceDefPostParseCommon(virDomainDeviceDef *dev, case VIR_DOMAIN_DEVICE_IOMMU: case VIR_DOMAIN_DEVICE_AUDIO: case VIR_DOMAIN_DEVICE_CRYPTO: + case VIR_DOMAIN_DEVICE_ACPI_INITIATOR: case VIR_DOMAIN_DEVICE_PSTORE: ret = 0; break; diff --git a/src/conf/domain_validate.c b/src/conf/domain_validate.c index d0d4bc0bf4..d7397e2a2f 100644 --- a/src/conf/domain_validate.c +++ b/src/conf/domain_validate.c @@ -2375,6 +2375,40 @@ virDomainHostdevDefValidate(const virDomainHostdevDef *hostdev) } +static int +virDomainAcpiInitiatorDefValidate(const virDomainDef *def, + const virDomainAcpiInitiatorDef *acpiinitiator) +{ + const size_t nodeCount = virDomainNumaGetNodeCount(def->numa); + + if (!nodeCount) { + virReportError(VIR_ERR_XML_DETAIL, "%s", + _("No NUMA node defined")); + return -1; + } + + if (acpiinitiator->numaNode >= nodeCount) { + virReportError(VIR_ERR_CONFIG_UNSUPPORTED, + _("invalid acpi-generic-initiator NUMA node %1$u"), + acpiinitiator->numaNode); + return -1; + } + + if (acpiinitiator->pciDev[0] == '\0') { + virReportError(VIR_ERR_XML_DETAIL, "%s", + _("acpi-generic-initiator must have a PCI device assigned")); + return -1; + } + + if (acpiinitiator->info.type != VIR_DOMAIN_DEVICE_ADDRESS_TYPE_NONE) { + virReportError(VIR_ERR_XML_DETAIL, "%s", + _("acpi-generic-initiator must have a device address type None")); + return -1; + } + + return 0; +} + /** * virDomainMemoryGetMappedSize: * @mem: memory device definition @@ -3293,6 +3327,9 @@ virDomainDeviceDefValidateInternal(const virDomainDeviceDef *dev, case VIR_DOMAIN_DEVICE_PSTORE: return virDomainPstoreDefValidate(dev->data.pstore); + case VIR_DOMAIN_DEVICE_ACPI_INITIATOR: + return virDomainAcpiInitiatorDefValidate(def, dev->data.acpiinitiator); + case VIR_DOMAIN_DEVICE_LEASE: case VIR_DOMAIN_DEVICE_WATCHDOG: case VIR_DOMAIN_DEVICE_HUB: diff --git a/src/conf/schemas/domaincommon.rng b/src/conf/schemas/domaincommon.rng index 2e307e4559..0909aa26a6 100644 --- a/src/conf/schemas/domaincommon.rng +++ b/src/conf/schemas/domaincommon.rng @@ -7707,13 +7707,8 @@ <define name="acpi-generic-initiator"> <element name="acpi-generic-initiator"> <interleave> - <element name="alias"> - <attribute name="name"> - <ref name="objectName"/> - </attribute> - </element> <element name="pci-dev"> - <ref name="alias"/> + <ref name="aliasName"/> </element> <element name="numa-node"> <ref name="unsignedInt"/> diff --git a/src/hyperv/hyperv_driver.c b/src/hyperv/hyperv_driver.c index 0d1e388c08..068d5db115 100644 --- a/src/hyperv/hyperv_driver.c +++ b/src/hyperv/hyperv_driver.c @@ -3122,6 +3122,7 @@ hypervDomainAttachDeviceFlags(virDomainPtr domain, const char *xml, unsigned int case VIR_DOMAIN_DEVICE_AUDIO: case VIR_DOMAIN_DEVICE_CRYPTO: case VIR_DOMAIN_DEVICE_PSTORE: + case VIR_DOMAIN_DEVICE_ACPI_INITIATOR: virReportError(VIR_ERR_INTERNAL_ERROR, _("Attaching devices of type %1$d is not implemented"), dev->type); return -1; diff --git a/src/libxl/libxl_driver.c b/src/libxl/libxl_driver.c index 0fb256e5c0..bc3f25b3cb 100644 --- a/src/libxl/libxl_driver.c +++ b/src/libxl/libxl_driver.c @@ -3492,6 +3492,7 @@ libxlDomainAttachDeviceLive(libxlDriverPrivate *driver, case VIR_DOMAIN_DEVICE_AUDIO: case VIR_DOMAIN_DEVICE_CRYPTO: case VIR_DOMAIN_DEVICE_PSTORE: + case VIR_DOMAIN_DEVICE_ACPI_INITIATOR: virReportError(VIR_ERR_CONFIG_UNSUPPORTED, _("device type '%1$s' cannot be attached"), virDomainDeviceTypeToString(dev->type)); @@ -3596,6 +3597,7 @@ libxlDomainAttachDeviceConfig(virDomainDef *vmdef, virDomainDeviceDef *dev) case VIR_DOMAIN_DEVICE_AUDIO: case VIR_DOMAIN_DEVICE_CRYPTO: case VIR_DOMAIN_DEVICE_PSTORE: + case VIR_DOMAIN_DEVICE_ACPI_INITIATOR: virReportError(VIR_ERR_CONFIG_UNSUPPORTED, "%s", _("persistent attach of device is not supported")); return -1; @@ -3965,6 +3967,7 @@ libxlDomainDetachDeviceLive(libxlDriverPrivate *driver, case VIR_DOMAIN_DEVICE_AUDIO: case VIR_DOMAIN_DEVICE_CRYPTO: case VIR_DOMAIN_DEVICE_PSTORE: + case VIR_DOMAIN_DEVICE_ACPI_INITIATOR: virReportError(VIR_ERR_CONFIG_UNSUPPORTED, _("device type '%1$s' cannot be detached"), virDomainDeviceTypeToString(dev->type)); @@ -4056,6 +4059,7 @@ libxlDomainDetachDeviceConfig(virDomainDef *vmdef, virDomainDeviceDef *dev) case VIR_DOMAIN_DEVICE_AUDIO: case VIR_DOMAIN_DEVICE_CRYPTO: case VIR_DOMAIN_DEVICE_PSTORE: + case VIR_DOMAIN_DEVICE_ACPI_INITIATOR: virReportError(VIR_ERR_CONFIG_UNSUPPORTED, "%s", _("persistent detach of device is not supported")); return -1; @@ -4119,6 +4123,7 @@ libxlDomainUpdateDeviceLive(virDomainObj *vm, virDomainDeviceDef *dev) case VIR_DOMAIN_DEVICE_AUDIO: case VIR_DOMAIN_DEVICE_CRYPTO: case VIR_DOMAIN_DEVICE_PSTORE: + case VIR_DOMAIN_DEVICE_ACPI_INITIATOR: virReportError(VIR_ERR_CONFIG_UNSUPPORTED, _("device type '%1$s' cannot be updated"), virDomainDeviceTypeToString(dev->type)); @@ -4182,6 +4187,7 @@ libxlDomainUpdateDeviceConfig(virDomainDef *vmdef, virDomainDeviceDef *dev) case VIR_DOMAIN_DEVICE_AUDIO: case VIR_DOMAIN_DEVICE_CRYPTO: case VIR_DOMAIN_DEVICE_PSTORE: + case VIR_DOMAIN_DEVICE_ACPI_INITIATOR: virReportError(VIR_ERR_CONFIG_UNSUPPORTED, "%s", _("persistent update of device is not supported")); return -1; diff --git a/src/lxc/lxc_driver.c b/src/lxc/lxc_driver.c index 80cf07d2e5..51071958e8 100644 --- a/src/lxc/lxc_driver.c +++ b/src/lxc/lxc_driver.c @@ -3020,6 +3020,7 @@ lxcDomainAttachDeviceConfig(virDomainDef *vmdef, case VIR_DOMAIN_DEVICE_AUDIO: case VIR_DOMAIN_DEVICE_CRYPTO: case VIR_DOMAIN_DEVICE_PSTORE: + case VIR_DOMAIN_DEVICE_ACPI_INITIATOR: virReportError(VIR_ERR_CONFIG_UNSUPPORTED, "%s", _("persistent attach of device is not supported")); break; @@ -3086,6 +3087,7 @@ lxcDomainUpdateDeviceConfig(virDomainDef *vmdef, case VIR_DOMAIN_DEVICE_AUDIO: case VIR_DOMAIN_DEVICE_CRYPTO: case VIR_DOMAIN_DEVICE_PSTORE: + case VIR_DOMAIN_DEVICE_ACPI_INITIATOR: virReportError(VIR_ERR_CONFIG_UNSUPPORTED, "%s", _("persistent update of device is not supported")); break; @@ -3168,6 +3170,7 @@ lxcDomainDetachDeviceConfig(virDomainDef *vmdef, case VIR_DOMAIN_DEVICE_CRYPTO: case VIR_DOMAIN_DEVICE_AUDIO: case VIR_DOMAIN_DEVICE_PSTORE: + case VIR_DOMAIN_DEVICE_ACPI_INITIATOR: virReportError(VIR_ERR_CONFIG_UNSUPPORTED, "%s", _("persistent detach of device is not supported")); break; @@ -3270,6 +3273,7 @@ lxcDomainAttachDeviceMknodHelper(pid_t pid G_GNUC_UNUSED, case VIR_DOMAIN_DEVICE_AUDIO: case VIR_DOMAIN_DEVICE_CRYPTO: case VIR_DOMAIN_DEVICE_PSTORE: + case VIR_DOMAIN_DEVICE_ACPI_INITIATOR: virReportError(VIR_ERR_INTERNAL_ERROR, _("Unexpected device type %1$d"), data->def->type); @@ -3946,6 +3950,7 @@ lxcDomainAttachDeviceLive(virLXCDriver *driver, case VIR_DOMAIN_DEVICE_AUDIO: case VIR_DOMAIN_DEVICE_CRYPTO: case VIR_DOMAIN_DEVICE_PSTORE: + case VIR_DOMAIN_DEVICE_ACPI_INITIATOR: virReportError(VIR_ERR_CONFIG_UNSUPPORTED, _("device type '%1$s' cannot be attached"), virDomainDeviceTypeToString(dev->type)); @@ -4364,6 +4369,7 @@ lxcDomainDetachDeviceLive(virLXCDriver *driver, case VIR_DOMAIN_DEVICE_AUDIO: case VIR_DOMAIN_DEVICE_CRYPTO: case VIR_DOMAIN_DEVICE_PSTORE: + case VIR_DOMAIN_DEVICE_ACPI_INITIATOR: virReportError(VIR_ERR_CONFIG_UNSUPPORTED, _("device type '%1$s' cannot be detached"), virDomainDeviceTypeToString(dev->type)); diff --git a/src/qemu/qemu_alias.c b/src/qemu/qemu_alias.c index 3e6bced4a8..0d1cb8afd7 100644 --- a/src/qemu/qemu_alias.c +++ b/src/qemu/qemu_alias.c @@ -665,6 +665,14 @@ qemuAssignDevicePstoreAlias(virDomainPstoreDef *pstore) pstore->info.alias = g_strdup("pstore0"); } +static void +qemuAssignDeviceAcpiInitiatorAlias(virDomainAcpiInitiatorDef *acpiinitiator, + int idx) +{ + if (!acpiinitiator->info.alias) + acpiinitiator->info.alias = g_strdup_printf("gi%d", idx); +} + int qemuAssignDeviceAliases(virDomainDef *def) @@ -757,6 +765,9 @@ qemuAssignDeviceAliases(virDomainDef *def) } if (def->pstore) qemuAssignDevicePstoreAlias(def->pstore); + for (i = 0; i < def->nacpiinitiator; i++) { + qemuAssignDeviceAcpiInitiatorAlias(def->acpiinitiator[i], i); + } return 0; } diff --git a/src/qemu/qemu_command.c b/src/qemu/qemu_command.c index 77e7ea1299..7ddadb37d7 100644 --- a/src/qemu/qemu_command.c +++ b/src/qemu/qemu_command.c @@ -985,6 +985,7 @@ qemuBuildVirtioDevGetConfigDev(const virDomainDeviceDef *device, case VIR_DOMAIN_DEVICE_IOMMU: case VIR_DOMAIN_DEVICE_AUDIO: case VIR_DOMAIN_DEVICE_PSTORE: + case VIR_DOMAIN_DEVICE_ACPI_INITIATOR: case VIR_DOMAIN_DEVICE_LAST: default: break; diff --git a/src/qemu/qemu_domain.c b/src/qemu/qemu_domain.c index ace42b516a..b76bd2e5ed 100644 --- a/src/qemu/qemu_domain.c +++ b/src/qemu/qemu_domain.c @@ -8791,6 +8791,7 @@ qemuDomainPrepareChardevSourceOne(virDomainDeviceDef *dev, case VIR_DOMAIN_DEVICE_AUDIO: case VIR_DOMAIN_DEVICE_CRYPTO: case VIR_DOMAIN_DEVICE_PSTORE: + case VIR_DOMAIN_DEVICE_ACPI_INITIATOR: break; } @@ -10680,6 +10681,7 @@ qemuDomainDeviceBackendChardevForeachOne(virDomainDeviceDef *dev, case VIR_DOMAIN_DEVICE_AUDIO: case VIR_DOMAIN_DEVICE_CRYPTO: case VIR_DOMAIN_DEVICE_PSTORE: + case VIR_DOMAIN_DEVICE_ACPI_INITIATOR: /* no chardev backend */ break; } diff --git a/src/qemu/qemu_domain_address.c b/src/qemu/qemu_domain_address.c index e89cdee487..573bbc282c 100644 --- a/src/qemu/qemu_domain_address.c +++ b/src/qemu/qemu_domain_address.c @@ -471,6 +471,7 @@ qemuDomainDeviceSupportZPCI(virDomainDeviceDef *device) case VIR_DOMAIN_DEVICE_AUDIO: case VIR_DOMAIN_DEVICE_CRYPTO: case VIR_DOMAIN_DEVICE_PSTORE: + case VIR_DOMAIN_DEVICE_ACPI_INITIATOR: break; case VIR_DOMAIN_DEVICE_NONE: @@ -819,6 +820,9 @@ qemuDomainDeviceCalculatePCIConnectFlags(virDomainDeviceDef *dev, return pciFlags; } + case VIR_DOMAIN_DEVICE_ACPI_INITIATOR: + return pciFlags; + case VIR_DOMAIN_DEVICE_MEMBALLOON: switch (dev->data.memballoon->model) { case VIR_DOMAIN_MEMBALLOON_MODEL_VIRTIO_TRANSITIONAL: diff --git a/src/qemu/qemu_driver.c b/src/qemu/qemu_driver.c index b3b0ee66f8..779395ed5a 100644 --- a/src/qemu/qemu_driver.c +++ b/src/qemu/qemu_driver.c @@ -6908,6 +6908,7 @@ qemuDomainAttachDeviceConfig(virDomainDef *vmdef, case VIR_DOMAIN_DEVICE_AUDIO: case VIR_DOMAIN_DEVICE_CRYPTO: case VIR_DOMAIN_DEVICE_PSTORE: + case VIR_DOMAIN_DEVICE_ACPI_INITIATOR: case VIR_DOMAIN_DEVICE_LAST: virReportError(VIR_ERR_OPERATION_UNSUPPORTED, _("persistent attach of device '%1$s' is not supported"), @@ -7127,6 +7128,7 @@ qemuDomainDetachDeviceConfig(virDomainDef *vmdef, case VIR_DOMAIN_DEVICE_AUDIO: case VIR_DOMAIN_DEVICE_CRYPTO: case VIR_DOMAIN_DEVICE_PSTORE: + case VIR_DOMAIN_DEVICE_ACPI_INITIATOR: case VIR_DOMAIN_DEVICE_LAST: virReportError(VIR_ERR_OPERATION_UNSUPPORTED, _("persistent detach of device '%1$s' is not supported"), @@ -7253,6 +7255,7 @@ qemuDomainUpdateDeviceConfig(virDomainDef *vmdef, case VIR_DOMAIN_DEVICE_AUDIO: case VIR_DOMAIN_DEVICE_CRYPTO: case VIR_DOMAIN_DEVICE_PSTORE: + case VIR_DOMAIN_DEVICE_ACPI_INITIATOR: case VIR_DOMAIN_DEVICE_LAST: virReportError(VIR_ERR_OPERATION_UNSUPPORTED, _("persistent update of device '%1$s' is not supported"), diff --git a/src/qemu/qemu_hotplug.c b/src/qemu/qemu_hotplug.c index e84ad816a0..c3b3851c1a 100644 --- a/src/qemu/qemu_hotplug.c +++ b/src/qemu/qemu_hotplug.c @@ -3538,6 +3538,7 @@ qemuDomainAttachDeviceLive(virDomainObj *vm, case VIR_DOMAIN_DEVICE_AUDIO: case VIR_DOMAIN_DEVICE_CRYPTO: case VIR_DOMAIN_DEVICE_PSTORE: + case VIR_DOMAIN_DEVICE_ACPI_INITIATOR: case VIR_DOMAIN_DEVICE_LAST: virReportError(VIR_ERR_OPERATION_UNSUPPORTED, _("live attach of device '%1$s' is not supported"), @@ -5508,6 +5509,7 @@ qemuDomainRemoveAuditDevice(virDomainObj *vm, case VIR_DOMAIN_DEVICE_AUDIO: case VIR_DOMAIN_DEVICE_CRYPTO: case VIR_DOMAIN_DEVICE_PSTORE: + case VIR_DOMAIN_DEVICE_ACPI_INITIATOR: case VIR_DOMAIN_DEVICE_LAST: /* libvirt doesn't yet support detaching these devices */ break; @@ -5613,6 +5615,7 @@ qemuDomainRemoveDevice(virQEMUDriver *driver, case VIR_DOMAIN_DEVICE_AUDIO: case VIR_DOMAIN_DEVICE_CRYPTO: case VIR_DOMAIN_DEVICE_PSTORE: + case VIR_DOMAIN_DEVICE_ACPI_INITIATOR: case VIR_DOMAIN_DEVICE_LAST: virReportError(VIR_ERR_OPERATION_UNSUPPORTED, _("don't know how to remove a %1$s device"), @@ -6508,6 +6511,7 @@ qemuDomainDetachDeviceLive(virDomainObj *vm, case VIR_DOMAIN_DEVICE_AUDIO: case VIR_DOMAIN_DEVICE_CRYPTO: case VIR_DOMAIN_DEVICE_PSTORE: + case VIR_DOMAIN_DEVICE_ACPI_INITIATOR: case VIR_DOMAIN_DEVICE_LAST: virReportError(VIR_ERR_OPERATION_UNSUPPORTED, _("live detach of device '%1$s' is not supported"), @@ -7499,6 +7503,7 @@ qemuDomainUpdateDeviceLive(virDomainObj *vm, case VIR_DOMAIN_DEVICE_AUDIO: case VIR_DOMAIN_DEVICE_CRYPTO: case VIR_DOMAIN_DEVICE_PSTORE: + case VIR_DOMAIN_DEVICE_ACPI_INITIATOR: case VIR_DOMAIN_DEVICE_LAST: virReportError(VIR_ERR_CONFIG_UNSUPPORTED, _("live update of device '%1$s' is not supported"), diff --git a/src/qemu/qemu_postparse.c b/src/qemu/qemu_postparse.c index ed4af9ca8e..a6f610265e 100644 --- a/src/qemu/qemu_postparse.c +++ b/src/qemu/qemu_postparse.c @@ -906,6 +906,7 @@ qemuDomainDeviceDefPostParse(virDomainDeviceDef *dev, case VIR_DOMAIN_DEVICE_RNG: case VIR_DOMAIN_DEVICE_AUDIO: case VIR_DOMAIN_DEVICE_CRYPTO: + case VIR_DOMAIN_DEVICE_ACPI_INITIATOR: ret = 0; break; diff --git a/src/qemu/qemu_validate.c b/src/qemu/qemu_validate.c index 2cc52ff3bc..c1bd3da293 100644 --- a/src/qemu/qemu_validate.c +++ b/src/qemu/qemu_validate.c @@ -5655,6 +5655,7 @@ qemuValidateDomainDeviceDef(const virDomainDeviceDef *dev, case VIR_DOMAIN_DEVICE_PSTORE: return qemuValidateDomainDeviceDefPstore(dev->data.pstore, def, qemuCaps); + case VIR_DOMAIN_DEVICE_ACPI_INITIATOR: case VIR_DOMAIN_DEVICE_LEASE: case VIR_DOMAIN_DEVICE_PANIC: case VIR_DOMAIN_DEVICE_NONE: diff --git a/src/test/test_driver.c b/src/test/test_driver.c index 6f18b2b2c8..5c706a1035 100644 --- a/src/test/test_driver.c +++ b/src/test/test_driver.c @@ -10459,6 +10459,7 @@ testDomainAttachDeviceLive(virDomainObj *vm, case VIR_DOMAIN_DEVICE_AUDIO: case VIR_DOMAIN_DEVICE_CRYPTO: case VIR_DOMAIN_DEVICE_PSTORE: + case VIR_DOMAIN_DEVICE_ACPI_INITIATOR: case VIR_DOMAIN_DEVICE_LAST: virReportError(VIR_ERR_OPERATION_UNSUPPORTED, _("live attach of device '%1$s' is not supported"), @@ -10602,6 +10603,7 @@ testDomainUpdateDevice(virDomainDef *vmdef, case VIR_DOMAIN_DEVICE_AUDIO: case VIR_DOMAIN_DEVICE_CRYPTO: case VIR_DOMAIN_DEVICE_PSTORE: + case VIR_DOMAIN_DEVICE_ACPI_INITIATOR: case VIR_DOMAIN_DEVICE_LAST: virReportError(VIR_ERR_OPERATION_UNSUPPORTED, _("persistent update of device '%1$s' is not supported"), @@ -10973,6 +10975,7 @@ testDomainRemoveDevice(testDriver *driver, case VIR_DOMAIN_DEVICE_AUDIO: case VIR_DOMAIN_DEVICE_CRYPTO: case VIR_DOMAIN_DEVICE_PSTORE: + case VIR_DOMAIN_DEVICE_ACPI_INITIATOR: case VIR_DOMAIN_DEVICE_LAST: virReportError(VIR_ERR_OPERATION_UNSUPPORTED, _("live detach of device '%1$s' is not supported"), @@ -11044,6 +11047,7 @@ testDomainDetachDeviceLive(testDriver *driver, case VIR_DOMAIN_DEVICE_AUDIO: case VIR_DOMAIN_DEVICE_CRYPTO: case VIR_DOMAIN_DEVICE_PSTORE: + case VIR_DOMAIN_DEVICE_ACPI_INITIATOR: case VIR_DOMAIN_DEVICE_LAST: virReportError(VIR_ERR_OPERATION_UNSUPPORTED, _("live detach of device '%1$s' is not supported"), -- 2.49.0

On 6/8/25 22:44, Andrea Righi via Devel wrote:
Introduce apci-generic-initiator device to the domain XML.
Example definition:
<acpi-generic-initiator> <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@nvidia.com> --- src/ch/ch_domain.c | 1 + src/conf/domain_conf.c | 122 ++++++++++++++++++++++++++++-- src/conf/domain_conf.h | 5 +- src/conf/domain_postparse.c | 1 + src/conf/domain_validate.c | 37 +++++++++ src/conf/schemas/domaincommon.rng | 7 +- src/hyperv/hyperv_driver.c | 1 + src/libxl/libxl_driver.c | 6 ++ src/lxc/lxc_driver.c | 6 ++ src/qemu/qemu_alias.c | 11 +++ 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 + 18 files changed, 205 insertions(+), 13 deletions(-)
diff --git a/src/qemu/qemu_domain_address.c b/src/qemu/qemu_domain_address.c index e89cdee487..573bbc282c 100644 --- a/src/qemu/qemu_domain_address.c +++ b/src/qemu/qemu_domain_address.c @@ -471,6 +471,7 @@ qemuDomainDeviceSupportZPCI(virDomainDeviceDef *device) case VIR_DOMAIN_DEVICE_AUDIO: case VIR_DOMAIN_DEVICE_CRYPTO: case VIR_DOMAIN_DEVICE_PSTORE: + case VIR_DOMAIN_DEVICE_ACPI_INITIATOR: break;
case VIR_DOMAIN_DEVICE_NONE: @@ -819,6 +820,9 @@ qemuDomainDeviceCalculatePCIConnectFlags(virDomainDeviceDef *dev, return pciFlags; }
+ case VIR_DOMAIN_DEVICE_ACPI_INITIATOR: + return pciFlags; +
This doesn't make much sense to me. In QEMU this is just an object, not a device. IOW, it's not 'guest visible' and thus doesn't connect to any bus really.
case VIR_DOMAIN_DEVICE_MEMBALLOON: switch (dev->data.memballoon->model) { case VIR_DOMAIN_MEMBALLOON_MODEL_VIRTIO_TRANSITIONAL:
Michal

Allow to define NUMA nodes without memory or CPUs assigned to properly support the new acpi-generic-initiator device. This is required because the NUMA nodes passed to the acpi-generic-initiator object must be independent and not be shared with other resources, such as CPU or memory. Signed-off-by: Andrea Righi <arighi@nvidia.com> --- src/conf/numa_conf.c | 3 +++ src/qemu/qemu_command.c | 20 +++++++++++++------- 2 files changed, 16 insertions(+), 7 deletions(-) diff --git a/src/conf/numa_conf.c b/src/conf/numa_conf.c index 00f0c605ee..5b50f3e3f5 100644 --- a/src/conf/numa_conf.c +++ b/src/conf/numa_conf.c @@ -1492,6 +1492,9 @@ virDomainNumaFillCPUsInNode(virDomainNuma *numa, if (node >= virDomainNumaGetNodeCount(numa)) return -1; + if (virDomainNumaGetNodeMemorySize(numa, node) == 0) + return 0; + virBitmapSetAll(maxCPUsBitmap); for (i = 0; i < numa->nmem_nodes; i++) { diff --git a/src/qemu/qemu_command.c b/src/qemu/qemu_command.c index 7ddadb37d7..79cfe60b09 100644 --- a/src/qemu/qemu_command.c +++ b/src/qemu/qemu_command.c @@ -7665,7 +7665,10 @@ qemuBuildNumaCommandLine(virQEMUDriverConfig *cfg, } } - if (masterInitiator < 0) { + /* HMAT requires a master initiator, so when it's enabled, ensure that + * at least one NUMA node has CPUs assigned. + */ + if (hmat && masterInitiator < 0) { virReportError(VIR_ERR_CONFIG_UNSUPPORTED, "%s", _("At least one NUMA node has to have CPUs")); goto cleanup; @@ -7673,8 +7676,9 @@ qemuBuildNumaCommandLine(virQEMUDriverConfig *cfg, for (i = 0; i < ncells; i++) { ssize_t initiator = virDomainNumaGetNodeInitiator(def->numa, i); + unsigned long long memSize = virDomainNumaGetNodeMemorySize(def->numa, i); - if (needBackend) { + if (needBackend && memSize > 0) { g_autoptr(virJSONValue) tcProps = NULL; if (qemuBuildThreadContextProps(&tcProps, &nodeBackends[i], @@ -7702,11 +7706,13 @@ qemuBuildNumaCommandLine(virQEMUDriverConfig *cfg, virBufferAsprintf(&buf, ",initiator=%zd", initiator); } - if (needBackend) - virBufferAsprintf(&buf, ",memdev=ram-node%zu", i); - else - virBufferAsprintf(&buf, ",mem=%llu", - virDomainNumaGetNodeMemorySize(def->numa, i) / 1024); + if (memSize > 0) { + if (needBackend) { + virBufferAsprintf(&buf, ",memdev=ram-node%zu", i); + } else { + virBufferAsprintf(&buf, ",mem=%llu", memSize / 1024); + } + } virCommandAddArgBuffer(cmd, &buf); } -- 2.49.0

This capability tracks whether QEMU supports the acpi-generic-initiator object type. This object has been introduced in QEMU with the commit: b64b7ed8bb ("qom: new object to associate device to NUMA node"). Signed-off-by: Andrea Righi <arighi@nvidia.com> --- src/qemu/qemu_capabilities.c | 2 ++ src/qemu/qemu_capabilities.h | 1 + tests/qemucapabilitiesdata/caps_10.0.0_aarch64.xml | 1 + tests/qemucapabilitiesdata/caps_10.0.0_x86_64+amdsev.xml | 1 + tests/qemucapabilitiesdata/caps_10.0.0_x86_64.xml | 1 + tests/qemucapabilitiesdata/caps_9.0.0_x86_64.xml | 1 + tests/qemucapabilitiesdata/caps_9.1.0_riscv64.xml | 1 + tests/qemucapabilitiesdata/caps_9.1.0_x86_64.xml | 1 + tests/qemucapabilitiesdata/caps_9.2.0_aarch64+hvf.xml | 1 + tests/qemucapabilitiesdata/caps_9.2.0_x86_64+amdsev.xml | 1 + tests/qemucapabilitiesdata/caps_9.2.0_x86_64.xml | 1 + 11 files changed, 12 insertions(+) diff --git a/src/qemu/qemu_capabilities.c b/src/qemu/qemu_capabilities.c index 8ba528fc07..a8a15c56f8 100644 --- a/src/qemu/qemu_capabilities.c +++ b/src/qemu/qemu_capabilities.c @@ -734,6 +734,7 @@ VIR_ENUM_IMPL(virQEMUCaps, "virtio-scsi.iothread-mapping", /* QEMU_CAPS_VIRTIO_SCSI_IOTHREAD_MAPPING */ "machine.virt.highmem-mmio-size", /* QEMU_CAPS_MACHINE_VIRT_HIGHMEM_MMIO_SIZE */ "bus-floppy", /* QEMU_CAPS_BUS_FLOPPY */ + "acpi-generic-initiator", /* QEMU_CAPS_ACPI_GENERIC_INITIATOR */ ); @@ -1423,6 +1424,7 @@ struct virQEMUCapsStringFlags virQEMUCapsObjectTypes[] = { { "sev-snp-guest", QEMU_CAPS_SEV_SNP_GUEST }, { "acpi-erst", QEMU_CAPS_DEVICE_ACPI_ERST }, { "virtio-mem-ccw", QEMU_CAPS_DEVICE_VIRTIO_MEM_CCW }, + { "acpi-generic-initiator", QEMU_CAPS_ACPI_GENERIC_INITIATOR }, }; diff --git a/src/qemu/qemu_capabilities.h b/src/qemu/qemu_capabilities.h index 1e7e4faa9b..fb6a0751f7 100644 --- a/src/qemu/qemu_capabilities.h +++ b/src/qemu/qemu_capabilities.h @@ -715,6 +715,7 @@ typedef enum { /* virQEMUCapsFlags grouping marker for syntax-check */ QEMU_CAPS_VIRTIO_SCSI_IOTHREAD_MAPPING, /* virtio-scsi supports per-virtqueue iothread mapping */ QEMU_CAPS_MACHINE_VIRT_HIGHMEM_MMIO_SIZE, /* -machine virt,highmem-mmio-size=<size> */ QEMU_CAPS_BUS_FLOPPY, /* floppy bus supported (isa-fdc/sysbus-fdc) */ + QEMU_CAPS_ACPI_GENERIC_INITIATOR, /* -object acpi-generic-initiator command supported */ QEMU_CAPS_LAST /* this must always be the last item */ } virQEMUCapsFlags; diff --git a/tests/qemucapabilitiesdata/caps_10.0.0_aarch64.xml b/tests/qemucapabilitiesdata/caps_10.0.0_aarch64.xml index 7fd5018557..da5469e1a0 100644 --- a/tests/qemucapabilitiesdata/caps_10.0.0_aarch64.xml +++ b/tests/qemucapabilitiesdata/caps_10.0.0_aarch64.xml @@ -161,6 +161,7 @@ <flag name='shim'/> <flag name='virtio-scsi.iothread-mapping'/> <flag name='machine.virt.highmem-mmio-size'/> + <flag name='acpi-generic-initiator'/> <version>10000000</version> <microcodeVersion>61700285</microcodeVersion> <package>v10.0.0</package> diff --git a/tests/qemucapabilitiesdata/caps_10.0.0_x86_64+amdsev.xml b/tests/qemucapabilitiesdata/caps_10.0.0_x86_64+amdsev.xml index 8da17978fb..8909796883 100644 --- a/tests/qemucapabilitiesdata/caps_10.0.0_x86_64+amdsev.xml +++ b/tests/qemucapabilitiesdata/caps_10.0.0_x86_64+amdsev.xml @@ -206,6 +206,7 @@ <flag name='shim'/> <flag name='virtio-scsi.iothread-mapping'/> <flag name='bus-floppy'/> + <flag name='acpi-generic-initiator'/> <version>10000000</version> <microcodeVersion>43100285</microcodeVersion> <package>v10.0.0</package> diff --git a/tests/qemucapabilitiesdata/caps_10.0.0_x86_64.xml b/tests/qemucapabilitiesdata/caps_10.0.0_x86_64.xml index 09332805f2..b581bd7c16 100644 --- a/tests/qemucapabilitiesdata/caps_10.0.0_x86_64.xml +++ b/tests/qemucapabilitiesdata/caps_10.0.0_x86_64.xml @@ -205,6 +205,7 @@ <flag name='shim'/> <flag name='virtio-scsi.iothread-mapping'/> <flag name='bus-floppy'/> + <flag name='acpi-generic-initiator'/> <version>10000000</version> <microcodeVersion>43100285</microcodeVersion> <package>v10.0.0</package> diff --git a/tests/qemucapabilitiesdata/caps_9.0.0_x86_64.xml b/tests/qemucapabilitiesdata/caps_9.0.0_x86_64.xml index b7bd10271a..d036fb8e32 100644 --- a/tests/qemucapabilitiesdata/caps_9.0.0_x86_64.xml +++ b/tests/qemucapabilitiesdata/caps_9.0.0_x86_64.xml @@ -201,6 +201,7 @@ <flag name='intel-iommu.dma-translation'/> <flag name='machine-i8042-opt'/> <flag name='bus-floppy'/> + <flag name='acpi-generic-initiator'/> <version>9000000</version> <microcodeVersion>43100245</microcodeVersion> <package>v9.0.0</package> diff --git a/tests/qemucapabilitiesdata/caps_9.1.0_riscv64.xml b/tests/qemucapabilitiesdata/caps_9.1.0_riscv64.xml index 3b1445718a..a0eb988378 100644 --- a/tests/qemucapabilitiesdata/caps_9.1.0_riscv64.xml +++ b/tests/qemucapabilitiesdata/caps_9.1.0_riscv64.xml @@ -160,6 +160,7 @@ <flag name='acpi-erst'/> <flag name='migrate-incoming.exit-on-error'/> <flag name='machine.virt.aia'/> + <flag name='acpi-generic-initiator'/> <version>9001000</version> <microcodeVersion>0</microcodeVersion> <package>v9.1.0</package> diff --git a/tests/qemucapabilitiesdata/caps_9.1.0_x86_64.xml b/tests/qemucapabilitiesdata/caps_9.1.0_x86_64.xml index aed9ba6564..e19a0daf14 100644 --- a/tests/qemucapabilitiesdata/caps_9.1.0_x86_64.xml +++ b/tests/qemucapabilitiesdata/caps_9.1.0_x86_64.xml @@ -200,6 +200,7 @@ <flag name='machine-i8042-opt'/> <flag name='migrate-incoming.exit-on-error'/> <flag name='bus-floppy'/> + <flag name='acpi-generic-initiator'/> <version>9001000</version> <microcodeVersion>43100246</microcodeVersion> <package>v9.1.0</package> diff --git a/tests/qemucapabilitiesdata/caps_9.2.0_aarch64+hvf.xml b/tests/qemucapabilitiesdata/caps_9.2.0_aarch64+hvf.xml index ac25159eff..19d29bbc20 100644 --- a/tests/qemucapabilitiesdata/caps_9.2.0_aarch64+hvf.xml +++ b/tests/qemucapabilitiesdata/caps_9.2.0_aarch64+hvf.xml @@ -133,6 +133,7 @@ <flag name='chardev-reconnect-miliseconds'/> <flag name='netdev-stream-reconnect-miliseconds'/> <flag name='migrate-incoming.exit-on-error'/> + <flag name='acpi-generic-initiator'/> <version>9002002</version> <microcodeVersion>61700247</microcodeVersion> <package></package> diff --git a/tests/qemucapabilitiesdata/caps_9.2.0_x86_64+amdsev.xml b/tests/qemucapabilitiesdata/caps_9.2.0_x86_64+amdsev.xml index 96426a28a7..9dbfc8edcf 100644 --- a/tests/qemucapabilitiesdata/caps_9.2.0_x86_64+amdsev.xml +++ b/tests/qemucapabilitiesdata/caps_9.2.0_x86_64+amdsev.xml @@ -204,6 +204,7 @@ <flag name='netdev-stream-reconnect-miliseconds'/> <flag name='migrate-incoming.exit-on-error'/> <flag name='bus-floppy'/> + <flag name='acpi-generic-initiator'/> <version>9002000</version> <microcodeVersion>43100247</microcodeVersion> <package>v9.2.0</package> diff --git a/tests/qemucapabilitiesdata/caps_9.2.0_x86_64.xml b/tests/qemucapabilitiesdata/caps_9.2.0_x86_64.xml index adb9202ff2..baf4f6a70f 100644 --- a/tests/qemucapabilitiesdata/caps_9.2.0_x86_64.xml +++ b/tests/qemucapabilitiesdata/caps_9.2.0_x86_64.xml @@ -202,6 +202,7 @@ <flag name='netdev-stream-reconnect-miliseconds'/> <flag name='migrate-incoming.exit-on-error'/> <flag name='bus-floppy'/> + <flag name='acpi-generic-initiator'/> <version>9002000</version> <microcodeVersion>43100247</microcodeVersion> <package>v9.2.0</package> -- 2.49.0

On 6/8/25 22:44, Andrea Righi via Devel wrote:
This capability tracks whether QEMU supports the acpi-generic-initiator object type.
This object has been introduced in QEMU with the commit: b64b7ed8bb ("qom: new object to associate device to NUMA node").
Signed-off-by: Andrea Righi <arighi@nvidia.com> --- src/qemu/qemu_capabilities.c | 2 ++ src/qemu/qemu_capabilities.h | 1 + tests/qemucapabilitiesdata/caps_10.0.0_aarch64.xml | 1 + tests/qemucapabilitiesdata/caps_10.0.0_x86_64+amdsev.xml | 1 + tests/qemucapabilitiesdata/caps_10.0.0_x86_64.xml | 1 + tests/qemucapabilitiesdata/caps_9.0.0_x86_64.xml | 1 + tests/qemucapabilitiesdata/caps_9.1.0_riscv64.xml | 1 + tests/qemucapabilitiesdata/caps_9.1.0_x86_64.xml | 1 + tests/qemucapabilitiesdata/caps_9.2.0_aarch64+hvf.xml | 1 + tests/qemucapabilitiesdata/caps_9.2.0_x86_64+amdsev.xml | 1 + tests/qemucapabilitiesdata/caps_9.2.0_x86_64.xml | 1 + 11 files changed, 12 insertions(+)
diff --git a/src/qemu/qemu_capabilities.c b/src/qemu/qemu_capabilities.c index 8ba528fc07..a8a15c56f8 100644 --- a/src/qemu/qemu_capabilities.c +++ b/src/qemu/qemu_capabilities.c @@ -734,6 +734,7 @@ VIR_ENUM_IMPL(virQEMUCaps, "virtio-scsi.iothread-mapping", /* QEMU_CAPS_VIRTIO_SCSI_IOTHREAD_MAPPING */ "machine.virt.highmem-mmio-size", /* QEMU_CAPS_MACHINE_VIRT_HIGHMEM_MMIO_SIZE */ "bus-floppy", /* QEMU_CAPS_BUS_FLOPPY */ + "acpi-generic-initiator", /* QEMU_CAPS_ACPI_GENERIC_INITIATOR */ );
@@ -1423,6 +1424,7 @@ struct virQEMUCapsStringFlags virQEMUCapsObjectTypes[] = { { "sev-snp-guest", QEMU_CAPS_SEV_SNP_GUEST }, { "acpi-erst", QEMU_CAPS_DEVICE_ACPI_ERST }, { "virtio-mem-ccw", QEMU_CAPS_DEVICE_VIRTIO_MEM_CCW }, + { "acpi-generic-initiator", QEMU_CAPS_ACPI_GENERIC_INITIATOR }, };
diff --git a/src/qemu/qemu_capabilities.h b/src/qemu/qemu_capabilities.h index 1e7e4faa9b..fb6a0751f7 100644 --- a/src/qemu/qemu_capabilities.h +++ b/src/qemu/qemu_capabilities.h @@ -715,6 +715,7 @@ typedef enum { /* virQEMUCapsFlags grouping marker for syntax-check */ QEMU_CAPS_VIRTIO_SCSI_IOTHREAD_MAPPING, /* virtio-scsi supports per-virtqueue iothread mapping */ QEMU_CAPS_MACHINE_VIRT_HIGHMEM_MMIO_SIZE, /* -machine virt,highmem-mmio-size=<size> */ QEMU_CAPS_BUS_FLOPPY, /* floppy bus supported (isa-fdc/sysbus-fdc) */ + QEMU_CAPS_ACPI_GENERIC_INITIATOR, /* -object acpi-generic-initiator command supported */
d/commmand/
QEMU_CAPS_LAST /* this must always be the last item */ } virQEMUCapsFlags;
Michal

Add support to the qemu driver to generate the proper command line for the acpi-generic-initiator definitions. Signed-off-by: Andrea Righi <arighi@nvidia.com> --- src/qemu/qemu_command.c | 28 ++++++++++++++++++++++++++++ 1 file changed, 28 insertions(+) diff --git a/src/qemu/qemu_command.c b/src/qemu/qemu_command.c index 79cfe60b09..cedcb7e5a5 100644 --- a/src/qemu/qemu_command.c +++ b/src/qemu/qemu_command.c @@ -10387,6 +10387,29 @@ qemuBuildPstoreCommandLine(virCommand *cmd, return 0; } +static int +qemuBuildAcpiInitiatorCommandLine(virCommand *cmd, + const virDomainAcpiInitiatorDef *acpiinitiator, + virQEMUCaps *qemuCaps) +{ + g_autoptr(virJSONValue) props = NULL; + + if (!virQEMUCapsGet(qemuCaps, QEMU_CAPS_ACPI_GENERIC_INITIATOR)) + return -1; + + if (virJSONValueObjectAdd(&props, + "s:qom-type", "acpi-generic-initiator", + "s:id", acpiinitiator->info.alias, + "s:pci-dev", acpiinitiator->pciDev, + "i:node", acpiinitiator->numaNode, + NULL) < 0) + return -1; + + if (qemuBuildObjectCommandlineFromJSON(cmd, props) < 0) + return -1; + + return 0; +} static int qemuBuildAsyncTeardownCommandLine(virCommand *cmd, @@ -10741,6 +10764,11 @@ qemuBuildCommandLine(virDomainObj *vm, qemuBuildPstoreCommandLine(cmd, def, def->pstore, qemuCaps) < 0) return NULL; + for (i = 0; i < def->nacpiinitiator; i++) { + if (qemuBuildAcpiInitiatorCommandLine(cmd, def->acpiinitiator[i], qemuCaps) < 0) + return NULL; + } + if (qemuBuildAsyncTeardownCommandLine(cmd, def, qemuCaps) < 0) return NULL; -- 2.49.0

On 6/8/25 22:44, Andrea Righi via Devel wrote:
Add support to the qemu driver to generate the proper command line for the acpi-generic-initiator definitions.
Signed-off-by: Andrea Righi <arighi@nvidia.com> --- src/qemu/qemu_command.c | 28 ++++++++++++++++++++++++++++ 1 file changed, 28 insertions(+)
diff --git a/src/qemu/qemu_command.c b/src/qemu/qemu_command.c index 79cfe60b09..cedcb7e5a5 100644 --- a/src/qemu/qemu_command.c +++ b/src/qemu/qemu_command.c @@ -10387,6 +10387,29 @@ qemuBuildPstoreCommandLine(virCommand *cmd, return 0; }
+static int +qemuBuildAcpiInitiatorCommandLine(virCommand *cmd, + const virDomainAcpiInitiatorDef *acpiinitiator, + virQEMUCaps *qemuCaps) +{ + g_autoptr(virJSONValue) props = NULL; + + if (!virQEMUCapsGet(qemuCaps, QEMU_CAPS_ACPI_GENERIC_INITIATOR)) + return -1; +
No. Firstly, this doesn't belong here but into qemu_validate.c where a new function must be invented that checks if domain def has an initiator defined and if so then whether the capability is present. Secondly, having this without any virReportError() will result in an unknown error.
+ if (virJSONValueObjectAdd(&props, + "s:qom-type", "acpi-generic-initiator", + "s:id", acpiinitiator->info.alias, + "s:pci-dev", acpiinitiator->pciDev, + "i:node", acpiinitiator->numaNode, + NULL) < 0) + return -1; + + if (qemuBuildObjectCommandlineFromJSON(cmd, props) < 0) + return -1; + + return 0; +}
static int qemuBuildAsyncTeardownCommandLine(virCommand *cmd, @@ -10741,6 +10764,11 @@ qemuBuildCommandLine(virDomainObj *vm, qemuBuildPstoreCommandLine(cmd, def, def->pstore, qemuCaps) < 0) return NULL;
+ for (i = 0; i < def->nacpiinitiator; i++) { + if (qemuBuildAcpiInitiatorCommandLine(cmd, def->acpiinitiator[i], qemuCaps) < 0) + return NULL; + } + if (qemuBuildAsyncTeardownCommandLine(cmd, def, qemuCaps) < 0) return NULL;
Michal

Implement a sub-test in qemuxmlconftest that uses acpi-generic-initiator to link a PCI device with multiple NUMA node definitions (without any memory/cpu resource assigned). Then translate the VM definition to the corresponding qemu command line that associates the hostdev with the NUMA nodes. Signed-off-by: Andrea Righi <arighi@nvidia.com> --- .../acpi-generic-initiator.x86_64-latest.args | 55 +++++++++++ .../acpi-generic-initiator.x86_64-latest.xml | 94 +++++++++++++++++++ .../acpi-generic-initiator.xml | 94 +++++++++++++++++++ tests/qemuxmlconftest.c | 1 + 4 files changed, 244 insertions(+) create mode 100644 tests/qemuxmlconfdata/acpi-generic-initiator.x86_64-latest.args create mode 100644 tests/qemuxmlconfdata/acpi-generic-initiator.x86_64-latest.xml create mode 100644 tests/qemuxmlconfdata/acpi-generic-initiator.xml diff --git a/tests/qemuxmlconfdata/acpi-generic-initiator.x86_64-latest.args b/tests/qemuxmlconfdata/acpi-generic-initiator.x86_64-latest.args new file mode 100644 index 0000000000..366b696435 --- /dev/null +++ b/tests/qemuxmlconfdata/acpi-generic-initiator.x86_64-latest.args @@ -0,0 +1,55 @@ +LC_ALL=C \ +PATH=/bin \ +HOME=/var/lib/libvirt/qemu/domain--1-QEMUGuest2 \ +USER=test \ +LOGNAME=test \ +XDG_DATA_HOME=/var/lib/libvirt/qemu/domain--1-QEMUGuest2/.local/share \ +XDG_CACHE_HOME=/var/lib/libvirt/qemu/domain--1-QEMUGuest2/.cache \ +XDG_CONFIG_HOME=/var/lib/libvirt/qemu/domain--1-QEMUGuest2/.config \ +/usr/bin/qemu-system-x86_64 \ +-name guest=QEMUGuest2,debug-threads=on \ +-S \ +-object '{"qom-type":"secret","id":"masterKey0","format":"raw","file":"/var/lib/libvirt/qemu/domain--1-QEMUGuest2/master-key.aes"}' \ +-machine q35,usb=off,dump-guest-core=off,acpi=off \ +-accel tcg \ +-cpu qemu64 \ +-m size=8388608k \ +-overcommit mem-lock=off \ +-smp 16,sockets=16,cores=1,threads=1 \ +-object '{"qom-type":"memory-backend-ram","id":"ram-node0","size":8589934592}' \ +-numa node,nodeid=0,cpus=0-15,memdev=ram-node0 \ +-numa node,nodeid=1 \ +-numa node,nodeid=2 \ +-numa node,nodeid=3 \ +-numa node,nodeid=4 \ +-numa node,nodeid=5 \ +-numa node,nodeid=6 \ +-numa node,nodeid=7 \ +-numa node,nodeid=8 \ +-uuid c7a5fdbd-edaf-9466-926a-d65c16db1809 \ +-display none \ +-no-user-config \ +-nodefaults \ +-chardev socket,id=charmonitor,fd=1729,server=on,wait=off \ +-mon chardev=charmonitor,id=monitor,mode=control \ +-rtc base=utc \ +-no-shutdown \ +-boot strict=on \ +-device '{"driver":"pcie-root-port","port":8,"chassis":1,"id":"pci.1","bus":"pcie.0","multifunction":true,"addr":"0x1"}' \ +-device '{"driver":"pcie-root-port","port":9,"chassis":2,"id":"pci.2","bus":"pcie.0","addr":"0x1.0x1"}' \ +-device '{"driver":"qemu-xhci","id":"usb","bus":"pci.1","addr":"0x0"}' \ +-audiodev '{"id":"audio1","driver":"none"}' \ +-global ICH9-LPC.noreboot=off \ +-watchdog-action reset \ +-device '{"driver":"vfio-pci","host":"0000:06:12.1","id":"hostdev0","bus":"pcie.0","addr":"0x2"}' \ +-device '{"driver":"virtio-balloon-pci","id":"balloon0","bus":"pcie.0","addr":"0x6"}' \ +-sandbox on,obsolete=deny,elevateprivileges=deny,spawn=deny,resourcecontrol=deny \ +-object '{"qom-type":"acpi-generic-initiator","id":"gi0","pci-dev":"hostdev0","node":1}' \ +-object '{"qom-type":"acpi-generic-initiator","id":"gi1","pci-dev":"hostdev0","node":2}' \ +-object '{"qom-type":"acpi-generic-initiator","id":"gi2","pci-dev":"hostdev0","node":3}' \ +-object '{"qom-type":"acpi-generic-initiator","id":"gi3","pci-dev":"hostdev0","node":4}' \ +-object '{"qom-type":"acpi-generic-initiator","id":"gi4","pci-dev":"hostdev0","node":5}' \ +-object '{"qom-type":"acpi-generic-initiator","id":"gi5","pci-dev":"hostdev0","node":6}' \ +-object '{"qom-type":"acpi-generic-initiator","id":"gi6","pci-dev":"hostdev0","node":7}' \ +-object '{"qom-type":"acpi-generic-initiator","id":"gi7","pci-dev":"hostdev0","node":8}' \ +-msg timestamp=on diff --git a/tests/qemuxmlconfdata/acpi-generic-initiator.x86_64-latest.xml b/tests/qemuxmlconfdata/acpi-generic-initiator.x86_64-latest.xml new file mode 100644 index 0000000000..6a5485f191 --- /dev/null +++ b/tests/qemuxmlconfdata/acpi-generic-initiator.x86_64-latest.xml @@ -0,0 +1,94 @@ +<domain type='qemu'> + <name>QEMUGuest2</name> + <uuid>c7a5fdbd-edaf-9466-926a-d65c16db1809</uuid> + <memory unit='KiB'>219100</memory> + <currentMemory unit='KiB'>219100</currentMemory> + <vcpu placement='static'>16</vcpu> + <os> + <type arch='x86_64' machine='q35'>hvm</type> + <boot dev='hd'/> + </os> + <cpu mode='custom' match='exact' check='none'> + <model fallback='forbid'>qemu64</model> + <numa> + <cell id='0' cpus='0-15' memory='8388608' unit='KiB'/> + <cell id='1' memory='0' unit='KiB'/> + <cell id='2' memory='0' unit='KiB'/> + <cell id='3' memory='0' unit='KiB'/> + <cell id='4' memory='0' unit='KiB'/> + <cell id='5' memory='0' unit='KiB'/> + <cell id='6' memory='0' unit='KiB'/> + <cell id='7' memory='0' unit='KiB'/> + <cell id='8' memory='0' unit='KiB'/> + </numa> + </cpu> + <clock offset='utc'/> + <on_poweroff>destroy</on_poweroff> + <on_reboot>restart</on_reboot> + <on_crash>destroy</on_crash> + <devices> + <emulator>/usr/bin/qemu-system-x86_64</emulator> + <controller type='pci' index='0' model='pcie-root'/> + <controller type='pci' index='1' model='pcie-root-port'> + <model name='pcie-root-port'/> + <target chassis='1' port='0x8'/> + <address type='pci' domain='0x0000' bus='0x00' slot='0x01' function='0x0' multifunction='on'/> + </controller> + <controller type='pci' index='2' model='pcie-root-port'> + <model name='pcie-root-port'/> + <target chassis='2' port='0x9'/> + <address type='pci' domain='0x0000' bus='0x00' slot='0x01' function='0x1'/> + </controller> + <controller type='usb' index='0' model='qemu-xhci'> + <address type='pci' domain='0x0000' bus='0x01' slot='0x00' function='0x0'/> + </controller> + <controller type='sata' index='0'> + <address type='pci' domain='0x0000' bus='0x00' slot='0x1f' function='0x2'/> + </controller> + <input type='mouse' bus='ps2'/> + <input type='keyboard' bus='ps2'/> + <audio id='1' type='none'/> + <hostdev mode='subsystem' type='pci' managed='yes'> + <source> + <address domain='0x0000' bus='0x06' slot='0x12' function='0x1'/> + </source> + <address type='pci' domain='0x0000' bus='0x00' slot='0x02' function='0x0'/> + </hostdev> + <watchdog model='itco' action='reset'/> + <memballoon model='virtio'> + <address type='pci' domain='0x0000' bus='0x00' slot='0x06' function='0x0'/> + </memballoon> + <acpi-generic-initiator> + <pci-dev>hostdev0</pci-dev> + <numa-node>1</numa-node> + </acpi-generic-initiator> + <acpi-generic-initiator> + <pci-dev>hostdev0</pci-dev> + <numa-node>2</numa-node> + </acpi-generic-initiator> + <acpi-generic-initiator> + <pci-dev>hostdev0</pci-dev> + <numa-node>3</numa-node> + </acpi-generic-initiator> + <acpi-generic-initiator> + <pci-dev>hostdev0</pci-dev> + <numa-node>4</numa-node> + </acpi-generic-initiator> + <acpi-generic-initiator> + <pci-dev>hostdev0</pci-dev> + <numa-node>5</numa-node> + </acpi-generic-initiator> + <acpi-generic-initiator> + <pci-dev>hostdev0</pci-dev> + <numa-node>6</numa-node> + </acpi-generic-initiator> + <acpi-generic-initiator> + <pci-dev>hostdev0</pci-dev> + <numa-node>7</numa-node> + </acpi-generic-initiator> + <acpi-generic-initiator> + <pci-dev>hostdev0</pci-dev> + <numa-node>8</numa-node> + </acpi-generic-initiator> + </devices> +</domain> diff --git a/tests/qemuxmlconfdata/acpi-generic-initiator.xml b/tests/qemuxmlconfdata/acpi-generic-initiator.xml new file mode 100644 index 0000000000..6a5485f191 --- /dev/null +++ b/tests/qemuxmlconfdata/acpi-generic-initiator.xml @@ -0,0 +1,94 @@ +<domain type='qemu'> + <name>QEMUGuest2</name> + <uuid>c7a5fdbd-edaf-9466-926a-d65c16db1809</uuid> + <memory unit='KiB'>219100</memory> + <currentMemory unit='KiB'>219100</currentMemory> + <vcpu placement='static'>16</vcpu> + <os> + <type arch='x86_64' machine='q35'>hvm</type> + <boot dev='hd'/> + </os> + <cpu mode='custom' match='exact' check='none'> + <model fallback='forbid'>qemu64</model> + <numa> + <cell id='0' cpus='0-15' memory='8388608' unit='KiB'/> + <cell id='1' memory='0' unit='KiB'/> + <cell id='2' memory='0' unit='KiB'/> + <cell id='3' memory='0' unit='KiB'/> + <cell id='4' memory='0' unit='KiB'/> + <cell id='5' memory='0' unit='KiB'/> + <cell id='6' memory='0' unit='KiB'/> + <cell id='7' memory='0' unit='KiB'/> + <cell id='8' memory='0' unit='KiB'/> + </numa> + </cpu> + <clock offset='utc'/> + <on_poweroff>destroy</on_poweroff> + <on_reboot>restart</on_reboot> + <on_crash>destroy</on_crash> + <devices> + <emulator>/usr/bin/qemu-system-x86_64</emulator> + <controller type='pci' index='0' model='pcie-root'/> + <controller type='pci' index='1' model='pcie-root-port'> + <model name='pcie-root-port'/> + <target chassis='1' port='0x8'/> + <address type='pci' domain='0x0000' bus='0x00' slot='0x01' function='0x0' multifunction='on'/> + </controller> + <controller type='pci' index='2' model='pcie-root-port'> + <model name='pcie-root-port'/> + <target chassis='2' port='0x9'/> + <address type='pci' domain='0x0000' bus='0x00' slot='0x01' function='0x1'/> + </controller> + <controller type='usb' index='0' model='qemu-xhci'> + <address type='pci' domain='0x0000' bus='0x01' slot='0x00' function='0x0'/> + </controller> + <controller type='sata' index='0'> + <address type='pci' domain='0x0000' bus='0x00' slot='0x1f' function='0x2'/> + </controller> + <input type='mouse' bus='ps2'/> + <input type='keyboard' bus='ps2'/> + <audio id='1' type='none'/> + <hostdev mode='subsystem' type='pci' managed='yes'> + <source> + <address domain='0x0000' bus='0x06' slot='0x12' function='0x1'/> + </source> + <address type='pci' domain='0x0000' bus='0x00' slot='0x02' function='0x0'/> + </hostdev> + <watchdog model='itco' action='reset'/> + <memballoon model='virtio'> + <address type='pci' domain='0x0000' bus='0x00' slot='0x06' function='0x0'/> + </memballoon> + <acpi-generic-initiator> + <pci-dev>hostdev0</pci-dev> + <numa-node>1</numa-node> + </acpi-generic-initiator> + <acpi-generic-initiator> + <pci-dev>hostdev0</pci-dev> + <numa-node>2</numa-node> + </acpi-generic-initiator> + <acpi-generic-initiator> + <pci-dev>hostdev0</pci-dev> + <numa-node>3</numa-node> + </acpi-generic-initiator> + <acpi-generic-initiator> + <pci-dev>hostdev0</pci-dev> + <numa-node>4</numa-node> + </acpi-generic-initiator> + <acpi-generic-initiator> + <pci-dev>hostdev0</pci-dev> + <numa-node>5</numa-node> + </acpi-generic-initiator> + <acpi-generic-initiator> + <pci-dev>hostdev0</pci-dev> + <numa-node>6</numa-node> + </acpi-generic-initiator> + <acpi-generic-initiator> + <pci-dev>hostdev0</pci-dev> + <numa-node>7</numa-node> + </acpi-generic-initiator> + <acpi-generic-initiator> + <pci-dev>hostdev0</pci-dev> + <numa-node>8</numa-node> + </acpi-generic-initiator> + </devices> +</domain> diff --git a/tests/qemuxmlconftest.c b/tests/qemuxmlconftest.c index 0f1c935267..2e304f3cb1 100644 --- a/tests/qemuxmlconftest.c +++ b/tests/qemuxmlconftest.c @@ -2766,6 +2766,7 @@ mymain(void) DO_TEST_CAPS_LATEST_PARSE_ERROR("virtio-iommu-invalid-address-type"); DO_TEST_CAPS_LATEST_PARSE_ERROR("virtio-iommu-invalid-address"); DO_TEST_CAPS_LATEST_PARSE_ERROR("virtio-iommu-dma-translation"); + DO_TEST_CAPS_LATEST("acpi-generic-initiator"); DO_TEST_CAPS_LATEST("cpu-hotplug-startup"); DO_TEST_CAPS_ARCH_LATEST_PARSE_ERROR("cpu-hotplug-granularity", "ppc64"); -- 2.49.0

Signed-off-by: Andrea Righi <arighi@nvidia.com> --- docs/formatdomain.rst | 36 ++++++++++++++++++++++++++++++++++++ 1 file changed, 36 insertions(+) diff --git a/docs/formatdomain.rst b/docs/formatdomain.rst index 1acf203d18..17c7ca2ae3 100644 --- a/docs/formatdomain.rst +++ b/docs/formatdomain.rst @@ -9093,6 +9093,42 @@ The ``virtio`` IOMMU devices can further have ``address`` element as described in `Device addresses`_ (address has to by type of ``pci``). +ACPI generic initiator +~~~~~~~~~~~~~~~~~~~~~~ + +The ACPI Generic Initiator device (GI) allows associating a PCI device with +a specific NUMA node in the guest through the ACPI Generic Initiator +namespace. + +This is required for certain accelerator configurations, such as NVIDIA +Multi-Instance GPU (MIG), where each virtual instance must be exposed to +the guest as a separate NUMA node. + +:since:`Since v11.5.0` + +:: + + ... + <acpi-generic-initiator> + <pci-dev>dev0</pci-dev> + <numa-node>1</numa-node> + </acpi-generic-initiator> + ... + +The ``acpi-generic-initiator`` element has the following child elements: + +``pci-dev`` + Mandatory. Refers to the alias of a PCI device defined in the domain + configuration. + +``numa-node`` + Mandatory. Specifies the guest NUMA node that the PCI device should be + associated with through the GI mechanism. + +Multiple ``acpi-generic-initiator`` elements can be defined to map different PCI +devices to different guest NUMA nodes. + + Vsock ~~~~~ -- 2.49.0

Signed-off-by: Andrea Righi <arighi@nvidia.com> --- NEWS.rst | 8 ++++++++ 1 file changed, 8 insertions(+) diff --git a/NEWS.rst b/NEWS.rst index b97f86ffb6..fed249744d 100644 --- a/NEWS.rst +++ b/NEWS.rst @@ -24,6 +24,14 @@ v11.5.0 (unreleased) * **New features** + * qemu: Introduce acpi-generic-initiator device + + To support NVIDIA Multi-Instance GPU (MIG) configurations, libvirt now + supports the ``acpi-generic-initiator`` device. MIG allows partitioning + a physical GPU into multiple isolated instances, each associated with a + separate virtual NUMA node. The ``acpi-generic-initiator`` device is + required by QEMU to represent these virtual NUMA nodes correctly in ACPI. + * **Improvements** * **Bug fixes** -- 2.49.0

On 6/8/25 22:44, Andrea Righi via Devel wrote:
= Overview =
This patch set introduces support for acpi-generic-initiator devices, supported by QEMU [1].
The acpi-generic-initiator object is required to support Multi-Instance GPU (MIG) configurations on NVIDIA GPUs [2]. MIG enables partitioning of GPU resources into multiple isolated instances, each requiring a dedicated NUMA node definition.
= Implementation =
This patch set implements the libvirt counterpart to the QEMU feature, enabling users to configure acpi-generic-initiator objects within libvirt domain XML.
This includes: - adding XML syntax to define acpi-generic-initiator objects, - resolving the acpi-generic-initiator definitions into the proper QEMU command-line arguments, - ensuring compatibility with existing NUMA configuration.
= Example =
- Domain XML: ``` ... <cpu mode='host-passthrough' check='none'> <numa> <cell id='0' cpus='0-15' memory='8388608' unit='KiB'/> <cell id='1' memory='0' unit='KiB'/> <cell id='2' memory='0' unit='KiB'/> <cell id='3' memory='0' unit='KiB'/> <cell id='4' memory='0' unit='KiB'/> <cell id='5' memory='0' unit='KiB'/> <cell id='6' memory='0' unit='KiB'/> <cell id='7' memory='0' unit='KiB'/> <cell id='8' memory='0' unit='KiB'/> </numa> </cpu> ... <devices> ... <hostdev mode='subsystem' type='pci' managed='no'> <source> <address domain='0x0009' bus='0x01' slot='0x00' function='0x0'/> </source> <address type='pci' domain='0x0000' bus='0x03' slot='0x00' function='0x0'/> </hostdev> <acpi-generic-initiator> <pci-dev>hostdev0</pci-dev> <numa-node>1</numa-node> </acpi-generic-initiator> <acpi-generic-initiator> <pci-dev>hostdev0</pci-dev> <numa-node>2</numa-node> </acpi-generic-initiator> <acpi-generic-initiator> <pci-dev>hostdev0</pci-dev> <numa-node>3</numa-node> </acpi-generic-initiator> <acpi-generic-initiator> <pci-dev>hostdev0</pci-dev> <numa-node>4</numa-node> </acpi-generic-initiator> <acpi-generic-initiator> <pci-dev>hostdev0</pci-dev> <numa-node>5</numa-node> </acpi-generic-initiator> <acpi-generic-initiator> <pci-dev>hostdev0</pci-dev> <numa-node>6</numa-node> </acpi-generic-initiator> <acpi-generic-initiator> <pci-dev>hostdev0</pci-dev> <numa-node>7</numa-node> </acpi-generic-initiator> <acpi-generic-initiator> <pci-dev>hostdev0</pci-dev> <numa-node>8</numa-node> </acpi-generic-initiator> </devices> ```
- Generated QEMU command line options: ``` ... /usr/bin/qemu-system-aarch64 \ ... -object '{"qom-type":"memory-backend-ram","id":"ram-node0","size":8589934592}' \ -numa node,nodeid=0,cpus=0-15,memdev=ram-node0 \ -numa node,nodeid=1 \ -numa node,nodeid=2 \ -numa node,nodeid=3 \ -numa node,nodeid=4 \ -numa node,nodeid=5 \ -numa node,nodeid=6 \ -numa node,nodeid=7 \ -numa node,nodeid=8 \ ... -device '{"driver":"vfio-pci","host":"0009:01:00.0","id":"hostdev0","bus":"pci.3","addr":"0x0"}' ... -object acpi-generic-initiator,id=gi0,pci-dev=hostdev0,node=1 \ -object acpi-generic-initiator,id=gi1,pci-dev=hostdev0,node=2 \ -object acpi-generic-initiator,id=gi2,pci-dev=hostdev0,node=3 \ -object acpi-generic-initiator,id=gi3,pci-dev=hostdev0,node=4 \ -object acpi-generic-initiator,id=gi4,pci-dev=hostdev0,node=5 \ -object acpi-generic-initiator,id=gi5,pci-dev=hostdev0,node=6 \ -object acpi-generic-initiator,id=gi6,pci-dev=hostdev0,node=7 \ -object acpi-generic-initiator,id=gi7,pci-dev=hostdev0,node=8 ```
= References =
[1] https://lore.kernel.org/all/20231225045603.7654-2-ankita@nvidia.com/ [2] https://www.nvidia.com/en-in/technologies/multi-instance-gpu/
This patchset is also available in the following git branch:
https://github.com/arighi/libvirt.git acpi-generic-initiator-v4
ChangeLog v3 -> v4: - add acpi-generic-initiator documentation - refactor virDomainAcpiInitiatorDef to use info->alias and drop the name attribute - auto-generate alias for the acpi-generic-initiator devices via qemuAssignDeviceAliases() - use g_autoptr() when possible - add a new entry to NEWS.rst
ChangeLog v2 -> v3: - replaced <text/> with proper types in the XML schema - avoid mixing g_free() and VIR_FREE() - use virXMLPropString() instead of looping all XML nodes - report proper errors with virReportError() - use virBufferEscapeString() to process strings passed by the user - fix broken formatting of function headers - misc coding style fixes
ChangeLog v1 -> v2: - split parser and driver changes in separate patches - introduce a new qemu capability flag - introduce test in qemuxmlconftest
Andrea Righi (8): schema: Introduce acpi-generic-initiator definition conf: Introduce acpi-generic-initiator device qemu: Allow to define NUMA nodes without memory or CPUs assigned qemu: capabilies: Introduce QEMU_CAPS_ACPI_GENERIC_INITIATOR qemu: Support acpi-generic-initiator qemu: Add test case for acpi-generic-initiator docs: Document acpi-generic-initiator device NEWS: Mention new acpi-generic-initiator device
NEWS.rst | 8 ++ docs/formatdomain.rst | 36 ++++++ src/ch/ch_domain.c | 1 + src/conf/domain_conf.c | 138 +++++++++++++++++++++ src/conf/domain_conf.h | 14 +++ src/conf/domain_postparse.c | 1 + src/conf/domain_validate.c | 37 ++++++ src/conf/numa_conf.c | 3 + src/conf/schemas/domaincommon.rng | 14 +++ src/conf/virconftypes.h | 2 + src/hyperv/hyperv_driver.c | 1 + src/libxl/libxl_driver.c | 6 + src/lxc/lxc_driver.c | 6 + src/qemu/qemu_alias.c | 11 ++ src/qemu/qemu_capabilities.c | 2 + src/qemu/qemu_capabilities.h | 1 + src/qemu/qemu_command.c | 49 ++++++-- 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 + tests/qemucapabilitiesdata/caps_10.0.0_aarch64.xml | 1 + .../caps_10.0.0_x86_64+amdsev.xml | 1 + tests/qemucapabilitiesdata/caps_10.0.0_x86_64.xml | 1 + tests/qemucapabilitiesdata/caps_9.0.0_x86_64.xml | 1 + tests/qemucapabilitiesdata/caps_9.1.0_riscv64.xml | 1 + tests/qemucapabilitiesdata/caps_9.1.0_x86_64.xml | 1 + .../caps_9.2.0_aarch64+hvf.xml | 1 + .../caps_9.2.0_x86_64+amdsev.xml | 1 + tests/qemucapabilitiesdata/caps_9.2.0_x86_64.xml | 1 + .../acpi-generic-initiator.x86_64-latest.args | 55 ++++++++ .../acpi-generic-initiator.x86_64-latest.xml | 94 ++++++++++++++ tests/qemuxmlconfdata/acpi-generic-initiator.xml | 94 ++++++++++++++ tests/qemuxmlconftest.c | 1 + 37 files changed, 596 insertions(+), 7 deletions(-) create mode 100644 tests/qemuxmlconfdata/acpi-generic-initiator.x86_64-latest.args create mode 100644 tests/qemuxmlconfdata/acpi-generic-initiator.x86_64-latest.xml create mode 100644 tests/qemuxmlconfdata/acpi-generic-initiator.xml
Code-wise this is okay. I've merged some patches together and made small changes. You can find them here: https://gitlab.com/MichalPrivoznik/libvirt/-/compare/master...review_acpi_in... (I'll be squashing those 'fixup' commits, naturally) What I am more worried about is the XML representation. But I'm failing to come up with a better one. Dan, what do you think? Michal

Hi Michal, On Mon, Jun 23, 2025 at 10:05:20AM +0200, Michal Prívozník wrote: ...
Code-wise this is okay. I've merged some patches together and made small changes. You can find them here:
https://gitlab.com/MichalPrivoznik/libvirt/-/compare/master...review_acpi_in...
(I'll be squashing those 'fixup' commits, naturally)
What I am more worried about is the XML representation. But I'm failing to come up with a better one. Dan, what do you think?
Thanks for reviewing this! All your fixup commits look good to me. I'm also unsure how to improve the XML representation, but I'm open to suggestions, if anyone has ideas, we can certainly update the schema. Do you want me to send a new patch set with your changes applied? Thanks, -Andrea
participants (2)
-
Andrea Righi
-
Michal Prívozník