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. Filesystem validation
is conditionally skipped in test environments while preserving full
validation for production use.
Signed-off-by: Ian May <ianm(a)nvidia.com>
---
tests/meson.build | 1 +
.../caps_10.0.0_aarch64.xml | 1 +
tests/qemuegmmock.c | 67 +++++++++++++++++++
.../acpi-egm-memory.aarch64-latest.args | 1 +
.../acpi-egm-memory.aarch64-latest.xml | 56 ++++++++++++++++
tests/qemuxmlconfdata/acpi-egm-memory.xml | 27 ++++++++
tests/qemuxmlconftest.c | 5 +-
7 files changed, 157 insertions(+), 1 deletion(-)
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/tests/meson.build b/tests/meson.build
index 0d76d37959..312c05a5f1 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/qemucapabilitiesdata/caps_10.0.0_aarch64.xml
b/tests/qemucapabilitiesdata/caps_10.0.0_aarch64.xml
index 200873b3a2..30abf65675 100644
--- a/tests/qemucapabilitiesdata/caps_10.0.0_aarch64.xml
+++ b/tests/qemucapabilitiesdata/caps_10.0.0_aarch64.xml
@@ -109,6 +109,7 @@
<flag name='vnc-power-control'/>
<flag name='rotation-rate'/>
<flag name='acpi-index'/>
+ <flag name='acpi-egm-memory'/>
<flag name='input-linux'/>
<flag name='confidential-guest-support'/>
<flag name='set-action'/>
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..773cc83946
--- /dev/null
+++ b/tests/qemuxmlconfdata/acpi-egm-memory.aarch64-latest.args
@@ -0,0 +1 @@
+-object acpi-egm-memory,id=egm0,pci-dev=ua-hostdev0,node=0
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..a62e6b1368
--- /dev/null
+++ b/tests/qemuxmlconfdata/acpi-egm-memory.aarch64-latest.xml
@@ -0,0 +1,56 @@
+<domain type='kvm'>
+ <name>egm</name>
+ <uuid>00010203-0405-4607-8809-0a0b0c0d0e0f</uuid>
+ <memory unit='KiB'>524288</memory>
+ <currentMemory unit='KiB'>524288</currentMemory>
+ <memoryBacking>
+ <source type='file'/>
+ <access mode='shared'/>
+ <allocation mode='immediate'/>
+ </memoryBacking>
+ <vcpu placement='static'>1</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='1' dies='1' clusters='1'
cores='1' threads='1'/>
+ <numa>
+ <cell id='0' cpus='0' memory='524288'
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>
+ <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>
+ <acpiEgmMemory>
+ <alias name='egm0'/>
+ <pciDev>ua-hostdev0</pciDev>
+ <numaNode>0</numaNode>
+ </acpiEgmMemory>
+ </devices>
+</domain>
diff --git a/tests/qemuxmlconfdata/acpi-egm-memory.xml
b/tests/qemuxmlconfdata/acpi-egm-memory.xml
new file mode 100644
index 0000000000..58dff4be8e
--- /dev/null
+++ b/tests/qemuxmlconfdata/acpi-egm-memory.xml
@@ -0,0 +1,27 @@
+<domain type="kvm">
+ <name>egm</name>
+ <memory unit="MiB">512</memory>
+ <vcpu>1</vcpu>
+ <os>
+ <type arch="aarch64" machine="virt">hvm</type>
+ </os>
+ <cpu mode="host-passthrough">
+ <topology sockets="1" cores="1" threads="1"/>
+ <numa>
+ <cell id="0" cpus="0" memory="512"
unit="MiB"/>
+ </numa>
+ </cpu>
+ <devices>
+ <hostdev mode="subsystem" type="pci"
managed="yes">
+ <alias name="ua-hostdev0"/>
+ <source>
+ <address domain="0x0000" bus="0x01" slot="0x00"
function="0x0"/>
+ </source>
+ </hostdev>
+ <acpiEgmMemory>
+ <alias name="egm0"/>
+ <pciDev>ua-hostdev0</pciDev>
+ <numaNode>0</numaNode>
+ </acpiEgmMemory>
+ </devices>
+</domain>
diff --git a/tests/qemuxmlconftest.c b/tests/qemuxmlconftest.c
index aeca353437..cf19a1bf73 100644
--- a/tests/qemuxmlconftest.c
+++ b/tests/qemuxmlconftest.c
@@ -2952,6 +2952,8 @@ mymain(void)
DO_TEST_CAPS_LATEST("devices-acpi-index");
+ DO_TEST_CAPS_ARCH_LATEST("acpi-egm-memory", "aarch64");
+
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 */
@@ -3049,7 +3051,8 @@ VIR_TEST_MAIN_PRELOAD(mymain,
VIR_TEST_MOCK("virrandom"),
VIR_TEST_MOCK("qemucpu"),
VIR_TEST_MOCK("virpci"),
- VIR_TEST_MOCK("virnuma"))
+ VIR_TEST_MOCK("virnuma"),
+ VIR_TEST_MOCK("qemuegm"))
#else
--
2.43.0