Skip to content

Commit

Permalink
clocksource: Always verify highres capability
Browse files Browse the repository at this point in the history
If a clocksource has a (wrong) high rating, but can't be used as a
timebase for oneshot tick mode, it is unconditionally selected even
when the system is already in oneshot tick mode. This causes full
system failure.

Verify the clocksource selection against the oneshot mode.

Signed-off-by: Thomas Gleixner <tglx@linutronix.de>
Acked-by: John Stultz <john.stultz@linaro.org>
Cc: Magnus Damm <magnus.damm@gmail.com>
Link: http://lkml.kernel.org/r/20130425143435.635040849@linutronix.de
Signed-off-by: Thomas Gleixner <tglx@linutronix.de>
  • Loading branch information
Thomas Gleixner committed May 16, 2013
1 parent fc1f7d5 commit 5d33b88
Showing 1 changed file with 26 additions and 5 deletions.
31 changes: 26 additions & 5 deletions kernel/time/clocksource.c
Original file line number Diff line number Diff line change
Expand Up @@ -553,6 +553,26 @@ static u64 clocksource_max_deferment(struct clocksource *cs)

#ifndef CONFIG_ARCH_USES_GETTIMEOFFSET

static struct clocksource *clocksource_find_best(bool oneshot)
{
struct clocksource *cs;

if (!finished_booting || list_empty(&clocksource_list))
return NULL;

/*
* We pick the clocksource with the highest rating. If oneshot
* mode is active, we pick the highres valid clocksource with
* the best rating.
*/
list_for_each_entry(cs, &clocksource_list, list) {
if (oneshot && !(cs->flags & CLOCK_SOURCE_VALID_FOR_HRES))
continue;
return cs;
}
return NULL;
}

/**
* clocksource_select - Select the best clocksource available
*
Expand All @@ -563,12 +583,14 @@ static u64 clocksource_max_deferment(struct clocksource *cs)
*/
static void clocksource_select(void)
{
bool oneshot = tick_oneshot_mode_active();
struct clocksource *best, *cs;

if (!finished_booting || list_empty(&clocksource_list))
/* Find the best suitable clocksource */
best = clocksource_find_best(oneshot);
if (!best)
return;
/* First clocksource on the list has the best rating. */
best = list_first_entry(&clocksource_list, struct clocksource, list);

/* Check for the override clocksource. */
list_for_each_entry(cs, &clocksource_list, list) {
if (strcmp(cs->name, override_name) != 0)
Expand All @@ -578,8 +600,7 @@ static void clocksource_select(void)
* capable clocksource if the tick code is in oneshot
* mode (highres or nohz)
*/
if (!(cs->flags & CLOCK_SOURCE_VALID_FOR_HRES) &&
tick_oneshot_mode_active()) {
if (!(cs->flags & CLOCK_SOURCE_VALID_FOR_HRES) && oneshot) {
/* Override clocksource cannot be used. */
printk(KERN_WARNING "Override clocksource %s is not "
"HRT compatible. Cannot switch while in "
Expand Down

0 comments on commit 5d33b88

Please sign in to comment.