From e8b2fc077dc9e81ad8796f528e15f2340ec7d2ad Mon Sep 17 00:00:00 2001 From: Daniel Henrique Barboza Date: Mon, 9 Dec 2019 20:15:21 -0300 Subject: [PATCH] qemu: command: move virDomainClockDef validation to qemu_domain.c @def->clock validation is done by qemuBuildClockCommandLine() and qemuBuildClockArgStr(). This patch centralize the validation done in both these functions to a new qemuDomainDefValidateClockTimers() function. This new function is then called by qemuDomainDefValidate(), promoting clock validation in domain define time. Tests were adapted to consider the new caps being needed in this earlier stage. Reviewed-by: Cole Robinson Signed-off-by: Daniel Henrique Barboza --- src/qemu/qemu_command.c | 35 ++------------ src/qemu/qemu_domain.c | 100 ++++++++++++++++++++++++++++++++++++++++ tests/qemuxml2xmltest.c | 2 +- 3 files changed, 106 insertions(+), 31 deletions(-) diff --git a/src/qemu/qemu_command.c b/src/qemu/qemu_command.c index 90f5f5642c..e94c977e85 100644 --- a/src/qemu/qemu_command.c +++ b/src/qemu/qemu_command.c @@ -6154,9 +6154,6 @@ qemuBuildClockArgStr(virDomainClockDefPtr def) case -1: /* unspecified - use hypervisor default */ break; case VIR_DOMAIN_TIMER_TRACK_BOOT: - virReportError(VIR_ERR_CONFIG_UNSUPPORTED, - _("unsupported rtc timer track '%s'"), - virDomainTimerTrackTypeToString(def->timers[i]->track)); return NULL; case VIR_DOMAIN_TIMER_TRACK_GUEST: virBufferAddLit(&buf, ",clock=vm"); @@ -6178,9 +6175,6 @@ qemuBuildClockArgStr(virDomainClockDefPtr def) break; case VIR_DOMAIN_TIMER_TICKPOLICY_MERGE: case VIR_DOMAIN_TIMER_TICKPOLICY_DISCARD: - virReportError(VIR_ERR_CONFIG_UNSUPPORTED, - _("unsupported rtc timer tickpolicy '%s'"), - virDomainTimerTickpolicyTypeToString(def->timers[i]->tickpolicy)); return NULL; } break; /* no need to check other timers - there is only one rtc */ @@ -6215,9 +6209,8 @@ qemuBuildClockCommandLine(virCommandPtr cmd, for (i = 0; i < def->clock.ntimers; i++) { switch ((virDomainTimerNameType)def->clock.timers[i]->name) { case VIR_DOMAIN_TIMER_NAME_PLATFORM: - virReportError(VIR_ERR_CONFIG_UNSUPPORTED, - _("unsupported timer type (name) '%s'"), - virDomainTimerNameTypeToString(def->clock.timers[i]->name)); + /* qemuDomainDefValidateClockTimers will handle this + * error condition */ return -1; case VIR_DOMAIN_TIMER_NAME_TSC: @@ -6228,7 +6221,7 @@ qemuBuildClockCommandLine(virCommandPtr cmd, break; case VIR_DOMAIN_TIMER_NAME_RTC: - /* Already handled in qemuBuildClockArgStr */ + /* Already handled in qemuDomainDefValidateClockTimers */ break; case VIR_DOMAIN_TIMER_NAME_PIT: @@ -6242,15 +6235,8 @@ qemuBuildClockCommandLine(virCommandPtr cmd, "kvm-pit.lost_tick_policy=delay", NULL); break; case VIR_DOMAIN_TIMER_TICKPOLICY_CATCHUP: - if (virQEMUCapsGet(qemuCaps, QEMU_CAPS_KVM_PIT_TICK_POLICY)) { - /* do nothing - this is default for kvm-pit */ - } else { - /* can't catchup if we don't have kvm-pit */ - virReportError(VIR_ERR_CONFIG_UNSUPPORTED, - _("unsupported pit tickpolicy '%s'"), - virDomainTimerTickpolicyTypeToString(def->clock.timers[i]->tickpolicy)); - return -1; - } + /* Do nothing - qemuDomainDefValidateClockTimers handled + * the possible error condition here. */ break; case VIR_DOMAIN_TIMER_TICKPOLICY_DISCARD: if (virQEMUCapsGet(qemuCaps, QEMU_CAPS_KVM_PIT_TICK_POLICY)) @@ -6259,9 +6245,6 @@ qemuBuildClockCommandLine(virCommandPtr cmd, 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(def->clock.timers[i]->tickpolicy)); return -1; } break; @@ -6277,14 +6260,6 @@ qemuBuildClockCommandLine(virCommandPtr cmd, if (virQEMUCapsGet(qemuCaps, QEMU_CAPS_NO_HPET)) { if (def->clock.timers[i]->present == 0) virCommandAddArg(cmd, "-no-hpet"); - } else { - /* no hpet timer available. The only possible action - is to raise an error if present="yes" */ - if (def->clock.timers[i]->present == 1) { - virReportError(VIR_ERR_CONFIG_UNSUPPORTED, - "%s", _("hpet timer is not supported")); - return -1; - } } break; } diff --git a/src/qemu/qemu_domain.c b/src/qemu/qemu_domain.c index 9b4882df96..3fc09dc4a5 100644 --- a/src/qemu/qemu_domain.c +++ b/src/qemu/qemu_domain.c @@ -5366,6 +5366,103 @@ 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; + } + } + + return 0; +} + + static int qemuDomainDefValidate(const virDomainDef *def, void *opaque) @@ -5479,6 +5576,9 @@ qemuDomainDefValidate(const virDomainDef *def, } } + if (qemuDomainDefValidateClockTimers(def, qemuCaps) < 0) + goto cleanup; + /* QEMU 2.7 (detected via the availability of query-hotpluggable-cpus) * enforces stricter rules than previous versions when it comes to guest * CPU topology. Verify known constraints are respected */ diff --git a/tests/qemuxml2xmltest.c b/tests/qemuxml2xmltest.c index 17519b8657..5e4766567a 100644 --- a/tests/qemuxml2xmltest.c +++ b/tests/qemuxml2xmltest.c @@ -266,7 +266,7 @@ mymain(void) DO_TEST("cpu-host-kvmclock", NONE); DO_TEST("cpu-host-passthrough-features", NONE); DO_TEST("cpu-host-model-features", NONE); - DO_TEST("clock-catchup", NONE); + DO_TEST("clock-catchup", QEMU_CAPS_KVM_PIT_TICK_POLICY); DO_TEST("kvmclock", NONE); DO_TEST("clock-timer-hyperv-rtc", NONE);