Sign Up
Log In
Log In
or
Sign Up
Places
All Projects
Status Monitor
Collapse sidebar
openSUSE:Leap:15.4
xen
61e029c8-x86-time-TSC-freq-calibration-accuracy...
Overview
Repositories
Revisions
Requests
Users
Attributes
Meta
File 61e029c8-x86-time-TSC-freq-calibration-accuracy.patch of Package xen
# Commit a5c9a80af34eefcd6e31d0ed2b083f452cd9076d # Date 2022-01-13 14:31:52 +0100 # Author Jan Beulich <jbeulich@suse.com> # Committer Jan Beulich <jbeulich@suse.com> x86/time: improve TSC / CPU freq calibration accuracy While the problem report was for extreme errors, even smaller ones would better be avoided: The calculated period to run calibration loops over can (and usually will) be shorter than the actual time elapsed between first and last platform timer and TSC reads. Adjust values returned from the init functions accordingly. On a Skylake system I've tested this on accuracy (using HPET) went from detecting in some cases more than 220kHz too high a value to about ±2kHz. On other systems (or on this system, but with PMTMR) the original error range was much smaller, with less (in some cases only very little) improvement. Reported-by: James Dingwall <james-xen@dingwall.me.uk> Signed-off-by: Jan Beulich <jbeulich@suse.com> Reviewed-by: Roger Pau Monné <roger.pau@citrix.com> --- a/xen/arch/x86/time.c +++ b/xen/arch/x86/time.c @@ -287,6 +287,23 @@ static char *freq_string(u64 freq) return s; } +static uint64_t adjust_elapsed(uint64_t elapsed, uint32_t actual, + uint32_t target) +{ + if ( likely(actual > target) ) + { + /* + * A (perhaps significant) delay before the last timer read (e.g. due + * to a SMI or NMI) can lead to (perhaps severe) inaccuracy if not + * accounting for the time elapsed beyond the originally calculated + * duration of the calibration interval. + */ + elapsed = muldiv64(elapsed, target, actual); + } + + return elapsed * CALIBRATE_FRAC; +} + /************************************************************ * PLATFORM TIMER 1: PROGRAMMABLE INTERVAL TIMER (LEGACY PIT) */ @@ -455,7 +472,7 @@ static int64_t __init init_hpet(struct p while ( (elapsed = hpet_read32(HPET_COUNTER) - count) < target ) continue; - return (rdtsc_ordered() - start) * CALIBRATE_FRAC; + return adjust_elapsed(rdtsc_ordered() - start, elapsed, target); } static void resume_hpet(struct platform_timesource *pts) @@ -505,7 +522,7 @@ static s64 __init init_pmtimer(struct pl while ( (elapsed = (inl(pmtmr_ioport) - count) & mask) < target ) continue; - return (rdtsc_ordered() - start) * CALIBRATE_FRAC; + return adjust_elapsed(rdtsc_ordered() - start, elapsed, target); } static struct platform_timesource __initdata plt_pmtimer =
Locations
Projects
Search
Status Monitor
Help
OpenBuildService.org
Documentation
API Documentation
Code of Conduct
Contact
Support
@OBShq
Terms
openSUSE Build Service is sponsored by
The Open Build Service is an
openSUSE project
.
Sign Up
Log In
Places
Places
All Projects
Status Monitor