[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