diff --git a/src/qemu/qemu_command.c b/src/qemu/qemu_command.c index 3126467420..deaf04f1b2 100644 --- a/src/qemu/qemu_command.c +++ b/src/qemu/qemu_command.c @@ -7447,26 +7447,6 @@ qemuBuildNumaArgStr(virQEMUDriverConfigPtr cfg, int rc; int ret = -1; size_t ncells = virDomainNumaGetNodeCount(def->numa); - const long system_page_size = virGetSystemPageSizeKB(); - - if (virDomainNumatuneHasPerNodeBinding(def->numa) && - !(virQEMUCapsGet(qemuCaps, QEMU_CAPS_OBJECT_MEMORY_RAM) || - virQEMUCapsGet(qemuCaps, QEMU_CAPS_OBJECT_MEMORY_FILE) || - virQEMUCapsGet(qemuCaps, QEMU_CAPS_OBJECT_MEMORY_MEMFD))) { - virReportError(VIR_ERR_CONFIG_UNSUPPORTED, "%s", - _("Per-node memory binding is not supported " - "with this QEMU")); - goto cleanup; - } - - if (def->mem.nhugepages && - def->mem.hugepages[0].size != system_page_size && - !virQEMUCapsGet(qemuCaps, QEMU_CAPS_OBJECT_MEMORY_FILE)) { - virReportError(VIR_ERR_CONFIG_UNSUPPORTED, "%s", - _("huge pages per NUMA node are not " - "supported with this QEMU")); - goto cleanup; - } if (!virDomainNumatuneNodesetIsAvailable(def->numa, priv->autoNodeset)) goto cleanup; @@ -7487,13 +7467,6 @@ qemuBuildNumaArgStr(virQEMUDriverConfigPtr cfg, if (rc == 0) needBackend = true; - } else { - if (virDomainNumaGetNodeMemoryAccessMode(def->numa, i)) { - virReportError(VIR_ERR_CONFIG_UNSUPPORTED, "%s", - _("Shared memory mapping is not supported " - "with this QEMU")); - goto cleanup; - } } } @@ -7506,14 +7479,6 @@ qemuBuildNumaArgStr(virQEMUDriverConfigPtr cfg, if (!(cpumask = virBitmapFormat(virDomainNumaGetNodeCpumask(def->numa, i)))) goto cleanup; - if (strchr(cpumask, ',') && - !virQEMUCapsGet(qemuCaps, QEMU_CAPS_NUMA)) { - virReportError(VIR_ERR_CONFIG_UNSUPPORTED, "%s", - _("disjoint NUMA cpu ranges are not supported " - "with this QEMU")); - goto cleanup; - } - if (needBackend) { virCommandAddArg(cmd, "-object"); virCommandAddArgBuffer(cmd, &nodeBackends[i]); @@ -7542,13 +7507,6 @@ qemuBuildNumaArgStr(virQEMUDriverConfigPtr cfg, * of nodes, we have to specify all the distances. Even * though they might be the default ones. */ if (virDomainNumaNodesDistancesAreBeingSet(def->numa)) { - if (!virQEMUCapsGet(qemuCaps, QEMU_CAPS_NUMA_DIST)) { - virReportError(VIR_ERR_CONFIG_UNSUPPORTED, "%s", - _("setting NUMA distances is not " - "supported with this qemu")); - goto cleanup; - } - for (i = 0; i < ncells; i++) { for (j = 0; j < ncells; j++) { size_t distance = virDomainNumaGetNodeDistance(def->numa, i, j); diff --git a/src/qemu/qemu_domain.c b/src/qemu/qemu_domain.c index 93c6af3bc6..432af66fa5 100644 --- a/src/qemu/qemu_domain.c +++ b/src/qemu/qemu_domain.c @@ -5225,6 +5225,69 @@ qemuDomainDefValidateMemory(const virDomainDef *def, } +static int +qemuDomainDefValidateNuma(const virDomainDef *def, + virQEMUCapsPtr qemuCaps) +{ + const long system_page_size = virGetSystemPageSizeKB(); + size_t ncells = virDomainNumaGetNodeCount(def->numa); + size_t i; + bool hasMemoryCap = virQEMUCapsGet(qemuCaps, QEMU_CAPS_OBJECT_MEMORY_RAM) || + virQEMUCapsGet(qemuCaps, QEMU_CAPS_OBJECT_MEMORY_FILE) || + virQEMUCapsGet(qemuCaps, QEMU_CAPS_OBJECT_MEMORY_MEMFD); + + if (virDomainNumatuneHasPerNodeBinding(def->numa) && !hasMemoryCap) { + virReportError(VIR_ERR_CONFIG_UNSUPPORTED, "%s", + _("Per-node memory binding is not supported " + "with this QEMU")); + return -1; + } + + if (def->mem.nhugepages && + def->mem.hugepages[0].size != system_page_size && + !virQEMUCapsGet(qemuCaps, QEMU_CAPS_OBJECT_MEMORY_FILE)) { + virReportError(VIR_ERR_CONFIG_UNSUPPORTED, "%s", + _("huge pages per NUMA node are not " + "supported with this QEMU")); + return -1; + } + + for (i = 0; i < ncells; i++) { + g_autofree char * cpumask = NULL; + + if (!hasMemoryCap && + virDomainNumaGetNodeMemoryAccessMode(def->numa, i)) { + virReportError(VIR_ERR_CONFIG_UNSUPPORTED, "%s", + _("Shared memory mapping is not supported " + "with this QEMU")); + return -1; + } + + if (!(cpumask = virBitmapFormat(virDomainNumaGetNodeCpumask(def->numa, i)))) + return -1; + + if (strchr(cpumask, ',') && + !virQEMUCapsGet(qemuCaps, QEMU_CAPS_NUMA)) { + virReportError(VIR_ERR_CONFIG_UNSUPPORTED, "%s", + _("disjoint NUMA cpu ranges are not supported " + "with this QEMU")); + return -1; + } + + } + + if (virDomainNumaNodesDistancesAreBeingSet(def->numa) && + !virQEMUCapsGet(qemuCaps, QEMU_CAPS_NUMA_DIST)) { + virReportError(VIR_ERR_CONFIG_UNSUPPORTED, "%s", + _("setting NUMA distances is not " + "supported with this qemu")); + return -1; + } + + return 0; +} + + static int qemuDomainValidateCpuCount(const virDomainDef *def, virQEMUCapsPtr qemuCaps) @@ -5412,6 +5475,9 @@ qemuDomainDefValidate(const virDomainDef *def, if (qemuDomainDefValidateMemory(def, qemuCaps) < 0) goto cleanup; + if (qemuDomainDefValidateNuma(def, qemuCaps) < 0) + goto cleanup; + if (cfg->vncTLS && cfg->vncTLSx509secretUUID && !virQEMUCapsGet(qemuCaps, QEMU_CAPS_OBJECT_TLS_CREDS_X509)) { for (i = 0; i < def->ngraphics; i++) { diff --git a/tests/qemuxml2argvtest.c b/tests/qemuxml2argvtest.c index 97e79bcb92..855784e77a 100644 --- a/tests/qemuxml2argvtest.c +++ b/tests/qemuxml2argvtest.c @@ -944,11 +944,11 @@ mymain(void) QEMU_CAPS_DEVICE_PC_DIMM, QEMU_CAPS_OBJECT_MEMORY_FILE, QEMU_CAPS_OBJECT_MEMORY_FILE_DISCARD); - DO_TEST("hugepages-default", NONE); - DO_TEST("hugepages-default-2M", NONE); + DO_TEST("hugepages-default", QEMU_CAPS_OBJECT_MEMORY_FILE); + DO_TEST("hugepages-default-2M", QEMU_CAPS_OBJECT_MEMORY_FILE); DO_TEST("hugepages-default-system-size", NONE); DO_TEST_PARSE_ERROR("hugepages-default-1G-nodeset-2M", NONE); - DO_TEST("hugepages-nodeset", NONE); + DO_TEST("hugepages-nodeset", QEMU_CAPS_OBJECT_MEMORY_FILE); DO_TEST_PARSE_ERROR("hugepages-nodeset-nonexist", QEMU_CAPS_DEVICE_PC_DIMM, QEMU_CAPS_OBJECT_MEMORY_FILE, @@ -1711,10 +1711,10 @@ mymain(void) DO_TEST("cpu-numa2", NONE); DO_TEST("cpu-numa-no-memory-element", NONE); DO_TEST_PARSE_ERROR("cpu-numa3", NONE); - DO_TEST_FAILURE("cpu-numa-disjoint", NONE); + DO_TEST_PARSE_ERROR("cpu-numa-disjoint", NONE); DO_TEST("cpu-numa-disjoint", QEMU_CAPS_NUMA); DO_TEST_FAILURE("cpu-numa-memshared", QEMU_CAPS_OBJECT_MEMORY_RAM); - DO_TEST_FAILURE("cpu-numa-memshared", NONE); + DO_TEST_PARSE_ERROR("cpu-numa-memshared", NONE); DO_TEST("cpu-numa-memshared", QEMU_CAPS_OBJECT_MEMORY_FILE); DO_TEST("cpu-host-model", NONE); DO_TEST("cpu-host-model-vendor", NONE); @@ -1777,12 +1777,12 @@ mymain(void) DO_TEST("numatune-memnode", QEMU_CAPS_NUMA, QEMU_CAPS_OBJECT_MEMORY_RAM); - DO_TEST_FAILURE("numatune-memnode", NONE); + DO_TEST_PARSE_ERROR("numatune-memnode", NONE); DO_TEST("numatune-memnode-no-memory", QEMU_CAPS_NUMA, QEMU_CAPS_OBJECT_MEMORY_RAM); - DO_TEST_FAILURE("numatune-memnode-no-memory", NONE); + DO_TEST_PARSE_ERROR("numatune-memnode-no-memory", NONE); DO_TEST("numatune-distances", QEMU_CAPS_NUMA, QEMU_CAPS_NUMA_DIST); diff --git a/tests/qemuxml2xmltest.c b/tests/qemuxml2xmltest.c index 67309f09ec..8e19ef1b33 100644 --- a/tests/qemuxml2xmltest.c +++ b/tests/qemuxml2xmltest.c @@ -289,20 +289,21 @@ mymain(void) DO_TEST("pmu-feature-off", NONE); DO_TEST("pages-discard", NONE); - DO_TEST("pages-discard-hugepages", NONE); + DO_TEST("pages-discard-hugepages", QEMU_CAPS_OBJECT_MEMORY_FILE); DO_TEST("pages-dimm-discard", NONE); - DO_TEST("hugepages-default", NONE); - DO_TEST("hugepages-default-2M", NONE); + DO_TEST("hugepages-default", QEMU_CAPS_OBJECT_MEMORY_FILE); + DO_TEST("hugepages-default-2M", QEMU_CAPS_OBJECT_MEMORY_FILE); DO_TEST("hugepages-default-system-size", NONE); - DO_TEST("hugepages-nodeset", NONE); - DO_TEST("hugepages-numa-default-2M", NONE); - DO_TEST("hugepages-numa-default-dimm", NONE); - DO_TEST("hugepages-numa-nodeset", NONE); - DO_TEST("hugepages-numa-nodeset-part", NONE); - DO_TEST("hugepages-shared", NONE); - DO_TEST("hugepages-memaccess", NONE); - DO_TEST("hugepages-memaccess2", NONE); - DO_TEST("hugepages-nvdimm", NONE); + DO_TEST("hugepages-nodeset", QEMU_CAPS_OBJECT_MEMORY_FILE); + DO_TEST("hugepages-numa-default-2M", QEMU_CAPS_OBJECT_MEMORY_FILE); + DO_TEST("hugepages-numa-default-dimm", QEMU_CAPS_OBJECT_MEMORY_FILE); + DO_TEST("hugepages-numa-nodeset", QEMU_CAPS_OBJECT_MEMORY_FILE); + DO_TEST("hugepages-numa-nodeset-part", QEMU_CAPS_OBJECT_MEMORY_FILE); + DO_TEST("hugepages-shared", QEMU_CAPS_OBJECT_MEMORY_FILE); + DO_TEST("hugepages-memaccess", QEMU_CAPS_OBJECT_MEMORY_FILE); + DO_TEST("hugepages-memaccess2", QEMU_CAPS_OBJECT_MEMORY_FILE); + DO_TEST("hugepages-nvdimm", QEMU_CAPS_DEVICE_NVDIMM, + QEMU_CAPS_OBJECT_MEMORY_FILE); DO_TEST("nosharepages", NONE); DO_TEST("restore-v2", NONE); DO_TEST("migrate", NONE); @@ -490,7 +491,8 @@ mymain(void) DO_TEST("event_idx", NONE); DO_TEST("vhost_queues", NONE); DO_TEST("interface-driver", NONE); - DO_TEST("interface-server", QEMU_CAPS_DEVICE_CIRRUS_VGA); + DO_TEST("interface-server", QEMU_CAPS_DEVICE_CIRRUS_VGA, + QEMU_CAPS_OBJECT_MEMORY_FILE); DO_TEST("virtio-lun", NONE); DO_TEST("usb-none", NONE); @@ -538,7 +540,8 @@ mymain(void) DO_TEST("seclabel-dynamic-none", NONE); DO_TEST("seclabel-device-multiple", NONE); DO_TEST_FULL("seclabel-dynamic-none-relabel", WHEN_INACTIVE, - ARG_QEMU_CAPS, QEMU_CAPS_DEVICE_CIRRUS_VGA, NONE); + ARG_QEMU_CAPS, QEMU_CAPS_DEVICE_CIRRUS_VGA, + QEMU_CAPS_OBJECT_MEMORY_FILE, NONE); DO_TEST("numad-static-vcpu-no-numatune", NONE); DO_TEST("disk-scsi-lun-passthrough-sgio", @@ -572,7 +575,8 @@ mymain(void) DO_TEST("pseries-phb-numa-node", QEMU_CAPS_NUMA, QEMU_CAPS_DEVICE_SPAPR_PCI_HOST_BRIDGE, - QEMU_CAPS_SPAPR_PCI_HOST_BRIDGE_NUMA_NODE); + QEMU_CAPS_SPAPR_PCI_HOST_BRIDGE_NUMA_NODE, + QEMU_CAPS_OBJECT_MEMORY_FILE); DO_TEST("pseries-many-devices", QEMU_CAPS_DEVICE_SPAPR_PCI_HOST_BRIDGE, @@ -1006,12 +1010,12 @@ mymain(void) DO_TEST("cpu-numa2", NONE); DO_TEST("cpu-numa-no-memory-element", NONE); DO_TEST("cpu-numa-disordered", NONE); - DO_TEST("cpu-numa-disjoint", NONE); - DO_TEST("cpu-numa-memshared", NONE); + DO_TEST("cpu-numa-disjoint", QEMU_CAPS_NUMA); + DO_TEST("cpu-numa-memshared", QEMU_CAPS_OBJECT_MEMORY_FILE); DO_TEST("numatune-auto-prefer", NONE); - DO_TEST("numatune-memnode", NONE); - DO_TEST("numatune-memnode-no-memory", NONE); + DO_TEST("numatune-memnode", QEMU_CAPS_NUMA, QEMU_CAPS_OBJECT_MEMORY_FILE); + DO_TEST("numatune-memnode-no-memory", QEMU_CAPS_OBJECT_MEMORY_FILE); DO_TEST("bios-nvram", NONE); DO_TEST("bios-nvram-os-interleave", NONE); @@ -1200,10 +1204,12 @@ mymain(void) DO_TEST("memfd-memory-numa", QEMU_CAPS_OBJECT_MEMORY_MEMFD, - QEMU_CAPS_OBJECT_MEMORY_MEMFD_HUGETLB); + QEMU_CAPS_OBJECT_MEMORY_MEMFD_HUGETLB, + QEMU_CAPS_OBJECT_MEMORY_FILE); DO_TEST("memfd-memory-default-hugepage", QEMU_CAPS_OBJECT_MEMORY_MEMFD, - QEMU_CAPS_OBJECT_MEMORY_MEMFD_HUGETLB); + QEMU_CAPS_OBJECT_MEMORY_MEMFD_HUGETLB, + QEMU_CAPS_OBJECT_MEMORY_FILE); DO_TEST("acpi-table", NONE); @@ -1264,7 +1270,8 @@ mymain(void) DO_TEST("user-aliases", QEMU_CAPS_DEVICE_CIRRUS_VGA, - QEMU_CAPS_QCOW2_LUKS); + QEMU_CAPS_QCOW2_LUKS, + QEMU_CAPS_OBJECT_MEMORY_FILE); DO_TEST("input-virtio-ccw", QEMU_CAPS_CCW, QEMU_CAPS_VIRTIO_KEYBOARD,