[PATCH 0/2] 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> <alias name="gi1" /> <pci-dev>hostdev0</pci-dev> <numa-node>1</numa-node> </acpi-generic-initiator> <acpi-generic-initiator> <alias name="gi2" /> <pci-dev>hostdev0</pci-dev> <numa-node>2</numa-node> </acpi-generic-initiator> <acpi-generic-initiator> <alias name="gi3" /> <pci-dev>hostdev0</pci-dev> <numa-node>3</numa-node> </acpi-generic-initiator> <acpi-generic-initiator> <alias name="gi4" /> <pci-dev>hostdev0</pci-dev> <numa-node>4</numa-node> </acpi-generic-initiator> <acpi-generic-initiator> <alias name="gi5" /> <pci-dev>hostdev0</pci-dev> <numa-node>5</numa-node> </acpi-generic-initiator> <acpi-generic-initiator> <alias name="gi6" /> <pci-dev>hostdev0</pci-dev> <numa-node>6</numa-node> </acpi-generic-initiator> <acpi-generic-initiator> <alias name="gi7" /> <pci-dev>hostdev0</pci-dev> <numa-node>7</numa-node> </acpi-generic-initiator> <acpi-generic-initiator> <alias name="gi8" /> <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=gi1,pci-dev=hostdev0,node=1 \ -object acpi-generic-initiator,id=gi2,pci-dev=hostdev0,node=2 \ -object acpi-generic-initiator,id=gi3,pci-dev=hostdev0,node=3 \ -object acpi-generic-initiator,id=gi4,pci-dev=hostdev0,node=4 \ -object acpi-generic-initiator,id=gi5,pci-dev=hostdev0,node=5 \ -object acpi-generic-initiator,id=gi6,pci-dev=hostdev0,node=6 \ -object acpi-generic-initiator,id=gi7,pci-dev=hostdev0,node=7 \ -object acpi-generic-initiator,id=gi8,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/ Andrea Righi (2): qemu: Allow to define NUMA nodes without memory or CPUs assigned qemu: Introduce acpi-generic-initiator device src/ch/ch_domain.c | 1 + src/conf/domain_conf.c | 153 ++++++++++++++++++++++++++++++++++++++ src/conf/domain_conf.h | 14 ++++ src/conf/domain_postparse.c | 1 + src/conf/domain_validate.c | 40 ++++++++++ src/conf/numa_conf.c | 3 + src/conf/schemas/domaincommon.rng | 19 +++++ src/conf/virconftypes.h | 2 + src/libxl/libxl_driver.c | 6 ++ src/lxc/lxc_driver.c | 6 ++ src/qemu/qemu_command.c | 40 ++++++++-- 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, 297 insertions(+), 8 deletions(-)

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 | 22 ++++++++++++++-------- 2 files changed, 17 insertions(+), 8 deletions(-) diff --git a/src/conf/numa_conf.c b/src/conf/numa_conf.c index 0a0e2911f7..0b311c9416 100644 --- a/src/conf/numa_conf.c +++ b/src/conf/numa_conf.c @@ -1498,6 +1498,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 7370711918..03d0676f45 100644 --- a/src/qemu/qemu_command.c +++ b/src/qemu/qemu_command.c @@ -7567,16 +7567,20 @@ 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")); + _("At least one NUMA node has to have CPUs")); goto cleanup; } 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], @@ -7606,11 +7610,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.48.1

Allow to define new acpi-generic-initiator objects 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/ch/ch_domain.c | 1 + src/conf/domain_conf.c | 153 ++++++++++++++++++++++++++++++ src/conf/domain_conf.h | 14 +++ src/conf/domain_postparse.c | 1 + src/conf/domain_validate.c | 40 ++++++++ src/conf/schemas/domaincommon.rng | 19 ++++ src/conf/virconftypes.h | 2 + src/libxl/libxl_driver.c | 6 ++ src/lxc/lxc_driver.c | 6 ++ src/qemu/qemu_command.c | 18 ++++ 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 + 17 files changed, 280 insertions(+) diff --git a/src/ch/ch_domain.c b/src/ch/ch_domain.c index 4f5966adce..224a97bd79 100644 --- a/src/ch/ch_domain.c +++ b/src/ch/ch_domain.c @@ -159,6 +159,7 @@ chValidateDomainDeviceDef(const virDomainDeviceDef *dev, case VIR_DOMAIN_DEVICE_CONTROLLER: case VIR_DOMAIN_DEVICE_CHR: case VIR_DOMAIN_DEVICE_HOSTDEV: + case VIR_DOMAIN_DEVICE_ACPI_INITIATOR: break; case VIR_DOMAIN_DEVICE_LEASE: diff --git a/src/conf/domain_conf.c b/src/conf/domain_conf.c index 87f87bbe56..095501f77c 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, @@ -3457,6 +3458,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) { @@ -3517,6 +3531,18 @@ void virDomainHostdevDefFree(virDomainHostdevDef *def) g_free(def); } +void virDomainAcpiInitiatorDefFree(virDomainAcpiInitiatorDef *def) +{ + if (!def) + return; + + VIR_FREE(def->name); + VIR_FREE(def->pciDev); + + virDomainDeviceInfoFree(def->info); + g_free(def); +} + void virDomainHubDefFree(virDomainHubDef *def) { if (!def) @@ -3679,6 +3705,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; @@ -4605,6 +4634,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: @@ -4713,6 +4744,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; @@ -4938,6 +4972,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; @@ -4998,6 +5039,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 @@ -13373,6 +13415,60 @@ virDomainHostdevDefParseXML(virDomainXMLOption *xmlopt, } +static virDomainAcpiInitiatorDef * +virDomainAcpiInitiatorDefParseXML(virDomainXMLOption *xmlopt, + xmlNodePtr node, + xmlXPathContextPtr ctxt, + unsigned int flags) +{ + virDomainAcpiInitiatorDef *def; + xmlNodePtr cur; + + VIR_XPATH_NODE_AUTORESTORE(ctxt) + + ctxt->node = node; + + if (!(def = virDomainAcpiInitiatorDefNew())) + goto error; + + for (cur = node->children; cur; cur = cur->next) { + if (cur->type != XML_ELEMENT_NODE) + continue; + + if (xmlStrEqual(cur->name, BAD_CAST "alias")) { + def->name = virXMLPropString(cur, "name"); + if (!def->name) + goto error; + } else if (xmlStrEqual(cur->name, BAD_CAST "pci-dev")) { + def->pciDev = virXMLNodeContentString(cur); + if (!def->pciDev) + goto error; + } else if (xmlStrEqual(cur->name, BAD_CAST "numa-node")) { + xmlChar *content = xmlNodeGetContent(cur); + + if (!content) + goto error; + if (virStrToLong_i((const char *)content, NULL, 10, &def->numaNode) < 0) { + xmlFree(content); + goto error; + } + xmlFree(content); + } + } + + if (def->info->type == VIR_DOMAIN_DEVICE_ADDRESS_TYPE_NONE) { + if (virDomainDeviceInfoParseXML(xmlopt, node, ctxt, def->info, + flags) < 0) + goto error; + } + return def; + + error: + virDomainAcpiInitiatorDefFree(def); + return NULL; +} + + static virDomainRedirdevDef * virDomainRedirdevDefParseXML(virDomainXMLOption *xmlopt, xmlNodePtr node, @@ -14374,6 +14470,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; @@ -19798,6 +19900,23 @@ virDomainDefParseXML(xmlXPathContextPtr ctxt, } VIR_FREE(nodes); + /* analysis of the acpi generic initiator */ + if ((n = virXPathNodeSet("./devices/acpi-generic-initiator", ctxt, &nodes)) < 0) + return NULL; + + 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; @@ -20725,6 +20844,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) @@ -22073,6 +22203,11 @@ 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, @@ -22243,6 +22378,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 @@ -28287,6 +28423,19 @@ virDomainPstoreDefFormat(virBuffer *buf, return 0; } +static void +virDomainAcpiInitiatorDefFormat(virBuffer *buf, + virDomainAcpiInitiatorDef *acpiinitiator) +{ + g_auto(virBuffer) attrBuf = VIR_BUFFER_INITIALIZER; + g_auto(virBuffer) childBuf = VIR_BUFFER_INIT_CHILD(buf); + + virBufferAsprintf(&childBuf, "<alias name=\"%s\" />\n", acpiinitiator->name); + virBufferAsprintf(&childBuf, "<pci-dev>%s</pci-dev>\n", acpiinitiator->pciDev); + virBufferAsprintf(&childBuf, "<numa-node>%d</numa-node>\n", acpiinitiator->numaNode); + + virXMLFormatElement(buf, "acpi-generic-initiator", &attrBuf, &childBuf); +} int virDomainDefFormatInternal(virDomainDef *def, @@ -28762,6 +28911,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"); @@ -28922,6 +29074,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 e51c74b6d1..b43d589760 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,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 @@ -3210,6 +3219,9 @@ struct _virDomainDef { size_t ntpms; virDomainTPMDef **tpms; + size_t nacpiinitiator; + virDomainAcpiInitiatorDef **acpiinitiator; + /* Only 1 */ virDomainMemballoonDef *memballoon; virDomainNVRAMDef *nvram; @@ -3690,6 +3702,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/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 eb5e764c02..3bcbedb4fb 100644 --- a/src/conf/domain_validate.c +++ b/src/conf/domain_validate.c @@ -2316,6 +2316,43 @@ virDomainHostdevDefValidate(const virDomainHostdevDef *hostdev) } +static int +virDomainAcpiInitiatorDefValidate(const virDomainDef *def, + const virDomainAcpiInitiatorDef *acpiinitiator) +{ + const size_t nodeCount = virDomainNumaGetNodeCount(def->numa); + size_t i; + + if (!nodeCount) { + virReportError(VIR_ERR_INTERNAL_ERROR, "%s", + _("No NUMA node defined")); + return -1; + } + + for (i = 0; i < nodeCount; i++) + if (acpiinitiator->numaNode == i) + break; + if (i == nodeCount) { + virReportError(VIR_ERR_INTERNAL_ERROR, "%s", + _("acpi-generic-initiator must have a valid NUMA node")); + return -1; + } + + if (acpiinitiator->name[0] == '\0') { + virReportError(VIR_ERR_INTERNAL_ERROR, "%s", + _("acpi-generic-initiator must have a name")); + return -1; + } + + if (acpiinitiator->pciDev[0] == '\0') { + virReportError(VIR_ERR_INTERNAL_ERROR, "%s", + _("acpi-generic-initiator must have a PCI device assigned")); + return -1; + } + + return 0; +} + /** * virDomainMemoryGetMappedSize: * @mem: memory device definition @@ -3234,6 +3271,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 96cedb85e8..f6c42a4844 100644 --- a/src/conf/schemas/domaincommon.rng +++ b/src/conf/schemas/domaincommon.rng @@ -6807,6 +6807,7 @@ <ref name="shmem"/> <ref name="memorydev"/> <ref name="crypto"/> + <ref name="acpi-generic-initiator"/> </choice> </zeroOrMore> <zeroOrMore> @@ -7626,6 +7627,24 @@ </element> </define> + <define name="acpi-generic-initiator"> + <element name="acpi-generic-initiator"> + <interleave> + <element name="alias"> + <attribute name="name"> + <text/> + </attribute> + </element> + <element name="pci-dev"> + <text/> + </element> + <element name="numa-node"> + <text/> + </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 59be61cea4..564c06638e 100644 --- a/src/conf/virconftypes.h +++ b/src/conf/virconftypes.h @@ -118,6 +118,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/libxl/libxl_driver.c b/src/libxl/libxl_driver.c index a76545c9ff..61e21dd85d 100644 --- a/src/libxl/libxl_driver.c +++ b/src/libxl/libxl_driver.c @@ -3511,6 +3511,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)); @@ -3620,6 +3621,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; @@ -3989,6 +3991,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)); @@ -4080,6 +4083,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; @@ -4143,6 +4147,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)); @@ -4206,6 +4211,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 4740aeed52..828abc5d32 100644 --- a/src/lxc/lxc_driver.c +++ b/src/lxc/lxc_driver.c @@ -3024,6 +3024,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; @@ -3090,6 +3091,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; @@ -3172,6 +3174,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; @@ -3274,6 +3277,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); @@ -3950,6 +3954,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)); @@ -4368,6 +4373,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_command.c b/src/qemu/qemu_command.c index 03d0676f45..0619e2b132 100644 --- a/src/qemu/qemu_command.c +++ b/src/qemu/qemu_command.c @@ -991,6 +991,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; @@ -10290,6 +10291,18 @@ qemuBuildPstoreCommandLine(virCommand *cmd, return 0; } +static int +qemuBuildAcpiInitiatorCommandLine(virCommand *cmd, + const virDomainAcpiInitiatorDef *acpiinitiator) +{ + g_autofree char *obj = NULL; + + obj = g_strdup_printf("acpi-generic-initiator,id=%s,pci-dev=%s,node=%d", + acpiinitiator->name, acpiinitiator->pciDev, acpiinitiator->numaNode); + virCommandAddArgList(cmd, "-object", obj, NULL); + + return 0; +} static int qemuBuildAsyncTeardownCommandLine(virCommand *cmd, @@ -10656,6 +10669,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/src/qemu/qemu_domain.c b/src/qemu/qemu_domain.c index cf05dca55a..36782b381e 100644 --- a/src/qemu/qemu_domain.c +++ b/src/qemu/qemu_domain.c @@ -8721,6 +8721,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; } @@ -10655,6 +10656,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 970ae3949d..aac0ca7ece 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 78bfaa5b3a..ada49fb389 100644 --- a/src/qemu/qemu_driver.c +++ b/src/qemu/qemu_driver.c @@ -6899,6 +6899,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"), @@ -7118,6 +7119,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"), @@ -7244,6 +7246,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 6c224c9793..089e5d9aad 100644 --- a/src/qemu/qemu_hotplug.c +++ b/src/qemu/qemu_hotplug.c @@ -3521,6 +3521,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"), @@ -5440,6 +5441,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; @@ -5545,6 +5547,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"), @@ -6440,6 +6443,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"), @@ -7432,6 +7436,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 20ee333e0d..c81f93e384 100644 --- a/src/qemu/qemu_postparse.c +++ b/src/qemu/qemu_postparse.c @@ -905,6 +905,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 76f2eafe49..ddd067c331 100644 --- a/src/qemu/qemu_validate.c +++ b/src/qemu/qemu_validate.c @@ -5498,6 +5498,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.48.1

On Wed, Feb 12, 2025 at 07:26:09 +0100, Andrea Righi via Devel wrote:
Allow to define new acpi-generic-initiator objects 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> ---
Note this is not a full review and I don't plan to review any further aspects of this series.
src/ch/ch_domain.c | 1 + src/conf/domain_conf.c | 153 ++++++++++++++++++++++++++++++ src/conf/domain_conf.h | 14 +++ src/conf/domain_postparse.c | 1 + src/conf/domain_validate.c | 40 ++++++++ src/conf/schemas/domaincommon.rng | 19 ++++
We usually tend to separate generic parser infrastructure ...
src/conf/virconftypes.h | 2 + src/libxl/libxl_driver.c | 6 ++ src/lxc/lxc_driver.c | 6 ++ src/qemu/qemu_command.c | 18 ++++ 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 +
... from any driver implementation into a separate patch.
src/test/test_driver.c | 4 + 17 files changed, 280 insertions(+)
So that's easier to review. You are also adding new XML but are completely missing test files which show how it's used and excercise the parser and formatter as well as the qemu driver implementation. The simplest way is to use qemuxmlconftest to add these. You're also referencing 'acpi-generic-initiator' object which is not supported by all versions so you'll need to add a capability flag for it. See qemu_capabilities.c/h
+static int +qemuBuildAcpiInitiatorCommandLine(virCommand *cmd, + const virDomainAcpiInitiatorDef *acpiinitiator) +{ + g_autofree char *obj = NULL; + + obj = g_strdup_printf("acpi-generic-initiator,id=%s,pci-dev=%s,node=%d", + acpiinitiator->name, acpiinitiator->pciDev, acpiinitiator->numaNode); + virCommandAddArgList(cmd, "-object", obj, NULL);
All other code which uses defines -object uses JSON props. You'll have to convert this to use the same approach and use qemuBuildObjectCommandlineFromJSON() to convert the JSON definition to the commandline. Apart from symmetry, this'll provide validation of the generated properties against qemu's internal schemas.

Hi Peter, On Wed, Feb 12, 2025 at 10:05:08AM +0100, Peter Krempa wrote:
On Wed, Feb 12, 2025 at 07:26:09 +0100, Andrea Righi via Devel wrote:
Allow to define new acpi-generic-initiator objects 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> ---
Note this is not a full review and I don't plan to review any further aspects of this series.
src/ch/ch_domain.c | 1 + src/conf/domain_conf.c | 153 ++++++++++++++++++++++++++++++ src/conf/domain_conf.h | 14 +++ src/conf/domain_postparse.c | 1 + src/conf/domain_validate.c | 40 ++++++++ src/conf/schemas/domaincommon.rng | 19 ++++
We usually tend to separate generic parser infrastructure ...
src/conf/virconftypes.h | 2 + src/libxl/libxl_driver.c | 6 ++ src/lxc/lxc_driver.c | 6 ++ src/qemu/qemu_command.c | 18 ++++ 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 +
... from any driver implementation into a separate patch.
Ok, I'll split the patch.
src/test/test_driver.c | 4 + 17 files changed, 280 insertions(+)
So that's easier to review.
You are also adding new XML but are completely missing test files which show how it's used and excercise the parser and formatter as well as the qemu driver implementation.
The simplest way is to use qemuxmlconftest to add these.
Ack, I'll add a test in qemuxmlconftest.
You're also referencing 'acpi-generic-initiator' object which is not supported by all versions so you'll need to add a capability flag for it. See qemu_capabilities.c/h
Ok.
+static int +qemuBuildAcpiInitiatorCommandLine(virCommand *cmd, + const virDomainAcpiInitiatorDef *acpiinitiator) +{ + g_autofree char *obj = NULL; + + obj = g_strdup_printf("acpi-generic-initiator,id=%s,pci-dev=%s,node=%d", + acpiinitiator->name, acpiinitiator->pciDev, acpiinitiator->numaNode); + virCommandAddArgList(cmd, "-object", obj, NULL);
All other code which uses defines -object uses JSON props. You'll have to convert this to use the same approach and use
qemuBuildObjectCommandlineFromJSON()
to convert the JSON definition to the commandline.
Apart from symmetry, this'll provide validation of the generated properties against qemu's internal schemas.
Ok, makes sense. Thanks for the hints! -Andrea
participants (2)
-
Andrea Righi
-
Peter Krempa