Re: [PATCH v6 1/4] sched/clock: interface to allow timestamps early in boot

From: Peter Zijlstra
Date: Wed Sep 27 2017 - 09:10:40 EST


On Wed, Sep 27, 2017 at 02:58:57PM +0200, Peter Zijlstra wrote:
> (we're violating "notsc" in any case and really should kill that
> option).

Something like so; in particular simple_udelay_calibrate() will issue
RDTSC _way_ early, so there is absolutely no point in then pretending we
can't use RDTSC for sched_clock.

---

diff --git a/arch/x86/kernel/tsc.c b/arch/x86/kernel/tsc.c
index 796d96bb0821..1dd3849a42ca 100644
--- a/arch/x86/kernel/tsc.c
+++ b/arch/x86/kernel/tsc.c
@@ -37,13 +37,6 @@ EXPORT_SYMBOL(tsc_khz);
*/
static int __read_mostly tsc_unstable;

-/* native_sched_clock() is called before tsc_init(), so
- we must start with the TSC soft disabled to prevent
- erroneous rdtsc usage on !boot_cpu_has(X86_FEATURE_TSC) processors */
-static int __read_mostly tsc_disabled = -1;
-
-static DEFINE_STATIC_KEY_FALSE(__use_tsc);
-
int tsc_clocksource_reliable;

static u32 art_to_tsc_numerator;
@@ -191,24 +184,7 @@ static void set_cyc2ns_scale(unsigned long khz, int cpu, unsigned long long tsc_
*/
u64 native_sched_clock(void)
{
- if (static_branch_likely(&__use_tsc)) {
- u64 tsc_now = rdtsc();
-
- /* return the value in ns */
- return cycles_2_ns(tsc_now);
- }
-
- /*
- * Fall back to jiffies if there's no TSC available:
- * ( But note that we still use it if the TSC is marked
- * unstable. We do this because unlike Time Of Day,
- * the scheduler clock tolerates small errors and it's
- * very important for it to be as fast as the platform
- * can achieve it. )
- */
-
- /* No locking but a rare wrong value is not a big deal: */
- return (jiffies_64 - INITIAL_JIFFIES) * (1000000000 / HZ);
+ return cycles_2_ns(rdtsc());
}

/*
@@ -244,27 +220,6 @@ int check_tsc_unstable(void)
}
EXPORT_SYMBOL_GPL(check_tsc_unstable);

-#ifdef CONFIG_X86_TSC
-int __init notsc_setup(char *str)
-{
- pr_warn("Kernel compiled with CONFIG_X86_TSC, cannot disable TSC completely\n");
- tsc_disabled = 1;
- return 1;
-}
-#else
-/*
- * disable flag for tsc. Takes effect by clearing the TSC cpu flag
- * in cpu/common.c
- */
-int __init notsc_setup(char *str)
-{
- setup_clear_cpu_cap(X86_FEATURE_TSC);
- return 1;
-}
-#endif
-
-__setup("notsc", notsc_setup);
-
static int no_sched_irq_time;

static int __init tsc_setup(char *str)
@@ -1229,7 +1184,7 @@ static void tsc_refine_calibration_work(struct work_struct *work)

static int __init init_tsc_clocksource(void)
{
- if (!boot_cpu_has(X86_FEATURE_TSC) || tsc_disabled > 0 || !tsc_khz)
+ if (!boot_cpu_has(X86_FEATURE_TSC) || !tsc_khz)
return 0;

if (tsc_clocksource_reliable)
@@ -1311,14 +1266,6 @@ void __init tsc_init(void)
set_cyc2ns_scale(tsc_khz, cpu, cyc);
}

- if (tsc_disabled > 0)
- return;
-
- /* now allow native_sched_clock() to use rdtsc */
-
- tsc_disabled = 0;
- static_branch_enable(&__use_tsc);
-
if (!no_sched_irq_time)
enable_sched_clock_irqtime();

@@ -1348,7 +1295,7 @@ unsigned long calibrate_delay_is_known(void)
int sibling, cpu = smp_processor_id();
struct cpumask *mask = topology_core_cpumask(cpu);

- if (!tsc_disabled && !cpu_has(&cpu_data(cpu), X86_FEATURE_CONSTANT_TSC))
+ if (!cpu_has(&cpu_data(cpu), X86_FEATURE_CONSTANT_TSC))
return 0;

if (!mask)