Since the timers are defined to cover all possible config cases for several different hypervisors, many of these possibilities generate an error on qemu. Here is what is currently supported: RTC: If the -rtc commandline option is available, allow setting "clock=host" or "clock=vm" based on the rtc timer clock='host|guest' value. Also add "driftfix=slew" if the tickpolicy is 'catchup', or add nothing if tickpolicy is 'delay'. (Other tickpolicies will raise an error). If -rtc isn't available, but -rtc-td-hack is, add that option if the tickpolicy is 'catchup', add -rtc-td-hack, if it is 'delay' add nothing, and if it's anything else, raise an error. PIT: If -no-kvm-pit-reinjection is available, and tickpolicy is 'delay', add that option. if tickpolicy is 'catchup', do nothing. Anything else --> raise an error. If -no-kvm-pit-reinjection *isn't* available, but -tdf is, when tickpolicy is 'catchup' add -tdf. If it's 'delay', do nothing. Anything else --> raise an error. If neither of those commandline options is available, and tickpolicy is anything other than 'delay' (or unspecified), raise an error. HPET: If -no-hpet flag is available and present='no', add -no-hpet. If -no-hpet is not available, and present='yes', raise an error. If present is unspecified, the default is to do whatever this particular qemu does by default, so don't raise an error. All other timer types are unsupported by QEMU, so they will raise an error. --- src/qemu/qemu_conf.c | 129 ++++++++++++++++++++++++++++++++++++++++++++++++++ 1 files changed, 129 insertions(+), 0 deletions(-) diff --git a/src/qemu/qemu_conf.c b/src/qemu/qemu_conf.c index e9197db..ad0468d 100644 --- a/src/qemu/qemu_conf.c +++ b/src/qemu/qemu_conf.c @@ -3149,6 +3149,36 @@ qemuBuildClockArgStr(virDomainClockDefPtr def) goto error; } + /* Look for an 'rtc' timer element, and add in appropriate clock= and driftfix= */ + int i; + for (i = 0; i < def->ntimers; i++) { + if (def->timers[i]->name == VIR_DOMAIN_TIMER_NAME_RTC) { + if (def->timers[i]->wallclock == VIR_DOMAIN_TIMER_WALLCLOCK_HOST) { + virBufferAddLit(&buf, ",clock=host"); + } else if (def->timers[i]->wallclock == VIR_DOMAIN_TIMER_WALLCLOCK_GUEST) { + virBufferAddLit(&buf, ",clock=vm"); + } + switch (def->timers[i]->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 */ + virBufferAddLit(&buf, ",driftfix=slew"); + break; + case VIR_DOMAIN_TIMER_TICKPOLICY_MERGE: + case VIR_DOMAIN_TIMER_TICKPOLICY_DISCARD: + qemuReportError(VIR_ERR_CONFIG_UNSUPPORTED, + _("unsupported rtc timer tickpolicy '%s'"), + virDomainTimerTickpolicyTypeToString(def->timers[i]->tickpolicy)); + goto error; + } + break; /* no need to check other timers - there is only one rtc */ + } + } + if (virBufferError(&buf)) { virReportOOMError(); goto error; @@ -3622,6 +3652,105 @@ int qemudBuildCommandLine(virConnectPtr conn, ADD_ENV_PAIR("TZ", def->clock.data.timezone); } + for (i = 0; i < def->clock.ntimers; i++) { + switch (def->clock.timers[i]->name) { + default: + case VIR_DOMAIN_TIMER_NAME_PLATFORM: + case VIR_DOMAIN_TIMER_NAME_TSC: + qemuReportError(VIR_ERR_CONFIG_UNSUPPORTED, + _("unsupported timer type (name) '%s'"), + virDomainTimerNameTypeToString(def->clock.timers[i]->name)); + goto error; + + case VIR_DOMAIN_TIMER_NAME_RTC: + /* This has already been taken care of (in qemuBuildClockArgStr) + if QEMUD_CMD_FLAG_RTC is set (mutually exclusive with + QEMUD_FLAG_RTC_TD_HACK) */ + if (qemuCmdFlags & QEMUD_CMD_FLAG_RTC_TD_HACK) { + switch (def->clock.timers[i]->tickpolicy) { + case -1: + case VIR_DOMAIN_TIMER_TICKPOLICY_DELAY: + /* the default - do nothing */ + break; + case VIR_DOMAIN_TIMER_TICKPOLICY_CATCHUP: + ADD_ARG_LIT("-rtc-td-hack"); + break; + case VIR_DOMAIN_TIMER_TICKPOLICY_MERGE: + case VIR_DOMAIN_TIMER_TICKPOLICY_DISCARD: + qemuReportError(VIR_ERR_CONFIG_UNSUPPORTED, + _("unsupported rtc tickpolicy '%s'"), + virDomainTimerTickpolicyTypeToString(def->clock.timers[i]->tickpolicy)); + goto error; + } + } else if (!(qemuCmdFlags & QEMUD_CMD_FLAG_RTC) + && (def->clock.timers[i]->tickpolicy + != VIR_DOMAIN_TIMER_TICKPOLICY_DELAY) + && (def->clock.timers[i]->tickpolicy != -1)) { + /* a non-default rtc policy was given, but there is no + way to implement it in this version of qemu */ + qemuReportError(VIR_ERR_CONFIG_UNSUPPORTED, + _("unsupported rtc tickpolicy '%s'"), + virDomainTimerTickpolicyTypeToString(def->clock.timers[i]->tickpolicy)); + goto error; + } + break; + + case VIR_DOMAIN_TIMER_NAME_PIT: + switch (def->clock.timers[i]->tickpolicy) { + case -1: + case VIR_DOMAIN_TIMER_TICKPOLICY_DELAY: + /* delay is the default if we don't have kernel + (-no-kvm-pit), otherwise, the default is catchup. */ + if (qemuCmdFlags & QEMUD_CMD_FLAG_NO_KVM_PIT) + ADD_ARG_LIT("-no-kvm-pit-reinjection"); + break; + case VIR_DOMAIN_TIMER_TICKPOLICY_CATCHUP: + if (qemuCmdFlags & QEMUD_CMD_FLAG_NO_KVM_PIT) { + /* do nothing - this is default for kvm-pit */ + } else if (qemuCmdFlags & QEMUD_CMD_FLAG_TDF) { + /* -tdf switches to 'catchup' with userspace pit. */ + ADD_ARG_LIT("-tdf"); + } else { + /* can't catchup if we have neither pit mode */ + qemuReportError(VIR_ERR_CONFIG_UNSUPPORTED, + _("unsupported pit tickpolicy '%s'"), + virDomainTimerTickpolicyTypeToString(def->clock.timers[i]->tickpolicy)); + goto error; + } + break; + case VIR_DOMAIN_TIMER_TICKPOLICY_MERGE: + case VIR_DOMAIN_TIMER_TICKPOLICY_DISCARD: + /* no way to support these modes for pit in qemu */ + qemuReportError(VIR_ERR_CONFIG_UNSUPPORTED, + _("unsupported pit tickpolicy '%s'"), + virDomainTimerTickpolicyTypeToString(def->clock.timers[i]->tickpolicy)); + goto error; + } + break; + + case VIR_DOMAIN_TIMER_NAME_HPET: + /* the only meaningful attribute for hpet is "present". If + * present is -1, that means it wasn't specified, and + * should be left at the default for the + * hypervisor. "default" when -no-hpet exists is "yes", + * and when -no-hpet doesn't exist is "no". "confusing"? + * "yes"! */ + + if (qemuCmdFlags & QEMUD_CMD_FLAG_NO_HPET) { + if (def->clock.timers[i]->present == 0) + ADD_ARG_LIT("-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) { + qemuReportError(VIR_ERR_CONFIG_UNSUPPORTED, + "%s", _("pit timer is not supported")); + } + } + break; + } + } + if ((qemuCmdFlags & QEMUD_CMD_FLAG_NO_REBOOT) && def->onReboot != VIR_DOMAIN_LIFECYCLE_RESTART) ADD_ARG_LIT("-no-reboot"); -- 1.6.6.1 -- libvir-list mailing list libvir-list@xxxxxxxxxx https://www.redhat.com/mailman/listinfo/libvir-list