Skip to content

Commit

Permalink
clocksource: sanity check sysfs clocksource changes
Browse files Browse the repository at this point in the history
Thomas, Andrew and Ingo pointed out that we don't have any safety checks
in the clocksource sysfs entries to make sure sysadmins don't try to
change the clocksource to a non high-res timer capable clocksource (such
as jiffies) when high-res timers (HRT) is enabled.  Doing so will likely
hang a system.

Correct this by filtering non HRT clocksources from available_clocksources
and not accepting non HRT clocksources with HRT enabled.

Signed-off-by: John Stultz <johnstul@us.ibm.com>
Signed-off-by: Andrew Morton <akpm@linux-foundation.org>
Signed-off-by: Thomas Gleixner <tglx@linutronix.de>
  • Loading branch information
john stultz authored and Thomas Gleixner committed Jun 11, 2009
1 parent 7d27558 commit 3f68535
Show file tree
Hide file tree
Showing 3 changed files with 20 additions and 4 deletions.
2 changes: 1 addition & 1 deletion include/linux/hrtimer.h
Original file line number Diff line number Diff line change
Expand Up @@ -305,7 +305,7 @@ static inline int hrtimer_is_hres_active(struct hrtimer *timer)

extern ktime_t ktime_get(void);
extern ktime_t ktime_get_real(void);

extern int hrtimer_hres_active(void);

DECLARE_PER_CPU(struct tick_device, tick_cpu_device);

Expand Down
4 changes: 2 additions & 2 deletions kernel/hrtimer.c
Original file line number Diff line number Diff line change
Expand Up @@ -476,7 +476,7 @@ static inline int hrtimer_is_hres_enabled(void)
/*
* Is the high resolution mode active ?
*/
static inline int hrtimer_hres_active(void)
int hrtimer_hres_active(void)
{
return __get_cpu_var(hrtimer_bases).hres_active;
}
Expand Down Expand Up @@ -704,7 +704,7 @@ static int hrtimer_switch_to_hres(void)

#else

static inline int hrtimer_hres_active(void) { return 0; }
int hrtimer_hres_active(void) { return 0; }
static inline int hrtimer_is_hres_enabled(void) { return 0; }
static inline int hrtimer_switch_to_hres(void) { return 0; }
static inline void hrtimer_force_reprogram(struct hrtimer_cpu_base *base) { }
Expand Down
18 changes: 17 additions & 1 deletion kernel/time/clocksource.c
Original file line number Diff line number Diff line change
Expand Up @@ -30,6 +30,7 @@
#include <linux/module.h>
#include <linux/sched.h> /* for spin_unlock_irq() using preempt_count() m68k */
#include <linux/tick.h>
#include <linux/hrtimer.h>

void timecounter_init(struct timecounter *tc,
const struct cyclecounter *cc,
Expand Down Expand Up @@ -509,6 +510,18 @@ static ssize_t sysfs_override_clocksource(struct sys_device *dev,
}
}

/*
* Check to make sure we don't switch to a non-HRT usable
* clocksource if HRT is enabled and running
*/
if (hrtimer_hres_active() &&
!(ovr->flags & CLOCK_SOURCE_VALID_FOR_HRES)) {
printk(KERN_WARNING "%s clocksource is not HRT compatible. "
"Cannot switch while in HRT mode\n", ovr->name);
ovr = NULL;
override_name[0] = 0;
}

/* Reselect, when the override name has changed */
if (ovr != clocksource_override) {
clocksource_override = ovr;
Expand Down Expand Up @@ -537,7 +550,10 @@ sysfs_show_available_clocksources(struct sys_device *dev,

spin_lock_irq(&clocksource_lock);
list_for_each_entry(src, &clocksource_list, list) {
count += snprintf(buf + count,
/* Don't show non-HRES clocksource if HRES is enabled */
if (!hrtimer_hres_active() ||
(src->flags & CLOCK_SOURCE_VALID_FOR_HRES))
count += snprintf(buf + count,
max((ssize_t)PAGE_SIZE - count, (ssize_t)0),
"%s ", src->name);
}
Expand Down

0 comments on commit 3f68535

Please sign in to comment.