mirror of
				https://github.com/torvalds/linux.git
				synced 2025-11-04 10:40:15 +02:00 
			
		
		
		
	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 <thomas.weissschuh@linutronix.de> Signed-off-by: Thomas Gleixner <tglx@linutronix.de> Link: https://lore.kernel.org/all/20250701-vdso-auxclock-v1-11-df7d9f87b9b8@linutronix.de
This commit is contained in:
		
							parent
							
								
									9b7fc3f145
								
							
						
					
					
						commit
						380b84e168
					
				
					 5 changed files with 66 additions and 0 deletions
				
			
		| 
						 | 
					@ -190,4 +190,10 @@ static inline void update_vsyscall_tz(void)
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
#endif
 | 
					#endif
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					#if defined(CONFIG_GENERIC_GETTIMEOFDAY) && defined(CONFIG_POSIX_AUX_CLOCKS)
 | 
				
			||||||
 | 
					extern void vdso_time_update_aux(struct timekeeper *tk);
 | 
				
			||||||
 | 
					#else
 | 
				
			||||||
 | 
					static inline void vdso_time_update_aux(struct timekeeper *tk) { }
 | 
				
			||||||
 | 
					#endif
 | 
				
			||||||
 | 
					
 | 
				
			||||||
#endif /* _LINUX_TIMEKEEPER_INTERNAL_H */
 | 
					#endif /* _LINUX_TIMEKEEPER_INTERNAL_H */
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
| 
						 | 
					@ -38,6 +38,7 @@ struct vdso_arch_data {
 | 
				
			||||||
#endif
 | 
					#endif
 | 
				
			||||||
 | 
					
 | 
				
			||||||
#define VDSO_BASES	(CLOCK_TAI + 1)
 | 
					#define VDSO_BASES	(CLOCK_TAI + 1)
 | 
				
			||||||
 | 
					#define VDSO_BASE_AUX	0
 | 
				
			||||||
#define VDSO_HRES	(BIT(CLOCK_REALTIME)		| \
 | 
					#define VDSO_HRES	(BIT(CLOCK_REALTIME)		| \
 | 
				
			||||||
			 BIT(CLOCK_MONOTONIC)		| \
 | 
								 BIT(CLOCK_MONOTONIC)		| \
 | 
				
			||||||
			 BIT(CLOCK_BOOTTIME)		| \
 | 
								 BIT(CLOCK_BOOTTIME)		| \
 | 
				
			||||||
| 
						 | 
					@ -117,6 +118,7 @@ struct vdso_clock {
 | 
				
			||||||
 * @arch_data:		architecture specific data (optional, defaults
 | 
					 * @arch_data:		architecture specific data (optional, defaults
 | 
				
			||||||
 *			to an empty struct)
 | 
					 *			to an empty struct)
 | 
				
			||||||
 * @clock_data:		clocksource related data (array)
 | 
					 * @clock_data:		clocksource related data (array)
 | 
				
			||||||
 | 
					 * @aux_clock_data:	auxiliary clocksource related data (array)
 | 
				
			||||||
 * @tz_minuteswest:	minutes west of Greenwich
 | 
					 * @tz_minuteswest:	minutes west of Greenwich
 | 
				
			||||||
 * @tz_dsttime:		type of DST correction
 | 
					 * @tz_dsttime:		type of DST correction
 | 
				
			||||||
 * @hrtimer_res:	hrtimer resolution
 | 
					 * @hrtimer_res:	hrtimer resolution
 | 
				
			||||||
| 
						 | 
					@ -133,6 +135,7 @@ struct vdso_time_data {
 | 
				
			||||||
	struct arch_vdso_time_data	arch_data;
 | 
						struct arch_vdso_time_data	arch_data;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	struct vdso_clock		clock_data[CS_BASES];
 | 
						struct vdso_clock		clock_data[CS_BASES];
 | 
				
			||||||
 | 
						struct vdso_clock		aux_clock_data[MAX_AUX_CLOCKS];
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	s32				tz_minuteswest;
 | 
						s32				tz_minuteswest;
 | 
				
			||||||
	s32				tz_dsttime;
 | 
						s32				tz_dsttime;
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
| 
						 | 
					@ -242,6 +242,11 @@ static void timens_set_vvar_page(struct task_struct *task,
 | 
				
			||||||
	for (i = 0; i < CS_BASES; i++)
 | 
						for (i = 0; i < CS_BASES; i++)
 | 
				
			||||||
		timens_setup_vdso_clock_data(&vc[i], ns);
 | 
							timens_setup_vdso_clock_data(&vc[i], ns);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						if (IS_ENABLED(CONFIG_POSIX_AUX_CLOCKS)) {
 | 
				
			||||||
 | 
							for (i = 0; i < ARRAY_SIZE(vdata->aux_clock_data); i++)
 | 
				
			||||||
 | 
								timens_setup_vdso_clock_data(&vdata->aux_clock_data[i], ns);
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
out:
 | 
					out:
 | 
				
			||||||
	mutex_unlock(&offset_lock);
 | 
						mutex_unlock(&offset_lock);
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
| 
						 | 
					@ -66,11 +66,21 @@ static inline bool tk_get_aux_ts64(unsigned int tkid, struct timespec64 *ts)
 | 
				
			||||||
{
 | 
					{
 | 
				
			||||||
	return ktime_get_aux_ts64(CLOCK_AUX + tkid - TIMEKEEPER_AUX_FIRST, ts);
 | 
						return ktime_get_aux_ts64(CLOCK_AUX + tkid - TIMEKEEPER_AUX_FIRST, ts);
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					static inline bool tk_is_aux(const struct timekeeper *tk)
 | 
				
			||||||
 | 
					{
 | 
				
			||||||
 | 
						return tk->id >= TIMEKEEPER_AUX_FIRST && tk->id <= TIMEKEEPER_AUX_LAST;
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
#else
 | 
					#else
 | 
				
			||||||
static inline bool tk_get_aux_ts64(unsigned int tkid, struct timespec64 *ts)
 | 
					static inline bool tk_get_aux_ts64(unsigned int tkid, struct timespec64 *ts)
 | 
				
			||||||
{
 | 
					{
 | 
				
			||||||
	return false;
 | 
						return false;
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					static inline bool tk_is_aux(const struct timekeeper *tk)
 | 
				
			||||||
 | 
					{
 | 
				
			||||||
 | 
						return false;
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
#endif
 | 
					#endif
 | 
				
			||||||
 | 
					
 | 
				
			||||||
/* flag for if timekeeping is suspended */
 | 
					/* flag for if timekeeping is suspended */
 | 
				
			||||||
| 
						 | 
					@ -719,6 +729,8 @@ static void timekeeping_update_from_shadow(struct tk_data *tkd, unsigned int act
 | 
				
			||||||
 | 
					
 | 
				
			||||||
		update_fast_timekeeper(&tk->tkr_mono, &tk_fast_mono);
 | 
							update_fast_timekeeper(&tk->tkr_mono, &tk_fast_mono);
 | 
				
			||||||
		update_fast_timekeeper(&tk->tkr_raw,  &tk_fast_raw);
 | 
							update_fast_timekeeper(&tk->tkr_raw,  &tk_fast_raw);
 | 
				
			||||||
 | 
						} else if (tk_is_aux(tk)) {
 | 
				
			||||||
 | 
							vdso_time_update_aux(tk);
 | 
				
			||||||
	}
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	if (action & TK_CLOCK_WAS_SET)
 | 
						if (action & TK_CLOCK_WAS_SET)
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
| 
						 | 
					@ -136,6 +136,46 @@ void update_vsyscall_tz(void)
 | 
				
			||||||
	__arch_sync_vdso_time_data(vdata);
 | 
						__arch_sync_vdso_time_data(vdata);
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					#ifdef CONFIG_POSIX_AUX_CLOCKS
 | 
				
			||||||
 | 
					void vdso_time_update_aux(struct timekeeper *tk)
 | 
				
			||||||
 | 
					{
 | 
				
			||||||
 | 
						struct vdso_time_data *vdata = vdso_k_time_data;
 | 
				
			||||||
 | 
						struct vdso_timestamp *vdso_ts;
 | 
				
			||||||
 | 
						struct vdso_clock *vc;
 | 
				
			||||||
 | 
						s32 clock_mode;
 | 
				
			||||||
 | 
						u64 nsec;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						vc = &vdata->aux_clock_data[tk->id - TIMEKEEPER_AUX_FIRST];
 | 
				
			||||||
 | 
						vdso_ts = &vc->basetime[VDSO_BASE_AUX];
 | 
				
			||||||
 | 
						clock_mode = tk->tkr_mono.clock->vdso_clock_mode;
 | 
				
			||||||
 | 
						if (!tk->clock_valid)
 | 
				
			||||||
 | 
							clock_mode = VDSO_CLOCKMODE_NONE;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						/* copy vsyscall data */
 | 
				
			||||||
 | 
						vdso_write_begin_clock(vc);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						vc->clock_mode = clock_mode;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						if (clock_mode != VDSO_CLOCKMODE_NONE) {
 | 
				
			||||||
 | 
							fill_clock_configuration(vc, &tk->tkr_mono);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
							vdso_ts->sec	= tk->xtime_sec;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
							nsec = tk->tkr_mono.xtime_nsec >> tk->tkr_mono.shift;
 | 
				
			||||||
 | 
							nsec += tk->offs_aux;
 | 
				
			||||||
 | 
							vdso_ts->sec += __iter_div_u64_rem(nsec, NSEC_PER_SEC, &nsec);
 | 
				
			||||||
 | 
							nsec = nsec << tk->tkr_mono.shift;
 | 
				
			||||||
 | 
							vdso_ts->nsec = nsec;
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						__arch_update_vdso_clock(vc);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						vdso_write_end_clock(vc);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						__arch_sync_vdso_time_data(vdata);
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					#endif
 | 
				
			||||||
 | 
					
 | 
				
			||||||
/**
 | 
					/**
 | 
				
			||||||
 * vdso_update_begin - Start of a VDSO update section
 | 
					 * vdso_update_begin - Start of a VDSO update section
 | 
				
			||||||
 *
 | 
					 *
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
		Loading…
	
		Reference in a new issue