Donate to e Foundation | Murena handsets with /e/OS | Own a part of Murena! Learn more

Commit acb04058 authored by Peter Zijlstra's avatar Peter Zijlstra Committed by Ingo Molnar
Browse files

sched/clock: Fix hotplug crash



Mike reported that he could trigger the WARN_ON_ONCE() in
set_sched_clock_stable() using hotplug.

This exposed a fundamental problem with the interface, we should never
mark the TSC stable if we ever find it to be unstable. Therefore
set_sched_clock_stable() is a broken interface.

The reason it existed is that not having it is a pain, it means all
relevant architecture code needs to call clear_sched_clock_stable()
where appropriate.

Of the three architectures that select HAVE_UNSTABLE_SCHED_CLOCK ia64
and parisc are trivial in that they never called
set_sched_clock_stable(), so add an unconditional call to
clear_sched_clock_stable() to them.

For x86 the story is a lot more involved, and what this patch tries to
do is ensure we preserve the status quo. So even is Cyrix or Transmeta
have usable TSC they never called set_sched_clock_stable() so they now
get an explicit mark unstable.

Reported-by: default avatarMike Galbraith <efault@gmx.de>
Signed-off-by: default avatarPeter Zijlstra (Intel) <peterz@infradead.org>
Cc: Borislav Petkov <bp@alien8.de>
Cc: Linus Torvalds <torvalds@linux-foundation.org>
Cc: Peter Zijlstra <peterz@infradead.org>
Cc: Thomas Gleixner <tglx@linutronix.de>
Fixes: 9881b024 ("sched/clock: Delay switching sched_clock to stable")
Link: http://lkml.kernel.org/r/20170119133633.GB6536@twins.programming.kicks-ass.net


Signed-off-by: default avatarIngo Molnar <mingo@kernel.org>
parent 02cfdc95
Loading
Loading
Loading
Loading
+2 −0
Original line number Diff line number Diff line
@@ -619,6 +619,8 @@ setup_arch (char **cmdline_p)
	check_sal_cache_flush();
#endif
	paging_init();

	clear_sched_clock_stable();
}

/*
+2 −0
Original line number Diff line number Diff line
@@ -36,6 +36,7 @@
#undef PCI_DEBUG
#include <linux/proc_fs.h>
#include <linux/export.h>
#include <linux/sched.h>

#include <asm/processor.h>
#include <asm/sections.h>
@@ -176,6 +177,7 @@ void __init setup_arch(char **cmdline_p)
	conswitchp = &dummy_con;	/* we use do_take_over_console() later ! */
#endif

	clear_sched_clock_stable();
}

/*
+4 −2
Original line number Diff line number Diff line
@@ -548,8 +548,10 @@ static void early_init_amd(struct cpuinfo_x86 *c)
	if (c->x86_power & (1 << 8)) {
		set_cpu_cap(c, X86_FEATURE_CONSTANT_TSC);
		set_cpu_cap(c, X86_FEATURE_NONSTOP_TSC);
		if (!check_tsc_unstable())
			set_sched_clock_stable();
		if (check_tsc_unstable())
			clear_sched_clock_stable();
	} else {
		clear_sched_clock_stable();
	}

	/* Bit 12 of 8000_0007 edx is accumulated power mechanism. */
+4 −2
Original line number Diff line number Diff line
#include <linux/bitops.h>
#include <linux/kernel.h>

#include <linux/sched.h>

#include <asm/cpufeature.h>
#include <asm/e820.h>
@@ -104,6 +104,8 @@ static void early_init_centaur(struct cpuinfo_x86 *c)
#ifdef CONFIG_X86_64
	set_cpu_cap(c, X86_FEATURE_SYSENTER32);
#endif

	clear_sched_clock_stable();
}

static void init_centaur(struct cpuinfo_x86 *c)
+3 −0
Original line number Diff line number Diff line
@@ -83,6 +83,7 @@ static void default_init(struct cpuinfo_x86 *c)
			strcpy(c->x86_model_id, "386");
	}
#endif
	clear_sched_clock_stable();
}

static const struct cpu_dev default_cpu = {
@@ -1055,6 +1056,8 @@ static void identify_cpu(struct cpuinfo_x86 *c)
	 */
	if (this_cpu->c_init)
		this_cpu->c_init(c);
	else
		clear_sched_clock_stable();

	/* Disable the PN if appropriate */
	squash_the_stupid_serial_number(c);
Loading