Skip to content

Commit 380b84e

Browse files
t-8chKAGA-KOKO
authored andcommitted
vdso/vsyscall: Update auxiliary clock data in the datapage
Expose the auxiliary clock data so it can be read from the vDSO. Architectures not using the generic vDSO time framework, namely SPARC64, are not supported. Signed-off-by: Thomas Weißschuh <[email protected]> Signed-off-by: Thomas Gleixner <[email protected]> Link: https://lore.kernel.org/all/[email protected]
1 parent 9b7fc3f commit 380b84e

File tree

5 files changed

+66
-0
lines changed

5 files changed

+66
-0
lines changed

include/linux/timekeeper_internal.h

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -190,4 +190,10 @@ static inline void update_vsyscall_tz(void)
190190
}
191191
#endif
192192

193+
#if defined(CONFIG_GENERIC_GETTIMEOFDAY) && defined(CONFIG_POSIX_AUX_CLOCKS)
194+
extern void vdso_time_update_aux(struct timekeeper *tk);
195+
#else
196+
static inline void vdso_time_update_aux(struct timekeeper *tk) { }
197+
#endif
198+
193199
#endif /* _LINUX_TIMEKEEPER_INTERNAL_H */

include/vdso/datapage.h

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -38,6 +38,7 @@ struct vdso_arch_data {
3838
#endif
3939

4040
#define VDSO_BASES (CLOCK_TAI + 1)
41+
#define VDSO_BASE_AUX 0
4142
#define VDSO_HRES (BIT(CLOCK_REALTIME) | \
4243
BIT(CLOCK_MONOTONIC) | \
4344
BIT(CLOCK_BOOTTIME) | \
@@ -117,6 +118,7 @@ struct vdso_clock {
117118
* @arch_data: architecture specific data (optional, defaults
118119
* to an empty struct)
119120
* @clock_data: clocksource related data (array)
121+
* @aux_clock_data: auxiliary clocksource related data (array)
120122
* @tz_minuteswest: minutes west of Greenwich
121123
* @tz_dsttime: type of DST correction
122124
* @hrtimer_res: hrtimer resolution
@@ -133,6 +135,7 @@ struct vdso_time_data {
133135
struct arch_vdso_time_data arch_data;
134136

135137
struct vdso_clock clock_data[CS_BASES];
138+
struct vdso_clock aux_clock_data[MAX_AUX_CLOCKS];
136139

137140
s32 tz_minuteswest;
138141
s32 tz_dsttime;

kernel/time/namespace.c

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -242,6 +242,11 @@ static void timens_set_vvar_page(struct task_struct *task,
242242
for (i = 0; i < CS_BASES; i++)
243243
timens_setup_vdso_clock_data(&vc[i], ns);
244244

245+
if (IS_ENABLED(CONFIG_POSIX_AUX_CLOCKS)) {
246+
for (i = 0; i < ARRAY_SIZE(vdata->aux_clock_data); i++)
247+
timens_setup_vdso_clock_data(&vdata->aux_clock_data[i], ns);
248+
}
249+
245250
out:
246251
mutex_unlock(&offset_lock);
247252
}

kernel/time/timekeeping.c

Lines changed: 12 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -66,11 +66,21 @@ static inline bool tk_get_aux_ts64(unsigned int tkid, struct timespec64 *ts)
6666
{
6767
return ktime_get_aux_ts64(CLOCK_AUX + tkid - TIMEKEEPER_AUX_FIRST, ts);
6868
}
69+
70+
static inline bool tk_is_aux(const struct timekeeper *tk)
71+
{
72+
return tk->id >= TIMEKEEPER_AUX_FIRST && tk->id <= TIMEKEEPER_AUX_LAST;
73+
}
6974
#else
7075
static inline bool tk_get_aux_ts64(unsigned int tkid, struct timespec64 *ts)
7176
{
7277
return false;
7378
}
79+
80+
static inline bool tk_is_aux(const struct timekeeper *tk)
81+
{
82+
return false;
83+
}
7484
#endif
7585

7686
/* flag for if timekeeping is suspended */
@@ -719,6 +729,8 @@ static void timekeeping_update_from_shadow(struct tk_data *tkd, unsigned int act
719729

720730
update_fast_timekeeper(&tk->tkr_mono, &tk_fast_mono);
721731
update_fast_timekeeper(&tk->tkr_raw, &tk_fast_raw);
732+
} else if (tk_is_aux(tk)) {
733+
vdso_time_update_aux(tk);
722734
}
723735

724736
if (action & TK_CLOCK_WAS_SET)

kernel/time/vsyscall.c

Lines changed: 40 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -136,6 +136,46 @@ void update_vsyscall_tz(void)
136136
__arch_sync_vdso_time_data(vdata);
137137
}
138138

139+
#ifdef CONFIG_POSIX_AUX_CLOCKS
140+
void vdso_time_update_aux(struct timekeeper *tk)
141+
{
142+
struct vdso_time_data *vdata = vdso_k_time_data;
143+
struct vdso_timestamp *vdso_ts;
144+
struct vdso_clock *vc;
145+
s32 clock_mode;
146+
u64 nsec;
147+
148+
vc = &vdata->aux_clock_data[tk->id - TIMEKEEPER_AUX_FIRST];
149+
vdso_ts = &vc->basetime[VDSO_BASE_AUX];
150+
clock_mode = tk->tkr_mono.clock->vdso_clock_mode;
151+
if (!tk->clock_valid)
152+
clock_mode = VDSO_CLOCKMODE_NONE;
153+
154+
/* copy vsyscall data */
155+
vdso_write_begin_clock(vc);
156+
157+
vc->clock_mode = clock_mode;
158+
159+
if (clock_mode != VDSO_CLOCKMODE_NONE) {
160+
fill_clock_configuration(vc, &tk->tkr_mono);
161+
162+
vdso_ts->sec = tk->xtime_sec;
163+
164+
nsec = tk->tkr_mono.xtime_nsec >> tk->tkr_mono.shift;
165+
nsec += tk->offs_aux;
166+
vdso_ts->sec += __iter_div_u64_rem(nsec, NSEC_PER_SEC, &nsec);
167+
nsec = nsec << tk->tkr_mono.shift;
168+
vdso_ts->nsec = nsec;
169+
}
170+
171+
__arch_update_vdso_clock(vc);
172+
173+
vdso_write_end_clock(vc);
174+
175+
__arch_sync_vdso_time_data(vdata);
176+
}
177+
#endif
178+
139179
/**
140180
* vdso_update_begin - Start of a VDSO update section
141181
*

0 commit comments

Comments
 (0)