Skip to content

timekeeping/ptp: Expand snapshot functionality

Thomas Gleixner kvmarm linux-sound linux-wireless lkml netdev virtualization 2 versions – Applied

Status from this message: The following commit has been merged into the timers/ptp branch of tip:

Get series with b4
b4 am [email protected]

Versions newest first · linked by author and title

  1. v2 Latest25 patches 13 repliesApplied
  2. v124 patches 59 repliesSuperseded

Changes in v2 from the cover letter

- Fixed the ptp_ocp typo - 0-day, Jakub

- Renamed the system_time_snapshot members sys and raw so systime and monoraw to make them less ambigous.

- Fixed the error case return values of get_device_system_crosststamp()

- Made ktime_snapshot_id() void as there is no point for the return value, which is nowhere checked and cannot be propagated. system_time_snapshot::valid has to be evaluated at the call sites anyway. - Jacob

- Picked up the first patch from Davids follow up series, which extends the snapshot mechanism so that derived clocksources (like kvmclock and Hyper-V scaled TSC) can return the actual underlying hardware counter value (TSC for the two examples).

- Collected Reviewed/Acked/Tested-by tags

Patches in v2 Applied

#Subject and filesSizeRepliesApplied
1/25timekeeping: Provide ktime_get_snapshot_id()include/linux/timekeeping.h kernel/time/timekeeping.c+88 -310 replies
2/25timekeeping: Use system_time_snapshot::systime/monoraw instead of ::real/rawkernel/time/timekeeping.c+4 -40 replies
3/25pps: generators: Use ktime_get_real_ts64() instead of ktime_get_snapshot()drivers/pps/generators/pps_gen-dummy.c drivers/pps/generators/pps_gen_tio.c+2 -101 reply
4/25pps: Convert to ktime_get_snapshot_id()include/linux/pps_kernel.h+6 -43 replies
5/25KVM: arm64: Use ktime_get_snapshot_id() to retrieve CLOCK_BOOTTIMEarch/arm64/kvm/hyp_trace.c+4 -42 replies
6/25KVM: arm64: Use ktime_get_snapshot_id() to snapshot CLOCK_REALTIMEarch/arm64/kvm/hypercalls.c+3 -30 replies
7/25ptp: ptp_vmclock: Convert to ktime_get_snapshot_id()drivers/ptp/ptp_vmclock.c+4 -40 replies
8/25timekeeping: Remove system_time_snapshot::real/boot/rawinclude/linux/timekeeping.h kernel/time/timekeeping.c+1 -170 replies
9/25timekeeping: Add CLOCK_AUX support for ktime_get_snapshot_id()kernel/time/timekeeping.c+15 -00 replies
10/25timekeeping: Add system_counterval_t to struct system_device_crosststampinclude/linux/timekeeping.h kernel/time/timekeeping.c+36 -380 replies
11/25timekeeping: Add CLOCK ID to system_device_crosststampdrivers/ptp/ptp_chardev.c include/linux/timekeeping.h sound/hda/common/controller.c+4 -20 replies
12/25wifi: iwlwifi: Adopt PTP cross timestamps to core changesdrivers/net/wireless/intel/iwlwifi/mld/ptp.c drivers/net/wireless/intel/iwlwifi/mvm/ptp.c+5 -30 replies
13/25ice/ptp: Use provided clock ID for history snapshotdrivers/net/ethernet/intel/ice/ice_ptp.c+4 -10 replies
14/25igc: Use provided clock ID for history snapshotdrivers/net/ethernet/intel/igc/igc.h drivers/net/ethernet/intel/igc/igc_ptp.c+4 -10 replies
15/25net/mlx5: Use provided clock ID for history snapshotdrivers/net/ethernet/mellanox/mlx5/core/lib/clock.c+2 -20 replies
16/25virtio_rtc: Use provided clock ID for history snapshotdrivers/virtio/virtio_rtc_ptp.c+1 -11 reply
17/25timekeeping: Remove ktime_get_snapshot()include/linux/timekeeping.h+0 -50 replies
18/25timekeeping: Prepare for cross timestamps on arbitrary clock IDsinclude/linux/timekeeping.h kernel/time/timekeeping.c+41 -263 replies
19/25ptp: Use system_device_crosststamp::sys_systimedrivers/ptp/ptp_chardev.c+1 -10 replies
20/25wifi: iwlwifi: Use system_device_crosststamp::sys_systimedrivers/net/wireless/intel/iwlwifi/mld/ptp.c drivers/net/wireless/intel/iwlwifi/mvm/ptp.c+2 -20 replies
21/25ALSA: hda/common: Use system_device_crosststamp::sys_systimesound/hda/common/controller.c+1 -11 reply
22/25timekeeping: Remove system_device_crosststamp::sys_realtimeinclude/linux/timekeeping.h+1 -60 replies
23/25timekeeping: Add support for AUX clock cross timestampingkernel/time/timekeeping.c+6 -00 replies
24/25ptp: Switch to ktime_get_snapshot_id() for pre/post timestampsdrivers/net/dsa/sja1105/sja1105_main.c drivers/ptp/ptp_chardev.c drivers/ptp/ptp_ocp.c +2 more+32 -390 replies
25/25timekeeping: Add clocksource read_snapshot() method and hw_cycles to snapshotinclude/linux/clocksource.h include/linux/timekeeping.h kernel/time/timekeeping.c+50 -10 replies

Reviews trailers per patch

24 of 25 patches have a Reviewed-by or Acked-by of their own; the series has one for all of them.

PatchDavid WoodhouseArthur KiyanovskiThomas WeißschuhJacob KellerMarc ZyngierVincent DonnefortVadim FedorenkoRodolfo GiomettiMichael S. TsirkinPeter HilberTakashi Iwai
SeriesR-b A-b
1/25T-b R-b T-b R-b R-b
2/25T-b R-b T-b R-b R-b
3/25R-b R-b T-b T-b R-b R-b R-b R-b A-b
4/25R-b T-b R-b R-b
5/25R-b T-b R-b R-b A-b A-b
6/25R-b T-b R-b R-b A-b
7/25T-b R-b T-b R-b R-b
8/25T-b R-b T-b R-b R-b
9/25R-b T-b R-b R-b
10/25T-b R-b T-b R-b
11/25T-b R-b T-b R-b
12/25R-b T-b R-b
13/25R-b T-b R-b A-b
14/25R-b T-b R-b A-b
15/25R-b T-b R-b
16/25R-b T-b R-b A-b
17/25T-b R-b T-b R-b R-b
18/25T-b R-b T-b R-b R-b
19/25T-b R-b T-b R-b
20/25R-b T-b R-b
21/25R-b T-b R-b A-b
22/25T-b R-b T-b R-b R-b
23/25R-b T-b R-b R-b
24/25T-b R-b T-b R-b A-b
25/25

Trailers given in replies are filled; those carried in the patches from earlier versions are outlined with dashes. Scroll the table sideways for all 11 reviewers.

Read the v2 thread

Cover letter [patch V2 00/25] timekeeping/ptp: Expand snapshot functionality

This is an update to V1 which can be found here:

https://lore.kernel.org/lkml/[email protected]

PTP wants to grow new snapshot functionality, which provides not only the captured CLOCK* values, but also the underlying clocksource counter value.

https://lore.kernel.org/[email protected]

There was quite some discussion in seemingly related threads how to capture these values and how to provide core infrastructure so that driver writers have something to work with

https://lore.kernel.org/[email protected]
https://lore.kernel.org/[email protected]

This series implements the timekeeping related mechanisms to:

1) Capture CLOCK values along with the clocksource counter value for non-hardware based sampling

2) Expanding the hardware cross time stamp mechanism to hand back the clocksource counter value, which was captured by the device, along with the related CLOCK values

3) Adding AUX clock support to the hardware cross timestamping core

4) Add support for derived clocksources to the snapshot mechanism (New in V2)

Changes vs. V1:

- Fixed the ptp_ocp typo - 0-day, Jakub

- Renamed the system_time_snapshot members sys and raw so systime and monoraw to make them less ambigous.

- Fixed the error case return values of get_device_system_crosststamp()

- Made ktime_snapshot_id() void as there is no point for the return value, which is nowhere checked and cannot be propagated. system_time_snapshot::valid has to be evaluated at the call sites anyway. - Jacob

- Picked up the first patch from Davids follow up series, which extends the snapshot mechanism so that derived clocksources (like kvmclock and Hyper-V scaled TSC) can return the actual underlying hardware counter value (TSC for the two examples).

- Collected Reviewed/Acked/Tested-by tags

Delta patch against v1 below.

The series is based on v7.1-rc2 and also available from git:

git://git.kernel.org/pub/scm/linux/kernel/git/tglx/devel.git timekeeping-ptp-extend-v2

Thanks,

tglx
---

arch/arm64/kvm/hyp_trace.c +3 -3
index 616062587510..b056c652ff01 100644
@@ -51,8 +51,8 @@ static void __hyp_clock_work(struct work_struct *work)
 
 	hyp_clock = container_of(dwork, struct hyp_trace_clock, work);
 
-	ktime_get_snapshot_id(&snap, CLOCK_BOOTTIME);
-	boot = ktime_to_ns(snap.sys);
+	ktime_get_snapshot_id(CLOCK_BOOTTIME, &snap);
+	boot = ktime_to_ns(snap.systime);
 
 	delta_boot = boot - hyp_clock->boot;
 	delta_cycles = snap.cycles - hyp_clock->cycles;
@@ -120,7 +120,7 @@ static void hyp_trace_clock_enable(struct hyp_trace_clock *hyp_clock, bool enabl
 
 	ktime_get_snapshot_id(&snap, CLOCK_BOOTTIME);
 
-	hyp_clock->boot = ktime_to_ns(snap.sys);
+	hyp_clock->boot = ktime_to_ns(snap.systime);
 	hyp_clock->cycles = snap.cycles;
 	hyp_clock->mult = 0;
 
arch/arm64/kvm/hypercalls.c +3 -3
index e60cc7ed3e70..b11b8821c9fb 100644
@@ -28,7 +28,7 @@ static void kvm_ptp_get_time(struct kvm_vcpu *vcpu, u64 *val)
 	 * system time and counter value must captured at the same
 	 * time to keep consistency and precision.
 	 */
-	ktime_get_snapshot_id(&systime_snapshot, CLOCK_REALTIME);
+	ktime_get_snapshot_id(CLOCK_REALTIME, &systime_snapshot);
 
 	/*
 	 * This is only valid if the current clocksource is the
@@ -61,8 +61,8 @@ static void kvm_ptp_get_time(struct kvm_vcpu *vcpu, u64 *val)
 	 * in the future (about 292 years from 1970, and at that stage
 	 * nobody will give a damn about it).
 	 */
-	val[0] = upper_32_bits(systime_snapshot.sys);
-	val[1] = lower_32_bits(systime_snapshot.sys);
+	val[0] = upper_32_bits(systime_snapshot.systime);
+	val[1] = lower_32_bits(systime_snapshot.systime);
 	val[2] = upper_32_bits(cycles);
 	val[3] = lower_32_bits(cycles);
 }
drivers/net/dsa/sja1105/sja1105_main.c +4 -4
index 1d5fef4df560..2697073dbf90 100644
@@ -2310,10 +2310,10 @@ int sja1105_static_config_reload(struct sja1105_private *priv,
 		goto out;
 	}
 
-	t1 = ktime_to_ns(ptp_sts_before.pre_sts.sys);
-	t2 = ktime_to_ns(ptp_sts_before.post_sts.sys);
-	t3 = ktime_to_ns(ptp_sts_after.pre_sts.sys);
-	t4 = ktime_to_ns(ptp_sts_after.post_sts.sys);
+	t1 = ktime_to_ns(ptp_sts_before.pre_sts.systime);
+	t2 = ktime_to_ns(ptp_sts_before.post_sts.systime);
+	t3 = ktime_to_ns(ptp_sts_after.pre_sts.systime);
+	t4 = ktime_to_ns(ptp_sts_after.post_sts.systime);
 	/* Mid point, corresponds to pre-reset PTPCLKVAL */
 	t12 = t1 + (t2 - t1) / 2;
 	/* Mid point, corresponds to post-reset PTPCLKVAL, aka 0 */
drivers/net/ethernet/intel/ice/ice_ptp.c +1 -1
index 5023fc1587f9..f9e4ec6f7ebb 100644
@@ -2117,7 +2117,7 @@ static int ice_capture_crosststamp(ktime_t *device,
 	}
 
 	/* Snapshot system time for historic interpolation */
-	ktime_get_snapshot_id(&ctx->snapshot, ctx->snapshot_clock_id);
+	ktime_get_snapshot_id(ctx->snapshot_clock_id, &ctx->snapshot);
 
 	/* Program cmd to master timer */
 	ice_ptp_src_cmd(hw, ICE_PTP_READ_TIME);
drivers/net/ethernet/intel/igc/igc_ptp.c +1 -1
index 9b8b4a04e32d..b40aba9ab685 100644
@@ -1049,7 +1049,7 @@ static int igc_phc_get_syncdevicetime(ktime_t *device,
 	 */
 	do {
 		/* Get a snapshot of system clocks to use as historic value. */
-		ktime_get_snapshot_id(&adapter->snapshot, adapter->snapshot_clock_id);
+		ktime_get_snapshot_id(adapter->snapshot_clock_id, &adapter->snapshot);
 
 		igc_ptm_trigger(hw);
 
drivers/net/ethernet/mellanox/mlx5/core/lib/clock.c +2 -2
index beb80912b9d5..5df786133e4b 100644
@@ -340,7 +340,7 @@ static int mlx5_ptp_getcrosststamp(struct ptp_clock_info *ptp,
 		goto unlock;
 	}
 
-	ktime_get_snapshot_id(&history_begin, cts->clock_id);
+	ktime_get_snapshot_id(cts->clock_id, &history_begin);
 
 	err = get_device_system_crosststamp(mlx5_mtctr_syncdevicetime, mdev,
 					    &history_begin, cts);
@@ -366,7 +366,7 @@ static int mlx5_ptp_getcrosscycles(struct ptp_clock_info *ptp,
 		goto unlock;
 	}
 
-	ktime_get_snapshot_id(&history_begin, cts->clock_id);
+	ktime_get_snapshot_id(cts->clock_id, &history_begin);
 
 	err = get_device_system_crosststamp(mlx5_mtctr_syncdevicecyclestime,
 					    mdev, &history_begin, cts);
drivers/ptp/ptp_chardev.c +2 -2
index aed5c13cd1be..dc23cd708cfe 100644
@@ -392,11 +392,11 @@ static long ptp_sys_offset_extended(struct ptp_clock *ptp, void __user *arg,
 		extoff->ts[i][1].sec = ts.tv_sec;
 		extoff->ts[i][1].nsec = ts.tv_nsec;
 
-		ts = ktime_to_timespec64(sts.pre_sts.sys);
+		ts = ktime_to_timespec64(sts.pre_sts.systime);
 		extoff->ts[i][0].sec = ts.tv_sec;
 		extoff->ts[i][0].nsec = ts.tv_nsec;
 
-		ts = ktime_to_timespec64(sts.post_sts.sys);
+		ts = ktime_to_timespec64(sts.post_sts.systime);
 		extoff->ts[i][2].sec = ts.tv_sec;
 		extoff->ts[i][2].nsec = ts.tv_nsec;
 	}
drivers/ptp/ptp_ocp.c +3 -3
index b7a23936a44d..28b0302c6250 100644
@@ -1492,7 +1492,7 @@ __ptp_ocp_gettime_locked(struct ptp_ocp *bp, struct timespec64 *ts,
 	ptp_read_system_postts(sts);
 
 	if (sts && bp->ts_window_adjust)
-		sts->post_ts.sys -= bp->ts_window_adjust;
+		sts->post_sts.systime -= bp->ts_window_adjust;
 
 	time_ns = ioread32(&bp->reg->time_ns);
 	time_sec = ioread32(&bp->reg->time_sec);
@@ -4592,8 +4592,8 @@ ptp_ocp_summary_show(struct seq_file *s, void *data)
 		struct timespec64 sys_ts;
 		s64 pre_ns, post_ns, ns;
 
-		pre_ns = ktime_to_ns(sts.pre_sts.sys);
-		post_ns = ktime_to_ns(sts.post_sts.sys);
+		pre_ns = ktime_to_ns(sts.pre_sts.systime);
+		post_ns = ktime_to_ns(sts.post_sts.systime);
 		ns = (pre_ns + post_ns) / 2;
 		ns += (s64)bp->utc_tai_offset * NSEC_PER_SEC;
 		sys_ts = ns_to_timespec64(ns);
drivers/ptp/ptp_vmclock.c +1 -1
index cb18c15a4697..d6a5a533164a 100644
@@ -263,7 +263,7 @@ static int ptp_vmclock_getcrosststamp(struct ptp_clock_info *ptp,
 	if (ret == -ENODEV) {
 		struct system_time_snapshot systime_snapshot;
 
-		ktime_get_snapshot_id(&systime_snapshot, CLOCK_REALTIME);
+		ktime_get_snapshot_id(CLOCK_REALTIME, &systime_snapshot);
 
 		if (systime_snapshot.cs_id == CSID_X86_TSC ||
 		    systime_snapshot.cs_id == CSID_X86_KVM_CLK) {
drivers/virtio/virtio_rtc_ptp.c +1 -1
index e15d00aeb01d..ff8d834493dc 100644
@@ -139,7 +139,7 @@ static int viortc_ptp_getcrosststamp(struct ptp_clock_info *ptp,
 	if (ret)
 		return ret;
 
-	ktime_get_snapshot_id(&history_begin, xtstamp->clock_id);
+	ktime_get_snapshot_id(xtstamp->clock_id, &history_begin);
 	if (history_begin.cs_id != cs_id)
 		return -EOPNOTSUPP;
 
include/linux/clocksource.h +24 -0
index 7c38190b10bf..6d9ddf1587a2 100644
@@ -31,6 +31,21 @@ struct module;
 
 #include <vdso/clocksource.h>
 
+/**
+ * struct clocksource_hw_snapshot - Snapshot for the underlying hardware counter of derived
+ *				    clocksources like kvmclock or Hyper-V scaled TSC
+ * @hw_cycles:		The hardware counter value
+ * @hw_csid:		Clocksource ID of the hardware counter
+ *
+ * Such clocksources must implement the read_snapshot() callback and fill in the
+ * hardware counter value, the clocksource ID of the hardware counter and derive
+ * the actual clocksource cycles from @hw_cycles to provide an atomic snapshot
+ */
+struct clocksource_hw_snapshot {
+	u64			hw_cycles;
+	enum clocksource_ids	hw_csid;
+};
+
 /**
  * struct clocksource - hardware abstraction for a free running counter
  *	Provides mostly state-free accessors to the underlying hardware.
@@ -72,6 +87,14 @@ struct module;
  * @flags:		Flags describing special properties
  * @base:		Hardware abstraction for clock on which a clocksource
  *			is based
+ * @read_snapshot:	Extended @read() function for clocksources such as
+ *			kvmclock or the Hyper-V scaled TSC where the actual
+ *			clocksource value for timekeeping is calculated from an
+ *			underlying hardware counter. Returns the timekeeping
+ *			relevant cycle value and stores the raw value of the
+ *			underlying counter from which it was calculated
+ *			including the clocksource ID of that counter in the
+ *			clocksource hardware snapshot.
  * @enable:		Optional function to enable the clocksource
  * @disable:		Optional function to disable the clocksource
  * @suspend:		Optional suspend function for the clocksource
@@ -113,6 +136,7 @@ struct clocksource {
 	unsigned long		flags;
 	struct clocksource_base *base;
 
+	u64			(*read_snapshot)(struct clocksource *cs, struct clocksource_hw_snapshot *chs);
 	int			(*enable)(struct clocksource *cs);
 	void			(*disable)(struct clocksource *cs);
 	void			(*suspend)(struct clocksource *cs);
include/linux/pps_kernel.h +3 -3
index cd80f1cb96a9..9f088c9023b1 100644
@@ -102,9 +102,9 @@ static inline void pps_get_ts(struct pps_event_time *ts)
 #ifdef CONFIG_NTP_PPS
 	struct system_time_snapshot snap;
 
-	ktime_get_snapshot_id(&snap, CLOCK_REALTIME);
-	ts->ts_real = ktime_to_timespec64(snap.sys);
-	ts->ts_raw = ktime_to_timespec64(snap.raw);
+	ktime_get_snapshot_id(CLOCK_REALTIME, &snap);
+	ts->ts_real = ktime_to_timespec64(snap.systime);
+	ts->ts_raw = ktime_to_timespec64(snap.monoraw);
 #else
 	ktime_get_real_ts64(&ts->ts_real);
 #endif
include/linux/ptp_clock_kernel.h +2 -2
index df6c9aac458b..36a27a910595 100644
@@ -511,13 +511,13 @@ static inline ktime_t ptp_convert_timestamp(const ktime_t *hwtstamp,
 static inline void ptp_read_system_prets(struct ptp_system_timestamp *sts)
 {
 	if (sts)
-		ktime_get_snapshot_id(&sts->pre_sts, sts->clockid);
+		ktime_get_snapshot_id(sts->clockid, &sts->pre_sts);
 }
 
 static inline void ptp_read_system_postts(struct ptp_system_timestamp *sts)
 {
 	if (sts)
-		ktime_get_snapshot_id(&sts->post_sts, sts->clockid);
+		ktime_get_snapshot_id(sts->clockid, &sts->post_sts);
 }
 
 #endif
include/linux/timekeeping.h +11 -6
index f7945f1048fc..984a866d293b 100644
@@ -279,18 +279,24 @@ static inline bool ktime_get_aux_ts64(clockid_t id, struct timespec64 *kt) { ret
  * struct system_time_snapshot - Simultaneous time capture of CLOCK_MONOTONIC_RAW,
  *				 a selected CLOCK_* and the clocksource counter value
  * @cycles:		Clocksource counter value to produce the system times
- * @sys:		The system time of the selected CLOCK ID
- * @raw:		Monotonic raw system time
+ * @hw_cycles:		For derived clocksources, the hardware counter value from
+ *			which @cycles was derived
+ * @systime:		The system time of the selected CLOCK ID
+ * @monoraw:		Monotonic raw system time
  * @cs_id:		Clocksource ID
+ * @hw_csid:		Clocksource ID of the underlying hardware counter for derived
+ *			clocksources which implement the read_snapshot() callback.
  * @clock_was_set_seq:	The sequence number of clock-was-set events
  * @cs_was_changed_seq:	The sequence number of clocksource change events
  * @valid:		True if the snapshot is valid
  */
 struct system_time_snapshot {
 	u64			cycles;
-	ktime_t			sys;
-	ktime_t			raw;
+	u64			hw_cycles;
+	ktime_t			systime;
+	ktime_t			monoraw;
 	enum clocksource_ids	cs_id;
+	enum clocksource_ids	hw_csid;
 	unsigned int		clock_was_set_seq;
 	u8			cs_was_changed_seq;
 	u8			valid;
@@ -348,8 +354,7 @@ extern int get_device_system_crosststamp(
  * Simultaneously snapshot a given clock with MONOTONIC_RAW and the underlying
  * clocksource counter value.
  */
-extern bool ktime_get_snapshot_id(struct system_time_snapshot *systime_snapshot,
-				  clockid_t clock_id);
+extern void ktime_get_snapshot_id(clockid_t clock_id, struct system_time_snapshot *systime_snapshot);
 
 /*
  * Persistent clock related interfaces
kernel/time/timekeeping.c +36 -18

140 lines not on this page · raw message