From fd2ccd79ab8bd58ac8d0624f4459fffbca192a5a Mon Sep 17 00:00:00 2001 From: Jan Beulich Date: Tue, 19 May 2026 13:35:57 +0200 Subject: [PATCH] x86/time: make do_settime() uses more accurate MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit As a comment next to one of the invocations states, get_wallclock_time() can take over a second. The order of evaluation of function arguments is in principle unspecified; in practice at least gcc looks to be evaluating them from last to first. Hence with NOW() invoked first, the respective value passed to do_settime() can be off by over a second (which is in contrast to __get_cmos_time() attempting to get the time exactly after an update, i.e. [pretty] precisely at a seconds boundary). This also addresses a Misra C:2012 rule 13.2 ("The value of an expression and its persistent side-effects shall be the same under all permitted evaluation orders") violation each. The violations aren't flagged because the entire file is (bogusly) excluded from scanning. Fixes: f64134cdb81c ("x86: Fix time_resume() to notify all domains of wallclock change") Fixes: 0bfcf984b727 ("x86: Reintroduce clocksource=tsc") Signed-off-by: Jan Beulich Acked-by: Roger Pau Monné master commit: 54ca0aadc8219b19199703038205cd01c2611995 master date: 2026-05-07 16:10:52 +0200 --- xen/arch/x86/time.c | 10 ++++++++-- 1 file changed, 8 insertions(+), 2 deletions(-) diff --git a/xen/arch/x86/time.c b/xen/arch/x86/time.c index 5680d299e7..503c43499a 100644 --- a/xen/arch/x86/time.c +++ b/xen/arch/x86/time.c @@ -2567,6 +2567,8 @@ __initcall(verify_tsc_reliability); /* Late init function (after interrupts are enabled). */ int __init init_xen_time(void) { + unsigned long wc; + tsc_check_writability(); open_softirq(TIME_CALIBRATE_SOFTIRQ, local_time_calibration); @@ -2584,7 +2586,8 @@ int __init init_xen_time(void) printk(XENLOG_INFO "Wallclock source: %s\n", wallclock_type_to_string()); /* NB. get_wallclock_time() can take over one second to execute. */ - do_settime(get_wallclock_time(), 0, NOW()); + wc = get_wallclock_time(); + do_settime(wc, 0, NOW()); /* Finish platform timer initialization. */ try_platform_timer_tail(); @@ -2737,6 +2740,8 @@ int time_suspend(void) int time_resume(void) { + unsigned long wc; + preinit_pit(); resume_platform_timer(); @@ -2748,7 +2753,8 @@ int time_resume(void) set_timer(&calibration_timer, NOW() + EPOCH); - do_settime(get_wallclock_time() + cmos_utc_offset, 0, NOW()); + wc = get_wallclock_time(); + do_settime(wc + cmos_utc_offset, 0, NOW()); update_vcpu_system_time(current);