[libvirt PATCH] qemu: Do not require TSC frequency to strictly match host
Daniel Henrique Barboza
danielhb413 at gmail.com
Wed Nov 11 23:10:39 UTC 2020
On 11/11/20 9:09 AM, Jiri Denemark wrote:
> Some CPUs provide a way to read exact TSC frequency, while measuring it
> is required on other CPUs. However, measuring is never exact and the
> result may slightly differ across reboots. For this reason both Linux
> kernel and QEMU recently started allowing for guests TSC frequency to
> fall into +/- 250 ppm tolerance interval around the host TSC frequency.
>
> Let's do the same to avoid unnecessary failures (esp. during migration)
> in case the host frequency does not exactly match the frequency
> configured in a domain XML.
>
> https://bugzilla.redhat.com/show_bug.cgi?id=1839095
>
> Signed-off-by: Jiri Denemark <jdenemar at redhat.com>
> ---
Reviewed-by: Daniel Henrique Barboza <danielhb413 at gmail.com>
> src/qemu/qemu_process.c | 35 ++++++++++++++++++++++++++---------
> 1 file changed, 26 insertions(+), 9 deletions(-)
>
> diff --git a/src/qemu/qemu_process.c b/src/qemu/qemu_process.c
> index 0a36b49c85..7f56ddf114 100644
> --- a/src/qemu/qemu_process.c
> +++ b/src/qemu/qemu_process.c
> @@ -5358,12 +5358,18 @@ qemuProcessStartValidateDisks(virDomainObjPtr vm,
> }
>
>
> +/* 250 parts per million (ppm) is a half of NTP threshold */
> +#define TSC_TOLERANCE 250
> +
> static int
> qemuProcessStartValidateTSC(virQEMUDriverPtr driver,
> virDomainObjPtr vm)
> {
> size_t i;
> unsigned long long freq = 0;
> + unsigned long long tolerance;
> + unsigned long long minFreq;
> + unsigned long long maxFreq;
> virHostCPUTscInfoPtr tsc;
> g_autoptr(virCPUDef) cpu = NULL;
>
> @@ -5389,23 +5395,34 @@ qemuProcessStartValidateTSC(virQEMUDriverPtr driver,
> }
>
> tsc = cpu->tsc;
> - VIR_DEBUG("Host TSC frequency %llu Hz, scaling %s",
> - tsc->frequency, virTristateBoolTypeToString(tsc->scaling));
> + tolerance = tsc->frequency * TSC_TOLERANCE / 1000000;
> + minFreq = tsc->frequency - tolerance;
> + maxFreq = tsc->frequency + tolerance;
> +
> + VIR_DEBUG("Host TSC frequency %llu Hz, scaling %s, tolerance +/- %llu Hz",
> + tsc->frequency, virTristateBoolTypeToString(tsc->scaling),
> + tolerance);
> +
> + if (freq > minFreq && freq < maxFreq) {
> + VIR_DEBUG("Requested TSC frequency is within tolerance interval");
> + return 0;
> + }
>
> - if (freq == tsc->frequency || tsc->scaling == VIR_TRISTATE_BOOL_YES)
> + if (tsc->scaling == VIR_TRISTATE_BOOL_YES)
> return 0;
>
> if (tsc->scaling == VIR_TRISTATE_BOOL_ABSENT) {
> - VIR_DEBUG("TSC frequencies do not match and scaling support is "
> - "unknown, QEMU will try and possibly fail later");
> + VIR_DEBUG("Requested TSC frequency falls outside tolerance range and "
> + "scaling support is unknown, QEMU will try and possibly "
> + "fail later");
> return 0;
> }
>
> virReportError(VIR_ERR_CONFIG_UNSUPPORTED,
> - _("Requested TSC frequency %llu Hz does not match "
> - "host (%llu Hz) and TSC scaling is not supported "
> - "by the host CPU"),
> - freq, tsc->frequency);
> + _("Requested TSC frequency %llu Hz is outside tolerance "
> + "range ([%llu, %llu] Hz) around host frequency %llu Hz "
> + "and TSC scaling is not supported by the host CPU"),
> + freq, minFreq, maxFreq, tsc->frequency);
> return -1;
> }
>
>
More information about the libvir-list
mailing list