]> git.ipfire.org Git - thirdparty/linux.git/commitdiff
clocksource: Fix the CPUs' choice in the watchdog per CPU verification
authorGuilherme G. Piccoli <gpiccoli@igalia.com>
Sun, 23 Mar 2025 17:36:24 +0000 (14:36 -0300)
committerThomas Gleixner <tglx@linutronix.de>
Tue, 13 May 2025 13:38:55 +0000 (15:38 +0200)
Right now, if the clocksource watchdog detects a clocksource skew, it might
perform a per CPU check, for example in the TSC case on x86.  In other
words: supposing TSC is detected as unstable by the clocksource watchdog
running at CPU1, as part of marking TSC unstable the kernel will also run a
check of TSC readings on some CPUs to be sure it is synced between them
all.

But that check happens only on some CPUs, not all of them; this choice is
based on the parameter "verify_n_cpus" and in some random cpumask
calculation. So, the watchdog runs such per CPU checks on up to
"verify_n_cpus" random CPUs among all online CPUs, with the risk of
repeating CPUs (that aren't double checked) in the cpumask random
calculation.

But if "verify_n_cpus" > num_online_cpus(), it should skip the random
calculation and just go ahead and check the clocksource sync between
all online CPUs, without the risk of skipping some CPUs due to
duplicity in the random cpumask calculation.

Tests in a 4 CPU laptop with TSC skew detected led to some cases of the per
CPU verification skipping some CPU even with verify_n_cpus=8, due to the
duplicity on random cpumask generation. Skipping the randomization when the
number of online CPUs is smaller than verify_n_cpus, solves that.

Suggested-by: Thadeu Lima de Souza Cascardo <cascardo@igalia.com>
Signed-off-by: Guilherme G. Piccoli <gpiccoli@igalia.com>
Signed-off-by: Thomas Gleixner <tglx@linutronix.de>
Reviewed-by: Paul E. McKenney <paulmck@kernel.org>
Link: https://lore.kernel.org/all/20250323173857.372390-1-gpiccoli@igalia.com
kernel/time/clocksource.c

index bb48498ebb5a804f6a77a30ac11e3ef8e0f69fd1..6a8bc7da906263319fc73ea55a220144feb79636 100644 (file)
@@ -310,7 +310,7 @@ static void clocksource_verify_choose_cpus(void)
 {
        int cpu, i, n = verify_n_cpus;
 
-       if (n < 0) {
+       if (n < 0 || n >= num_online_cpus()) {
                /* Check all of the CPUs. */
                cpumask_copy(&cpus_chosen, cpu_online_mask);
                cpumask_clear_cpu(smp_processor_id(), &cpus_chosen);