summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorThomas Gleixner <tglx@kernel.org>2026-01-24 02:17:55 +0300
committerThomas Gleixner <tglx@kernel.org>2026-03-12 14:23:27 +0300
commit79ccb0693a99e1b91eba95c6bd32a3e02be156ae (patch)
tree9974def962b3ce2663e0a67089b5a1b3cb7f9f87
parentced7072a3ad65698f0ad378c8f8566379fe50723 (diff)
downloadlinux-79ccb0693a99e1b91eba95c6bd32a3e02be156ae.tar.xz
x86/tsc: Handle CLOCK_SOURCE_VALID_FOR_HRES correctly
Unconditionally setting the CLOCK_SOURCE_VALID_FOR_HRES for the real TSC clocksource is wrong as there is no guarantee that the early TSC was validated for high resolution mode. Set the flag only when the early TSC was validated as otherwise the clocksource selection might enable high resolution mode with a TSC of unknown quality and possibly no way to back out once it is discovered to be unsuitable. Signed-off-by: Thomas Gleixner <tglx@kernel.org> Link: https://patch.msgid.link/20260123231521.790598171@kernel.org
-rw-r--r--arch/x86/kernel/tsc.c10
1 files changed, 9 insertions, 1 deletions
diff --git a/arch/x86/kernel/tsc.c b/arch/x86/kernel/tsc.c
index f31046f98a92..9ccd58c29409 100644
--- a/arch/x86/kernel/tsc.c
+++ b/arch/x86/kernel/tsc.c
@@ -1200,7 +1200,6 @@ static struct clocksource clocksource_tsc = {
.read = read_tsc,
.mask = CLOCKSOURCE_MASK(64),
.flags = CLOCK_SOURCE_IS_CONTINUOUS |
- CLOCK_SOURCE_VALID_FOR_HRES |
CLOCK_SOURCE_CAN_INLINE_READ |
CLOCK_SOURCE_MUST_VERIFY |
CLOCK_SOURCE_VERIFY_PERCPU |
@@ -1411,6 +1410,15 @@ out:
have_art = true;
clocksource_tsc.base = &art_base_clk;
}
+
+ /*
+ * Transfer the valid for high resolution flag if it was set on the
+ * early TSC already. That guarantees that there is no intermediate
+ * clocksource selected once the early TSC is unregistered.
+ */
+ if (clocksource_tsc_early.flags & CLOCK_SOURCE_VALID_FOR_HRES)
+ clocksource_tsc.flags |= CLOCK_SOURCE_VALID_FOR_HRES;
+
clocksource_register_khz(&clocksource_tsc, tsc_khz);
unreg:
clocksource_unregister(&clocksource_tsc_early);