Skip to content

Commit 9d349d4

Browse files
KAGA-KOKOPeter Zijlstra
authored andcommitted
x86/smpboot: Make TSC synchronization function call based
Spin-waiting on the control CPU until the AP reaches the TSC synchronization is just a waste especially in the case that there is no synchronization required. As the synchronization has to run with interrupts disabled the control CPU part can just be done from a SMP function call. The upcoming AP issues that call async only in the case that synchronization is required. Signed-off-by: Thomas Gleixner <[email protected]> Signed-off-by: Peter Zijlstra (Intel) <[email protected]> Tested-by: Michael Kelley <[email protected]> Tested-by: Oleksandr Natalenko <[email protected]> Tested-by: Helge Deller <[email protected]> # parisc Tested-by: Guilherme G. Piccoli <[email protected]> # Steam Deck Link: https://lore.kernel.org/r/[email protected]
1 parent d4f28f0 commit 9d349d4

File tree

3 files changed

+14
-44
lines changed

3 files changed

+14
-44
lines changed

arch/x86/include/asm/tsc.h

Lines changed: 0 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -55,12 +55,10 @@ extern bool tsc_async_resets;
5555
#ifdef CONFIG_X86_TSC
5656
extern bool tsc_store_and_check_tsc_adjust(bool bootcpu);
5757
extern void tsc_verify_tsc_adjust(bool resume);
58-
extern void check_tsc_sync_source(int cpu);
5958
extern void check_tsc_sync_target(void);
6059
#else
6160
static inline bool tsc_store_and_check_tsc_adjust(bool bootcpu) { return false; }
6261
static inline void tsc_verify_tsc_adjust(bool resume) { }
63-
static inline void check_tsc_sync_source(int cpu) { }
6462
static inline void check_tsc_sync_target(void) { }
6563
#endif
6664

arch/x86/kernel/smpboot.c

Lines changed: 3 additions & 17 deletions
Original file line numberDiff line numberDiff line change
@@ -275,11 +275,7 @@ static void notrace start_secondary(void *unused)
275275
*/
276276
smp_callin();
277277

278-
/*
279-
* Check TSC synchronization with the control CPU, which will do
280-
* its part of this from wait_cpu_online(), making it an implicit
281-
* synchronization point.
282-
*/
278+
/* Check TSC synchronization with the control CPU. */
283279
check_tsc_sync_target();
284280

285281
/*
@@ -1141,21 +1137,11 @@ static void wait_cpu_callin(unsigned int cpu)
11411137
}
11421138

11431139
/*
1144-
* Bringup step four: Synchronize the TSC and wait for the target AP
1145-
* to reach set_cpu_online() in start_secondary().
1140+
* Bringup step four: Wait for the target AP to reach set_cpu_online() in
1141+
* start_secondary().
11461142
*/
11471143
static void wait_cpu_online(unsigned int cpu)
11481144
{
1149-
unsigned long flags;
1150-
1151-
/*
1152-
* Check TSC synchronization with the AP (keep irqs disabled
1153-
* while doing so):
1154-
*/
1155-
local_irq_save(flags);
1156-
check_tsc_sync_source(cpu);
1157-
local_irq_restore(flags);
1158-
11591145
/*
11601146
* Wait for the AP to mark itself online, so the core caller
11611147
* can drop sparse_irq_lock.

arch/x86/kernel/tsc_sync.c

Lines changed: 11 additions & 25 deletions
Original file line numberDiff line numberDiff line change
@@ -245,7 +245,6 @@ bool tsc_store_and_check_tsc_adjust(bool bootcpu)
245245
*/
246246
static atomic_t start_count;
247247
static atomic_t stop_count;
248-
static atomic_t skip_test;
249248
static atomic_t test_runs;
250249

251250
/*
@@ -344,20 +343,13 @@ static inline unsigned int loop_timeout(int cpu)
344343
}
345344

346345
/*
347-
* Source CPU calls into this - it waits for the freshly booted
348-
* target CPU to arrive and then starts the measurement:
346+
* The freshly booted CPU initiates this via an async SMP function call.
349347
*/
350-
void check_tsc_sync_source(int cpu)
348+
static void check_tsc_sync_source(void *__cpu)
351349
{
350+
unsigned int cpu = (unsigned long)__cpu;
352351
int cpus = 2;
353352

354-
/*
355-
* No need to check if we already know that the TSC is not
356-
* synchronized or if we have no TSC.
357-
*/
358-
if (unsynchronized_tsc())
359-
return;
360-
361353
/*
362354
* Set the maximum number of test runs to
363355
* 1 if the CPU does not provide the TSC_ADJUST MSR
@@ -368,16 +360,9 @@ void check_tsc_sync_source(int cpu)
368360
else
369361
atomic_set(&test_runs, 3);
370362
retry:
371-
/*
372-
* Wait for the target to start or to skip the test:
373-
*/
374-
while (atomic_read(&start_count) != cpus - 1) {
375-
if (atomic_read(&skip_test) > 0) {
376-
atomic_set(&skip_test, 0);
377-
return;
378-
}
363+
/* Wait for the target to start. */
364+
while (atomic_read(&start_count) != cpus - 1)
379365
cpu_relax();
380-
}
381366

382367
/*
383368
* Trigger the target to continue into the measurement too:
@@ -397,14 +382,14 @@ void check_tsc_sync_source(int cpu)
397382
if (!nr_warps) {
398383
atomic_set(&test_runs, 0);
399384

400-
pr_debug("TSC synchronization [CPU#%d -> CPU#%d]: passed\n",
385+
pr_debug("TSC synchronization [CPU#%d -> CPU#%u]: passed\n",
401386
smp_processor_id(), cpu);
402387

403388
} else if (atomic_dec_and_test(&test_runs) || random_warps) {
404389
/* Force it to 0 if random warps brought us here */
405390
atomic_set(&test_runs, 0);
406391

407-
pr_warn("TSC synchronization [CPU#%d -> CPU#%d]:\n",
392+
pr_warn("TSC synchronization [CPU#%d -> CPU#%u]:\n",
408393
smp_processor_id(), cpu);
409394
pr_warn("Measured %Ld cycles TSC warp between CPUs, "
410395
"turning off TSC clock.\n", max_warp);
@@ -457,11 +442,12 @@ void check_tsc_sync_target(void)
457442
* SoCs the TSC is frequency synchronized, but still the TSC ADJUST
458443
* register might have been wreckaged by the BIOS..
459444
*/
460-
if (tsc_store_and_check_tsc_adjust(false) || tsc_clocksource_reliable) {
461-
atomic_inc(&skip_test);
445+
if (tsc_store_and_check_tsc_adjust(false) || tsc_clocksource_reliable)
462446
return;
463-
}
464447

448+
/* Kick the control CPU into the TSC synchronization function */
449+
smp_call_function_single(cpumask_first(cpu_online_mask), check_tsc_sync_source,
450+
(unsigned long *)(unsigned long)cpu, 0);
465451
retry:
466452
/*
467453
* Register this CPU's participation and wait for the

0 commit comments

Comments
 (0)