From: Feng Tang feng.tang@intel.com
hulk inclusion category: bugfix bugzilla: 187942, https://gitee.com/openeuler/kernel/issues/I5U037 CVE: NA
-------------------------------
Commit b50db7095fe0 ("x86/tsc: Disable clocksource watchdog for TSC on qualified platorms") was introduced to solve problem that sometimes TSC clocksource is wrongly judged as unstable by watchdog like 'jiffies', HPET, etc.
In it, the hardware socket number is a key factor for judging whether to disable the watchdog for TSC, and 'nr_online_nodes' was chosen as an estimation due to it is needed in early boot phase before registering 'tsc-early' clocksource, where all none-boot CPUs are not brought up yet.
In recent patch review, Dave Hansen pointed out there are many cases that 'nr_online_nodes' could have issue, like: * numa emulation (numa=fake=4 etc.) * numa=off * platforms with CPU+DRAM nodes, CPU-less HBM nodes, CPU-less persistent memory nodes.
Peter Zijlstra suggested to use logical package ids, but it is only usable after smp_init() and all CPUs are initialized.
One solution is to skip the watchdog for 'tsc-early' clocksource, and move the check after smp_init(), while before 'tsc' clocksoure is registered, where topology_max_packages() could be used as a much more accurate socket number.
Signed-off-by: Feng Tang feng.tang@intel.com
Conflict: arch/x86/kernel/tsc.c Signed-off-by: Yu Liao liaoyu15@huawei.com Reviewed-by: Xiongfeng Wang wangxiongfeng2@huawei.com Signed-off-by: Yongqiang Liu liuyongqiang13@huawei.com --- arch/x86/kernel/tsc.c | 20 +++++++++++++++----- 1 file changed, 15 insertions(+), 5 deletions(-)
diff --git a/arch/x86/kernel/tsc.c b/arch/x86/kernel/tsc.c index b1ae78bdba50..a7f447c30089 100644 --- a/arch/x86/kernel/tsc.c +++ b/arch/x86/kernel/tsc.c @@ -1095,8 +1095,7 @@ static struct clocksource clocksource_tsc_early = { .rating = 299, .read = read_tsc, .mask = CLOCKSOURCE_MASK(64), - .flags = CLOCK_SOURCE_IS_CONTINUOUS | - CLOCK_SOURCE_MUST_VERIFY, + .flags = CLOCK_SOURCE_IS_CONTINUOUS, .archdata = { .vclock_mode = VCLOCK_TSC }, .resume = tsc_resume, .mark_unstable = tsc_cs_mark_unstable, @@ -1353,6 +1352,20 @@ static int __init init_tsc_clocksource(void) if (boot_cpu_has(X86_FEATURE_NONSTOP_TSC_S3)) clocksource_tsc.flags |= CLOCK_SOURCE_SUSPEND_NONSTOP;
+ /* + * Disable the clocksource watchdog when the system has: + * - TSC running at constant frequency + * - TSC which does not stop in C-States + * - the TSC_ADJUST register which allows to detect even minimal + * modifications + * - not more than four sockets. + */ + if (boot_cpu_has(X86_FEATURE_CONSTANT_TSC) && + boot_cpu_has(X86_FEATURE_NONSTOP_TSC) && + boot_cpu_has(X86_FEATURE_TSC_ADJUST) && + topology_max_packages() <= 4) + clocksource_tsc.flags &= ~CLOCK_SOURCE_MUST_VERIFY; + /* * When TSC frequency is known (retrieved via MSR or CPUID), we skip * the refined calibration and directly register it as a clocksource. @@ -1483,9 +1496,6 @@ void __init tsc_init(void) return; }
- if (tsc_clocksource_reliable) - clocksource_tsc_early.flags &= ~CLOCK_SOURCE_MUST_VERIFY; - clocksource_register_khz(&clocksource_tsc_early, tsc_khz); detect_art(); }