Skip to content

Commit cf7a63e

Browse files
Pavel TatashinKAGA-KOKO
authored andcommitted
x86/tsc: Calibrate tsc only once
During boot tsc is calibrated twice: once in tsc_early_delay_calibrate(), and the second time in tsc_init(). Rename tsc_early_delay_calibrate() to tsc_early_init(), and rework it so the calibration is done only early, and make tsc_init() to use the values already determined in tsc_early_init(). Sometimes it is not possible to determine tsc early, as the subsystem that is required is not yet initialized, in such case try again later in tsc_init(). Suggested-by: Thomas Gleixner <tglx@linutronix.de> Signed-off-by: Pavel Tatashin <pasha.tatashin@oracle.com> Signed-off-by: Thomas Gleixner <tglx@linutronix.de> Cc: steven.sistare@oracle.com Cc: daniel.m.jordan@oracle.com Cc: linux@armlinux.org.uk Cc: schwidefsky@de.ibm.com Cc: heiko.carstens@de.ibm.com Cc: john.stultz@linaro.org Cc: sboyd@codeaurora.org Cc: hpa@zytor.com Cc: douly.fnst@cn.fujitsu.com Cc: peterz@infradead.org Cc: prarit@redhat.com Cc: feng.tang@intel.com Cc: pmladek@suse.com Cc: gnomes@lxorguk.ukuu.org.uk Cc: linux-s390@vger.kernel.org Cc: boris.ostrovsky@oracle.com Cc: jgross@suse.com Cc: pbonzini@redhat.com Link: https://lkml.kernel.org/r/20180719205545.16512-20-pasha.tatashin@oracle.com
1 parent 227e395 commit cf7a63e

File tree

3 files changed

+49
-42
lines changed

3 files changed

+49
-42
lines changed

arch/x86/include/asm/tsc.h

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -33,7 +33,7 @@ static inline cycles_t get_cycles(void)
3333
extern struct system_counterval_t convert_art_to_tsc(u64 art);
3434
extern struct system_counterval_t convert_art_ns_to_tsc(u64 art_ns);
3535

36-
extern void tsc_early_delay_calibrate(void);
36+
extern void tsc_early_init(void);
3737
extern void tsc_init(void);
3838
extern void mark_tsc_unstable(char *reason);
3939
extern int unsynchronized_tsc(void);

arch/x86/kernel/setup.c

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1014,6 +1014,7 @@ void __init setup_arch(char **cmdline_p)
10141014
*/
10151015
init_hypervisor_platform();
10161016

1017+
tsc_early_init();
10171018
x86_init.resources.probe_roms();
10181019

10191020
/* after parse_early_param, so could debug it */
@@ -1199,7 +1200,6 @@ void __init setup_arch(char **cmdline_p)
11991200

12001201
memblock_find_dma_reserve();
12011202

1202-
tsc_early_delay_calibrate();
12031203
if (!early_xdbc_setup_hardware())
12041204
early_xdbc_register_console();
12051205

arch/x86/kernel/tsc.c

Lines changed: 47 additions & 40 deletions
Original file line numberDiff line numberDiff line change
@@ -33,6 +33,8 @@ EXPORT_SYMBOL(cpu_khz);
3333
unsigned int __read_mostly tsc_khz;
3434
EXPORT_SYMBOL(tsc_khz);
3535

36+
#define KHZ 1000
37+
3638
/*
3739
* TSC can be unstable due to cpufreq or due to unsynced TSCs
3840
*/
@@ -1335,34 +1337,10 @@ static int __init init_tsc_clocksource(void)
13351337
*/
13361338
device_initcall(init_tsc_clocksource);
13371339

1338-
void __init tsc_early_delay_calibrate(void)
1339-
{
1340-
unsigned long lpj;
1341-
1342-
if (!boot_cpu_has(X86_FEATURE_TSC))
1343-
return;
1344-
1345-
cpu_khz = x86_platform.calibrate_cpu();
1346-
tsc_khz = x86_platform.calibrate_tsc();
1347-
1348-
tsc_khz = tsc_khz ? : cpu_khz;
1349-
if (!tsc_khz)
1350-
return;
1351-
1352-
lpj = tsc_khz * 1000;
1353-
do_div(lpj, HZ);
1354-
loops_per_jiffy = lpj;
1355-
}
1356-
1357-
void __init tsc_init(void)
1340+
static bool __init determine_cpu_tsc_frequencies(void)
13581341
{
1359-
u64 lpj, cyc;
1360-
int cpu;
1361-
1362-
if (!boot_cpu_has(X86_FEATURE_TSC)) {
1363-
setup_clear_cpu_cap(X86_FEATURE_TSC_DEADLINE_TIMER);
1364-
return;
1365-
}
1342+
/* Make sure that cpu and tsc are not already calibrated */
1343+
WARN_ON(cpu_khz || tsc_khz);
13661344

13671345
cpu_khz = x86_platform.calibrate_cpu();
13681346
tsc_khz = x86_platform.calibrate_tsc();
@@ -1377,20 +1355,52 @@ void __init tsc_init(void)
13771355
else if (abs(cpu_khz - tsc_khz) * 10 > tsc_khz)
13781356
cpu_khz = tsc_khz;
13791357

1380-
if (!tsc_khz) {
1381-
mark_tsc_unstable("could not calculate TSC khz");
1382-
setup_clear_cpu_cap(X86_FEATURE_TSC_DEADLINE_TIMER);
1383-
return;
1384-
}
1358+
if (tsc_khz == 0)
1359+
return false;
13851360

13861361
pr_info("Detected %lu.%03lu MHz processor\n",
1387-
(unsigned long)cpu_khz / 1000,
1388-
(unsigned long)cpu_khz % 1000);
1362+
(unsigned long)cpu_khz / KHZ,
1363+
(unsigned long)cpu_khz % KHZ);
13891364

13901365
if (cpu_khz != tsc_khz) {
13911366
pr_info("Detected %lu.%03lu MHz TSC",
1392-
(unsigned long)tsc_khz / 1000,
1393-
(unsigned long)tsc_khz % 1000);
1367+
(unsigned long)tsc_khz / KHZ,
1368+
(unsigned long)tsc_khz % KHZ);
1369+
}
1370+
return true;
1371+
}
1372+
1373+
static unsigned long __init get_loops_per_jiffy(void)
1374+
{
1375+
unsigned long lpj = tsc_khz * KHZ;
1376+
1377+
do_div(lpj, HZ);
1378+
return lpj;
1379+
}
1380+
1381+
void __init tsc_early_init(void)
1382+
{
1383+
if (!boot_cpu_has(X86_FEATURE_TSC))
1384+
return;
1385+
if (!determine_cpu_tsc_frequencies())
1386+
return;
1387+
loops_per_jiffy = get_loops_per_jiffy();
1388+
}
1389+
1390+
void __init tsc_init(void)
1391+
{
1392+
if (!boot_cpu_has(X86_FEATURE_TSC)) {
1393+
setup_clear_cpu_cap(X86_FEATURE_TSC_DEADLINE_TIMER);
1394+
return;
1395+
}
1396+
1397+
if (!tsc_khz) {
1398+
/* We failed to determine frequencies earlier, try again */
1399+
if (!determine_cpu_tsc_frequencies()) {
1400+
mark_tsc_unstable("could not calculate TSC khz");
1401+
setup_clear_cpu_cap(X86_FEATURE_TSC_DEADLINE_TIMER);
1402+
return;
1403+
}
13941404
}
13951405

13961406
/* Sanitize TSC ADJUST before cyc2ns gets initialized */
@@ -1413,10 +1423,7 @@ void __init tsc_init(void)
14131423
if (!no_sched_irq_time)
14141424
enable_sched_clock_irqtime();
14151425

1416-
lpj = ((u64)tsc_khz * 1000);
1417-
do_div(lpj, HZ);
1418-
lpj_fine = lpj;
1419-
1426+
lpj_fine = get_loops_per_jiffy();
14201427
use_tsc_delay();
14211428

14221429
check_system_tsc_reliable();

0 commit comments

Comments
 (0)