Commit 5d51bee7 authored by Thomas Gleixner's avatar Thomas Gleixner

clocksource: Add common vdso clock mode storage

All architectures which use the generic VDSO code have their own storage
for the VDSO clock mode. That's pointless and just requires duplicate code.

Provide generic storage for it. The new Kconfig symbol is intermediate and
will be removed once all architectures are converted over.
Signed-off-by: default avatarThomas Gleixner <tglx@linutronix.de>
Tested-by: default avatarVincenzo Frascino <vincenzo.frascino@arm.com>
Reviewed-by: default avatarVincenzo Frascino <vincenzo.frascino@arm.com>
Link: https://lkml.kernel.org/r/20200207124403.028046322@linutronix.de
parent eec399dd
...@@ -23,10 +23,19 @@ ...@@ -23,10 +23,19 @@
struct clocksource; struct clocksource;
struct module; struct module;
#ifdef CONFIG_ARCH_CLOCKSOURCE_DATA #if defined(CONFIG_ARCH_CLOCKSOURCE_DATA) || \
defined(CONFIG_GENERIC_VDSO_CLOCK_MODE)
#include <asm/clocksource.h> #include <asm/clocksource.h>
#endif #endif
enum vdso_clock_mode {
VDSO_CLOCKMODE_NONE,
#ifdef CONFIG_GENERIC_VDSO_CLOCK_MODE
VDSO_ARCH_CLOCKMODES,
#endif
VDSO_CLOCKMODE_MAX,
};
/** /**
* struct clocksource - hardware abstraction for a free running counter * struct clocksource - hardware abstraction for a free running counter
* Provides mostly state-free accessors to the underlying hardware. * Provides mostly state-free accessors to the underlying hardware.
...@@ -97,6 +106,7 @@ struct clocksource { ...@@ -97,6 +106,7 @@ struct clocksource {
const char *name; const char *name;
struct list_head list; struct list_head list;
int rating; int rating;
enum vdso_clock_mode vdso_clock_mode;
unsigned long flags; unsigned long flags;
int (*enable)(struct clocksource *cs); int (*enable)(struct clocksource *cs);
......
...@@ -928,6 +928,15 @@ int __clocksource_register_scale(struct clocksource *cs, u32 scale, u32 freq) ...@@ -928,6 +928,15 @@ int __clocksource_register_scale(struct clocksource *cs, u32 scale, u32 freq)
clocksource_arch_init(cs); clocksource_arch_init(cs);
#ifdef CONFIG_GENERIC_VDSO_CLOCK_MODE
if (cs->vdso_clock_mode < 0 ||
cs->vdso_clock_mode >= VDSO_CLOCKMODE_MAX) {
pr_warn("clocksource %s registered with invalid VDSO mode %d. Disabling VDSO support.\n",
cs->name, cs->vdso_clock_mode);
cs->vdso_clock_mode = VDSO_CLOCKMODE_NONE;
}
#endif
/* Initialize mult/shift and max_idle_ns */ /* Initialize mult/shift and max_idle_ns */
__clocksource_update_freq_scale(cs, scale, freq); __clocksource_update_freq_scale(cs, scale, freq);
......
...@@ -71,13 +71,19 @@ void update_vsyscall(struct timekeeper *tk) ...@@ -71,13 +71,19 @@ void update_vsyscall(struct timekeeper *tk)
{ {
struct vdso_data *vdata = __arch_get_k_vdso_data(); struct vdso_data *vdata = __arch_get_k_vdso_data();
struct vdso_timestamp *vdso_ts; struct vdso_timestamp *vdso_ts;
s32 clock_mode;
u64 nsec; u64 nsec;
/* copy vsyscall data */ /* copy vsyscall data */
vdso_write_begin(vdata); vdso_write_begin(vdata);
vdata[CS_HRES_COARSE].clock_mode = __arch_get_clock_mode(tk); #ifdef CONFIG_GENERIC_VDSO_CLOCK_MODE
vdata[CS_RAW].clock_mode = __arch_get_clock_mode(tk); clock_mode = tk->tkr_mono.clock->vdso_clock_mode;
#else
clock_mode = __arch_get_clock_mode(tk);
#endif
vdata[CS_HRES_COARSE].clock_mode = clock_mode;
vdata[CS_RAW].clock_mode = clock_mode;
/* CLOCK_REALTIME also required for time() */ /* CLOCK_REALTIME also required for time() */
vdso_ts = &vdata[CS_HRES_COARSE].basetime[CLOCK_REALTIME]; vdso_ts = &vdata[CS_HRES_COARSE].basetime[CLOCK_REALTIME];
......
...@@ -30,4 +30,7 @@ config GENERIC_VDSO_TIME_NS ...@@ -30,4 +30,7 @@ config GENERIC_VDSO_TIME_NS
Selected by architectures which support time namespaces in the Selected by architectures which support time namespaces in the
VDSO VDSO
config GENERIC_VDSO_CLOCK_MODE
bool
endif endif
...@@ -7,6 +7,7 @@ ...@@ -7,6 +7,7 @@
#include <linux/time.h> #include <linux/time.h>
#include <linux/kernel.h> #include <linux/kernel.h>
#include <linux/hrtimer_defs.h> #include <linux/hrtimer_defs.h>
#include <linux/clocksource.h>
#include <vdso/datapage.h> #include <vdso/datapage.h>
#include <vdso/helpers.h> #include <vdso/helpers.h>
...@@ -64,10 +65,14 @@ static int do_hres_timens(const struct vdso_data *vdns, clockid_t clk, ...@@ -64,10 +65,14 @@ static int do_hres_timens(const struct vdso_data *vdns, clockid_t clk,
do { do {
seq = vdso_read_begin(vd); seq = vdso_read_begin(vd);
if (IS_ENABLED(CONFIG_GENERIC_VDSO_CLOCK_MODE) &&
vd->clock_mode == VDSO_CLOCKMODE_NONE)
return -1;
cycles = __arch_get_hw_counter(vd->clock_mode); cycles = __arch_get_hw_counter(vd->clock_mode);
ns = vdso_ts->nsec; ns = vdso_ts->nsec;
last = vd->cycle_last; last = vd->cycle_last;
if (unlikely((s64)cycles < 0)) if (!IS_ENABLED(CONFIG_GENERIC_VDSO_CLOCK_MODE) &&
unlikely((s64)cycles < 0))
return -1; return -1;
ns += vdso_calc_delta(cycles, last, vd->mask, vd->mult); ns += vdso_calc_delta(cycles, last, vd->mask, vd->mult);
...@@ -132,10 +137,14 @@ static __always_inline int do_hres(const struct vdso_data *vd, clockid_t clk, ...@@ -132,10 +137,14 @@ static __always_inline int do_hres(const struct vdso_data *vd, clockid_t clk,
} }
smp_rmb(); smp_rmb();
if (IS_ENABLED(CONFIG_GENERIC_VDSO_CLOCK_MODE) &&
vd->clock_mode == VDSO_CLOCKMODE_NONE)
return -1;
cycles = __arch_get_hw_counter(vd->clock_mode); cycles = __arch_get_hw_counter(vd->clock_mode);
ns = vdso_ts->nsec; ns = vdso_ts->nsec;
last = vd->cycle_last; last = vd->cycle_last;
if (unlikely((s64)cycles < 0)) if (!IS_ENABLED(CONFIG_GENERIC_VDSO_CLOCK_MODE) &&
unlikely((s64)cycles < 0))
return -1; return -1;
ns += vdso_calc_delta(cycles, last, vd->mask, vd->mult); ns += vdso_calc_delta(cycles, last, vd->mask, vd->mult);
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment