[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

Re: [PATCH v2 1/4] x86/time: further improve TSC / CPU freq calibration accuracy


  • To: "xen-devel@xxxxxxxxxxxxxxxxxxxx" <xen-devel@xxxxxxxxxxxxxxxxxxxx>
  • From: Jan Beulich <jbeulich@xxxxxxxx>
  • Date: Tue, 8 Feb 2022 14:49:07 +0100
  • Arc-authentication-results: i=1; mx.microsoft.com 1; spf=none; dmarc=none; dkim=none; arc=none
  • Arc-message-signature: i=1; a=rsa-sha256; c=relaxed/relaxed; d=microsoft.com; s=arcselector9901; h=From:Date:Subject:Message-ID:Content-Type:MIME-Version:X-MS-Exchange-AntiSpam-MessageData-ChunkCount:X-MS-Exchange-AntiSpam-MessageData-0:X-MS-Exchange-AntiSpam-MessageData-1; bh=K0zDDN4nzaJQe8tSrcHGASi0/1j2RHCcWB5fzveZ5EM=; b=me8Y5jwlmzp8k03QldeMYISU3Jh14cTVqy1mPPnxjsoPQ7Hi9ej23UBg3PTJ1QKuIQ646W4/Q2AjyLu+Z+coZhkC4Ym3Estme7+d6Zg7SHXCKzOdOreOqyRkqri52FflqJi/db3VbvdFrK+tgyGDZHuKyZT8nhQ1wMifgl67SVoVQIpYcnTOFAN/oO0nqGIKAYy0cIPmeOedqf4NY5dpaKD6pY+h5Z0LQjt2gen6FOTlT2rJzoWelWRDGWmlmJgJZTHb/ioYTXKGDb4VmRiAS3C0vXICESWRgq17qJOu+2NCc4z292Sy9tlPo5Em3kCulfvEHgkyByl9OsXojDKbFg==
  • Arc-seal: i=1; a=rsa-sha256; s=arcselector9901; d=microsoft.com; cv=none; b=KvUt8YKoqCIOdamB0M04b3ncShmfpxhps4zPF92XOMG5x3QKJWso6txoG6+ellu9m9eaxDWBF2NFWoxm1/jkv2VwSCxgfCCIkBSaxqJmi49P777dCBXPKgAzMuosrjUbHR+46SxLZ1Po32lywpanrTL8aXtcyOQzhh8smoKIcrUfL90cf8xEt0ZW+xoGNMRbOyWB6Rf/hMks4nZYwI3/wa6pYRZ0BSbwoa4atyhWThhKOE02xeUe4B6Wgi30Qoa4v1pVXsqlLN2ZJ9WUvp3ZKK8uWNIEkYI7qIIKm/GzH8w/SthtfB++1xRw/ooUVFzdUVYSHkLISG+wSuWGq8AfrQ==
  • Authentication-results: dkim=none (message not signed) header.d=none;dmarc=none action=none header.from=suse.com;
  • Cc: Andrew Cooper <andrew.cooper3@xxxxxxxxxx>, Wei Liu <wl@xxxxxxx>, Roger Pau Monné <roger.pau@xxxxxxxxxx>
  • Delivery-date: Tue, 08 Feb 2022 13:49:22 +0000
  • List-id: Xen developer discussion <xen-devel.lists.xenproject.org>

On 24.01.2022 09:25, Jan Beulich wrote:
> --- a/xen/arch/x86/time.c
> +++ b/xen/arch/x86/time.c
> @@ -287,9 +287,47 @@ static char *freq_string(u64 freq)
>      return s;
>  }
>  
> -static uint64_t adjust_elapsed(uint64_t elapsed, uint32_t actual,
> -                               uint32_t target)
> +static uint32_t __init read_pt_and_tsc(uint64_t *tsc,
> +                                       const struct platform_timesource *pts)
>  {
> +    uint64_t tsc_prev = *tsc = rdtsc_ordered(), tsc_min = ~0;
> +    uint32_t best = best;
> +    unsigned int i;
> +
> +    for ( i = 0; ; ++i )
> +    {
> +        uint32_t pt = pts->read_counter();
> +        uint64_t tsc_cur = rdtsc_ordered();
> +        uint64_t tsc_delta = tsc_cur - tsc_prev;
> +
> +        if ( tsc_delta < tsc_min )
> +        {
> +            tsc_min = tsc_delta;
> +            *tsc = tsc_cur;
> +            best = pt;
> +        }
> +        else if ( i > 2 )
> +            break;
> +
> +        tsc_prev = tsc_cur;
> +    }
> +
> +    return best;
> +}
> +
> +static uint64_t __init calibrate_tsc(const struct platform_timesource *pts)
> +{
> +    uint64_t start, end, elapsed;
> +    uint32_t count = read_pt_and_tsc(&start, pts);
> +    uint32_t target = CALIBRATE_VALUE(pts->frequency), actual;
> +    uint32_t mask = (uint32_t)~0 >> (32 - pts->counter_bits);
> +
> +    while ( ((pts->read_counter() - count) & mask) < target )
> +        continue;
> +
> +    actual = read_pt_and_tsc(&end, pts) - count;

Having run into a case where the resulting CPU freq was 141 kHz (and
boot failing slightly later because of this), I've spotted that this
also needs masking by "mask", to guard against a 24-bit PM timer
wrapping between the earlier read and this one. The original code ...

> @@ -508,22 +539,12 @@ static u64 read_pmtimer_count(void)
>  
>  static s64 __init init_pmtimer(struct platform_timesource *pts)
>  {
> -    uint64_t start;
> -    uint32_t count, target, mask, elapsed;
> -
>      if ( !pmtmr_ioport || (pmtmr_width != 24 && pmtmr_width != 32) )
>          return 0;
>  
>      pts->counter_bits = pmtmr_width;
> -    mask = 0xffffffff >> (32 - pmtmr_width);
> -
> -    count = inl(pmtmr_ioport);
> -    start = rdtsc_ordered();
> -    target = CALIBRATE_VALUE(ACPI_PM_FREQUENCY);
> -    while ( (elapsed = (inl(pmtmr_ioport) - count) & mask) < target )
> -        continue;

... ended up requiring use of "mask" just once.

Jan

> -    return adjust_elapsed(rdtsc_ordered() - start, elapsed, target);
> +    return calibrate_tsc(pts);
>  }
>  
>  static struct platform_timesource __initdata plt_pmtimer =
> 
> 




 


Rackspace

Lists.xenproject.org is hosted with RackSpace, monitoring our
servers 24x7x365 and backed by RackSpace's Fanatical Support®.