libvirt-11.10.0-10.7.el10nv
- conf: Support EGM memory device model (VOYAGER-13) - qemu: Add cgroup, namespace, and seclabel setup for EGM memory device model (VOYAGER-13) - qemu: Add qemu CLI support for EGM (VOYAGER-13) - tests: Add qemuxmlconftest for ACPI EGM memory device (VOYAGER-13) Resolves: VOYAGER-13
This commit is contained in:
parent
f61b15baa2
commit
dd91c3be50
10
gating.yaml
10
gating.yaml
@ -1,10 +0,0 @@
|
||||
# recipients: libvirt-qe
|
||||
--- !Policy
|
||||
product_versions:
|
||||
- rhel-10
|
||||
decision_context: osci_compose_gate
|
||||
subject_type: brew-build
|
||||
rules:
|
||||
- !PassingTestCaseRule {test_case_name: libvirt-ci.libvirt.brew-build.gating.x86_64.tier1.functional}
|
||||
- !PassingTestCaseRule {test_case_name: libvirt-ci.libvirt-python.brew-build.gating.x86_64.tier1.functional}
|
||||
- !PassingTestCaseRule {test_case_name: libvirt-ci.libvirt.brew-build.gating.s390x.tier1.functional}
|
||||
275
libvirt-conf-Support-EGM-memory-device-model.patch
Normal file
275
libvirt-conf-Support-EGM-memory-device-model.patch
Normal file
@ -0,0 +1,275 @@
|
||||
From 8049e03589d633edba613c6775dcd5656d851460 Mon Sep 17 00:00:00 2001
|
||||
Message-ID: <8049e03589d633edba613c6775dcd5656d851460.1779098642.git.phrdina@redhat.com>
|
||||
From: Pavel Hrdina <phrdina@redhat.com>
|
||||
Date: Tue, 25 Nov 2025 11:17:01 -0800
|
||||
Subject: [PATCH] conf: Support EGM memory device model
|
||||
|
||||
From: Nathan Chen via Devel <devel@lists.libvirt.org>
|
||||
|
||||
Add support for EGM memory device model with
|
||||
'path' source attribute and 'pciDev' target
|
||||
attribute to denote host EGM device backing path
|
||||
and PCI device alias to associate the vEGM with,
|
||||
respectively.
|
||||
|
||||
Signed-off-by: Nathan Chen <nathanc@nvidia.com>
|
||||
|
||||
Resolves: https://redhat.atlassian.net/browse/VOYAGER-13
|
||||
---
|
||||
docs/formatdomain.rst | 18 +++++++++++++++++-
|
||||
src/conf/domain_conf.c | 29 +++++++++++++++++++++++++++++
|
||||
src/conf/domain_conf.h | 7 +++++++
|
||||
src/conf/domain_postparse.c | 1 +
|
||||
src/conf/domain_validate.c | 15 +++++++++++++++
|
||||
src/conf/schemas/domaincommon.rng | 6 ++++++
|
||||
6 files changed, 75 insertions(+), 1 deletion(-)
|
||||
|
||||
diff --git a/docs/formatdomain.rst b/docs/formatdomain.rst
|
||||
index 44f9b6e197..4fde1534d6 100644
|
||||
--- a/docs/formatdomain.rst
|
||||
+++ b/docs/formatdomain.rst
|
||||
@@ -9119,6 +9119,16 @@ Example: usage of the memory devices
|
||||
<size unit='KiB'>16384</size>
|
||||
</target>
|
||||
</memory>
|
||||
+ <memory model='egm' access='shared'>
|
||||
+ <source>
|
||||
+ <path>/dev/egm0</path>
|
||||
+ </source>
|
||||
+ <target>
|
||||
+ <size unit='KiB'>524288</size>
|
||||
+ <node>0</node>
|
||||
+ <pciDev>ua-hostdev0</pciDev>
|
||||
+ </target>
|
||||
+ </memory>
|
||||
</devices>
|
||||
...
|
||||
|
||||
@@ -9130,7 +9140,8 @@ Example: usage of the memory devices
|
||||
persistent memory device. :since:`Since 7.1.0` Provide ``virtio-mem`` model
|
||||
to add paravirtualized memory device. :since:`Since 7.9.0` Provide
|
||||
``sgx-epc`` model to add a SGX enclave page cache (EPC) memory to the guest.
|
||||
- :since:`Since 8.10.0 and QEMU 7.0.0`
|
||||
+ :since:`Since 8.10.0 and QEMU 7.0.0` Provide ``egm`` model to add a EGM
|
||||
+ (Extended GPU Memory) device.
|
||||
|
||||
``access``
|
||||
An optional attribute ``access`` ( :since:`since 3.2.0` ) that provides
|
||||
@@ -9265,6 +9276,11 @@ Example: usage of the memory devices
|
||||
The physical address in memory, where device is mapped.
|
||||
:since:`Since 9.4.0`
|
||||
|
||||
+ ``pciDev``
|
||||
+ For ``egm`` only.
|
||||
+ The PCI device that is enabled to access the system memory via
|
||||
+ association with the EGM device.
|
||||
+
|
||||
|
||||
IOMMU devices
|
||||
~~~~~~~~~~~~~
|
||||
diff --git a/src/conf/domain_conf.c b/src/conf/domain_conf.c
|
||||
index 06790e0962..038476edd7 100644
|
||||
--- a/src/conf/domain_conf.c
|
||||
+++ b/src/conf/domain_conf.c
|
||||
@@ -1522,6 +1522,7 @@ VIR_ENUM_IMPL(virDomainMemoryModel,
|
||||
"virtio-pmem",
|
||||
"virtio-mem",
|
||||
"sgx-epc",
|
||||
+ "egm",
|
||||
);
|
||||
|
||||
VIR_ENUM_IMPL(virDomainShmemModel,
|
||||
@@ -3638,6 +3639,9 @@ void virDomainMemoryDefFree(virDomainMemoryDef *def)
|
||||
case VIR_DOMAIN_MEMORY_MODEL_SGX_EPC:
|
||||
virBitmapFree(def->source.sgx_epc.nodes);
|
||||
break;
|
||||
+ case VIR_DOMAIN_MEMORY_MODEL_EGM:
|
||||
+ g_free(def->source.egm.path);
|
||||
+ g_free(def->target.egm.pciDev);
|
||||
case VIR_DOMAIN_MEMORY_MODEL_NONE:
|
||||
case VIR_DOMAIN_MEMORY_MODEL_LAST:
|
||||
break;
|
||||
@@ -14216,6 +14220,10 @@ virDomainMemorySourceDefParseXML(xmlNodePtr node,
|
||||
}
|
||||
break;
|
||||
|
||||
+ case VIR_DOMAIN_MEMORY_MODEL_EGM:
|
||||
+ def->source.egm.path = virXPathString("string(./path)", ctxt);
|
||||
+ break;
|
||||
+
|
||||
case VIR_DOMAIN_MEMORY_MODEL_NONE:
|
||||
case VIR_DOMAIN_MEMORY_MODEL_LAST:
|
||||
break;
|
||||
@@ -14292,6 +14300,10 @@ virDomainMemoryTargetDefParseXML(xmlNodePtr node,
|
||||
addr = &def->target.virtio_pmem.address;
|
||||
break;
|
||||
|
||||
+ case VIR_DOMAIN_MEMORY_MODEL_EGM:
|
||||
+ def->target.egm.pciDev = virXPathString("string(./pciDev)", ctxt);
|
||||
+ break;
|
||||
+
|
||||
case VIR_DOMAIN_MEMORY_MODEL_NONE:
|
||||
case VIR_DOMAIN_MEMORY_MODEL_DIMM:
|
||||
case VIR_DOMAIN_MEMORY_MODEL_SGX_EPC:
|
||||
@@ -14513,6 +14525,7 @@ virDomainMemoryIsVirtioModel(const virDomainMemoryDef *def)
|
||||
case VIR_DOMAIN_MEMORY_MODEL_DIMM:
|
||||
case VIR_DOMAIN_MEMORY_MODEL_NVDIMM:
|
||||
case VIR_DOMAIN_MEMORY_MODEL_SGX_EPC:
|
||||
+ case VIR_DOMAIN_MEMORY_MODEL_EGM:
|
||||
case VIR_DOMAIN_MEMORY_MODEL_LAST:
|
||||
break;
|
||||
}
|
||||
@@ -16415,6 +16428,12 @@ virDomainMemoryFindByDefInternal(virDomainDef *def,
|
||||
continue;
|
||||
break;
|
||||
|
||||
+ case VIR_DOMAIN_MEMORY_MODEL_EGM:
|
||||
+ if (STRNEQ(tmp->source.egm.path, mem->source.egm.path))
|
||||
+ continue;
|
||||
+ if (STRNEQ(tmp->target.egm.pciDev, mem->target.egm.pciDev))
|
||||
+ continue;
|
||||
+
|
||||
case VIR_DOMAIN_MEMORY_MODEL_NONE:
|
||||
case VIR_DOMAIN_MEMORY_MODEL_LAST:
|
||||
break;
|
||||
@@ -22430,6 +22449,7 @@ virDomainMemoryDefCheckABIStability(virDomainMemoryDef *src,
|
||||
|
||||
case VIR_DOMAIN_MEMORY_MODEL_DIMM:
|
||||
case VIR_DOMAIN_MEMORY_MODEL_SGX_EPC:
|
||||
+ case VIR_DOMAIN_MEMORY_MODEL_EGM:
|
||||
case VIR_DOMAIN_MEMORY_MODEL_NONE:
|
||||
case VIR_DOMAIN_MEMORY_MODEL_LAST:
|
||||
break;
|
||||
@@ -26998,6 +27018,10 @@ virDomainMemorySourceDefFormat(virBuffer *buf,
|
||||
}
|
||||
break;
|
||||
|
||||
+ case VIR_DOMAIN_MEMORY_MODEL_EGM:
|
||||
+ virBufferEscapeString(&childBuf, "<path>%s</path>\n", def->source.egm.path);
|
||||
+ break;
|
||||
+
|
||||
case VIR_DOMAIN_MEMORY_MODEL_NONE:
|
||||
case VIR_DOMAIN_MEMORY_MODEL_LAST:
|
||||
break;
|
||||
@@ -27060,6 +27084,11 @@ virDomainMemoryTargetDefFormat(virBuffer *buf,
|
||||
}
|
||||
break;
|
||||
|
||||
+ case VIR_DOMAIN_MEMORY_MODEL_EGM:
|
||||
+ if (def->target.egm.pciDev)
|
||||
+ virBufferAsprintf(&childBuf, "<pciDev>%s</pciDev>\n", def->target.egm.pciDev);
|
||||
+ break;
|
||||
+
|
||||
case VIR_DOMAIN_MEMORY_MODEL_SGX_EPC:
|
||||
case VIR_DOMAIN_MEMORY_MODEL_DIMM:
|
||||
case VIR_DOMAIN_MEMORY_MODEL_NONE:
|
||||
diff --git a/src/conf/domain_conf.h b/src/conf/domain_conf.h
|
||||
index 06e03deafe..4d03521245 100644
|
||||
--- a/src/conf/domain_conf.h
|
||||
+++ b/src/conf/domain_conf.h
|
||||
@@ -2755,6 +2755,7 @@ typedef enum {
|
||||
VIR_DOMAIN_MEMORY_MODEL_VIRTIO_PMEM, /* virtio-pmem memory device */
|
||||
VIR_DOMAIN_MEMORY_MODEL_VIRTIO_MEM, /* virtio-mem memory device */
|
||||
VIR_DOMAIN_MEMORY_MODEL_SGX_EPC, /* SGX enclave page cache */
|
||||
+ VIR_DOMAIN_MEMORY_MODEL_EGM, /* Extended GPU memory */
|
||||
|
||||
VIR_DOMAIN_MEMORY_MODEL_LAST
|
||||
} virDomainMemoryModel;
|
||||
@@ -2787,6 +2788,9 @@ struct _virDomainMemoryDef {
|
||||
struct {
|
||||
virBitmap *nodes; /* source NUMA nodes */
|
||||
} sgx_epc;
|
||||
+ struct {
|
||||
+ char *path;
|
||||
+ } egm;
|
||||
} source;
|
||||
|
||||
union {
|
||||
@@ -2812,6 +2816,9 @@ struct _virDomainMemoryDef {
|
||||
} virtio_mem;
|
||||
struct {
|
||||
} sgx_epc;
|
||||
+ struct {
|
||||
+ char *pciDev;
|
||||
+ } egm;
|
||||
} target;
|
||||
|
||||
virDomainDeviceInfo info;
|
||||
diff --git a/src/conf/domain_postparse.c b/src/conf/domain_postparse.c
|
||||
index 38e731348d..0181d21f0e 100644
|
||||
--- a/src/conf/domain_postparse.c
|
||||
+++ b/src/conf/domain_postparse.c
|
||||
@@ -632,6 +632,7 @@ virDomainMemoryDefPostParse(virDomainMemoryDef *mem,
|
||||
case VIR_DOMAIN_MEMORY_MODEL_VIRTIO_MEM:
|
||||
case VIR_DOMAIN_MEMORY_MODEL_SGX_EPC:
|
||||
case VIR_DOMAIN_MEMORY_MODEL_DIMM:
|
||||
+ case VIR_DOMAIN_MEMORY_MODEL_EGM:
|
||||
case VIR_DOMAIN_MEMORY_MODEL_NONE:
|
||||
case VIR_DOMAIN_MEMORY_MODEL_LAST:
|
||||
break;
|
||||
diff --git a/src/conf/domain_validate.c b/src/conf/domain_validate.c
|
||||
index f243b119a4..34906ddc84 100644
|
||||
--- a/src/conf/domain_validate.c
|
||||
+++ b/src/conf/domain_validate.c
|
||||
@@ -2525,6 +2525,7 @@ virDomainMemoryDefCheckConflict(const virDomainMemoryDef *mem,
|
||||
}
|
||||
break;
|
||||
case VIR_DOMAIN_MEMORY_MODEL_SGX_EPC:
|
||||
+ case VIR_DOMAIN_MEMORY_MODEL_EGM:
|
||||
case VIR_DOMAIN_MEMORY_MODEL_NONE:
|
||||
case VIR_DOMAIN_MEMORY_MODEL_LAST:
|
||||
break;
|
||||
@@ -2571,6 +2572,7 @@ virDomainMemoryDefCheckConflict(const virDomainMemoryDef *mem,
|
||||
switch (other->model) {
|
||||
case VIR_DOMAIN_MEMORY_MODEL_NONE:
|
||||
case VIR_DOMAIN_MEMORY_MODEL_SGX_EPC:
|
||||
+ case VIR_DOMAIN_MEMORY_MODEL_EGM:
|
||||
case VIR_DOMAIN_MEMORY_MODEL_LAST:
|
||||
continue;
|
||||
break;
|
||||
@@ -2751,6 +2753,19 @@ virDomainMemoryDefValidate(const virDomainMemoryDef *mem,
|
||||
}
|
||||
break;
|
||||
|
||||
+ case VIR_DOMAIN_MEMORY_MODEL_EGM:
|
||||
+ if (!mem->source.egm.path) {
|
||||
+ virReportError(VIR_ERR_XML_DETAIL, "%s",
|
||||
+ _("path is required for model 'egm'"));
|
||||
+ return -1;
|
||||
+ }
|
||||
+ if (!mem->target.egm.pciDev) {
|
||||
+ virReportError(VIR_ERR_XML_DETAIL, "%s",
|
||||
+ _("pciDev is required for model 'egm'"));
|
||||
+ return -1;
|
||||
+ }
|
||||
+ break;
|
||||
+
|
||||
case VIR_DOMAIN_MEMORY_MODEL_NONE:
|
||||
case VIR_DOMAIN_MEMORY_MODEL_LAST:
|
||||
default:
|
||||
diff --git a/src/conf/schemas/domaincommon.rng b/src/conf/schemas/domaincommon.rng
|
||||
index 839a144da8..123e4057b7 100644
|
||||
--- a/src/conf/schemas/domaincommon.rng
|
||||
+++ b/src/conf/schemas/domaincommon.rng
|
||||
@@ -7561,6 +7561,7 @@
|
||||
<value>virtio-pmem</value>
|
||||
<value>virtio-mem</value>
|
||||
<value>sgx-epc</value>
|
||||
+ <value>egm</value>
|
||||
</choice>
|
||||
</attribute>
|
||||
<optional>
|
||||
@@ -7692,6 +7693,11 @@
|
||||
</attribute>
|
||||
</element>
|
||||
</optional>
|
||||
+ <optional>
|
||||
+ <element name="pciDev">
|
||||
+ <data type="string"/>
|
||||
+ </element>
|
||||
+ </optional>
|
||||
</interleave>
|
||||
</element>
|
||||
</define>
|
||||
--
|
||||
2.54.0
|
||||
@ -0,0 +1,166 @@
|
||||
From d1f3b404a08e097e6ddac10452b4ed142e35a89b Mon Sep 17 00:00:00 2001
|
||||
Message-ID: <d1f3b404a08e097e6ddac10452b4ed142e35a89b.1779098642.git.phrdina@redhat.com>
|
||||
From: Pavel Hrdina <phrdina@redhat.com>
|
||||
Date: Tue, 25 Nov 2025 11:17:02 -0800
|
||||
Subject: [PATCH] qemu: Add cgroup, namespace, and seclabel setup for EGM
|
||||
memory device model
|
||||
|
||||
From: Nathan Chen via Devel <devel@lists.libvirt.org>
|
||||
|
||||
Implement proper isolation and access control for EGM memory devices:
|
||||
|
||||
- Add device to cgroup for access control
|
||||
- Set up namespace mappings for device access
|
||||
- Ensure proper permissions in containerized environments
|
||||
- Allow EGM device path access to bypass SELinux, AppArmor,
|
||||
and DAC permissions
|
||||
|
||||
Signed-off-by: Nathan Chen <nathanc@nvidia.com>
|
||||
|
||||
Resolves: https://redhat.atlassian.net/browse/VOYAGER-13
|
||||
---
|
||||
src/qemu/qemu_cgroup.c | 10 ++++++++++
|
||||
src/qemu/qemu_namespace.c | 3 +++
|
||||
src/security/apparmor/usr.sbin.libvirtd.in | 3 +++
|
||||
src/security/security_apparmor.c | 2 ++
|
||||
src/security/security_dac.c | 8 ++++++++
|
||||
src/security/security_selinux.c | 6 ++++++
|
||||
src/security/virt-aa-helper.c | 4 ++++
|
||||
7 files changed, 36 insertions(+)
|
||||
|
||||
diff --git a/src/qemu/qemu_cgroup.c b/src/qemu/qemu_cgroup.c
|
||||
index 0e1815f571..ee3795329a 100644
|
||||
--- a/src/qemu/qemu_cgroup.c
|
||||
+++ b/src/qemu/qemu_cgroup.c
|
||||
@@ -580,6 +580,11 @@ qemuSetupMemoryDevicesCgroup(virDomainObj *vm,
|
||||
VIR_CGROUP_DEVICE_RW, false) < 0)
|
||||
return -1;
|
||||
break;
|
||||
+ case VIR_DOMAIN_MEMORY_MODEL_EGM:
|
||||
+ if (qemuCgroupAllowDevicePath(vm, mem->source.egm.path,
|
||||
+ VIR_CGROUP_DEVICE_RW, false) < 0)
|
||||
+ return -1;
|
||||
+ break;
|
||||
case VIR_DOMAIN_MEMORY_MODEL_NONE:
|
||||
case VIR_DOMAIN_MEMORY_MODEL_DIMM:
|
||||
case VIR_DOMAIN_MEMORY_MODEL_VIRTIO_MEM:
|
||||
@@ -618,6 +623,11 @@ qemuTeardownMemoryDevicesCgroup(virDomainObj *vm,
|
||||
VIR_CGROUP_DEVICE_RW, false) < 0)
|
||||
return -1;
|
||||
break;
|
||||
+ case VIR_DOMAIN_MEMORY_MODEL_EGM:
|
||||
+ if (qemuCgroupDenyDevicePath(vm, mem->source.egm.path,
|
||||
+ VIR_CGROUP_DEVICE_RWM, false) < 0)
|
||||
+ return -1;
|
||||
+ break;
|
||||
case VIR_DOMAIN_MEMORY_MODEL_NONE:
|
||||
case VIR_DOMAIN_MEMORY_MODEL_DIMM:
|
||||
case VIR_DOMAIN_MEMORY_MODEL_VIRTIO_MEM:
|
||||
diff --git a/src/qemu/qemu_namespace.c b/src/qemu/qemu_namespace.c
|
||||
index 4a063064f1..f17a59545b 100644
|
||||
--- a/src/qemu/qemu_namespace.c
|
||||
+++ b/src/qemu/qemu_namespace.c
|
||||
@@ -397,6 +397,9 @@ qemuDomainSetupMemory(virDomainMemoryDef *mem,
|
||||
*paths = g_slist_prepend(*paths, g_strdup(QEMU_DEV_SGX_VEPVC));
|
||||
*paths = g_slist_prepend(*paths, g_strdup(QEMU_DEV_SGX_PROVISION));
|
||||
break;
|
||||
+ case VIR_DOMAIN_MEMORY_MODEL_EGM:
|
||||
+ *paths = g_slist_prepend(*paths, g_strdup(mem->source.egm.path));
|
||||
+ break;
|
||||
|
||||
case VIR_DOMAIN_MEMORY_MODEL_NONE:
|
||||
case VIR_DOMAIN_MEMORY_MODEL_DIMM:
|
||||
diff --git a/src/security/apparmor/usr.sbin.libvirtd.in b/src/security/apparmor/usr.sbin.libvirtd.in
|
||||
index 6267e4f737..2a6a4b979c 100644
|
||||
--- a/src/security/apparmor/usr.sbin.libvirtd.in
|
||||
+++ b/src/security/apparmor/usr.sbin.libvirtd.in
|
||||
@@ -47,6 +47,9 @@ profile libvirtd @sbindir@/libvirtd flags=(attach_disconnected) {
|
||||
mount options=(rw, move) /{,var/}run/libvirt/qemu/*{,/} -> /dev/**,
|
||||
umount /{,var/}run/libvirt/qemu/*{,/},
|
||||
|
||||
+ # Allow bind mounting EGM devices into qemu namespaces
|
||||
+ mount options=(rw, bind) /dev/egm* -> /{,var/}run/libvirt/qemu/**,
|
||||
+
|
||||
network inet stream,
|
||||
network inet dgram,
|
||||
network inet6 stream,
|
||||
diff --git a/src/security/security_apparmor.c b/src/security/security_apparmor.c
|
||||
index e53486ee0c..4d8b1e20d3 100644
|
||||
--- a/src/security/security_apparmor.c
|
||||
+++ b/src/security/security_apparmor.c
|
||||
@@ -631,6 +631,8 @@ AppArmorSetMemoryLabel(virSecurityManager *mgr,
|
||||
case VIR_DOMAIN_MEMORY_MODEL_DIMM:
|
||||
case VIR_DOMAIN_MEMORY_MODEL_VIRTIO_MEM:
|
||||
case VIR_DOMAIN_MEMORY_MODEL_SGX_EPC:
|
||||
+ case VIR_DOMAIN_MEMORY_MODEL_EGM:
|
||||
+ path = mem->source.egm.path;
|
||||
case VIR_DOMAIN_MEMORY_MODEL_LAST:
|
||||
break;
|
||||
}
|
||||
diff --git a/src/security/security_dac.c b/src/security/security_dac.c
|
||||
index b891f6f121..bff0e03f35 100644
|
||||
--- a/src/security/security_dac.c
|
||||
+++ b/src/security/security_dac.c
|
||||
@@ -1909,6 +1909,9 @@ virSecurityDACRestoreMemoryLabel(virSecurityManager *mgr,
|
||||
* don't need to restore anything. */
|
||||
break;
|
||||
|
||||
+ case VIR_DOMAIN_MEMORY_MODEL_EGM:
|
||||
+ return virSecurityDACRestoreFileLabel(mgr, mem->source.egm.path);
|
||||
+
|
||||
case VIR_DOMAIN_MEMORY_MODEL_DIMM:
|
||||
case VIR_DOMAIN_MEMORY_MODEL_VIRTIO_MEM:
|
||||
case VIR_DOMAIN_MEMORY_MODEL_LAST:
|
||||
@@ -2140,6 +2143,11 @@ virSecurityDACSetMemoryLabel(virSecurityManager *mgr,
|
||||
return -1;
|
||||
break;
|
||||
|
||||
+ case VIR_DOMAIN_MEMORY_MODEL_EGM:
|
||||
+ return virSecurityDACSetOwnership(mgr, NULL,
|
||||
+ mem->source.egm.path,
|
||||
+ user, group, true);
|
||||
+
|
||||
case VIR_DOMAIN_MEMORY_MODEL_DIMM:
|
||||
case VIR_DOMAIN_MEMORY_MODEL_VIRTIO_MEM:
|
||||
case VIR_DOMAIN_MEMORY_MODEL_LAST:
|
||||
diff --git a/src/security/security_selinux.c b/src/security/security_selinux.c
|
||||
index 2b801aecd5..fd7d5ff703 100644
|
||||
--- a/src/security/security_selinux.c
|
||||
+++ b/src/security/security_selinux.c
|
||||
@@ -1666,6 +1666,9 @@ virSecuritySELinuxSetMemoryLabel(virSecurityManager *mgr,
|
||||
seclabel->imagelabel, true) < 0)
|
||||
return -1;
|
||||
break;
|
||||
+ case VIR_DOMAIN_MEMORY_MODEL_EGM:
|
||||
+ path = mem->source.egm.path;
|
||||
+ break;
|
||||
|
||||
case VIR_DOMAIN_MEMORY_MODEL_NONE:
|
||||
case VIR_DOMAIN_MEMORY_MODEL_DIMM:
|
||||
@@ -1709,6 +1712,9 @@ virSecuritySELinuxRestoreMemoryLabel(virSecurityManager *mgr,
|
||||
if (virSecuritySELinuxRestoreFileLabel(mgr, DEV_SGX_PROVISION, true, false) < 0)
|
||||
ret = -1;
|
||||
return ret;
|
||||
+ case VIR_DOMAIN_MEMORY_MODEL_EGM:
|
||||
+ path = mem->source.egm.path;
|
||||
+ break;
|
||||
|
||||
case VIR_DOMAIN_MEMORY_MODEL_DIMM:
|
||||
case VIR_DOMAIN_MEMORY_MODEL_VIRTIO_MEM:
|
||||
diff --git a/src/security/virt-aa-helper.c b/src/security/virt-aa-helper.c
|
||||
index af95a64c42..0a62a30da3 100644
|
||||
--- a/src/security/virt-aa-helper.c
|
||||
+++ b/src/security/virt-aa-helper.c
|
||||
@@ -1196,6 +1196,10 @@ get_files(vahControl * ctl)
|
||||
return -1;
|
||||
}
|
||||
break;
|
||||
+ case VIR_DOMAIN_MEMORY_MODEL_EGM:
|
||||
+ if (vah_add_file(&buf, mem->source.egm.path, "rw") != 0)
|
||||
+ return -1;
|
||||
+ break;
|
||||
|
||||
case VIR_DOMAIN_MEMORY_MODEL_DIMM:
|
||||
case VIR_DOMAIN_MEMORY_MODEL_VIRTIO_MEM:
|
||||
--
|
||||
2.54.0
|
||||
528
libvirt-qemu-Add-qemu-CLI-support-for-EGM.patch
Normal file
528
libvirt-qemu-Add-qemu-CLI-support-for-EGM.patch
Normal file
@ -0,0 +1,528 @@
|
||||
From 9965f1b7b0fb1810fe32498f7892aa549a754d19 Mon Sep 17 00:00:00 2001
|
||||
Message-ID: <9965f1b7b0fb1810fe32498f7892aa549a754d19.1779098642.git.phrdina@redhat.com>
|
||||
From: Pavel Hrdina <phrdina@redhat.com>
|
||||
Date: Tue, 25 Nov 2025 11:17:03 -0800
|
||||
Subject: [PATCH] qemu: Add qemu CLI support for EGM
|
||||
|
||||
From: Nathan Chen via Devel <devel@lists.libvirt.org>
|
||||
|
||||
Add qemu CLI support for EGM memory device model:
|
||||
- Specify EGM device path to memory-backend-file object
|
||||
- Support acpi-egm-memory object with id, pci-dev, and
|
||||
node attributes
|
||||
- Consolidate all acpi-egm-memory objects' memory into
|
||||
a single memory-backend-file per EGM chardev
|
||||
specified.
|
||||
|
||||
Signed-off-by: Ian May <ianm@nvidia.com>
|
||||
Signed-off-by: Nathan Chen <nathanc@nvidia.com>
|
||||
|
||||
Resolves: https://redhat.atlassian.net/browse/VOYAGER-13
|
||||
---
|
||||
src/qemu/qemu_alias.c | 7 +-
|
||||
src/qemu/qemu_capabilities.c | 2 +
|
||||
src/qemu/qemu_capabilities.h | 1 +
|
||||
src/qemu/qemu_command.c | 158 ++++++++++++++++++++++++++++++---
|
||||
src/qemu/qemu_domain.c | 13 ++-
|
||||
src/qemu/qemu_domain_address.c | 3 +
|
||||
src/qemu/qemu_driver.c | 1 +
|
||||
src/qemu/qemu_hotplug.c | 1 +
|
||||
src/qemu/qemu_monitor_json.c | 1 +
|
||||
src/qemu/qemu_postparse.c | 1 +
|
||||
src/qemu/qemu_process.c | 2 +
|
||||
src/qemu/qemu_validate.c | 6 ++
|
||||
12 files changed, 180 insertions(+), 16 deletions(-)
|
||||
|
||||
diff --git a/src/qemu/qemu_alias.c b/src/qemu/qemu_alias.c
|
||||
index 400ce73283..719224e1ba 100644
|
||||
--- a/src/qemu/qemu_alias.c
|
||||
+++ b/src/qemu/qemu_alias.c
|
||||
@@ -504,7 +504,8 @@ qemuDeviceMemoryGetAliasID(virDomainDef *def,
|
||||
* valid */
|
||||
if (mem->model != VIR_DOMAIN_MEMORY_MODEL_VIRTIO_PMEM &&
|
||||
mem->model != VIR_DOMAIN_MEMORY_MODEL_VIRTIO_MEM &&
|
||||
- mem->model != VIR_DOMAIN_MEMORY_MODEL_SGX_EPC)
|
||||
+ mem->model != VIR_DOMAIN_MEMORY_MODEL_SGX_EPC &&
|
||||
+ mem->model != VIR_DOMAIN_MEMORY_MODEL_EGM)
|
||||
return mem->info.addr.dimm.slot;
|
||||
|
||||
for (i = 0; i < def->nmems; i++) {
|
||||
@@ -553,6 +554,10 @@ qemuAssignDeviceMemoryAlias(virDomainDef *def,
|
||||
case VIR_DOMAIN_MEMORY_MODEL_SGX_EPC:
|
||||
prefix = "epc";
|
||||
break;
|
||||
+ case VIR_DOMAIN_MEMORY_MODEL_EGM: {
|
||||
+ prefix = "egm";
|
||||
+ break;
|
||||
+ }
|
||||
case VIR_DOMAIN_MEMORY_MODEL_NONE:
|
||||
case VIR_DOMAIN_MEMORY_MODEL_LAST:
|
||||
default:
|
||||
diff --git a/src/qemu/qemu_capabilities.c b/src/qemu/qemu_capabilities.c
|
||||
index ed6aa86da2..010933bc4e 100644
|
||||
--- a/src/qemu/qemu_capabilities.c
|
||||
+++ b/src/qemu/qemu_capabilities.c
|
||||
@@ -760,6 +760,7 @@ VIR_ENUM_IMPL(virQEMUCaps,
|
||||
|
||||
/* 490 */
|
||||
"iommufd", /* QEMU_CAPS_OBJECT_IOMMUFD */
|
||||
+ "acpi-egm-memory", /* QEMU_CAPS_DEVICE_ACPI_EGM_MEMORY */
|
||||
);
|
||||
|
||||
|
||||
@@ -1468,6 +1469,7 @@ struct virQEMUCapsStringFlags virQEMUCapsObjectTypes[] = {
|
||||
{ "tpm-passthrough", QEMU_CAPS_DEVICE_TPM_PASSTHROUGH },
|
||||
{ "acpi-generic-initiator", QEMU_CAPS_ACPI_GENERIC_INITIATOR },
|
||||
{ "iommufd", QEMU_CAPS_OBJECT_IOMMUFD },
|
||||
+ { "acpi-egm-memory", QEMU_CAPS_DEVICE_ACPI_EGM_MEMORY },
|
||||
};
|
||||
|
||||
|
||||
diff --git a/src/qemu/qemu_capabilities.h b/src/qemu/qemu_capabilities.h
|
||||
index f7c8680f94..85615b4524 100644
|
||||
--- a/src/qemu/qemu_capabilities.h
|
||||
+++ b/src/qemu/qemu_capabilities.h
|
||||
@@ -734,6 +734,7 @@ typedef enum { /* virQEMUCapsFlags grouping marker for syntax-check */
|
||||
|
||||
/* 490 */
|
||||
QEMU_CAPS_OBJECT_IOMMUFD, /* -object iommufd */
|
||||
+ QEMU_CAPS_DEVICE_ACPI_EGM_MEMORY, /* For using extended GPU memory */
|
||||
|
||||
QEMU_CAPS_LAST /* this must always be the last item */
|
||||
} virQEMUCapsFlags;
|
||||
diff --git a/src/qemu/qemu_command.c b/src/qemu/qemu_command.c
|
||||
index a76f504e6f..63fd9885b7 100644
|
||||
--- a/src/qemu/qemu_command.c
|
||||
+++ b/src/qemu/qemu_command.c
|
||||
@@ -135,6 +135,21 @@ VIR_ENUM_IMPL(qemuACPITableSIG,
|
||||
"SLIC",
|
||||
"MSDM");
|
||||
|
||||
+typedef struct _qemuEGMBackendInfo {
|
||||
+ char *alias;
|
||||
+ unsigned long long totalSize;
|
||||
+ bool created;
|
||||
+ virDomainMemoryDef *firstMem; /* Pointer to first device for this path */
|
||||
+} qemuEGMBackendInfo;
|
||||
+
|
||||
+static void
|
||||
+qemuEGMBackendInfoFree(qemuEGMBackendInfo *info)
|
||||
+{
|
||||
+ if (!info)
|
||||
+ return;
|
||||
+ g_free(info->alias);
|
||||
+ g_free(info);
|
||||
+}
|
||||
|
||||
const char *
|
||||
qemuAudioDriverTypeToString(virDomainAudioType type)
|
||||
@@ -992,6 +1007,7 @@ qemuBuildVirtioDevGetConfigDev(const virDomainDeviceDef *device,
|
||||
case VIR_DOMAIN_MEMORY_MODEL_DIMM:
|
||||
case VIR_DOMAIN_MEMORY_MODEL_NVDIMM:
|
||||
case VIR_DOMAIN_MEMORY_MODEL_SGX_EPC:
|
||||
+ case VIR_DOMAIN_MEMORY_MODEL_EGM:
|
||||
case VIR_DOMAIN_MEMORY_MODEL_NONE:
|
||||
case VIR_DOMAIN_MEMORY_MODEL_LAST:
|
||||
break;
|
||||
@@ -3166,6 +3182,7 @@ qemuBuildMemoryGetPagesize(virQEMUDriverConfig *cfg,
|
||||
nvdimmPath = mem->source.virtio_pmem.path;
|
||||
break;
|
||||
case VIR_DOMAIN_MEMORY_MODEL_SGX_EPC:
|
||||
+ case VIR_DOMAIN_MEMORY_MODEL_EGM:
|
||||
case VIR_DOMAIN_MEMORY_MODEL_NONE:
|
||||
case VIR_DOMAIN_MEMORY_MODEL_LAST:
|
||||
break;
|
||||
@@ -3366,6 +3383,9 @@ qemuBuildMemoryBackendProps(virJSONValue **backendProps,
|
||||
case VIR_DOMAIN_MEMORY_MODEL_VIRTIO_PMEM:
|
||||
nvdimmPath = mem->source.virtio_pmem.path;
|
||||
break;
|
||||
+ case VIR_DOMAIN_MEMORY_MODEL_EGM:
|
||||
+ nvdimmPath = mem->source.egm.path;
|
||||
+ break;
|
||||
case VIR_DOMAIN_MEMORY_MODEL_NONE:
|
||||
case VIR_DOMAIN_MEMORY_MODEL_LAST:
|
||||
break;
|
||||
@@ -3577,12 +3597,17 @@ qemuBuildMemoryDimmBackendStr(virCommand *cmd,
|
||||
virDomainMemoryDef *mem,
|
||||
virDomainDef *def,
|
||||
virQEMUDriverConfig *cfg,
|
||||
- qemuDomainObjPrivate *priv)
|
||||
+ qemuDomainObjPrivate *priv,
|
||||
+ GHashTable *egmBackends)
|
||||
{
|
||||
g_autoptr(virJSONValue) props = NULL;
|
||||
g_autoptr(virJSONValue) tcProps = NULL;
|
||||
virBitmap *nodemask = NULL;
|
||||
g_autofree char *alias = NULL;
|
||||
+ unsigned long long originalSize = 0;
|
||||
+ bool isEGM = (mem->model == VIR_DOMAIN_MEMORY_MODEL_EGM);
|
||||
+ bool shouldCreateBackend = true;
|
||||
+ qemuEGMBackendInfo *egmInfo = NULL;
|
||||
|
||||
if (!mem->info.alias) {
|
||||
virReportError(VIR_ERR_INTERNAL_ERROR, "%s",
|
||||
@@ -3592,19 +3617,65 @@ qemuBuildMemoryDimmBackendStr(virCommand *cmd,
|
||||
|
||||
alias = g_strdup_printf("mem%s", mem->info.alias);
|
||||
|
||||
- if (qemuBuildMemoryBackendProps(&props, alias, cfg, priv,
|
||||
- def, mem, true, false, &nodemask) < 0)
|
||||
- return -1;
|
||||
+ /* Handle EGM shared backend logic */
|
||||
+ if (isEGM && egmBackends) {
|
||||
+ const char *egmPath = mem->source.egm.path;
|
||||
+ egmInfo = g_hash_table_lookup(egmBackends, egmPath);
|
||||
|
||||
- if (qemuBuildThreadContextProps(&tcProps, &props, def, priv, nodemask) < 0)
|
||||
- return -1;
|
||||
+ if (egmInfo) {
|
||||
+ alias = g_strdup(egmInfo->alias);
|
||||
+ if (egmInfo->created) {
|
||||
+ /* Backend already created, skip backend creation */
|
||||
+ shouldCreateBackend = false;
|
||||
+ } else {
|
||||
+ /* First device for this path - temporarily use accumulated size */
|
||||
+ originalSize = mem->size;
|
||||
+ mem->size = egmInfo->totalSize;
|
||||
+ egmInfo->created = true;
|
||||
+ }
|
||||
+ }
|
||||
+ }
|
||||
|
||||
- if (tcProps &&
|
||||
- qemuBuildObjectCommandlineFromJSON(cmd, tcProps) < 0)
|
||||
- return -1;
|
||||
+ if (shouldCreateBackend) {
|
||||
+ /* Use existing function unchanged */
|
||||
+ if (qemuBuildMemoryBackendProps(&props, alias, cfg, priv,
|
||||
+ def, mem, true, false, &nodemask) < 0) {
|
||||
+ if (originalSize > 0)
|
||||
+ mem->size = originalSize; /* Restore on error */
|
||||
+ return -1;
|
||||
+ }
|
||||
|
||||
- if (qemuBuildObjectCommandlineFromJSON(cmd, props) < 0)
|
||||
- return -1;
|
||||
+ /* Restore original size after backend props are built */
|
||||
+ if (originalSize > 0)
|
||||
+ mem->size = originalSize;
|
||||
+
|
||||
+ if (qemuBuildThreadContextProps(&tcProps, &props, def, priv, nodemask) < 0)
|
||||
+ return -1;
|
||||
+
|
||||
+ if (tcProps &&
|
||||
+ qemuBuildObjectCommandlineFromJSON(cmd, tcProps) < 0)
|
||||
+ return -1;
|
||||
+
|
||||
+ if (qemuBuildObjectCommandlineFromJSON(cmd, props) < 0)
|
||||
+ return -1;
|
||||
+ }
|
||||
+
|
||||
+ if (isEGM) {
|
||||
+ g_autofree char *egmObjStr = NULL;
|
||||
+ g_auto(virBuffer) buf = VIR_BUFFER_INITIALIZER;
|
||||
+
|
||||
+ virBufferAsprintf(&buf, "acpi-egm-memory,id=%s", mem->info.alias);
|
||||
+
|
||||
+ if (mem->target.egm.pciDev)
|
||||
+ virBufferAsprintf(&buf, ",pci-dev=%s", mem->target.egm.pciDev);
|
||||
+
|
||||
+ if (mem->targetNode >= 0)
|
||||
+ virBufferAsprintf(&buf, ",node=%d", mem->targetNode);
|
||||
+
|
||||
+ egmObjStr = virBufferContentAndReset(&buf);
|
||||
+
|
||||
+ virCommandAddArgList(cmd, "-object", egmObjStr, NULL);
|
||||
+ }
|
||||
|
||||
return 0;
|
||||
}
|
||||
@@ -3675,6 +3746,7 @@ qemuBuildMemoryDeviceProps(virQEMUDriverConfig *cfg,
|
||||
dynamicMemslots = mem->target.virtio_mem.dynamicMemslots;
|
||||
break;
|
||||
|
||||
+ case VIR_DOMAIN_MEMORY_MODEL_EGM:
|
||||
case VIR_DOMAIN_MEMORY_MODEL_SGX_EPC:
|
||||
case VIR_DOMAIN_MEMORY_MODEL_NONE:
|
||||
case VIR_DOMAIN_MEMORY_MODEL_LAST:
|
||||
@@ -7193,6 +7265,7 @@ qemuAppendDomainMemoryMachineParams(virBuffer *buf,
|
||||
case VIR_DOMAIN_MEMORY_MODEL_DIMM:
|
||||
case VIR_DOMAIN_MEMORY_MODEL_VIRTIO_PMEM:
|
||||
case VIR_DOMAIN_MEMORY_MODEL_VIRTIO_MEM:
|
||||
+ case VIR_DOMAIN_MEMORY_MODEL_EGM:
|
||||
case VIR_DOMAIN_MEMORY_MODEL_NONE:
|
||||
case VIR_DOMAIN_MEMORY_MODEL_LAST:
|
||||
break;
|
||||
@@ -7910,6 +7983,8 @@ qemuBuildNumaCommandLine(virQEMUDriverConfig *cfg,
|
||||
size_t ncells = virDomainNumaGetNodeCount(def->numa);
|
||||
ssize_t masterInitiator = -1;
|
||||
int rc;
|
||||
+ g_autoptr(GHashTable) egmBackends = NULL;
|
||||
+ size_t egmBackendCount = 0;
|
||||
|
||||
if (!virDomainNumatuneNodesetIsAvailable(def->numa, priv->autoNodeset))
|
||||
goto cleanup;
|
||||
@@ -7924,6 +7999,37 @@ qemuBuildNumaCommandLine(virQEMUDriverConfig *cfg,
|
||||
hmat = true;
|
||||
}
|
||||
|
||||
+ /* Pre-scan EGM devices to group by path and calculate total sizes */
|
||||
+ egmBackends = g_hash_table_new_full(g_str_hash, g_str_equal, g_free,
|
||||
+ (GDestroyNotify)qemuEGMBackendInfoFree);
|
||||
+
|
||||
+ for (i = 0; i < def->nmems; i++) {
|
||||
+ if (def->mems[i]->model == VIR_DOMAIN_MEMORY_MODEL_EGM) {
|
||||
+ const char *egmPath = def->mems[i]->source.egm.path;
|
||||
+ qemuEGMBackendInfo *info = g_hash_table_lookup(egmBackends, egmPath);
|
||||
+
|
||||
+ if (!info) {
|
||||
+ info = g_new0(qemuEGMBackendInfo, 1);
|
||||
+ info->alias = g_strdup_printf("memegm%zu", egmBackendCount);
|
||||
+ egmBackendCount++;
|
||||
+ info->totalSize = def->mems[i]->size;
|
||||
+ info->created = false;
|
||||
+ info->firstMem = def->mems[i];
|
||||
+ g_hash_table_insert(egmBackends, g_strdup(egmPath), info);
|
||||
+ } else {
|
||||
+ info->totalSize += def->mems[i]->size;
|
||||
+ }
|
||||
+ }
|
||||
+ }
|
||||
+
|
||||
+ /* Build the actual backend and device objects */
|
||||
+ for (i = 0; i < def->nmems; i++) {
|
||||
+ if (def->mems[i]->model == VIR_DOMAIN_MEMORY_MODEL_EGM) {
|
||||
+ if (qemuBuildMemoryDimmBackendStr(cmd, def->mems[i], def, cfg, priv, egmBackends) < 0)
|
||||
+ goto cleanup;
|
||||
+ }
|
||||
+ }
|
||||
+
|
||||
nodeBackends = g_new0(virJSONValue *, ncells);
|
||||
nodemask = g_new0(virBitmap *, ncells);
|
||||
|
||||
@@ -7959,8 +8065,18 @@ qemuBuildNumaCommandLine(virQEMUDriverConfig *cfg,
|
||||
for (i = 0; i < ncells; i++) {
|
||||
ssize_t initiator = virDomainNumaGetNodeInitiator(def->numa, i);
|
||||
unsigned long long memSize = virDomainNumaGetNodeMemorySize(def->numa, i);
|
||||
+ bool egmBacked = false;
|
||||
+ size_t k;
|
||||
|
||||
- if (needBackend && memSize > 0) {
|
||||
+ for (k = 0; k < def->nmems; k++) {
|
||||
+ if (def->mems[k]->model == VIR_DOMAIN_MEMORY_MODEL_EGM &&
|
||||
+ def->mems[k]->targetNode == (int)i) {
|
||||
+ egmBacked = true;
|
||||
+ break;
|
||||
+ }
|
||||
+ }
|
||||
+
|
||||
+ if (needBackend && memSize > 0 && !egmBacked) {
|
||||
g_autoptr(virJSONValue) tcProps = NULL;
|
||||
|
||||
if (qemuBuildThreadContextProps(&tcProps, &nodeBackends[i],
|
||||
@@ -7990,7 +8106,15 @@ qemuBuildNumaCommandLine(virQEMUDriverConfig *cfg,
|
||||
|
||||
if (memSize > 0) {
|
||||
if (needBackend) {
|
||||
- virBufferAsprintf(&buf, ",memdev=ram-node%zu", i);
|
||||
+ if (egmBacked) {
|
||||
+ /* Look up the actual backend alias for EGM */
|
||||
+ const char *egmPath = def->mems[k]->source.egm.path;
|
||||
+ qemuEGMBackendInfo *egmInfo = g_hash_table_lookup(egmBackends, egmPath);
|
||||
+ const char *backendAlias = egmInfo ? egmInfo->alias : def->mems[k]->info.alias;
|
||||
+ virBufferAsprintf(&buf, ",memdev=%s", backendAlias);
|
||||
+ } else {
|
||||
+ virBufferAsprintf(&buf, ",memdev=ram-node%zu", i);
|
||||
+ }
|
||||
} else {
|
||||
virBufferAsprintf(&buf, ",mem=%llu", memSize / 1024);
|
||||
}
|
||||
@@ -8054,7 +8178,10 @@ qemuBuildMemoryDeviceCommandLine(virCommand *cmd,
|
||||
for (i = 0; i < def->nmems; i++) {
|
||||
g_autoptr(virJSONValue) props = NULL;
|
||||
|
||||
- if (qemuBuildMemoryDimmBackendStr(cmd, def->mems[i], def, cfg, priv) < 0)
|
||||
+ if (def->mems[i]->model == VIR_DOMAIN_MEMORY_MODEL_EGM)
|
||||
+ continue;
|
||||
+
|
||||
+ if (qemuBuildMemoryDimmBackendStr(cmd, def->mems[i], def, cfg, priv, NULL) < 0)
|
||||
return -1;
|
||||
|
||||
switch (def->mems[i]->model) {
|
||||
@@ -8074,6 +8201,9 @@ qemuBuildMemoryDeviceCommandLine(virCommand *cmd,
|
||||
case VIR_DOMAIN_MEMORY_MODEL_SGX_EPC:
|
||||
break;
|
||||
|
||||
+ /* EGM memory backing is via memory-backend-file object */
|
||||
+ case VIR_DOMAIN_MEMORY_MODEL_EGM:
|
||||
+ break;
|
||||
case VIR_DOMAIN_MEMORY_MODEL_NONE:
|
||||
case VIR_DOMAIN_MEMORY_MODEL_LAST:
|
||||
break;
|
||||
diff --git a/src/qemu/qemu_domain.c b/src/qemu/qemu_domain.c
|
||||
index 495cbd4f7d..c5e3d09360 100644
|
||||
--- a/src/qemu/qemu_domain.c
|
||||
+++ b/src/qemu/qemu_domain.c
|
||||
@@ -7266,6 +7266,7 @@ qemuDomainUpdateMemoryDeviceInfo(virDomainObj *vm,
|
||||
break;
|
||||
|
||||
case VIR_DOMAIN_MEMORY_MODEL_SGX_EPC:
|
||||
+ case VIR_DOMAIN_MEMORY_MODEL_EGM:
|
||||
case VIR_DOMAIN_MEMORY_MODEL_NONE:
|
||||
case VIR_DOMAIN_MEMORY_MODEL_LAST:
|
||||
break;
|
||||
@@ -7500,7 +7501,8 @@ qemuDomainAlignMemorySizes(virDomainDef *def)
|
||||
def->mems[i]->size = VIR_ROUND_UP(def->mems[i]->size, align);
|
||||
}
|
||||
|
||||
- hotplugmem += def->mems[i]->size;
|
||||
+ if (def->mems[i]->model != VIR_DOMAIN_MEMORY_MODEL_EGM)
|
||||
+ hotplugmem += def->mems[i]->size;
|
||||
|
||||
if (def->mems[i]->size > maxmemkb) {
|
||||
virReportError(VIR_ERR_CONFIG_UNSUPPORTED,
|
||||
@@ -7988,6 +7990,12 @@ qemuDomainDefValidateMemoryHotplugDevice(const virDomainMemoryDef *mem,
|
||||
virDomainMemoryModelTypeToString(mem->model));
|
||||
return -1;
|
||||
|
||||
+ case VIR_DOMAIN_MEMORY_MODEL_EGM:
|
||||
+ virReportError(VIR_ERR_CONFIG_UNSUPPORTED,
|
||||
+ _("hotplug is not supported for the %1$s device"),
|
||||
+ virDomainMemoryModelTypeToString(mem->model));
|
||||
+ return -1;
|
||||
+
|
||||
case VIR_DOMAIN_MEMORY_MODEL_NONE:
|
||||
case VIR_DOMAIN_MEMORY_MODEL_LAST:
|
||||
return -1;
|
||||
@@ -8046,6 +8054,7 @@ qemuDomainDefValidateMemoryHotplug(const virDomainDef *def,
|
||||
case VIR_DOMAIN_MEMORY_MODEL_VIRTIO_PMEM:
|
||||
case VIR_DOMAIN_MEMORY_MODEL_VIRTIO_MEM:
|
||||
case VIR_DOMAIN_MEMORY_MODEL_SGX_EPC:
|
||||
+ case VIR_DOMAIN_MEMORY_MODEL_EGM:
|
||||
case VIR_DOMAIN_MEMORY_MODEL_LAST:
|
||||
case VIR_DOMAIN_MEMORY_MODEL_NONE:
|
||||
break;
|
||||
@@ -8093,6 +8102,8 @@ qemuDomainDefValidateMemoryHotplug(const virDomainDef *def,
|
||||
|
||||
case VIR_DOMAIN_MEMORY_MODEL_SGX_EPC:
|
||||
/* sgx epc memory does not support hotplug, skip this check */
|
||||
+ case VIR_DOMAIN_MEMORY_MODEL_EGM:
|
||||
+ /* egm memory does not support hotplug, skip this check */
|
||||
case VIR_DOMAIN_MEMORY_MODEL_LAST:
|
||||
case VIR_DOMAIN_MEMORY_MODEL_NONE:
|
||||
break;
|
||||
diff --git a/src/qemu/qemu_domain_address.c b/src/qemu/qemu_domain_address.c
|
||||
index 7233df888c..97e533bf9a 100644
|
||||
--- a/src/qemu/qemu_domain_address.c
|
||||
+++ b/src/qemu/qemu_domain_address.c
|
||||
@@ -3124,6 +3124,7 @@ qemuDomainAssignMemoryDeviceSlot(virDomainObj *vm,
|
||||
return qemuDomainEnsureVirtioAddress(&releaseaddr, vm, &dev);
|
||||
|
||||
case VIR_DOMAIN_MEMORY_MODEL_SGX_EPC:
|
||||
+ case VIR_DOMAIN_MEMORY_MODEL_EGM:
|
||||
case VIR_DOMAIN_MEMORY_MODEL_NONE:
|
||||
case VIR_DOMAIN_MEMORY_MODEL_LAST:
|
||||
break;
|
||||
@@ -3151,6 +3152,7 @@ qemuDomainReleaseMemoryDeviceSlot(virDomainObj *vm,
|
||||
break;
|
||||
|
||||
case VIR_DOMAIN_MEMORY_MODEL_SGX_EPC:
|
||||
+ case VIR_DOMAIN_MEMORY_MODEL_EGM:
|
||||
case VIR_DOMAIN_MEMORY_MODEL_NONE:
|
||||
case VIR_DOMAIN_MEMORY_MODEL_LAST:
|
||||
break;
|
||||
@@ -3185,6 +3187,7 @@ qemuDomainAssignMemorySlots(virDomainDef *def)
|
||||
/* handled in qemuDomainAssignPCIAddresses() */
|
||||
break;
|
||||
case VIR_DOMAIN_MEMORY_MODEL_SGX_EPC:
|
||||
+ case VIR_DOMAIN_MEMORY_MODEL_EGM:
|
||||
case VIR_DOMAIN_MEMORY_MODEL_NONE:
|
||||
case VIR_DOMAIN_MEMORY_MODEL_LAST:
|
||||
break;
|
||||
diff --git a/src/qemu/qemu_driver.c b/src/qemu/qemu_driver.c
|
||||
index 5e63614b4a..247c98d84e 100644
|
||||
--- a/src/qemu/qemu_driver.c
|
||||
+++ b/src/qemu/qemu_driver.c
|
||||
@@ -6712,6 +6712,7 @@ qemuDomainAttachMemoryConfig(virDomainDef *vmdef,
|
||||
case VIR_DOMAIN_MEMORY_MODEL_VIRTIO_PMEM:
|
||||
case VIR_DOMAIN_MEMORY_MODEL_VIRTIO_MEM:
|
||||
case VIR_DOMAIN_MEMORY_MODEL_SGX_EPC:
|
||||
+ case VIR_DOMAIN_MEMORY_MODEL_EGM:
|
||||
break;
|
||||
case VIR_DOMAIN_MEMORY_MODEL_NONE:
|
||||
case VIR_DOMAIN_MEMORY_MODEL_LAST:
|
||||
diff --git a/src/qemu/qemu_hotplug.c b/src/qemu/qemu_hotplug.c
|
||||
index 8944062aa4..de47702bc5 100644
|
||||
--- a/src/qemu/qemu_hotplug.c
|
||||
+++ b/src/qemu/qemu_hotplug.c
|
||||
@@ -7417,6 +7417,7 @@ qemuDomainChangeMemoryLiveValidateChange(const virDomainMemoryDef *oldDef,
|
||||
case VIR_DOMAIN_MEMORY_MODEL_NVDIMM:
|
||||
case VIR_DOMAIN_MEMORY_MODEL_VIRTIO_PMEM:
|
||||
case VIR_DOMAIN_MEMORY_MODEL_SGX_EPC:
|
||||
+ case VIR_DOMAIN_MEMORY_MODEL_EGM:
|
||||
case VIR_DOMAIN_MEMORY_MODEL_LAST:
|
||||
virReportError(VIR_ERR_CONFIG_UNSUPPORTED,
|
||||
_("cannot modify memory of model '%1$s'"),
|
||||
diff --git a/src/qemu/qemu_monitor_json.c b/src/qemu/qemu_monitor_json.c
|
||||
index 45f690d9e2..2bf9bb885e 100644
|
||||
--- a/src/qemu/qemu_monitor_json.c
|
||||
+++ b/src/qemu/qemu_monitor_json.c
|
||||
@@ -7285,6 +7285,7 @@ qemuMonitorJSONGetMemoryDeviceInfo(qemuMonitor *mon,
|
||||
switch ((virDomainMemoryModel) model) {
|
||||
case VIR_DOMAIN_MEMORY_MODEL_DIMM:
|
||||
case VIR_DOMAIN_MEMORY_MODEL_NVDIMM:
|
||||
+ case VIR_DOMAIN_MEMORY_MODEL_EGM:
|
||||
case VIR_DOMAIN_MEMORY_MODEL_VIRTIO_MEM:
|
||||
case VIR_DOMAIN_MEMORY_MODEL_VIRTIO_PMEM:
|
||||
/* While 'id' attribute is marked as optional in QEMU's QAPI
|
||||
diff --git a/src/qemu/qemu_postparse.c b/src/qemu/qemu_postparse.c
|
||||
index 840d6a1174..c74824322a 100644
|
||||
--- a/src/qemu/qemu_postparse.c
|
||||
+++ b/src/qemu/qemu_postparse.c
|
||||
@@ -1839,6 +1839,7 @@ qemuDomainDefNumaAutoAdd(virDomainDef *def,
|
||||
case VIR_DOMAIN_MEMORY_MODEL_NONE:
|
||||
case VIR_DOMAIN_MEMORY_MODEL_VIRTIO_PMEM:
|
||||
case VIR_DOMAIN_MEMORY_MODEL_SGX_EPC:
|
||||
+ case VIR_DOMAIN_MEMORY_MODEL_EGM:
|
||||
case VIR_DOMAIN_MEMORY_MODEL_LAST:
|
||||
break;
|
||||
}
|
||||
diff --git a/src/qemu/qemu_process.c b/src/qemu/qemu_process.c
|
||||
index 10a4a70f1c..8132f13791 100644
|
||||
--- a/src/qemu/qemu_process.c
|
||||
+++ b/src/qemu/qemu_process.c
|
||||
@@ -4158,6 +4158,7 @@ qemuProcessDomainMemoryDefNeedHugepagesPath(const virDomainMemoryDef *mem,
|
||||
case VIR_DOMAIN_MEMORY_MODEL_VIRTIO_MEM:
|
||||
pagesize = mem->source.virtio_mem.pagesize;
|
||||
break;
|
||||
+ case VIR_DOMAIN_MEMORY_MODEL_EGM:
|
||||
case VIR_DOMAIN_MEMORY_MODEL_NONE:
|
||||
case VIR_DOMAIN_MEMORY_MODEL_NVDIMM:
|
||||
case VIR_DOMAIN_MEMORY_MODEL_VIRTIO_PMEM:
|
||||
@@ -4247,6 +4248,7 @@ qemuProcessNeedMemoryBackingPath(virDomainDef *def,
|
||||
case VIR_DOMAIN_MEMORY_MODEL_NVDIMM:
|
||||
case VIR_DOMAIN_MEMORY_MODEL_VIRTIO_PMEM:
|
||||
case VIR_DOMAIN_MEMORY_MODEL_SGX_EPC:
|
||||
+ case VIR_DOMAIN_MEMORY_MODEL_EGM:
|
||||
case VIR_DOMAIN_MEMORY_MODEL_LAST:
|
||||
/* Backed by user provided path. Not stored in memory
|
||||
* backing dir anyway. */
|
||||
diff --git a/src/qemu/qemu_validate.c b/src/qemu/qemu_validate.c
|
||||
index c39d8c869f..e03da3e27e 100644
|
||||
--- a/src/qemu/qemu_validate.c
|
||||
+++ b/src/qemu/qemu_validate.c
|
||||
@@ -5892,6 +5892,12 @@ qemuValidateDomainDeviceDefMemory(const virDomainMemoryDef *mem,
|
||||
|
||||
break;
|
||||
|
||||
+ case VIR_DOMAIN_MEMORY_MODEL_EGM:
|
||||
+ if (!virQEMUCapsGet(qemuCaps, QEMU_CAPS_DEVICE_ACPI_EGM_MEMORY)) {
|
||||
+ virReportError(VIR_ERR_CONFIG_UNSUPPORTED, "%s",
|
||||
+ _("ACPI EGM memory device is not supported with this QEMU binary"));
|
||||
+ return -1;
|
||||
+ }
|
||||
case VIR_DOMAIN_MEMORY_MODEL_NONE:
|
||||
case VIR_DOMAIN_MEMORY_MODEL_LAST:
|
||||
break;
|
||||
--
|
||||
2.54.0
|
||||
@ -0,0 +1,526 @@
|
||||
From 980f098c11773796a35b8e2cb6ae9a1c2296c8b4 Mon Sep 17 00:00:00 2001
|
||||
Message-ID: <980f098c11773796a35b8e2cb6ae9a1c2296c8b4.1779098642.git.phrdina@redhat.com>
|
||||
From: Pavel Hrdina <phrdina@redhat.com>
|
||||
Date: Tue, 25 Nov 2025 11:17:04 -0800
|
||||
Subject: [PATCH] tests: Add qemuxmlconftest for ACPI EGM memory device
|
||||
|
||||
From: Ian May <ianm@nvidia.com>
|
||||
|
||||
Add test coverage for the ACPI EGM memory device feature:
|
||||
|
||||
- Add test case to qemuxmlconftest.c for aarch64 architecture
|
||||
- Add acpi-egm-memory capability to QEMU 10.0.0 aarch64 capabilities
|
||||
- Create test input XML with EGM device configuration
|
||||
- Generate expected output XML and QEMU command line args
|
||||
- Update validation to skip filesystem checks during tests
|
||||
|
||||
The test validates XML parsing, formatting, device validation, and
|
||||
QEMU command line generation for the EGM device.
|
||||
|
||||
Signed-off-by: Ian May <ianm@nvidia.com>
|
||||
Signed-off-by: Nathan Chen <nathanc@nvidia.com>
|
||||
|
||||
Resolves: https://redhat.atlassian.net/browse/VOYAGER-13
|
||||
---
|
||||
src/conf/domain_conf.c | 5 +-
|
||||
src/conf/domain_postparse.c | 5 +-
|
||||
src/qemu/qemu_domain.c | 2 +
|
||||
src/util/virfile.h | 2 +-
|
||||
tests/meson.build | 1 +
|
||||
tests/qemuegmmock.c | 67 ++++++++++
|
||||
.../acpi-egm-memory.aarch64-latest.args | 47 +++++++
|
||||
.../acpi-egm-memory.aarch64-latest.xml | 124 ++++++++++++++++++
|
||||
tests/qemuxmlconfdata/acpi-egm-memory.xml | 124 ++++++++++++++++++
|
||||
tests/qemuxmlconftest.c | 8 +-
|
||||
10 files changed, 381 insertions(+), 4 deletions(-)
|
||||
create mode 100644 tests/qemuegmmock.c
|
||||
create mode 100644 tests/qemuxmlconfdata/acpi-egm-memory.aarch64-latest.args
|
||||
create mode 100644 tests/qemuxmlconfdata/acpi-egm-memory.aarch64-latest.xml
|
||||
create mode 100644 tests/qemuxmlconfdata/acpi-egm-memory.xml
|
||||
|
||||
diff --git a/src/conf/domain_conf.c b/src/conf/domain_conf.c
|
||||
index 038476edd7..d3236b7425 100644
|
||||
--- a/src/conf/domain_conf.c
|
||||
+++ b/src/conf/domain_conf.c
|
||||
@@ -8930,8 +8930,11 @@ virDomainDefGetMemoryInitial(const virDomainDef *def)
|
||||
size_t i;
|
||||
unsigned long long ret = def->mem.total_memory;
|
||||
|
||||
- for (i = 0; i < def->nmems; i++)
|
||||
+ for (i = 0; i < def->nmems; i++) {
|
||||
+ if (def->mems[i]->model == VIR_DOMAIN_MEMORY_MODEL_EGM)
|
||||
+ continue;
|
||||
ret -= def->mems[i]->size;
|
||||
+ }
|
||||
|
||||
return ret;
|
||||
}
|
||||
diff --git a/src/conf/domain_postparse.c b/src/conf/domain_postparse.c
|
||||
index 0181d21f0e..bb4a61b7d8 100644
|
||||
--- a/src/conf/domain_postparse.c
|
||||
+++ b/src/conf/domain_postparse.c
|
||||
@@ -44,8 +44,11 @@ virDomainDefPostParseMemory(virDomainDef *def,
|
||||
numaMemory = virDomainNumaGetMemorySize(def->numa);
|
||||
|
||||
/* calculate the sizes of hotplug memory */
|
||||
- for (i = 0; i < def->nmems; i++)
|
||||
+ for (i = 0; i < def->nmems; i++) {
|
||||
+ if (def->mems[i]->model == VIR_DOMAIN_MEMORY_MODEL_EGM)
|
||||
+ continue;
|
||||
hotplugMemory += def->mems[i]->size;
|
||||
+ }
|
||||
|
||||
if (numaMemory) {
|
||||
/* update the sizes in XML if nothing was set in the XML or ABI update
|
||||
diff --git a/src/qemu/qemu_domain.c b/src/qemu/qemu_domain.c
|
||||
index c5e3d09360..d1bc9aa621 100644
|
||||
--- a/src/qemu/qemu_domain.c
|
||||
+++ b/src/qemu/qemu_domain.c
|
||||
@@ -8085,6 +8085,8 @@ qemuDomainDefValidateMemoryHotplug(const virDomainDef *def,
|
||||
}
|
||||
|
||||
for (i = 0; i < def->nmems; i++) {
|
||||
+ if (def->mems[i]->model == VIR_DOMAIN_MEMORY_MODEL_EGM)
|
||||
+ continue;
|
||||
hotplugMemory += def->mems[i]->size;
|
||||
|
||||
switch (def->mems[i]->model) {
|
||||
diff --git a/src/util/virfile.h b/src/util/virfile.h
|
||||
index ce2ffb8ed4..5203ef4425 100644
|
||||
--- a/src/util/virfile.h
|
||||
+++ b/src/util/virfile.h
|
||||
@@ -167,7 +167,7 @@ int virFileReadHeaderQuiet(const char *path, int maxlen, char **buf)
|
||||
int virFileReadLimFD(int fd, int maxlen, char **buf)
|
||||
G_GNUC_WARN_UNUSED_RESULT ATTRIBUTE_NONNULL(3);
|
||||
int virFileReadAll(const char *path, int maxlen, char **buf)
|
||||
- G_GNUC_WARN_UNUSED_RESULT ATTRIBUTE_NONNULL(1) ATTRIBUTE_NONNULL(3);
|
||||
+ G_GNUC_WARN_UNUSED_RESULT ATTRIBUTE_NONNULL(1) ATTRIBUTE_NONNULL(3) ATTRIBUTE_MOCKABLE;
|
||||
int virFileReadAllQuiet(const char *path, int maxlen, char **buf)
|
||||
G_GNUC_WARN_UNUSED_RESULT ATTRIBUTE_NONNULL(1) ATTRIBUTE_NONNULL(3);
|
||||
int virFileReadBufQuiet(const char *file, char *buf, int len)
|
||||
diff --git a/tests/meson.build b/tests/meson.build
|
||||
index bb6ee6b4ee..28ee8591a3 100644
|
||||
--- a/tests/meson.build
|
||||
+++ b/tests/meson.build
|
||||
@@ -174,6 +174,7 @@ if conf.has('WITH_QEMU')
|
||||
{ 'name': 'qemucaps2xmlmock' },
|
||||
{ 'name': 'qemucapsprobemock', 'link_with': [ test_qemu_driver_lib ] },
|
||||
{ 'name': 'qemucpumock' },
|
||||
+ { 'name': 'qemuegmmock' },
|
||||
{ 'name': 'qemuhotplugmock', 'link_with': [ test_qemu_driver_lib, test_utils_qemu_lib, test_utils_lib ] },
|
||||
{ 'name': 'qemuxml2argvmock' },
|
||||
{ 'name': 'virhostidmock' },
|
||||
diff --git a/tests/qemuegmmock.c b/tests/qemuegmmock.c
|
||||
new file mode 100644
|
||||
index 0000000000..c915212f45
|
||||
--- /dev/null
|
||||
+++ b/tests/qemuegmmock.c
|
||||
@@ -0,0 +1,67 @@
|
||||
+/*
|
||||
+ * Copyright (C) 2024 Red Hat, Inc.
|
||||
+ * SPDX-License-Identifier: LGPL-2.1-or-later
|
||||
+ */
|
||||
+
|
||||
+#include <config.h>
|
||||
+#include <unistd.h>
|
||||
+
|
||||
+#include "internal.h"
|
||||
+#include "virfile.h"
|
||||
+#include "virmock.h"
|
||||
+
|
||||
+static bool (*real_virFileExists)(const char *path);
|
||||
+static int (*real_access)(const char *path, int mode);
|
||||
+static int (*real_virFileReadAll)(const char *path, int maxlen, char **buf);
|
||||
+
|
||||
+static void
|
||||
+init_syms(void)
|
||||
+{
|
||||
+ if (real_virFileExists && real_access && real_virFileReadAll)
|
||||
+ return;
|
||||
+
|
||||
+ VIR_MOCK_REAL_INIT(virFileExists);
|
||||
+ VIR_MOCK_REAL_INIT(access);
|
||||
+ VIR_MOCK_REAL_INIT(virFileReadAll);
|
||||
+}
|
||||
+
|
||||
+bool
|
||||
+virFileExists(const char *path)
|
||||
+{
|
||||
+ init_syms();
|
||||
+
|
||||
+ /* Mock EGM device paths for testing */
|
||||
+ if (g_str_has_prefix(path, "/dev/egm") ||
|
||||
+ g_str_has_prefix(path, "/sys/class/egm/"))
|
||||
+ return true;
|
||||
+
|
||||
+ return real_virFileExists(path);
|
||||
+}
|
||||
+
|
||||
+int
|
||||
+access(const char *path, int mode)
|
||||
+{
|
||||
+ init_syms();
|
||||
+
|
||||
+ /* Mock EGM device paths for testing */
|
||||
+ if (g_str_has_prefix(path, "/dev/egm") ||
|
||||
+ g_str_has_prefix(path, "/sys/class/egm/"))
|
||||
+ return 0; /* success */
|
||||
+
|
||||
+ return real_access(path, mode);
|
||||
+}
|
||||
+
|
||||
+int
|
||||
+virFileReadAll(const char *path, int maxlen, char **buf)
|
||||
+{
|
||||
+ init_syms();
|
||||
+
|
||||
+ /* Mock EGM GPU device file for testing */
|
||||
+ if (g_str_has_prefix(path, "/sys/class/egm/") &&
|
||||
+ g_str_has_suffix(path, "/gpu_devices")) {
|
||||
+ *buf = g_strdup("0000:01:00.0\n");
|
||||
+ return strlen(*buf);
|
||||
+ }
|
||||
+
|
||||
+ return real_virFileReadAll(path, maxlen, buf);
|
||||
+}
|
||||
diff --git a/tests/qemuxmlconfdata/acpi-egm-memory.aarch64-latest.args b/tests/qemuxmlconfdata/acpi-egm-memory.aarch64-latest.args
|
||||
new file mode 100644
|
||||
index 0000000000..41d1fcc026
|
||||
--- /dev/null
|
||||
+++ b/tests/qemuxmlconfdata/acpi-egm-memory.aarch64-latest.args
|
||||
@@ -0,0 +1,47 @@
|
||||
+LC_ALL=C \
|
||||
+PATH=/bin \
|
||||
+HOME=/var/lib/libvirt/qemu/domain--1-egm \
|
||||
+USER=test \
|
||||
+LOGNAME=test \
|
||||
+XDG_DATA_HOME=/var/lib/libvirt/qemu/domain--1-egm/.local/share \
|
||||
+XDG_CACHE_HOME=/var/lib/libvirt/qemu/domain--1-egm/.cache \
|
||||
+XDG_CONFIG_HOME=/var/lib/libvirt/qemu/domain--1-egm/.config \
|
||||
+/usr/bin/qemu-system-aarch64 \
|
||||
+-name guest=egm,debug-threads=on \
|
||||
+-S \
|
||||
+-object '{"qom-type":"secret","id":"masterKey0","format":"raw","file":"/var/lib/libvirt/qemu/domain--1-egm/master-key.aes"}' \
|
||||
+-machine virt,usb=off,gic-version=3,dump-guest-core=off,acpi=off \
|
||||
+-accel kvm \
|
||||
+-cpu host \
|
||||
+-m size=524288k,maxmem=524288k \
|
||||
+-overcommit mem-lock=off \
|
||||
+-smp 4,sockets=2,dies=1,clusters=1,cores=2,threads=1 \
|
||||
+-object '{"qom-type":"memory-backend-file","id":"memegm0","mem-path":"/dev/egm4","share":true,"size":268435456}' \
|
||||
+-object acpi-egm-memory,id=egm0,pci-dev=ua-hostdev0,node=0 \
|
||||
+-object acpi-egm-memory,id=egm1,pci-dev=ua-hostdev1,node=0 \
|
||||
+-object '{"qom-type":"memory-backend-file","id":"memegm1","mem-path":"/dev/egm5","share":true,"size":268435456}' \
|
||||
+-object acpi-egm-memory,id=egm2,pci-dev=ua-hostdev2,node=1 \
|
||||
+-object acpi-egm-memory,id=egm3,pci-dev=ua-hostdev3,node=1 \
|
||||
+-numa node,nodeid=0,cpus=0-1,memdev=memegm0 \
|
||||
+-numa node,nodeid=1,cpus=2-3,memdev=memegm1 \
|
||||
+-uuid 00010203-0405-4607-8809-0a0b0c0d0e0f \
|
||||
+-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":"pcie-root-port","port":10,"chassis":3,"id":"pci.3","bus":"pcie.0","addr":"0x2"}' \
|
||||
+-device '{"driver":"pcie-root-port","port":11,"chassis":4,"id":"pci.4","bus":"pcie.0","addr":"0x3"}' \
|
||||
+-device '{"driver":"pcie-root-port","port":12,"chassis":5,"id":"pci.5","bus":"pcie.0","addr":"0x4"}' \
|
||||
+-audiodev '{"id":"audio1","driver":"none"}' \
|
||||
+-device '{"driver":"vfio-pci","host":"0000:01:00.0","id":"ua-hostdev0","bus":"pci.1","addr":"0x0"}' \
|
||||
+-device '{"driver":"vfio-pci","host":"0000:02:00.0","id":"ua-hostdev1","bus":"pci.3","addr":"0x0"}' \
|
||||
+-device '{"driver":"vfio-pci","host":"0000:03:00.0","id":"ua-hostdev2","bus":"pci.4","addr":"0x0"}' \
|
||||
+-device '{"driver":"vfio-pci","host":"0000:04:00.0","id":"ua-hostdev3","bus":"pci.5","addr":"0x0"}' \
|
||||
+-sandbox on,obsolete=deny,elevateprivileges=deny,spawn=deny,resourcecontrol=deny \
|
||||
+-msg timestamp=on
|
||||
diff --git a/tests/qemuxmlconfdata/acpi-egm-memory.aarch64-latest.xml b/tests/qemuxmlconfdata/acpi-egm-memory.aarch64-latest.xml
|
||||
new file mode 100644
|
||||
index 0000000000..bd73d613e5
|
||||
--- /dev/null
|
||||
+++ b/tests/qemuxmlconfdata/acpi-egm-memory.aarch64-latest.xml
|
||||
@@ -0,0 +1,124 @@
|
||||
+<domain type='kvm'>
|
||||
+ <name>egm</name>
|
||||
+ <uuid>00010203-0405-4607-8809-0a0b0c0d0e0f</uuid>
|
||||
+ <maxMemory unit='KiB'>524288</maxMemory>
|
||||
+ <memory unit='KiB'>524288</memory>
|
||||
+ <currentMemory unit='KiB'>524288</currentMemory>
|
||||
+ <vcpu placement='static'>4</vcpu>
|
||||
+ <os>
|
||||
+ <type arch='aarch64' machine='virt'>hvm</type>
|
||||
+ <boot dev='hd'/>
|
||||
+ </os>
|
||||
+ <features>
|
||||
+ <gic version='3'/>
|
||||
+ </features>
|
||||
+ <cpu mode='host-passthrough' check='none'>
|
||||
+ <topology sockets='2' dies='1' clusters='1' cores='2' threads='1'/>
|
||||
+ <numa>
|
||||
+ <cell id='0' cpus='0-1' memory='262144' unit='KiB'/>
|
||||
+ <cell id='1' cpus='2-3' memory='262144' 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-aarch64</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='pci' index='3' model='pcie-root-port'>
|
||||
+ <model name='pcie-root-port'/>
|
||||
+ <target chassis='3' port='0xa'/>
|
||||
+ <address type='pci' domain='0x0000' bus='0x00' slot='0x02' function='0x0'/>
|
||||
+ </controller>
|
||||
+ <controller type='pci' index='4' model='pcie-root-port'>
|
||||
+ <model name='pcie-root-port'/>
|
||||
+ <target chassis='4' port='0xb'/>
|
||||
+ <address type='pci' domain='0x0000' bus='0x00' slot='0x03' function='0x0'/>
|
||||
+ </controller>
|
||||
+ <controller type='pci' index='5' model='pcie-root-port'>
|
||||
+ <model name='pcie-root-port'/>
|
||||
+ <target chassis='5' port='0xc'/>
|
||||
+ <address type='pci' domain='0x0000' bus='0x00' slot='0x04' function='0x0'/>
|
||||
+ </controller>
|
||||
+ <audio id='1' type='none'/>
|
||||
+ <hostdev mode='subsystem' type='pci' managed='yes'>
|
||||
+ <source>
|
||||
+ <address domain='0x0000' bus='0x01' slot='0x00' function='0x0'/>
|
||||
+ </source>
|
||||
+ <alias name='ua-hostdev0'/>
|
||||
+ <address type='pci' domain='0x0000' bus='0x01' slot='0x00' function='0x0'/>
|
||||
+ </hostdev>
|
||||
+ <hostdev mode='subsystem' type='pci' managed='yes'>
|
||||
+ <source>
|
||||
+ <address domain='0x0000' bus='0x02' slot='0x00' function='0x0'/>
|
||||
+ </source>
|
||||
+ <alias name='ua-hostdev1'/>
|
||||
+ <address type='pci' domain='0x0000' bus='0x03' slot='0x00' function='0x0'/>
|
||||
+ </hostdev>
|
||||
+ <hostdev mode='subsystem' type='pci' managed='yes'>
|
||||
+ <source>
|
||||
+ <address domain='0x0000' bus='0x03' slot='0x00' function='0x0'/>
|
||||
+ </source>
|
||||
+ <alias name='ua-hostdev2'/>
|
||||
+ <address type='pci' domain='0x0000' bus='0x04' slot='0x00' function='0x0'/>
|
||||
+ </hostdev>
|
||||
+ <hostdev mode='subsystem' type='pci' managed='yes'>
|
||||
+ <source>
|
||||
+ <address domain='0x0000' bus='0x04' slot='0x00' function='0x0'/>
|
||||
+ </source>
|
||||
+ <alias name='ua-hostdev3'/>
|
||||
+ <address type='pci' domain='0x0000' bus='0x05' slot='0x00' function='0x0'/>
|
||||
+ </hostdev>
|
||||
+ <memory model='egm' access='shared'>
|
||||
+ <source>
|
||||
+ <path>/dev/egm4</path>
|
||||
+ </source>
|
||||
+ <target>
|
||||
+ <size unit='KiB'>131072</size>
|
||||
+ <node>0</node>
|
||||
+ <pciDev>ua-hostdev0</pciDev>
|
||||
+ </target>
|
||||
+ </memory>
|
||||
+ <memory model='egm' access='shared'>
|
||||
+ <source>
|
||||
+ <path>/dev/egm4</path>
|
||||
+ </source>
|
||||
+ <target>
|
||||
+ <size unit='KiB'>131072</size>
|
||||
+ <node>0</node>
|
||||
+ <pciDev>ua-hostdev1</pciDev>
|
||||
+ </target>
|
||||
+ </memory>
|
||||
+ <memory model='egm' access='shared'>
|
||||
+ <source>
|
||||
+ <path>/dev/egm5</path>
|
||||
+ </source>
|
||||
+ <target>
|
||||
+ <size unit='KiB'>131072</size>
|
||||
+ <node>1</node>
|
||||
+ <pciDev>ua-hostdev2</pciDev>
|
||||
+ </target>
|
||||
+ </memory>
|
||||
+ <memory model='egm' access='shared'>
|
||||
+ <source>
|
||||
+ <path>/dev/egm5</path>
|
||||
+ </source>
|
||||
+ <target>
|
||||
+ <size unit='KiB'>131072</size>
|
||||
+ <node>1</node>
|
||||
+ <pciDev>ua-hostdev3</pciDev>
|
||||
+ </target>
|
||||
+ </memory>
|
||||
+ </devices>
|
||||
+</domain>
|
||||
diff --git a/tests/qemuxmlconfdata/acpi-egm-memory.xml b/tests/qemuxmlconfdata/acpi-egm-memory.xml
|
||||
new file mode 100644
|
||||
index 0000000000..bd73d613e5
|
||||
--- /dev/null
|
||||
+++ b/tests/qemuxmlconfdata/acpi-egm-memory.xml
|
||||
@@ -0,0 +1,124 @@
|
||||
+<domain type='kvm'>
|
||||
+ <name>egm</name>
|
||||
+ <uuid>00010203-0405-4607-8809-0a0b0c0d0e0f</uuid>
|
||||
+ <maxMemory unit='KiB'>524288</maxMemory>
|
||||
+ <memory unit='KiB'>524288</memory>
|
||||
+ <currentMemory unit='KiB'>524288</currentMemory>
|
||||
+ <vcpu placement='static'>4</vcpu>
|
||||
+ <os>
|
||||
+ <type arch='aarch64' machine='virt'>hvm</type>
|
||||
+ <boot dev='hd'/>
|
||||
+ </os>
|
||||
+ <features>
|
||||
+ <gic version='3'/>
|
||||
+ </features>
|
||||
+ <cpu mode='host-passthrough' check='none'>
|
||||
+ <topology sockets='2' dies='1' clusters='1' cores='2' threads='1'/>
|
||||
+ <numa>
|
||||
+ <cell id='0' cpus='0-1' memory='262144' unit='KiB'/>
|
||||
+ <cell id='1' cpus='2-3' memory='262144' 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-aarch64</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='pci' index='3' model='pcie-root-port'>
|
||||
+ <model name='pcie-root-port'/>
|
||||
+ <target chassis='3' port='0xa'/>
|
||||
+ <address type='pci' domain='0x0000' bus='0x00' slot='0x02' function='0x0'/>
|
||||
+ </controller>
|
||||
+ <controller type='pci' index='4' model='pcie-root-port'>
|
||||
+ <model name='pcie-root-port'/>
|
||||
+ <target chassis='4' port='0xb'/>
|
||||
+ <address type='pci' domain='0x0000' bus='0x00' slot='0x03' function='0x0'/>
|
||||
+ </controller>
|
||||
+ <controller type='pci' index='5' model='pcie-root-port'>
|
||||
+ <model name='pcie-root-port'/>
|
||||
+ <target chassis='5' port='0xc'/>
|
||||
+ <address type='pci' domain='0x0000' bus='0x00' slot='0x04' function='0x0'/>
|
||||
+ </controller>
|
||||
+ <audio id='1' type='none'/>
|
||||
+ <hostdev mode='subsystem' type='pci' managed='yes'>
|
||||
+ <source>
|
||||
+ <address domain='0x0000' bus='0x01' slot='0x00' function='0x0'/>
|
||||
+ </source>
|
||||
+ <alias name='ua-hostdev0'/>
|
||||
+ <address type='pci' domain='0x0000' bus='0x01' slot='0x00' function='0x0'/>
|
||||
+ </hostdev>
|
||||
+ <hostdev mode='subsystem' type='pci' managed='yes'>
|
||||
+ <source>
|
||||
+ <address domain='0x0000' bus='0x02' slot='0x00' function='0x0'/>
|
||||
+ </source>
|
||||
+ <alias name='ua-hostdev1'/>
|
||||
+ <address type='pci' domain='0x0000' bus='0x03' slot='0x00' function='0x0'/>
|
||||
+ </hostdev>
|
||||
+ <hostdev mode='subsystem' type='pci' managed='yes'>
|
||||
+ <source>
|
||||
+ <address domain='0x0000' bus='0x03' slot='0x00' function='0x0'/>
|
||||
+ </source>
|
||||
+ <alias name='ua-hostdev2'/>
|
||||
+ <address type='pci' domain='0x0000' bus='0x04' slot='0x00' function='0x0'/>
|
||||
+ </hostdev>
|
||||
+ <hostdev mode='subsystem' type='pci' managed='yes'>
|
||||
+ <source>
|
||||
+ <address domain='0x0000' bus='0x04' slot='0x00' function='0x0'/>
|
||||
+ </source>
|
||||
+ <alias name='ua-hostdev3'/>
|
||||
+ <address type='pci' domain='0x0000' bus='0x05' slot='0x00' function='0x0'/>
|
||||
+ </hostdev>
|
||||
+ <memory model='egm' access='shared'>
|
||||
+ <source>
|
||||
+ <path>/dev/egm4</path>
|
||||
+ </source>
|
||||
+ <target>
|
||||
+ <size unit='KiB'>131072</size>
|
||||
+ <node>0</node>
|
||||
+ <pciDev>ua-hostdev0</pciDev>
|
||||
+ </target>
|
||||
+ </memory>
|
||||
+ <memory model='egm' access='shared'>
|
||||
+ <source>
|
||||
+ <path>/dev/egm4</path>
|
||||
+ </source>
|
||||
+ <target>
|
||||
+ <size unit='KiB'>131072</size>
|
||||
+ <node>0</node>
|
||||
+ <pciDev>ua-hostdev1</pciDev>
|
||||
+ </target>
|
||||
+ </memory>
|
||||
+ <memory model='egm' access='shared'>
|
||||
+ <source>
|
||||
+ <path>/dev/egm5</path>
|
||||
+ </source>
|
||||
+ <target>
|
||||
+ <size unit='KiB'>131072</size>
|
||||
+ <node>1</node>
|
||||
+ <pciDev>ua-hostdev2</pciDev>
|
||||
+ </target>
|
||||
+ </memory>
|
||||
+ <memory model='egm' access='shared'>
|
||||
+ <source>
|
||||
+ <path>/dev/egm5</path>
|
||||
+ </source>
|
||||
+ <target>
|
||||
+ <size unit='KiB'>131072</size>
|
||||
+ <node>1</node>
|
||||
+ <pciDev>ua-hostdev3</pciDev>
|
||||
+ </target>
|
||||
+ </memory>
|
||||
+ </devices>
|
||||
+</domain>
|
||||
diff --git a/tests/qemuxmlconftest.c b/tests/qemuxmlconftest.c
|
||||
index 26287e1f8d..4c13dca6d0 100644
|
||||
--- a/tests/qemuxmlconftest.c
|
||||
+++ b/tests/qemuxmlconftest.c
|
||||
@@ -3275,6 +3275,10 @@ mymain(void)
|
||||
|
||||
DO_TEST_CAPS_LATEST("devices-acpi-index");
|
||||
|
||||
+ DO_TEST_CAPS_ARCH_LATEST_FULL("acpi-egm-memory", "aarch64",
|
||||
+ ARG_QEMU_CAPS, QEMU_CAPS_DEVICE_ACPI_EGM_MEMORY,
|
||||
+ ARG_END);
|
||||
+
|
||||
DO_TEST_CAPS_ARCH_LATEST_FULL("hvf-x86_64-q35-headless", "x86_64", ARG_CAPS_VARIANT, "+hvf", ARG_END);
|
||||
DO_TEST_CAPS_ARCH_LATEST_FULL("hvf-aarch64-virt-headless", "aarch64", ARG_CAPS_VARIANT, "+hvf", ARG_END);
|
||||
/* HVF guests should not work on Linux with KVM */
|
||||
@@ -3381,7 +3385,9 @@ VIR_TEST_MAIN_PRELOAD(mymain,
|
||||
VIR_TEST_MOCK("domaincaps"),
|
||||
VIR_TEST_MOCK("virrandom"),
|
||||
VIR_TEST_MOCK("qemucpu"),
|
||||
- VIR_TEST_MOCK("virnuma"))
|
||||
+ VIR_TEST_MOCK("virnuma"),
|
||||
+ VIR_TEST_MOCK("virpci"),
|
||||
+ VIR_TEST_MOCK("qemuegm"))
|
||||
|
||||
#else
|
||||
|
||||
--
|
||||
2.54.0
|
||||
12
libvirt.spec
12
libvirt.spec
@ -294,7 +294,7 @@
|
||||
Summary: Library providing a simple virtualization API
|
||||
Name: libvirt
|
||||
Version: 11.10.0
|
||||
Release: 10.6%{?dist}%{?extra_release}
|
||||
Release: 10.7%{?dist}%{?extra_release}
|
||||
License: GPL-2.0-or-later AND LGPL-2.1-only AND LGPL-2.1-or-later AND OFL-1.1
|
||||
URL: https://libvirt.org/
|
||||
|
||||
@ -406,6 +406,10 @@ Patch101: libvirt-qemu-Implement-iommufd-fdgroup.patch
|
||||
Patch102: libvirt-tests-Add-iommufd-fdgroup-test.patch
|
||||
Patch103: libvirt-hypervisor-Call-virWaitForDevices-after-detaching-host-devices.patch
|
||||
Patch104: libvirt-util-Fix-max-socket-calculation.patch
|
||||
Patch105: libvirt-conf-Support-EGM-memory-device-model.patch
|
||||
Patch106: libvirt-qemu-Add-cgroup-namespace-and-seclabel-setup-for-EGM-memory-device-model.patch
|
||||
Patch107: libvirt-qemu-Add-qemu-CLI-support-for-EGM.patch
|
||||
Patch108: libvirt-tests-Add-qemuxmlconftest-for-ACPI-EGM-memory-device.patch
|
||||
|
||||
|
||||
Requires: libvirt-daemon = %{version}-%{release}
|
||||
@ -2797,6 +2801,12 @@ exit 0
|
||||
%endif
|
||||
|
||||
%changelog
|
||||
* Mon May 18 2026 Pavel Hrdina <phrdina@redhat.com> - 11.10.0-10.7
|
||||
- conf: Support EGM memory device model (VOYAGER-13)
|
||||
- qemu: Add cgroup, namespace, and seclabel setup for EGM memory device model (VOYAGER-13)
|
||||
- qemu: Add qemu CLI support for EGM (VOYAGER-13)
|
||||
- tests: Add qemuxmlconftest for ACPI EGM memory device (VOYAGER-13)
|
||||
|
||||
* Sat Mar 28 2026 Pavel Hrdina <phrdina@redhat.com> - 11.10.0-10.6
|
||||
- util: Fix max socket calculation (VOYAGER-338)
|
||||
|
||||
|
||||
Loading…
Reference in New Issue
Block a user