We're going to move qemuDomainDefValidate() to qemu_validate.c in
two steps. First steps is to finish up moving all static functions
qemuDomainDefValidate() uses, then in the next patch we can
move the function itself.
Signed-off-by: Daniel Henrique Barboza <danielhb413(a)gmail.com>
---
src/qemu/qemu_domain.c | 394 +--------------------------------------
src/qemu/qemu_validate.c | 381 +++++++++++++++++++++++++++++++++++++
src/qemu/qemu_validate.h | 16 ++
3 files changed, 404 insertions(+), 387 deletions(-)
diff --git a/src/qemu/qemu_domain.c b/src/qemu/qemu_domain.c
index c4f36b000b..413ce4a2dc 100644
--- a/src/qemu/qemu_domain.c
+++ b/src/qemu/qemu_domain.c
@@ -5040,148 +5040,6 @@ qemuDomainDefGetVcpuHotplugGranularity(const virDomainDef *def)
#define QEMU_MAX_VCPUS_WITHOUT_EIM 255
-static int
-qemuDomainDefValidateMemory(const virDomainDef *def,
- virQEMUCapsPtr qemuCaps)
-{
- const long system_page_size = virGetSystemPageSizeKB();
- const virDomainMemtune *mem = &def->mem;
-
- if (mem->nhugepages == 0)
- return 0;
-
- if (mem->allocation == VIR_DOMAIN_MEMORY_ALLOCATION_ONDEMAND) {
- virReportError(VIR_ERR_CONFIG_UNSUPPORTED, "%s",
- _("hugepages are not allowed with memory "
- "allocation ondemand"));
- return -1;
- }
-
- if (mem->source == VIR_DOMAIN_MEMORY_SOURCE_ANONYMOUS) {
- virReportError(VIR_ERR_CONFIG_UNSUPPORTED, "%s",
- _("hugepages are not allowed with anonymous "
- "memory source"));
- return -1;
- }
-
- if (mem->source == VIR_DOMAIN_MEMORY_SOURCE_MEMFD &&
- !virQEMUCapsGet(qemuCaps, QEMU_CAPS_OBJECT_MEMORY_MEMFD_HUGETLB)) {
- virReportError(VIR_ERR_CONFIG_UNSUPPORTED, "%s",
- _("hugepages is not supported with memfd memory
source"));
- return -1;
- }
-
- /* We can't guarantee any other mem.access
- * if no guest NUMA nodes are defined. */
- if (mem->hugepages[0].size != system_page_size &&
- virDomainNumaGetNodeCount(def->numa) == 0 &&
- mem->access != VIR_DOMAIN_MEMORY_ACCESS_DEFAULT &&
- mem->access != VIR_DOMAIN_MEMORY_ACCESS_PRIVATE) {
- virReportError(VIR_ERR_CONFIG_UNSUPPORTED,
- _("memory access mode '%s' not supported "
- "without guest numa node"),
- virDomainMemoryAccessTypeToString(mem->access));
- return -1;
- }
-
- if (mem->nosharepages && !virQEMUCapsGet(qemuCaps, QEMU_CAPS_MEM_MERGE))
{
- virReportError(VIR_ERR_CONFIG_UNSUPPORTED, "%s",
- _("disable shared memory is not available "
- "with this QEMU binary"));
- return -1;
- }
-
- return 0;
-}
-
-
-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)
-{
- unsigned int maxCpus = virQEMUCapsGetMachineMaxCpus(qemuCaps, def->virtType,
- def->os.machine);
-
- if (virDomainDefGetVcpus(def) == 0) {
- virReportError(VIR_ERR_CONFIG_UNSUPPORTED, "%s",
- _("Domain requires at least 1 vCPU"));
- return -1;
- }
-
- if (maxCpus > 0 && virDomainDefGetVcpusMax(def) > maxCpus) {
- virReportError(VIR_ERR_CONFIG_UNSUPPORTED,
- _("Maximum CPUs greater than specified machine "
- "type limit %u"), maxCpus);
- return -1;
- }
-
- return 0;
-}
-
-
static int
qemuDomainDeviceDefValidateNVRAM(virDomainNVRAMDefPtr nvram,
const virDomainDef *def,
@@ -5236,244 +5094,6 @@ qemuDomainDeviceDefValidateHub(virDomainHubDefPtr hub,
}
-static int
-qemuDomainDefValidateClockTimers(const virDomainDef *def,
- virQEMUCapsPtr qemuCaps)
-{
- size_t i;
-
- for (i = 0; i < def->clock.ntimers; i++) {
- virDomainTimerDefPtr timer = def->clock.timers[i];
-
- switch ((virDomainTimerNameType)timer->name) {
- case VIR_DOMAIN_TIMER_NAME_PLATFORM:
- virReportError(VIR_ERR_CONFIG_UNSUPPORTED,
- _("unsupported timer type (name) '%s'"),
- virDomainTimerNameTypeToString(timer->name));
- return -1;
-
- case VIR_DOMAIN_TIMER_NAME_TSC:
- case VIR_DOMAIN_TIMER_NAME_KVMCLOCK:
- case VIR_DOMAIN_TIMER_NAME_HYPERVCLOCK:
- case VIR_DOMAIN_TIMER_NAME_LAST:
- break;
-
- case VIR_DOMAIN_TIMER_NAME_RTC:
- switch (timer->track) {
- case -1: /* unspecified - use hypervisor default */
- case VIR_DOMAIN_TIMER_TRACK_GUEST:
- case VIR_DOMAIN_TIMER_TRACK_WALL:
- break;
- case VIR_DOMAIN_TIMER_TRACK_BOOT:
- virReportError(VIR_ERR_CONFIG_UNSUPPORTED,
- _("unsupported rtc timer track '%s'"),
- virDomainTimerTrackTypeToString(timer->track));
- return -1;
- }
-
- switch (timer->tickpolicy) {
- case -1:
- case VIR_DOMAIN_TIMER_TICKPOLICY_DELAY:
- /* This is the default - missed ticks delivered when
- next scheduled, at normal rate */
- break;
- case VIR_DOMAIN_TIMER_TICKPOLICY_CATCHUP:
- /* deliver ticks at a faster rate until caught up */
- break;
- case VIR_DOMAIN_TIMER_TICKPOLICY_MERGE:
- case VIR_DOMAIN_TIMER_TICKPOLICY_DISCARD:
- virReportError(VIR_ERR_CONFIG_UNSUPPORTED,
- _("unsupported rtc timer tickpolicy
'%s'"),
- virDomainTimerTickpolicyTypeToString(
- timer->tickpolicy));
- return -1;
- }
- break;
-
- case VIR_DOMAIN_TIMER_NAME_PIT:
- switch (timer->tickpolicy) {
- case -1:
- case VIR_DOMAIN_TIMER_TICKPOLICY_DELAY:
- case VIR_DOMAIN_TIMER_TICKPOLICY_DISCARD:
- break;
- case VIR_DOMAIN_TIMER_TICKPOLICY_CATCHUP:
- if (!virQEMUCapsGet(qemuCaps, QEMU_CAPS_KVM_PIT_TICK_POLICY)) {
- /* can't catchup if we don't have kvm-pit */
- virReportError(VIR_ERR_CONFIG_UNSUPPORTED,
- _("unsupported pit tickpolicy
'%s'"),
- virDomainTimerTickpolicyTypeToString(
- timer->tickpolicy));
- return -1;
- }
- break;
- case VIR_DOMAIN_TIMER_TICKPOLICY_MERGE:
- /* no way to support this mode for pit in qemu */
- virReportError(VIR_ERR_CONFIG_UNSUPPORTED,
- _("unsupported pit tickpolicy '%s'"),
- virDomainTimerTickpolicyTypeToString(
- timer->tickpolicy));
- return -1;
- }
- break;
-
- case VIR_DOMAIN_TIMER_NAME_HPET:
- /* no hpet timer available. The only possible action
- is to raise an error if present="yes" */
- if (!virQEMUCapsGet(qemuCaps, QEMU_CAPS_NO_HPET) &&
- timer->present == 1) {
- virReportError(VIR_ERR_CONFIG_UNSUPPORTED,
- "%s", _("hpet timer is not
supported"));
- return -1;
- }
- break;
-
- case VIR_DOMAIN_TIMER_NAME_ARMVTIMER:
- if (def->virtType != VIR_DOMAIN_VIRT_KVM ||
- !qemuDomainIsARMVirt(def)) {
- virReportError(VIR_ERR_CONFIG_UNSUPPORTED,
- _("Configuring the '%s' timer is not
supported "
- "for virtType=%s arch=%s machine=%s guests"),
- virDomainTimerNameTypeToString(timer->name),
- virDomainVirtTypeToString(def->virtType),
- virArchToString(def->os.arch),
- def->os.machine);
- return -1;
- }
- if (timer->present == 0) {
- virReportError(VIR_ERR_CONFIG_UNSUPPORTED,
- _("The '%s' timer can't be
disabled"),
- virDomainTimerNameTypeToString(timer->name));
- return -1;
- }
- if (!virQEMUCapsGet(qemuCaps, QEMU_CAPS_CPU_KVM_NO_ADJVTIME)) {
- virReportError(VIR_ERR_CONFIG_UNSUPPORTED,
- _("Configuring the '%s' timer is not
supported "
- "with this QEMU binary"),
- virDomainTimerNameTypeToString(timer->name));
- return -1;
- }
-
- switch (timer->tickpolicy) {
- case -1:
- case VIR_DOMAIN_TIMER_TICKPOLICY_DELAY:
- case VIR_DOMAIN_TIMER_TICKPOLICY_DISCARD:
- break;
- case VIR_DOMAIN_TIMER_TICKPOLICY_CATCHUP:
- case VIR_DOMAIN_TIMER_TICKPOLICY_MERGE:
- virReportError(VIR_ERR_CONFIG_UNSUPPORTED,
- _("The '%s' timer does not support tickpolicy
'%s'"),
- virDomainTimerNameTypeToString(timer->name),
-
virDomainTimerTickpolicyTypeToString(timer->tickpolicy));
- return -1;
- }
- break;
- }
- }
-
- return 0;
-}
-
-
-static int
-qemuDomainDefValidatePM(const virDomainDef *def,
- virQEMUCapsPtr qemuCaps)
-{
- bool q35Dom = qemuDomainIsQ35(def);
-
- if (def->pm.s3) {
- bool q35ICH9_S3 = q35Dom &&
- virQEMUCapsGet(qemuCaps, QEMU_CAPS_ICH9_DISABLE_S3);
-
- if (!q35ICH9_S3 && !virQEMUCapsGet(qemuCaps, QEMU_CAPS_PIIX_DISABLE_S3))
{
- virReportError(VIR_ERR_CONFIG_UNSUPPORTED,
- "%s", _("setting ACPI S3 not
supported"));
- return -1;
- }
- }
-
- if (def->pm.s4) {
- bool q35ICH9_S4 = q35Dom &&
- virQEMUCapsGet(qemuCaps, QEMU_CAPS_ICH9_DISABLE_S4);
-
- if (!q35ICH9_S4 && !virQEMUCapsGet(qemuCaps, QEMU_CAPS_PIIX_DISABLE_S4))
{
- virReportError(VIR_ERR_CONFIG_UNSUPPORTED,
- "%s", _("setting ACPI S4 not
supported"));
- return -1;
- }
- }
-
- return 0;
-}
-
-
-static int
-qemuDomainDefValidateBoot(const virDomainDef *def,
- virQEMUCapsPtr qemuCaps)
-{
- if (def->os.bios.rt_set) {
- if (!virQEMUCapsGet(qemuCaps, QEMU_CAPS_REBOOT_TIMEOUT)) {
- virReportError(VIR_ERR_CONFIG_UNSUPPORTED, "%s",
- _("reboot timeout is not supported "
- "by this QEMU binary"));
- return -1;
- }
- }
-
- if (def->os.bm_timeout_set) {
- if (!virQEMUCapsGet(qemuCaps, QEMU_CAPS_SPLASH_TIMEOUT)) {
- virReportError(VIR_ERR_CONFIG_UNSUPPORTED, "%s",
- _("splash timeout is not supported "
- "by this QEMU binary"));
- return -1;
- }
- }
-
- return 0;
-}
-
-static int
-qemuDomainDefValidateConsole(const virDomainDef *def,
- virQEMUCapsPtr qemuCaps)
-{
- size_t i;
-
- /* Explicit console devices */
- for (i = 0; i < def->nconsoles; i++) {
- virDomainChrDefPtr console = def->consoles[i];
-
- switch (console->targetType) {
- case VIR_DOMAIN_CHR_CONSOLE_TARGET_TYPE_SCLP:
- if (!virQEMUCapsGet(qemuCaps, QEMU_CAPS_DEVICE_SCLPCONSOLE)) {
- virReportError(VIR_ERR_CONFIG_UNSUPPORTED, "%s",
- _("sclpconsole is not supported in this QEMU
binary"));
- return -1;
- }
- break;
-
- case VIR_DOMAIN_CHR_CONSOLE_TARGET_TYPE_SCLPLM:
- if (!virQEMUCapsGet(qemuCaps, QEMU_CAPS_DEVICE_SCLPLMCONSOLE)) {
- virReportError(VIR_ERR_CONFIG_UNSUPPORTED, "%s",
- _("sclplmconsole is not supported in this QEMU
binary"));
- return -1;
- }
- break;
-
- case VIR_DOMAIN_CHR_CONSOLE_TARGET_TYPE_VIRTIO:
- case VIR_DOMAIN_CHR_CONSOLE_TARGET_TYPE_SERIAL:
- break;
-
- default:
- virReportError(VIR_ERR_CONFIG_UNSUPPORTED,
- _("unsupported console target type %s"),
-
NULLSTR(virDomainChrConsoleTargetTypeToString(console->targetType)));
- return -1;
- }
- }
-
- return 0;
-}
-
-
static int
qemuSoundCodecTypeToCaps(int type)
{
@@ -5680,13 +5300,13 @@ qemuDomainDefValidate(const virDomainDef *def,
}
}
- if (qemuDomainDefValidateClockTimers(def, qemuCaps) < 0)
+ if (qemuValidateDomainDefClockTimers(def, qemuCaps) < 0)
return -1;
- if (qemuDomainDefValidatePM(def, qemuCaps) < 0)
+ if (qemuValidateDomainDefPM(def, qemuCaps) < 0)
return -1;
- if (qemuDomainDefValidateBoot(def, qemuCaps) < 0)
+ if (qemuValidateDomainDefBoot(def, qemuCaps) < 0)
return -1;
/* QEMU 2.7 (detected via the availability of query-hotpluggable-cpus)
@@ -5726,7 +5346,7 @@ qemuDomainDefValidate(const virDomainDef *def,
}
}
- if (qemuDomainValidateCpuCount(def, qemuCaps) < 0)
+ if (qemuValidateDomainCpuCount(def, qemuCaps) < 0)
return -1;
if (ARCH_IS_X86(def->os.arch) &&
@@ -5757,13 +5377,13 @@ qemuDomainDefValidate(const virDomainDef *def,
if (qemuValidateDomainDefFeatures(def, qemuCaps) < 0)
return -1;
- if (qemuDomainDefValidateMemory(def, qemuCaps) < 0)
+ if (qemuValidateDomainDefMemory(def, qemuCaps) < 0)
return -1;
- if (qemuDomainDefValidateNuma(def, qemuCaps) < 0)
+ if (qemuValidateDomainDefNuma(def, qemuCaps) < 0)
return -1;
- if (qemuDomainDefValidateConsole(def, qemuCaps) < 0)
+ if (qemuValidateDomainDefConsole(def, qemuCaps) < 0)
return -1;
if (cfg->vncTLS && cfg->vncTLSx509secretUUID &&
diff --git a/src/qemu/qemu_validate.c b/src/qemu/qemu_validate.c
index 8f4c5af582..b2a8c3c0b5 100644
--- a/src/qemu/qemu_validate.c
+++ b/src/qemu/qemu_validate.c
@@ -22,6 +22,7 @@
#include "qemu_validate.h"
#include "qemu_domain.h"
+#include "virutil.h"
#define VIR_FROM_THIS VIR_FROM_QEMU
@@ -308,3 +309,383 @@ qemuValidateDomainDefFeatures(const virDomainDef *def,
return 0;
}
+
+
+int
+qemuValidateDomainDefClockTimers(const virDomainDef *def,
+ virQEMUCapsPtr qemuCaps)
+{
+ size_t i;
+
+ for (i = 0; i < def->clock.ntimers; i++) {
+ virDomainTimerDefPtr timer = def->clock.timers[i];
+
+ switch ((virDomainTimerNameType)timer->name) {
+ case VIR_DOMAIN_TIMER_NAME_PLATFORM:
+ virReportError(VIR_ERR_CONFIG_UNSUPPORTED,
+ _("unsupported timer type (name) '%s'"),
+ virDomainTimerNameTypeToString(timer->name));
+ return -1;
+
+ case VIR_DOMAIN_TIMER_NAME_TSC:
+ case VIR_DOMAIN_TIMER_NAME_KVMCLOCK:
+ case VIR_DOMAIN_TIMER_NAME_HYPERVCLOCK:
+ case VIR_DOMAIN_TIMER_NAME_LAST:
+ break;
+
+ case VIR_DOMAIN_TIMER_NAME_RTC:
+ switch (timer->track) {
+ case -1: /* unspecified - use hypervisor default */
+ case VIR_DOMAIN_TIMER_TRACK_GUEST:
+ case VIR_DOMAIN_TIMER_TRACK_WALL:
+ break;
+ case VIR_DOMAIN_TIMER_TRACK_BOOT:
+ virReportError(VIR_ERR_CONFIG_UNSUPPORTED,
+ _("unsupported rtc timer track '%s'"),
+ virDomainTimerTrackTypeToString(timer->track));
+ return -1;
+ }
+
+ switch (timer->tickpolicy) {
+ case -1:
+ case VIR_DOMAIN_TIMER_TICKPOLICY_DELAY:
+ /* This is the default - missed ticks delivered when
+ next scheduled, at normal rate */
+ break;
+ case VIR_DOMAIN_TIMER_TICKPOLICY_CATCHUP:
+ /* deliver ticks at a faster rate until caught up */
+ break;
+ case VIR_DOMAIN_TIMER_TICKPOLICY_MERGE:
+ case VIR_DOMAIN_TIMER_TICKPOLICY_DISCARD:
+ virReportError(VIR_ERR_CONFIG_UNSUPPORTED,
+ _("unsupported rtc timer tickpolicy
'%s'"),
+ virDomainTimerTickpolicyTypeToString(
+ timer->tickpolicy));
+ return -1;
+ }
+ break;
+
+ case VIR_DOMAIN_TIMER_NAME_PIT:
+ switch (timer->tickpolicy) {
+ case -1:
+ case VIR_DOMAIN_TIMER_TICKPOLICY_DELAY:
+ case VIR_DOMAIN_TIMER_TICKPOLICY_DISCARD:
+ break;
+ case VIR_DOMAIN_TIMER_TICKPOLICY_CATCHUP:
+ if (!virQEMUCapsGet(qemuCaps, QEMU_CAPS_KVM_PIT_TICK_POLICY)) {
+ /* can't catchup if we don't have kvm-pit */
+ virReportError(VIR_ERR_CONFIG_UNSUPPORTED,
+ _("unsupported pit tickpolicy
'%s'"),
+ virDomainTimerTickpolicyTypeToString(
+ timer->tickpolicy));
+ return -1;
+ }
+ break;
+ case VIR_DOMAIN_TIMER_TICKPOLICY_MERGE:
+ /* no way to support this mode for pit in qemu */
+ virReportError(VIR_ERR_CONFIG_UNSUPPORTED,
+ _("unsupported pit tickpolicy '%s'"),
+ virDomainTimerTickpolicyTypeToString(
+ timer->tickpolicy));
+ return -1;
+ }
+ break;
+
+ case VIR_DOMAIN_TIMER_NAME_HPET:
+ /* no hpet timer available. The only possible action
+ is to raise an error if present="yes" */
+ if (!virQEMUCapsGet(qemuCaps, QEMU_CAPS_NO_HPET) &&
+ timer->present == 1) {
+ virReportError(VIR_ERR_CONFIG_UNSUPPORTED,
+ "%s", _("hpet timer is not
supported"));
+ return -1;
+ }
+ break;
+
+ case VIR_DOMAIN_TIMER_NAME_ARMVTIMER:
+ if (def->virtType != VIR_DOMAIN_VIRT_KVM ||
+ !qemuDomainIsARMVirt(def)) {
+ virReportError(VIR_ERR_CONFIG_UNSUPPORTED,
+ _("Configuring the '%s' timer is not
supported "
+ "for virtType=%s arch=%s machine=%s guests"),
+ virDomainTimerNameTypeToString(timer->name),
+ virDomainVirtTypeToString(def->virtType),
+ virArchToString(def->os.arch),
+ def->os.machine);
+ return -1;
+ }
+ if (timer->present == 0) {
+ virReportError(VIR_ERR_CONFIG_UNSUPPORTED,
+ _("The '%s' timer can't be
disabled"),
+ virDomainTimerNameTypeToString(timer->name));
+ return -1;
+ }
+ if (!virQEMUCapsGet(qemuCaps, QEMU_CAPS_CPU_KVM_NO_ADJVTIME)) {
+ virReportError(VIR_ERR_CONFIG_UNSUPPORTED,
+ _("Configuring the '%s' timer is not
supported "
+ "with this QEMU binary"),
+ virDomainTimerNameTypeToString(timer->name));
+ return -1;
+ }
+
+ switch (timer->tickpolicy) {
+ case -1:
+ case VIR_DOMAIN_TIMER_TICKPOLICY_DELAY:
+ case VIR_DOMAIN_TIMER_TICKPOLICY_DISCARD:
+ break;
+ case VIR_DOMAIN_TIMER_TICKPOLICY_CATCHUP:
+ case VIR_DOMAIN_TIMER_TICKPOLICY_MERGE:
+ virReportError(VIR_ERR_CONFIG_UNSUPPORTED,
+ _("The '%s' timer does not support tickpolicy
'%s'"),
+ virDomainTimerNameTypeToString(timer->name),
+
virDomainTimerTickpolicyTypeToString(timer->tickpolicy));
+ return -1;
+ }
+ break;
+ }
+ }
+
+ return 0;
+}
+
+
+int
+qemuValidateDomainDefPM(const virDomainDef *def,
+ virQEMUCapsPtr qemuCaps)
+{
+ bool q35Dom = qemuDomainIsQ35(def);
+
+ if (def->pm.s3) {
+ bool q35ICH9_S3 = q35Dom &&
+ virQEMUCapsGet(qemuCaps, QEMU_CAPS_ICH9_DISABLE_S3);
+
+ if (!q35ICH9_S3 && !virQEMUCapsGet(qemuCaps, QEMU_CAPS_PIIX_DISABLE_S3))
{
+ virReportError(VIR_ERR_CONFIG_UNSUPPORTED,
+ "%s", _("setting ACPI S3 not
supported"));
+ return -1;
+ }
+ }
+
+ if (def->pm.s4) {
+ bool q35ICH9_S4 = q35Dom &&
+ virQEMUCapsGet(qemuCaps, QEMU_CAPS_ICH9_DISABLE_S4);
+
+ if (!q35ICH9_S4 && !virQEMUCapsGet(qemuCaps, QEMU_CAPS_PIIX_DISABLE_S4))
{
+ virReportError(VIR_ERR_CONFIG_UNSUPPORTED,
+ "%s", _("setting ACPI S4 not
supported"));
+ return -1;
+ }
+ }
+
+ return 0;
+}
+
+
+int
+qemuValidateDomainDefBoot(const virDomainDef *def,
+ virQEMUCapsPtr qemuCaps)
+{
+ if (def->os.bios.rt_set) {
+ if (!virQEMUCapsGet(qemuCaps, QEMU_CAPS_REBOOT_TIMEOUT)) {
+ virReportError(VIR_ERR_CONFIG_UNSUPPORTED, "%s",
+ _("reboot timeout is not supported "
+ "by this QEMU binary"));
+ return -1;
+ }
+ }
+
+ if (def->os.bm_timeout_set) {
+ if (!virQEMUCapsGet(qemuCaps, QEMU_CAPS_SPLASH_TIMEOUT)) {
+ virReportError(VIR_ERR_CONFIG_UNSUPPORTED, "%s",
+ _("splash timeout is not supported "
+ "by this QEMU binary"));
+ return -1;
+ }
+ }
+
+ return 0;
+}
+
+
+int
+qemuValidateDomainCpuCount(const virDomainDef *def, virQEMUCapsPtr qemuCaps)
+{
+ unsigned int maxCpus = virQEMUCapsGetMachineMaxCpus(qemuCaps, def->virtType,
+ def->os.machine);
+
+ if (virDomainDefGetVcpus(def) == 0) {
+ virReportError(VIR_ERR_CONFIG_UNSUPPORTED, "%s",
+ _("Domain requires at least 1 vCPU"));
+ return -1;
+ }
+
+ if (maxCpus > 0 && virDomainDefGetVcpusMax(def) > maxCpus) {
+ virReportError(VIR_ERR_CONFIG_UNSUPPORTED,
+ _("Maximum CPUs greater than specified machine "
+ "type limit %u"), maxCpus);
+ return -1;
+ }
+
+ return 0;
+}
+
+
+int
+qemuValidateDomainDefMemory(const virDomainDef *def,
+ virQEMUCapsPtr qemuCaps)
+{
+ const long system_page_size = virGetSystemPageSizeKB();
+ const virDomainMemtune *mem = &def->mem;
+
+ if (mem->nhugepages == 0)
+ return 0;
+
+ if (mem->allocation == VIR_DOMAIN_MEMORY_ALLOCATION_ONDEMAND) {
+ virReportError(VIR_ERR_CONFIG_UNSUPPORTED, "%s",
+ _("hugepages are not allowed with memory "
+ "allocation ondemand"));
+ return -1;
+ }
+
+ if (mem->source == VIR_DOMAIN_MEMORY_SOURCE_ANONYMOUS) {
+ virReportError(VIR_ERR_CONFIG_UNSUPPORTED, "%s",
+ _("hugepages are not allowed with anonymous "
+ "memory source"));
+ return -1;
+ }
+
+ if (mem->source == VIR_DOMAIN_MEMORY_SOURCE_MEMFD &&
+ !virQEMUCapsGet(qemuCaps, QEMU_CAPS_OBJECT_MEMORY_MEMFD_HUGETLB)) {
+ virReportError(VIR_ERR_CONFIG_UNSUPPORTED, "%s",
+ _("hugepages is not supported with memfd memory
source"));
+ return -1;
+ }
+
+ /* We can't guarantee any other mem.access
+ * if no guest NUMA nodes are defined. */
+ if (mem->hugepages[0].size != system_page_size &&
+ virDomainNumaGetNodeCount(def->numa) == 0 &&
+ mem->access != VIR_DOMAIN_MEMORY_ACCESS_DEFAULT &&
+ mem->access != VIR_DOMAIN_MEMORY_ACCESS_PRIVATE) {
+ virReportError(VIR_ERR_CONFIG_UNSUPPORTED,
+ _("memory access mode '%s' not supported "
+ "without guest numa node"),
+ virDomainMemoryAccessTypeToString(mem->access));
+ return -1;
+ }
+
+ if (mem->nosharepages && !virQEMUCapsGet(qemuCaps, QEMU_CAPS_MEM_MERGE))
{
+ virReportError(VIR_ERR_CONFIG_UNSUPPORTED, "%s",
+ _("disable shared memory is not available "
+ "with this QEMU binary"));
+ return -1;
+ }
+
+ return 0;
+}
+
+
+int
+qemuValidateDomainDefNuma(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;
+}
+
+
+int
+qemuValidateDomainDefConsole(const virDomainDef *def,
+ virQEMUCapsPtr qemuCaps)
+{
+ size_t i;
+
+ /* Explicit console devices */
+ for (i = 0; i < def->nconsoles; i++) {
+ virDomainChrDefPtr console = def->consoles[i];
+
+ switch (console->targetType) {
+ case VIR_DOMAIN_CHR_CONSOLE_TARGET_TYPE_SCLP:
+ if (!virQEMUCapsGet(qemuCaps, QEMU_CAPS_DEVICE_SCLPCONSOLE)) {
+ virReportError(VIR_ERR_CONFIG_UNSUPPORTED, "%s",
+ _("sclpconsole is not supported in this QEMU
binary"));
+ return -1;
+ }
+ break;
+
+ case VIR_DOMAIN_CHR_CONSOLE_TARGET_TYPE_SCLPLM:
+ if (!virQEMUCapsGet(qemuCaps, QEMU_CAPS_DEVICE_SCLPLMCONSOLE)) {
+ virReportError(VIR_ERR_CONFIG_UNSUPPORTED, "%s",
+ _("sclplmconsole is not supported in this QEMU
binary"));
+ return -1;
+ }
+ break;
+
+ case VIR_DOMAIN_CHR_CONSOLE_TARGET_TYPE_VIRTIO:
+ case VIR_DOMAIN_CHR_CONSOLE_TARGET_TYPE_SERIAL:
+ break;
+
+ default:
+ virReportError(VIR_ERR_CONFIG_UNSUPPORTED,
+ _("unsupported console target type %s"),
+
NULLSTR(virDomainChrConsoleTargetTypeToString(console->targetType)));
+ return -1;
+ }
+ }
+
+ return 0;
+}
diff --git a/src/qemu/qemu_validate.h b/src/qemu/qemu_validate.h
index ed269f29e4..85d1bc07cb 100644
--- a/src/qemu/qemu_validate.h
+++ b/src/qemu/qemu_validate.h
@@ -27,3 +27,19 @@
int qemuValidateDomainDefFeatures(const virDomainDef *def,
virQEMUCapsPtr qemuCaps);
+int qemuValidateDomainDefClockTimers(const virDomainDef *def,
+ virQEMUCapsPtr qemuCaps);
+int qemuValidateDomainDefPM(const virDomainDef *def,
+ virQEMUCapsPtr qemuCaps);
+int qemuValidateDomainDefBoot(const virDomainDef *def,
+ virQEMUCapsPtr qemuCaps);
+int qemuValidateDomainCpuCount(const virDomainDef *def,
+ virQEMUCapsPtr qemuCaps);
+int qemuValidateDomainCpuCount(const virDomainDef *def,
+ virQEMUCapsPtr qemuCaps);
+int qemuValidateDomainDefMemory(const virDomainDef *def,
+ virQEMUCapsPtr qemuCaps);
+int qemuValidateDomainDefNuma(const virDomainDef *def,
+ virQEMUCapsPtr qemuCaps);
+int qemuValidateDomainDefConsole(const virDomainDef *def,
+ virQEMUCapsPtr qemuCaps);
--
2.25.1