Implement validation logic for ACPI EGM memory device configuration:

- Validate PCI device reference exists and is properly configured
- Check NUMA node assignment is valid
- Verify device paths exist and are accessible
- Ensure proper permissions on device files

Signed-off-by: Ian May <i...@nvidia.com>
---
 src/conf/domain_validate.c | 22 +++++++++
 src/qemu/qemu_validate.c   | 99 ++++++++++++++++++++++++++++++++++++++
 2 files changed, 121 insertions(+)

diff --git a/src/conf/domain_validate.c b/src/conf/domain_validate.c
index 88e61fb878..3cbfe867dc 100644
--- a/src/conf/domain_validate.c
+++ b/src/conf/domain_validate.c
@@ -3203,6 +3203,26 @@ virDomainPstoreDefValidate(const virDomainPstoreDef 
*pstore)
     return 0;
 }
 
+static int
+virDomainAcpiEgmDefValidate(const virDomainAcpiEgmDef *egm)
+{
+    if (egm->pciDev == NULL || egm->pciDev[0] == '\0') {
+        virReportError(VIR_ERR_XML_ERROR, "%s",
+                       _("missing pciDev for ACPI EGM device"));
+        return -1;
+    }
+
+    if (egm->numaNode < 0) {
+        virReportError(VIR_ERR_XML_ERROR, "%s",
+                       _("NUMA node must be specified for ACPI EGM device"));
+        return -1;
+    }
+
+    VIR_DEBUG("Validating EGM device: alias=%s pciDev=%s numaNode=%d",
+              egm->alias, egm->pciDev, egm->numaNode);
+
+    return 0;
+}
 
 static int
 virDomainDeviceInfoValidate(const virDomainDeviceDef *dev)
@@ -3318,6 +3338,8 @@ virDomainDeviceDefValidateInternal(const 
virDomainDeviceDef *dev,
         return virDomainPstoreDefValidate(dev->data.pstore);
 
     case VIR_DOMAIN_DEVICE_EGM:
+        return virDomainAcpiEgmDefValidate(dev->data.egm);
+
     case VIR_DOMAIN_DEVICE_LEASE:
     case VIR_DOMAIN_DEVICE_WATCHDOG:
     case VIR_DOMAIN_DEVICE_HUB:
diff --git a/src/qemu/qemu_validate.c b/src/qemu/qemu_validate.c
index 57dc4171fe..b7cb0c632b 100644
--- a/src/qemu/qemu_validate.c
+++ b/src/qemu/qemu_validate.c
@@ -4977,6 +4977,102 @@ qemuValidateDomainDeviceDefPstore(virDomainPstoreDef 
*pstore,
     return 0;
 }
 
+static int
+qemuValidateDomainDeviceDefAcpiEgm(virDomainAcpiEgmDef *egm,
+                                  const virDomainDef *def,
+                                  virQEMUCaps *qemuCaps)
+{
+    g_autofree char *egm_path = NULL;
+    g_autofree char *egm_pci_path = NULL;
+    g_autofree char *expected_pci = NULL;
+    g_autofree char *gpu_devices_content = NULL;
+    virDomainHostdevDef *hostdev = NULL;
+    size_t i;
+
+    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;
+    }
+
+    /* Find the referenced PCI hostdev */
+    for (i = 0; i < def->nhostdevs; i++) {
+        virDomainHostdevDef *dev = def->hostdevs[i];
+
+        if (dev->mode != VIR_DOMAIN_HOSTDEV_MODE_SUBSYS ||
+            dev->source.subsys.type != VIR_DOMAIN_HOSTDEV_SUBSYS_TYPE_PCI)
+            continue;
+
+        if (dev->info && dev->info->alias && STREQ(dev->info->alias, 
egm->pciDev)) {
+            hostdev = dev;
+            break;
+        }
+    }
+
+    if (!hostdev) {
+        virReportError(VIR_ERR_CONFIG_UNSUPPORTED,
+                      _("Cannot find PCI device '%1$s' referenced by EGM 
device"),
+                      egm->pciDev);
+        return -1;
+    }
+
+    /* Validate NUMA node if configured */
+    if (egm->numaNode > virDomainNumaGetNodeCount(def->numa)) {
+            virReportError(VIR_ERR_CONFIG_UNSUPPORTED,
+                          _("NUMA node %1$d for EGM device does not exist"),
+                          egm->numaNode);
+            return -1;
+    }
+
+    /* Validate EGM device path exists and is accessible */
+    egm_path = g_strdup_printf("/dev/%s", egm->alias);
+    if (!virFileExists(egm_path)) {
+        virReportError(VIR_ERR_CONFIG_UNSUPPORTED,
+                      _("EGM device path '%1$s' does not exist"),
+                      egm_path);
+        return -1;
+    }
+
+    /* Check if we have proper permissions */
+    if (access(egm_path, R_OK | W_OK) < 0) {
+        virReportSystemError(errno,
+                          _("Cannot access EGM device '%1$s'"),
+                          egm_path);
+        return -1;
+    }
+
+    /* Validate EGM pci device path */
+    egm_pci_path = g_strdup_printf("/sys/class/egm/%s/gpu_devices", 
egm->alias);
+    if (!virFileExists(egm_pci_path)) {
+        virReportError(VIR_ERR_CONFIG_UNSUPPORTED,
+                       _("Cannot find GPU device information for EGM device 
'%1$s'"),
+                       egm->alias);
+        return -1;
+    }
+
+    /* Read and validate PCI address from gpu_devices file */
+    expected_pci = g_strdup_printf("%04x:%02x:%02x.%x",
+                                    hostdev->source.subsys.u.pci.addr.domain,
+                                    hostdev->source.subsys.u.pci.addr.bus,
+                                    hostdev->source.subsys.u.pci.addr.slot,
+                                    
hostdev->source.subsys.u.pci.addr.function);
+
+    if (virFileReadAll(egm_pci_path, 1024, &gpu_devices_content) < 0) {
+        virReportError(VIR_ERR_CONFIG_UNSUPPORTED,
+                       _("Cannot read GPU device information for EGM device 
'%1$s'"),
+                       egm->alias);
+        return -1;
+    }
+
+    if (!strstr(gpu_devices_content, expected_pci)) {
+        virReportError(VIR_ERR_CONFIG_UNSUPPORTED,
+                       _("PCI device '%2$s' is not associated with EGM device 
'%1$s'"),
+                       egm->alias, expected_pci);
+        return -1;
+    }
+
+    return 0;
+}
 
 static int
 qemuSoundCodecTypeToCaps(int type)
@@ -5748,6 +5844,9 @@ qemuValidateDomainDeviceDef(const virDomainDeviceDef *dev,
     case VIR_DOMAIN_DEVICE_PSTORE:
         return qemuValidateDomainDeviceDefPstore(dev->data.pstore, def, 
qemuCaps);
 
+    case VIR_DOMAIN_DEVICE_EGM:
+        return qemuValidateDomainDeviceDefAcpiEgm(dev->data.egm, def, 
qemuCaps);
+
     case VIR_DOMAIN_DEVICE_LEASE:
     case VIR_DOMAIN_DEVICE_PANIC:
     case VIR_DOMAIN_DEVICE_NONE:
-- 
2.43.0

Reply via email to