-
Notifications
You must be signed in to change notification settings - Fork 0
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
timekeeping: Provide a generic update_vsyscall() implementation
The new generic VDSO library allows to unify the update_vsyscall[_tz]() implementations. Provide a generic implementation based on the x86 code and the bindings which need to be implemented in architecture specific code. [ tglx: Moved it into kernel/time where it belongs. Removed the pointless line breaks in the stub functions. Massaged changelog ] Signed-off-by: Vincenzo Frascino <vincenzo.frascino@arm.com> Signed-off-by: Thomas Gleixner <tglx@linutronix.de> Tested-by: Shijith Thotton <sthotton@marvell.com> Tested-by: Andre Przywara <andre.przywara@arm.com> Cc: linux-arch@vger.kernel.org Cc: linux-arm-kernel@lists.infradead.org Cc: linux-mips@vger.kernel.org Cc: linux-kselftest@vger.kernel.org Cc: Catalin Marinas <catalin.marinas@arm.com> Cc: Will Deacon <will.deacon@arm.com> Cc: Arnd Bergmann <arnd@arndb.de> Cc: Russell King <linux@armlinux.org.uk> Cc: Ralf Baechle <ralf@linux-mips.org> Cc: Paul Burton <paul.burton@mips.com> Cc: Daniel Lezcano <daniel.lezcano@linaro.org> Cc: Mark Salyzyn <salyzyn@android.com> Cc: Peter Collingbourne <pcc@google.com> Cc: Shuah Khan <shuah@kernel.org> Cc: Dmitry Safonov <0x7f454c46@gmail.com> Cc: Rasmus Villemoes <linux@rasmusvillemoes.dk> Cc: Huw Davies <huw@codeweavers.com> Link: https://lkml.kernel.org/r/20190621095252.32307-4-vincenzo.frascino@arm.com
- Loading branch information
Vincenzo Frascino
authored and
Thomas Gleixner
committed
Jun 22, 2019
1 parent
629fdf7
commit 44f57d7
Showing
4 changed files
with
195 additions
and
0 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,50 @@ | ||
/* SPDX-License-Identifier: GPL-2.0 */ | ||
#ifndef __ASM_GENERIC_VSYSCALL_H | ||
#define __ASM_GENERIC_VSYSCALL_H | ||
|
||
#ifndef __ASSEMBLY__ | ||
|
||
#ifndef __arch_get_k_vdso_data | ||
static __always_inline struct vdso_data *__arch_get_k_vdso_data(void) | ||
{ | ||
return NULL; | ||
} | ||
#endif /* __arch_get_k_vdso_data */ | ||
|
||
#ifndef __arch_update_vdso_data | ||
static __always_inline int __arch_update_vdso_data(void) | ||
{ | ||
return 0; | ||
} | ||
#endif /* __arch_update_vdso_data */ | ||
|
||
#ifndef __arch_get_clock_mode | ||
static __always_inline int __arch_get_clock_mode(struct timekeeper *tk) | ||
{ | ||
return 0; | ||
} | ||
#endif /* __arch_get_clock_mode */ | ||
|
||
#ifndef __arch_use_vsyscall | ||
static __always_inline int __arch_use_vsyscall(struct vdso_data *vdata) | ||
{ | ||
return 1; | ||
} | ||
#endif /* __arch_use_vsyscall */ | ||
|
||
#ifndef __arch_update_vsyscall | ||
static __always_inline void __arch_update_vsyscall(struct vdso_data *vdata, | ||
struct timekeeper *tk) | ||
{ | ||
} | ||
#endif /* __arch_update_vsyscall */ | ||
|
||
#ifndef __arch_sync_vdso_data | ||
static __always_inline void __arch_sync_vdso_data(struct vdso_data *vdata) | ||
{ | ||
} | ||
#endif /* __arch_sync_vdso_data */ | ||
|
||
#endif /* !__ASSEMBLY__ */ | ||
|
||
#endif /* __ASM_GENERIC_VSYSCALL_H */ |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,11 @@ | ||
/* SPDX-License-Identifier: GPL-2.0 */ | ||
#ifndef __VDSO_VSYSCALL_H | ||
#define __VDSO_VSYSCALL_H | ||
|
||
#ifndef __ASSEMBLY__ | ||
|
||
#include <asm/vdso/vsyscall.h> | ||
|
||
#endif /* !__ASSEMBLY__ */ | ||
|
||
#endif /* __VDSO_VSYSCALL_H */ |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,133 @@ | ||
// SPDX-License-Identifier: GPL-2.0 | ||
/* | ||
* Copyright 2019 ARM Ltd. | ||
* | ||
* Generic implementation of update_vsyscall and update_vsyscall_tz. | ||
* | ||
* Based on the x86 specific implementation. | ||
*/ | ||
|
||
#include <linux/hrtimer.h> | ||
#include <linux/timekeeper_internal.h> | ||
#include <vdso/datapage.h> | ||
#include <vdso/helpers.h> | ||
#include <vdso/vsyscall.h> | ||
|
||
static inline void update_vdso_data(struct vdso_data *vdata, | ||
struct timekeeper *tk) | ||
{ | ||
struct vdso_timestamp *vdso_ts; | ||
u64 nsec; | ||
|
||
vdata[CS_HRES_COARSE].cycle_last = tk->tkr_mono.cycle_last; | ||
vdata[CS_HRES_COARSE].mask = tk->tkr_mono.mask; | ||
vdata[CS_HRES_COARSE].mult = tk->tkr_mono.mult; | ||
vdata[CS_HRES_COARSE].shift = tk->tkr_mono.shift; | ||
vdata[CS_RAW].cycle_last = tk->tkr_raw.cycle_last; | ||
vdata[CS_RAW].mask = tk->tkr_raw.mask; | ||
vdata[CS_RAW].mult = tk->tkr_raw.mult; | ||
vdata[CS_RAW].shift = tk->tkr_raw.shift; | ||
|
||
/* CLOCK_REALTIME */ | ||
vdso_ts = &vdata[CS_HRES_COARSE].basetime[CLOCK_REALTIME]; | ||
vdso_ts->sec = tk->xtime_sec; | ||
vdso_ts->nsec = tk->tkr_mono.xtime_nsec; | ||
|
||
/* CLOCK_MONOTONIC */ | ||
vdso_ts = &vdata[CS_HRES_COARSE].basetime[CLOCK_MONOTONIC]; | ||
vdso_ts->sec = tk->xtime_sec + tk->wall_to_monotonic.tv_sec; | ||
|
||
nsec = tk->tkr_mono.xtime_nsec; | ||
nsec += ((u64)tk->wall_to_monotonic.tv_nsec << tk->tkr_mono.shift); | ||
while (nsec >= (((u64)NSEC_PER_SEC) << tk->tkr_mono.shift)) { | ||
nsec -= (((u64)NSEC_PER_SEC) << tk->tkr_mono.shift); | ||
vdso_ts->sec++; | ||
} | ||
vdso_ts->nsec = nsec; | ||
|
||
/* CLOCK_MONOTONIC_RAW */ | ||
vdso_ts = &vdata[CS_RAW].basetime[CLOCK_MONOTONIC_RAW]; | ||
vdso_ts->sec = tk->raw_sec; | ||
vdso_ts->nsec = tk->tkr_raw.xtime_nsec; | ||
|
||
/* CLOCK_BOOTTIME */ | ||
vdso_ts = &vdata[CS_HRES_COARSE].basetime[CLOCK_BOOTTIME]; | ||
vdso_ts->sec = tk->xtime_sec + tk->wall_to_monotonic.tv_sec; | ||
nsec = tk->tkr_mono.xtime_nsec; | ||
nsec += ((u64)(tk->wall_to_monotonic.tv_nsec + | ||
ktime_to_ns(tk->offs_boot)) << tk->tkr_mono.shift); | ||
while (nsec >= (((u64)NSEC_PER_SEC) << tk->tkr_mono.shift)) { | ||
nsec -= (((u64)NSEC_PER_SEC) << tk->tkr_mono.shift); | ||
vdso_ts->sec++; | ||
} | ||
vdso_ts->nsec = nsec; | ||
|
||
/* CLOCK_TAI */ | ||
vdso_ts = &vdata[CS_HRES_COARSE].basetime[CLOCK_TAI]; | ||
vdso_ts->sec = tk->xtime_sec + (s64)tk->tai_offset; | ||
vdso_ts->nsec = tk->tkr_mono.xtime_nsec; | ||
|
||
/* | ||
* Read without the seqlock held by clock_getres(). | ||
* Note: No need to have a second copy. | ||
*/ | ||
WRITE_ONCE(vdata[CS_HRES_COARSE].hrtimer_res, hrtimer_resolution); | ||
} | ||
|
||
void update_vsyscall(struct timekeeper *tk) | ||
{ | ||
struct vdso_data *vdata = __arch_get_k_vdso_data(); | ||
struct vdso_timestamp *vdso_ts; | ||
u64 nsec; | ||
|
||
if (__arch_update_vdso_data()) { | ||
/* | ||
* Some architectures might want to skip the update of the | ||
* data page. | ||
*/ | ||
return; | ||
} | ||
|
||
/* copy vsyscall data */ | ||
vdso_write_begin(vdata); | ||
|
||
vdata[CS_HRES_COARSE].clock_mode = __arch_get_clock_mode(tk); | ||
vdata[CS_RAW].clock_mode = __arch_get_clock_mode(tk); | ||
|
||
/* CLOCK_REALTIME_COARSE */ | ||
vdso_ts = &vdata[CS_HRES_COARSE].basetime[CLOCK_REALTIME_COARSE]; | ||
vdso_ts->sec = tk->xtime_sec; | ||
vdso_ts->nsec = tk->tkr_mono.xtime_nsec >> tk->tkr_mono.shift; | ||
|
||
/* CLOCK_MONOTONIC_COARSE */ | ||
vdso_ts = &vdata[CS_HRES_COARSE].basetime[CLOCK_MONOTONIC_COARSE]; | ||
vdso_ts->sec = tk->xtime_sec + tk->wall_to_monotonic.tv_sec; | ||
nsec = tk->tkr_mono.xtime_nsec >> tk->tkr_mono.shift; | ||
nsec = nsec + tk->wall_to_monotonic.tv_nsec; | ||
while (nsec >= NSEC_PER_SEC) { | ||
nsec = nsec - NSEC_PER_SEC; | ||
vdso_ts->sec++; | ||
} | ||
vdso_ts->nsec = nsec; | ||
|
||
if (__arch_use_vsyscall(vdata)) | ||
update_vdso_data(vdata, tk); | ||
|
||
__arch_update_vsyscall(vdata, tk); | ||
|
||
vdso_write_end(vdata); | ||
|
||
__arch_sync_vdso_data(vdata); | ||
} | ||
|
||
void update_vsyscall_tz(void) | ||
{ | ||
struct vdso_data *vdata = __arch_get_k_vdso_data(); | ||
|
||
if (__arch_use_vsyscall(vdata)) { | ||
vdata[CS_HRES_COARSE].tz_minuteswest = sys_tz.tz_minuteswest; | ||
vdata[CS_HRES_COARSE].tz_dsttime = sys_tz.tz_dsttime; | ||
} | ||
|
||
__arch_sync_vdso_data(vdata); | ||
} |