Linux Audio

Check our new training course

Loading...
Note: File does not exist in v3.15.
  1// SPDX-License-Identifier: GPL-2.0
  2/*
  3 * Copyright 2019 ARM Ltd.
  4 *
  5 * Generic implementation of update_vsyscall and update_vsyscall_tz.
  6 *
  7 * Based on the x86 specific implementation.
  8 */
  9
 10#include <linux/hrtimer.h>
 11#include <linux/timekeeper_internal.h>
 12#include <vdso/datapage.h>
 13#include <vdso/helpers.h>
 14#include <vdso/vsyscall.h>
 15
 16static inline void update_vdso_data(struct vdso_data *vdata,
 17				    struct timekeeper *tk)
 18{
 19	struct vdso_timestamp *vdso_ts;
 20	u64 nsec, sec;
 21
 22	vdata[CS_HRES_COARSE].cycle_last	= tk->tkr_mono.cycle_last;
 23	vdata[CS_HRES_COARSE].mask		= tk->tkr_mono.mask;
 24	vdata[CS_HRES_COARSE].mult		= tk->tkr_mono.mult;
 25	vdata[CS_HRES_COARSE].shift		= tk->tkr_mono.shift;
 26	vdata[CS_RAW].cycle_last		= tk->tkr_raw.cycle_last;
 27	vdata[CS_RAW].mask			= tk->tkr_raw.mask;
 28	vdata[CS_RAW].mult			= tk->tkr_raw.mult;
 29	vdata[CS_RAW].shift			= tk->tkr_raw.shift;
 30
 31	/* CLOCK_REALTIME */
 32	vdso_ts		= &vdata[CS_HRES_COARSE].basetime[CLOCK_REALTIME];
 33	vdso_ts->sec	= tk->xtime_sec;
 34	vdso_ts->nsec	= tk->tkr_mono.xtime_nsec;
 35
 36	/* CLOCK_MONOTONIC */
 37	vdso_ts		= &vdata[CS_HRES_COARSE].basetime[CLOCK_MONOTONIC];
 38	vdso_ts->sec	= tk->xtime_sec + tk->wall_to_monotonic.tv_sec;
 39
 40	nsec = tk->tkr_mono.xtime_nsec;
 41	nsec += ((u64)tk->wall_to_monotonic.tv_nsec << tk->tkr_mono.shift);
 42	while (nsec >= (((u64)NSEC_PER_SEC) << tk->tkr_mono.shift)) {
 43		nsec -= (((u64)NSEC_PER_SEC) << tk->tkr_mono.shift);
 44		vdso_ts->sec++;
 45	}
 46	vdso_ts->nsec	= nsec;
 47
 48	/* Copy MONOTONIC time for BOOTTIME */
 49	sec	= vdso_ts->sec;
 50	/* Add the boot offset */
 51	sec	+= tk->monotonic_to_boot.tv_sec;
 52	nsec	+= (u64)tk->monotonic_to_boot.tv_nsec << tk->tkr_mono.shift;
 53
 54	/* CLOCK_BOOTTIME */
 55	vdso_ts		= &vdata[CS_HRES_COARSE].basetime[CLOCK_BOOTTIME];
 56	vdso_ts->sec	= sec;
 57
 58	while (nsec >= (((u64)NSEC_PER_SEC) << tk->tkr_mono.shift)) {
 59		nsec -= (((u64)NSEC_PER_SEC) << tk->tkr_mono.shift);
 60		vdso_ts->sec++;
 61	}
 62	vdso_ts->nsec	= nsec;
 63
 64	/* CLOCK_MONOTONIC_RAW */
 65	vdso_ts		= &vdata[CS_RAW].basetime[CLOCK_MONOTONIC_RAW];
 66	vdso_ts->sec	= tk->raw_sec;
 67	vdso_ts->nsec	= tk->tkr_raw.xtime_nsec;
 68
 69	/* CLOCK_TAI */
 70	vdso_ts		= &vdata[CS_HRES_COARSE].basetime[CLOCK_TAI];
 71	vdso_ts->sec	= tk->xtime_sec + (s64)tk->tai_offset;
 72	vdso_ts->nsec	= tk->tkr_mono.xtime_nsec;
 73
 74	/*
 75	 * Read without the seqlock held by clock_getres().
 76	 * Note: No need to have a second copy.
 77	 */
 78	WRITE_ONCE(vdata[CS_HRES_COARSE].hrtimer_res, hrtimer_resolution);
 79}
 80
 81void update_vsyscall(struct timekeeper *tk)
 82{
 83	struct vdso_data *vdata = __arch_get_k_vdso_data();
 84	struct vdso_timestamp *vdso_ts;
 85	u64 nsec;
 86
 87	if (__arch_update_vdso_data()) {
 88		/*
 89		 * Some architectures might want to skip the update of the
 90		 * data page.
 91		 */
 92		return;
 93	}
 94
 95	/* copy vsyscall data */
 96	vdso_write_begin(vdata);
 97
 98	vdata[CS_HRES_COARSE].clock_mode	= __arch_get_clock_mode(tk);
 99	vdata[CS_RAW].clock_mode		= __arch_get_clock_mode(tk);
100
101	/* CLOCK_REALTIME_COARSE */
102	vdso_ts		= &vdata[CS_HRES_COARSE].basetime[CLOCK_REALTIME_COARSE];
103	vdso_ts->sec	= tk->xtime_sec;
104	vdso_ts->nsec	= tk->tkr_mono.xtime_nsec >> tk->tkr_mono.shift;
105
106	/* CLOCK_MONOTONIC_COARSE */
107	vdso_ts		= &vdata[CS_HRES_COARSE].basetime[CLOCK_MONOTONIC_COARSE];
108	vdso_ts->sec	= tk->xtime_sec + tk->wall_to_monotonic.tv_sec;
109	nsec		= tk->tkr_mono.xtime_nsec >> tk->tkr_mono.shift;
110	nsec		= nsec + tk->wall_to_monotonic.tv_nsec;
111	vdso_ts->sec	+= __iter_div_u64_rem(nsec, NSEC_PER_SEC, &vdso_ts->nsec);
112
113	update_vdso_data(vdata, tk);
114
115	__arch_update_vsyscall(vdata, tk);
116
117	vdso_write_end(vdata);
118
119	__arch_sync_vdso_data(vdata);
120}
121
122void update_vsyscall_tz(void)
123{
124	struct vdso_data *vdata = __arch_get_k_vdso_data();
125
126	vdata[CS_HRES_COARSE].tz_minuteswest = sys_tz.tz_minuteswest;
127	vdata[CS_HRES_COARSE].tz_dsttime = sys_tz.tz_dsttime;
128
129	__arch_sync_vdso_data(vdata);
130}