[PATCH v5 0/6] 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/ ChangeLog v4 -> v5: - Integrate suggestions and changes from Michal's review - Update qemu capabilities - Rebase to v11.6.0 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 (5): 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 NEWS: Mention new acpi-generic-initiator device Michal Prívozník (1): qemu_validate: Validate acpi-generic-initiator 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 | 50 ++++++-- 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 | 18 +++ 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 + .../caps_10.1.0_x86_64+inteltdx.xml | 1 + tests/qemucapabilitiesdata/caps_10.1.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 | 1 + tests/qemuxmlconfdata/acpi-generic-initiator.xml | 94 ++++++++++++++ tests/qemuxmlconftest.c | 1 + 39 files changed, 523 insertions(+), 7 deletions(-) create mode 100644 tests/qemuxmlconfdata/acpi-generic-initiator.x86_64-latest.args create mode 120000 tests/qemuxmlconfdata/acpi-generic-initiator.x86_64-latest.xml create mode 100644 tests/qemuxmlconfdata/acpi-generic-initiator.xml

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 | 19 +++++++++------ .../acpi-generic-initiator.x86_64-latest.args | 24 +++++++------------ 3 files changed, 23 insertions(+), 23 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 cf9529dafc..46af5abd62 100644 --- a/src/qemu/qemu_command.c +++ b/src/qemu/qemu_command.c @@ -7818,7 +7818,9 @@ 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; @@ -7826,8 +7828,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], @@ -7855,11 +7858,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); } diff --git a/tests/qemuxmlconfdata/acpi-generic-initiator.x86_64-latest.args b/tests/qemuxmlconfdata/acpi-generic-initiator.x86_64-latest.args index 1a8ac0dfc7..37712fb68d 100644 --- a/tests/qemuxmlconfdata/acpi-generic-initiator.x86_64-latest.args +++ b/tests/qemuxmlconfdata/acpi-generic-initiator.x86_64-latest.args @@ -18,22 +18,14 @@ XDG_CONFIG_HOME=/var/lib/libvirt/qemu/domain--1-QEMUGuest2/.config \ -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 \ --object '{"qom-type":"memory-backend-ram","id":"ram-node1","size":0}' \ --numa node,nodeid=1,memdev=ram-node1 \ --object '{"qom-type":"memory-backend-ram","id":"ram-node2","size":0}' \ --numa node,nodeid=2,memdev=ram-node2 \ --object '{"qom-type":"memory-backend-ram","id":"ram-node3","size":0}' \ --numa node,nodeid=3,memdev=ram-node3 \ --object '{"qom-type":"memory-backend-ram","id":"ram-node4","size":0}' \ --numa node,nodeid=4,memdev=ram-node4 \ --object '{"qom-type":"memory-backend-ram","id":"ram-node5","size":0}' \ --numa node,nodeid=5,memdev=ram-node5 \ --object '{"qom-type":"memory-backend-ram","id":"ram-node6","size":0}' \ --numa node,nodeid=6,memdev=ram-node6 \ --object '{"qom-type":"memory-backend-ram","id":"ram-node7","size":0}' \ --numa node,nodeid=7,memdev=ram-node7 \ --object '{"qom-type":"memory-backend-ram","id":"ram-node8","size":0}' \ --numa node,nodeid=8,memdev=ram-node8 \ +-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 \ -- 2.50.1

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. Link: https://mail.gnu.org/archive/html/qemu-arm/2024-03/msg00358.html Signed-off-by: Andrea Righi <arighi@nvidia.com> --- 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/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_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 + .../acpi-generic-initiator.x86_64-latest.args | 55 +++++++ .../acpi-generic-initiator.x86_64-latest.xml | 1 + .../acpi-generic-initiator.xml | 94 ++++++++++++ tests/qemuxmlconftest.c | 1 + 24 files changed, 439 insertions(+) create mode 100644 tests/qemuxmlconfdata/acpi-generic-initiator.x86_64-latest.args create mode 120000 tests/qemuxmlconfdata/acpi-generic-initiator.x86_64-latest.xml create mode 100644 tests/qemuxmlconfdata/acpi-generic-initiator.xml diff --git a/docs/formatdomain.rst b/docs/formatdomain.rst index d3c04d8b2a..3eeafade67 100644 --- a/docs/formatdomain.rst +++ b/docs/formatdomain.rst @@ -9152,6 +9152,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 ~~~~~ 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 cb096f2e1e..dcc0c82f70 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, @@ -3489,6 +3490,17 @@ virDomainHostdevDefNew(void) } +virDomainAcpiInitiatorDef * +virDomainAcpiInitiatorDefNew(void) +{ + virDomainAcpiInitiatorDef *def; + + def = g_new0(virDomainAcpiInitiatorDef, 1); + + return def; +} + + static virDomainTPMDef * virDomainTPMDefNew(virDomainXMLOption *xmlopt) { @@ -3549,6 +3561,16 @@ void virDomainHostdevDefFree(virDomainHostdevDef *def) g_free(def); } +void +virDomainAcpiInitiatorDefFree(virDomainAcpiInitiatorDef *def) +{ + if (!def) + return; + + g_free(def->pciDev); + g_free(def); +} + void virDomainHubDefFree(virDomainHubDef *def) { if (!def) @@ -3711,6 +3733,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; @@ -4695,6 +4720,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: @@ -4803,6 +4830,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; @@ -5028,6 +5058,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; @@ -5088,6 +5125,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 @@ -13671,6 +13709,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, @@ -14734,6 +14815,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; @@ -20162,6 +20249,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; @@ -21103,6 +21208,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) @@ -22465,6 +22581,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, @@ -22635,6 +22757,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 @@ -28920,6 +29043,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, @@ -29409,6 +29543,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"); @@ -29569,6 +29706,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 984e5bfc76..6105ab956b 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; @@ -122,6 +123,7 @@ struct _virDomainDeviceDef { virDomainAudioDef *audio; virDomainCryptoDef *crypto; virDomainPstoreDef *pstore; + virDomainAcpiInitiatorDef *acpiinitiator; } data; }; @@ -353,6 +355,12 @@ typedef enum { VIR_DOMAIN_STARTUP_POLICY_LAST } virDomainStartupPolicy; +struct _virDomainAcpiInitiatorDef { + char *pciDev; + int numaNode; + virDomainDeviceInfo info; +}; + /* basic device for direct passthrough */ struct _virDomainHostdevDef { /* If 'parentnet' is non-NULL it means this host dev was @@ -3296,6 +3304,9 @@ struct _virDomainDef { size_t ntpms; virDomainTPMDef **tpms; + size_t nacpiinitiator; + virDomainAcpiInitiatorDef **acpiinitiator; + /* Only 1 */ virDomainMemballoonDef *memballoon; virDomainNVRAMDef *nvram; @@ -3781,6 +3792,9 @@ 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); +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 a07ec8d94e..b297755477 100644 --- a/src/conf/domain_postparse.c +++ b/src/conf/domain_postparse.c @@ -760,6 +760,7 @@ virDomainDeviceDefPostParseCommon(virDomainDeviceDef *dev, case VIR_DOMAIN_DEVICE_AUDIO: case VIR_DOMAIN_DEVICE_CRYPTO: case VIR_DOMAIN_DEVICE_PSTORE: + case VIR_DOMAIN_DEVICE_ACPI_INITIATOR: ret = 0; break; diff --git a/src/conf/domain_validate.c b/src/conf/domain_validate.c index 40edecef83..675fc9f768 100644 --- a/src/conf/domain_validate.c +++ b/src/conf/domain_validate.c @@ -2388,6 +2388,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 @@ -3328,6 +3362,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 9782dca147..cb8441aa83 100644 --- a/src/conf/schemas/domaincommon.rng +++ b/src/conf/schemas/domaincommon.rng @@ -6924,6 +6924,7 @@ <ref name="shmem"/> <ref name="memorydev"/> <ref name="crypto"/> + <ref name="acpi-generic-initiator"/> </choice> </zeroOrMore> <zeroOrMore> @@ -7666,6 +7667,19 @@ </element> </define> + <define name="acpi-generic-initiator"> + <element name="acpi-generic-initiator"> + <interleave> + <element name="pci-dev"> + <ref name="aliasName"/> + </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 93fc9c9217..ea37593980 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; diff --git a/src/hyperv/hyperv_driver.c b/src/hyperv/hyperv_driver.c index 0c17ef16ec..7361b2fbb7 100644 --- a/src/hyperv/hyperv_driver.c +++ b/src/hyperv/hyperv_driver.c @@ -3124,6 +3124,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 308c0372aa..1f698dc570 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 a27c688d79..a1e9e70492 100644 --- a/src/qemu/qemu_alias.c +++ b/src/qemu/qemu_alias.c @@ -681,6 +681,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) @@ -773,6 +781,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 4e4f1e87eb..cf9529dafc 100644 --- a/src/qemu/qemu_command.c +++ b/src/qemu/qemu_command.c @@ -1011,6 +1011,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 a2c7c88a7e..6c0c41c3f4 100644 --- a/src/qemu/qemu_domain.c +++ b/src/qemu/qemu_domain.c @@ -8820,6 +8820,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; } @@ -10710,6 +10711,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 96a9ca9b14..5037e4a9ea 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: @@ -825,6 +826,9 @@ qemuDomainDeviceCalculatePCIConnectFlags(virDomainDeviceDef *dev, return pciFlags; } + case VIR_DOMAIN_DEVICE_ACPI_INITIATOR: + return 0; + 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 ac72ea5cb0..36acedc1f6 100644 --- a/src/qemu/qemu_driver.c +++ b/src/qemu/qemu_driver.c @@ -6914,6 +6914,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"), @@ -7133,6 +7134,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"), @@ -7259,6 +7261,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 e9568af125..3376d4d2b5 100644 --- a/src/qemu/qemu_hotplug.c +++ b/src/qemu/qemu_hotplug.c @@ -3563,6 +3563,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"), @@ -5533,6 +5534,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; @@ -5638,6 +5640,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"), @@ -6540,6 +6543,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"), @@ -7531,6 +7535,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 9c2427970d..9611f46831 100644 --- a/src/qemu/qemu_postparse.c +++ b/src/qemu/qemu_postparse.c @@ -959,6 +959,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 adba3e4a89..5ead231dd0 100644 --- a/src/qemu/qemu_validate.c +++ b/src/qemu/qemu_validate.c @@ -5793,6 +5793,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 25335d9002..1a086f5f47 100644 --- a/src/test/test_driver.c +++ b/src/test/test_driver.c @@ -10460,6 +10460,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"), @@ -10603,6 +10604,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"), @@ -10975,6 +10977,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"), @@ -11046,6 +11049,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"), 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..1a8ac0dfc7 --- /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 \ +-object '{"qom-type":"memory-backend-ram","id":"ram-node1","size":0}' \ +-numa node,nodeid=1,memdev=ram-node1 \ +-object '{"qom-type":"memory-backend-ram","id":"ram-node2","size":0}' \ +-numa node,nodeid=2,memdev=ram-node2 \ +-object '{"qom-type":"memory-backend-ram","id":"ram-node3","size":0}' \ +-numa node,nodeid=3,memdev=ram-node3 \ +-object '{"qom-type":"memory-backend-ram","id":"ram-node4","size":0}' \ +-numa node,nodeid=4,memdev=ram-node4 \ +-object '{"qom-type":"memory-backend-ram","id":"ram-node5","size":0}' \ +-numa node,nodeid=5,memdev=ram-node5 \ +-object '{"qom-type":"memory-backend-ram","id":"ram-node6","size":0}' \ +-numa node,nodeid=6,memdev=ram-node6 \ +-object '{"qom-type":"memory-backend-ram","id":"ram-node7","size":0}' \ +-numa node,nodeid=7,memdev=ram-node7 \ +-object '{"qom-type":"memory-backend-ram","id":"ram-node8","size":0}' \ +-numa node,nodeid=8,memdev=ram-node8 \ +-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 \ +-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 120000 index 0000000000..0e61738945 --- /dev/null +++ b/tests/qemuxmlconfdata/acpi-generic-initiator.x86_64-latest.xml @@ -0,0 +1 @@ +acpi-generic-initiator.xml \ No newline at end of file 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 0d1804f101..fc906824e2 100644 --- a/tests/qemuxmlconftest.c +++ b/tests/qemuxmlconftest.c @@ -2796,6 +2796,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.50.1

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 435760e797..36388a736b 100644 --- a/NEWS.rst +++ b/NEWS.rst @@ -17,6 +17,14 @@ v11.7.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.50.1

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_10.1.0_x86_64+inteltdx.xml | 1 + tests/qemucapabilitiesdata/caps_10.1.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 + 13 files changed, 14 insertions(+) diff --git a/src/qemu/qemu_capabilities.c b/src/qemu/qemu_capabilities.c index af238894b5..3db7b2f96d 100644 --- a/src/qemu/qemu_capabilities.c +++ b/src/qemu/qemu_capabilities.c @@ -742,6 +742,7 @@ VIR_ENUM_IMPL(virQEMUCaps, "amd-iommu.pci-id", /* QEMU_CAPS_AMD_IOMMU_PCI_ID */ "usb-bot", /* QEMU_CAPS_DEVICE_USB_BOT */ "tdx-guest", /* QEMU_CAPS_TDX_GUEST */ + "acpi-generic-initiator", /* QEMU_CAPS_ACPI_GENERIC_INITIATOR */ ); @@ -1431,6 +1432,7 @@ struct virQEMUCapsStringFlags virQEMUCapsObjectTypes[] = { { "amd-iommu", QEMU_CAPS_AMD_IOMMU }, { "usb-bot", QEMU_CAPS_DEVICE_USB_BOT }, { "tdx-guest", QEMU_CAPS_TDX_GUEST}, + { "acpi-generic-initiator", QEMU_CAPS_ACPI_GENERIC_INITIATOR }, }; diff --git a/src/qemu/qemu_capabilities.h b/src/qemu/qemu_capabilities.h index 55b05bea84..ccb5510869 100644 --- a/src/qemu/qemu_capabilities.h +++ b/src/qemu/qemu_capabilities.h @@ -723,6 +723,7 @@ typedef enum { /* virQEMUCapsFlags grouping marker for syntax-check */ QEMU_CAPS_AMD_IOMMU_PCI_ID, /* amd-iommu.pci-id */ QEMU_CAPS_DEVICE_USB_BOT, /* -device usb-bot */ QEMU_CAPS_TDX_GUEST, /* -object tdx-guest,... */ + QEMU_CAPS_ACPI_GENERIC_INITIATOR, /* -object acpi-generic-initiator */ 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 200873b3a2..8a11815991 100644 --- a/tests/qemucapabilitiesdata/caps_10.0.0_aarch64.xml +++ b/tests/qemucapabilitiesdata/caps_10.0.0_aarch64.xml @@ -164,6 +164,7 @@ <flag name='nvme'/> <flag name='nvme-ns'/> <flag name='usb-bot'/> + <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 c8104c967f..eade097de0 100644 --- a/tests/qemucapabilitiesdata/caps_10.0.0_x86_64+amdsev.xml +++ b/tests/qemucapabilitiesdata/caps_10.0.0_x86_64+amdsev.xml @@ -210,6 +210,7 @@ <flag name='nvme-ns'/> <flag name='amd-iommu'/> <flag name='usb-bot'/> + <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 ad1ffcff32..94bde91bd5 100644 --- a/tests/qemucapabilitiesdata/caps_10.0.0_x86_64.xml +++ b/tests/qemucapabilitiesdata/caps_10.0.0_x86_64.xml @@ -210,6 +210,7 @@ <flag name='amd-iommu'/> <flag name='amd-iommu.pci-id'/> <flag name='usb-bot'/> + <flag name='acpi-generic-initiator'/> <version>10000000</version> <microcodeVersion>43100285</microcodeVersion> <package>v10.0.0</package> diff --git a/tests/qemucapabilitiesdata/caps_10.1.0_x86_64+inteltdx.xml b/tests/qemucapabilitiesdata/caps_10.1.0_x86_64+inteltdx.xml index 4be89b68d9..e166d09f7d 100644 --- a/tests/qemucapabilitiesdata/caps_10.1.0_x86_64+inteltdx.xml +++ b/tests/qemucapabilitiesdata/caps_10.1.0_x86_64+inteltdx.xml @@ -192,6 +192,7 @@ <flag name='amd-iommu.pci-id'/> <flag name='usb-bot'/> <flag name='tdx-guest'/> + <flag name='acpi-generic-initiator'/> <version>10000050</version> <microcodeVersion>43100286</microcodeVersion> <package>v10.0.0-1724-gf9a3def17b</package> diff --git a/tests/qemucapabilitiesdata/caps_10.1.0_x86_64.xml b/tests/qemucapabilitiesdata/caps_10.1.0_x86_64.xml index b09707919b..afb3dd254c 100644 --- a/tests/qemucapabilitiesdata/caps_10.1.0_x86_64.xml +++ b/tests/qemucapabilitiesdata/caps_10.1.0_x86_64.xml @@ -214,6 +214,7 @@ <flag name='amd-iommu.pci-id'/> <flag name='usb-bot'/> <flag name='tdx-guest'/> + <flag name='acpi-generic-initiator'/> <version>10000050</version> <microcodeVersion>43100286</microcodeVersion> <package>v10.0.0-1874-gc77283dd5d</package> diff --git a/tests/qemucapabilitiesdata/caps_9.0.0_x86_64.xml b/tests/qemucapabilitiesdata/caps_9.0.0_x86_64.xml index a6190aba3c..ee03733cd9 100644 --- a/tests/qemucapabilitiesdata/caps_9.0.0_x86_64.xml +++ b/tests/qemucapabilitiesdata/caps_9.0.0_x86_64.xml @@ -205,6 +205,7 @@ <flag name='nvme-ns'/> <flag name='amd-iommu'/> <flag name='usb-bot'/> + <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 0f7ce7ce1b..6650e398e4 100644 --- a/tests/qemucapabilitiesdata/caps_9.1.0_riscv64.xml +++ b/tests/qemucapabilitiesdata/caps_9.1.0_riscv64.xml @@ -163,6 +163,7 @@ <flag name='nvme'/> <flag name='nvme-ns'/> <flag name='usb-bot'/> + <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 bf463fbb77..d24a31371c 100644 --- a/tests/qemucapabilitiesdata/caps_9.1.0_x86_64.xml +++ b/tests/qemucapabilitiesdata/caps_9.1.0_x86_64.xml @@ -204,6 +204,7 @@ <flag name='nvme-ns'/> <flag name='amd-iommu'/> <flag name='usb-bot'/> + <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 aa964b4885..3c89625fa3 100644 --- a/tests/qemucapabilitiesdata/caps_9.2.0_aarch64+hvf.xml +++ b/tests/qemucapabilitiesdata/caps_9.2.0_aarch64+hvf.xml @@ -136,6 +136,7 @@ <flag name='nvme'/> <flag name='nvme-ns'/> <flag name='usb-bot'/> + <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 b660de997a..b7191aab93 100644 --- a/tests/qemucapabilitiesdata/caps_9.2.0_x86_64+amdsev.xml +++ b/tests/qemucapabilitiesdata/caps_9.2.0_x86_64+amdsev.xml @@ -208,6 +208,7 @@ <flag name='nvme-ns'/> <flag name='amd-iommu'/> <flag name='usb-bot'/> + <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 bcc89fcff0..c6929e81fe 100644 --- a/tests/qemucapabilitiesdata/caps_9.2.0_x86_64.xml +++ b/tests/qemucapabilitiesdata/caps_9.2.0_x86_64.xml @@ -206,6 +206,7 @@ <flag name='nvme-ns'/> <flag name='amd-iommu'/> <flag name='usb-bot'/> + <flag name='acpi-generic-initiator'/> <version>9002000</version> <microcodeVersion>43100247</microcodeVersion> <package>v9.2.0</package> -- 2.50.1

From: Michal Privoznik <mprivozn@redhat.com> Signed-off-by: Michal Privoznik <mprivozn@redhat.com> --- src/qemu/qemu_validate.c | 17 +++++++++++++++++ 1 file changed, 17 insertions(+) diff --git a/src/qemu/qemu_validate.c b/src/qemu/qemu_validate.c index 5ead231dd0..0aaf40f971 100644 --- a/src/qemu/qemu_validate.c +++ b/src/qemu/qemu_validate.c @@ -5023,6 +5023,21 @@ qemuValidateDomainDeviceDefPstore(virDomainPstoreDef *pstore, } +static int +qemuValidateDomainDeviceAcpiInitiator(virDomainAcpiInitiatorDef *acpiinitiator G_GNUC_UNUSED, + const virDomainDef *def G_GNUC_UNUSED, + virQEMUCaps *qemuCaps) +{ + if (!virQEMUCapsGet(qemuCaps, QEMU_CAPS_ACPI_GENERIC_INITIATOR)) { + virReportError(VIR_ERR_CONFIG_UNSUPPORTED, "%s", + _("acpi-generic-initiator device is not supported")); + return -1; + } + + return 0; +} + + static int qemuSoundCodecTypeToCaps(int type) { @@ -5794,6 +5809,8 @@ qemuValidateDomainDeviceDef(const virDomainDeviceDef *dev, return qemuValidateDomainDeviceDefPstore(dev->data.pstore, def, qemuCaps); case VIR_DOMAIN_DEVICE_ACPI_INITIATOR: + return qemuValidateDomainDeviceAcpiInitiator(dev->data.acpiinitiator, def, qemuCaps); + case VIR_DOMAIN_DEVICE_LEASE: case VIR_DOMAIN_DEVICE_PANIC: case VIR_DOMAIN_DEVICE_NONE: -- 2.50.1

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 | 30 +++++++++++++++++++ .../acpi-generic-initiator.x86_64-latest.args | 8 +++++ 2 files changed, 38 insertions(+) diff --git a/src/qemu/qemu_command.c b/src/qemu/qemu_command.c index 46af5abd62..b40967f27a 100644 --- a/src/qemu/qemu_command.c +++ b/src/qemu/qemu_command.c @@ -10582,6 +10582,31 @@ qemuBuildPstoreCommandLine(virCommand *cmd, return 0; } +static int +qemuBuildAcpiInitiatorCommandLine(virCommand *cmd, + const virDomainAcpiInitiatorDef *acpiinitiator) +{ + g_autoptr(virJSONValue) props = NULL; + + 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) { + virReportError(VIR_ERR_INTERNAL_ERROR, "%s", + _("Failed to build acpi-generic-initiator properties")); + return -1; + } + + if (qemuBuildObjectCommandlineFromJSON(cmd, props) < 0) { + virReportError(VIR_ERR_INTERNAL_ERROR, "%s", + _("Failed to build QEMU command line for acpi-generic-initiator")); + return -1; + } + + return 0; +} static int qemuBuildAsyncTeardownCommandLine(virCommand *cmd, @@ -10940,6 +10965,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]) < 0) + return NULL; + } + if (qemuBuildAsyncTeardownCommandLine(cmd, def, qemuCaps) < 0) return NULL; diff --git a/tests/qemuxmlconfdata/acpi-generic-initiator.x86_64-latest.args b/tests/qemuxmlconfdata/acpi-generic-initiator.x86_64-latest.args index 37712fb68d..366b696435 100644 --- a/tests/qemuxmlconfdata/acpi-generic-initiator.x86_64-latest.args +++ b/tests/qemuxmlconfdata/acpi-generic-initiator.x86_64-latest.args @@ -44,4 +44,12 @@ XDG_CONFIG_HOME=/var/lib/libvirt/qemu/domain--1-QEMUGuest2/.config \ -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 -- 2.50.1

On Wed, Aug 06, 2025 at 02:42:10PM +0200, 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.
Ok, this took me a while to understand, but after looking at the actual QEMU code for acpi-generic-initiator it is finally clear how ridiculously simple the entire use case is. We can have multiple virtual NUMA nodes, which traditionally would have virtual CPUs and RAM assigned. Virtual PCI devices could be indirectly associated with a NUMA node by having them placed on a PXB which has affinity with a *single* NUMA node. For the NVIDIA GPU use case, however, the PCI device itself to have direct affinity with *multiple* NUMA nodes. Those nodes would not have any CPUs or memory associated with them typically. Conceptually that is an easy thing to model in the XML. The 'acpi-generic-initiator' object exposed by QEMU is a direct reflection of how the NUMA affinity is mapped at the ACPI table level. This is an inappropriate low level impl detail to expose at a high level, as well as being an insanely verbose way to configure what is really just a bitmask (of NUMA node IDs) against a device. IOW, we should not expose any of this acpi-generic-initiator stuff in libvirt XML at all. In the virDomainDeviceInfo struct we record 'acpiIndex' which is a property that sets an ACPI table index for PCI devices. This maps to the XML: <acpi index='8'/> We should extend virDomainDeviceInfo to hold 'virBitmap *acpiNodeset' to record the NUMA affinity of PCI devives (if any), and expose this as a bitset on the existing <acpi> element eg <acpi nodeset="3-5,8-10,11,15' index='8'/> Or possibly 'numaNodeset' as the attr name. With regards, Daniel -- |: https://berrange.com -o- https://www.flickr.com/photos/dberrange :| |: https://libvirt.org -o- https://fstop138.berrange.com :| |: https://entangle-photo.org -o- https://www.instagram.com/dberrange :|
participants (2)
-
Andrea Righi
-
Daniel P. Berrangé