Skip to content

Commit 2d6d57f

Browse files
committed
Merge tag 'timers-ptp-2026-06-13' of gitolite.kernel.org:pub/scm/linux/kernel/git/tip/tip
Pull timekeeping updates from Thomas Gleixner: "Updates for NTP/timekeeping and PTP: - Expand timekeeping snapshot mechanisms The various snapshot functions are mostly used for PTP to collect "atomic" snapshots of various involved clocks. They lack support for the recently introduced AUX clocks and do not provide the underlying counter value (e.g. TSC) to user space. Exposing the counter value snapshot allows for better control and steering. Convert the hard wired ktime_get_snapshot() to take a clock ID, which allows the caller to select the clock ID to be captured along with CLOCK_MONONOTONIC_RAW. Additionally capture the underlying hardware counter value and the clock source ID of the counter. Expand the hardware based snapshot capture where devices provide a mechanism to snapshot the hardware PTP clock and the system counter (usually via PCI/PTM) to support AUX clocks and also provide the captured counter value back to the caller and not only the clock timestamps derived from it. - Add a new optional read_snapshot() callback to clocksources That is required to capture atomic snapshots from clocksources which are derived from TSC with a scaling mechanism (e.g. Hyper-V, KVMclock). The value pair is handed back in the snapshot structure to the callers, so they can do the necessary correlations in a more precise way. This touches usage sites of the affected functions and data structure all over the tree, but stays fully backwards compatible for the existing user space exposed interfaces. New PTP IOCTLs will provide access to the extended functionality in later kernel versions" * tag 'timers-ptp-2026-06-13' of gitolite.kernel.org:pub/scm/linux/kernel/git/tip/tip: (28 commits) ptp: vmclock: Use hw_cycles from snapshot for precise TSC pairing x86/kvmclock: Implement read_snapshot() for kvmclock clocksource clocksource/hyperv: Implement read_snapshot() for TSC page clocksource timekeeping: Add clocksource read_snapshot() method and hw_cycles to snapshot ptp: Switch to ktime_get_snapshot_id() for pre/post timestamps timekeeping: Add support for AUX clock cross timestamping timekeeping: Remove system_device_crosststamp::sys_realtime ALSA: hda/common: Use system_device_crosststamp::sys_systime wifi: iwlwifi: Use system_device_crosststamp::sys_systime ptp: Use system_device_crosststamp::sys_systime timekeeping: Prepare for cross timestamps on arbitrary clock IDs timekeeping: Remove ktime_get_snapshot() virtio_rtc: Use provided clock ID for history snapshot net/mlx5: Use provided clock ID for history snapshot igc: Use provided clock ID for history snapshot ice/ptp: Use provided clock ID for history snapshot wifi: iwlwifi: Adopt PTP cross timestamps to core changes timekeeping: Add CLOCK ID to system_device_crosststamp timekeeping: Add system_counterval_t to struct system_device_crosststamp timekeeping: Add CLOCK_AUX support for ktime_get_snapshot_id() ...
2 parents a53fcff + bc484a5 commit 2d6d57f

23 files changed

Lines changed: 348 additions & 194 deletions

File tree

arch/arm64/kvm/hyp_trace.c

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -51,8 +51,8 @@ static void __hyp_clock_work(struct work_struct *work)
5151

5252
hyp_clock = container_of(dwork, struct hyp_trace_clock, work);
5353

54-
ktime_get_snapshot(&snap);
55-
boot = ktime_to_ns(snap.boot);
54+
ktime_get_snapshot_id(CLOCK_BOOTTIME, &snap);
55+
boot = ktime_to_ns(snap.systime);
5656

5757
delta_boot = boot - hyp_clock->boot;
5858
delta_cycles = snap.cycles - hyp_clock->cycles;
@@ -118,9 +118,9 @@ static void hyp_trace_clock_enable(struct hyp_trace_clock *hyp_clock, bool enabl
118118
hyp_clock->running = false;
119119
}
120120

121-
ktime_get_snapshot(&snap);
121+
ktime_get_snapshot_id(CLOCK_BOOTTIME, &snap);
122122

123-
hyp_clock->boot = ktime_to_ns(snap.boot);
123+
hyp_clock->boot = ktime_to_ns(snap.systime);
124124
hyp_clock->cycles = snap.cycles;
125125
hyp_clock->mult = 0;
126126

arch/arm64/kvm/hypercalls.c

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -28,7 +28,7 @@ static void kvm_ptp_get_time(struct kvm_vcpu *vcpu, u64 *val)
2828
* system time and counter value must captured at the same
2929
* time to keep consistency and precision.
3030
*/
31-
ktime_get_snapshot(&systime_snapshot);
31+
ktime_get_snapshot_id(CLOCK_REALTIME, &systime_snapshot);
3232

3333
/*
3434
* 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)
6161
* in the future (about 292 years from 1970, and at that stage
6262
* nobody will give a damn about it).
6363
*/
64-
val[0] = upper_32_bits(systime_snapshot.real);
65-
val[1] = lower_32_bits(systime_snapshot.real);
64+
val[0] = upper_32_bits(systime_snapshot.systime);
65+
val[1] = lower_32_bits(systime_snapshot.systime);
6666
val[2] = upper_32_bits(cycles);
6767
val[3] = lower_32_bits(cycles);
6868
}

arch/x86/kernel/kvmclock.c

Lines changed: 29 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -87,6 +87,27 @@ static u64 kvm_clock_get_cycles(struct clocksource *cs)
8787
return kvm_clock_read();
8888
}
8989

90+
static u64 kvm_clock_get_cycles_snapshot(struct clocksource *cs,
91+
struct clocksource_hw_snapshot *chs)
92+
{
93+
struct pvclock_vcpu_time_info *src;
94+
unsigned version;
95+
u64 ret, tsc;
96+
97+
preempt_disable_notrace();
98+
src = this_cpu_pvti();
99+
do {
100+
version = pvclock_read_begin(src);
101+
tsc = rdtsc_ordered();
102+
ret = __pvclock_read_cycles(src, tsc);
103+
} while (pvclock_read_retry(src, version));
104+
preempt_enable_notrace();
105+
106+
chs->hw_cycles = tsc;
107+
chs->hw_csid = CSID_X86_TSC;
108+
return ret;
109+
}
110+
90111
static noinstr u64 kvm_sched_clock_read(void)
91112
{
92113
return pvclock_clocksource_read_nowd(this_cpu_pvti()) - kvm_sched_clock_offset;
@@ -156,13 +177,14 @@ static int kvm_cs_enable(struct clocksource *cs)
156177
}
157178

158179
static struct clocksource kvm_clock = {
159-
.name = "kvm-clock",
160-
.read = kvm_clock_get_cycles,
161-
.rating = 400,
162-
.mask = CLOCKSOURCE_MASK(64),
163-
.flags = CLOCK_SOURCE_IS_CONTINUOUS,
164-
.id = CSID_X86_KVM_CLK,
165-
.enable = kvm_cs_enable,
180+
.name = "kvm-clock",
181+
.read = kvm_clock_get_cycles,
182+
.read_snapshot = kvm_clock_get_cycles_snapshot,
183+
.rating = 400,
184+
.mask = CLOCKSOURCE_MASK(64),
185+
.flags = CLOCK_SOURCE_IS_CONTINUOUS,
186+
.id = CSID_X86_KVM_CLK,
187+
.enable = kvm_cs_enable,
166188
};
167189

168190
static void kvm_register_clock(char *txt)

drivers/clocksource/hyperv_timer.c

Lines changed: 27 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -444,6 +444,22 @@ static u64 notrace read_hv_clock_tsc_cs(struct clocksource *arg)
444444
return read_hv_clock_tsc();
445445
}
446446

447+
static u64 notrace read_hv_clock_tsc_cs_snapshot(struct clocksource *arg,
448+
struct clocksource_hw_snapshot *chs)
449+
{
450+
u64 time;
451+
452+
if (hv_read_tsc_page_tsc(tsc_page, &chs->hw_cycles, &time)) {
453+
chs->hw_csid = CSID_X86_TSC;
454+
} else {
455+
chs->hw_cycles = 0;
456+
chs->hw_csid = CSID_GENERIC;
457+
time = read_hv_clock_msr();
458+
}
459+
460+
return time;
461+
}
462+
447463
static u64 noinstr read_hv_sched_clock_tsc(void)
448464
{
449465
return (read_hv_clock_tsc() - hv_sched_clock_offset) *
@@ -492,18 +508,19 @@ static int hv_cs_enable(struct clocksource *cs)
492508
#endif
493509

494510
static struct clocksource hyperv_cs_tsc = {
495-
.name = "hyperv_clocksource_tsc_page",
496-
.rating = 500,
497-
.read = read_hv_clock_tsc_cs,
498-
.mask = CLOCKSOURCE_MASK(64),
499-
.flags = CLOCK_SOURCE_IS_CONTINUOUS,
500-
.suspend= suspend_hv_clock_tsc,
501-
.resume = resume_hv_clock_tsc,
511+
.name = "hyperv_clocksource_tsc_page",
512+
.rating = 500,
513+
.read = read_hv_clock_tsc_cs,
514+
.read_snapshot = read_hv_clock_tsc_cs_snapshot,
515+
.mask = CLOCKSOURCE_MASK(64),
516+
.flags = CLOCK_SOURCE_IS_CONTINUOUS,
517+
.suspend = suspend_hv_clock_tsc,
518+
.resume = resume_hv_clock_tsc,
502519
#ifdef HAVE_VDSO_CLOCKMODE_HVCLOCK
503-
.enable = hv_cs_enable,
504-
.vdso_clock_mode = VDSO_CLOCKMODE_HVCLOCK,
520+
.enable = hv_cs_enable,
521+
.vdso_clock_mode = VDSO_CLOCKMODE_HVCLOCK,
505522
#else
506-
.vdso_clock_mode = VDSO_CLOCKMODE_NONE,
523+
.vdso_clock_mode = VDSO_CLOCKMODE_NONE,
507524
#endif
508525
};
509526

drivers/net/dsa/sja1105/sja1105_main.c

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -2310,10 +2310,10 @@ int sja1105_static_config_reload(struct sja1105_private *priv,
23102310
goto out;
23112311
}
23122312

2313-
t1 = timespec64_to_ns(&ptp_sts_before.pre_ts);
2314-
t2 = timespec64_to_ns(&ptp_sts_before.post_ts);
2315-
t3 = timespec64_to_ns(&ptp_sts_after.pre_ts);
2316-
t4 = timespec64_to_ns(&ptp_sts_after.post_ts);
2313+
t1 = ktime_to_ns(ptp_sts_before.pre_sts.systime);
2314+
t2 = ktime_to_ns(ptp_sts_before.post_sts.systime);
2315+
t3 = ktime_to_ns(ptp_sts_after.pre_sts.systime);
2316+
t4 = ktime_to_ns(ptp_sts_after.post_sts.systime);
23172317
/* Mid point, corresponds to pre-reset PTPCLKVAL */
23182318
t12 = t1 + (t2 - t1) / 2;
23192319
/* Mid point, corresponds to post-reset PTPCLKVAL, aka 0 */

drivers/net/ethernet/intel/ice/ice_ptp.c

Lines changed: 4 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -2065,11 +2065,13 @@ static const struct ice_crosststamp_cfg ice_crosststamp_cfg_e830 = {
20652065
/**
20662066
* struct ice_crosststamp_ctx - Device cross timestamp context
20672067
* @snapshot: snapshot of system clocks for historic interpolation
2068+
* @snapshot_clock_id: System clock ID for @snapshot
20682069
* @pf: pointer to the PF private structure
20692070
* @cfg: pointer to hardware configuration for cross timestamp
20702071
*/
20712072
struct ice_crosststamp_ctx {
20722073
struct system_time_snapshot snapshot;
2074+
clockid_t snapshot_clock_id;
20732075
struct ice_pf *pf;
20742076
const struct ice_crosststamp_cfg *cfg;
20752077
};
@@ -2115,7 +2117,7 @@ static int ice_capture_crosststamp(ktime_t *device,
21152117
}
21162118

21172119
/* Snapshot system time for historic interpolation */
2118-
ktime_get_snapshot(&ctx->snapshot);
2120+
ktime_get_snapshot_id(ctx->snapshot_clock_id, &ctx->snapshot);
21192121

21202122
/* Program cmd to master timer */
21212123
ice_ptp_src_cmd(hw, ICE_PTP_READ_TIME);
@@ -2176,6 +2178,7 @@ static int ice_ptp_getcrosststamp(struct ptp_clock_info *info,
21762178
{
21772179
struct ice_pf *pf = ptp_info_to_pf(info);
21782180
struct ice_crosststamp_ctx ctx = {
2181+
.snapshot_clock_id = cts->clock_id,
21792182
.pf = pf,
21802183
};
21812184

drivers/net/ethernet/intel/igc/igc.h

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -326,6 +326,7 @@ struct igc_adapter {
326326
struct timespec64 prev_ptp_time; /* Pre-reset PTP clock */
327327
ktime_t ptp_reset_start; /* Reset time in clock mono */
328328
struct system_time_snapshot snapshot;
329+
clockid_t snapshot_clock_id;
329330
struct mutex ptm_lock; /* Only allow one PTM transaction at a time */
330331

331332
char fw_version[32];

drivers/net/ethernet/intel/igc/igc_ptp.c

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1049,7 +1049,7 @@ static int igc_phc_get_syncdevicetime(ktime_t *device,
10491049
*/
10501050
do {
10511051
/* Get a snapshot of system clocks to use as historic value. */
1052-
ktime_get_snapshot(&adapter->snapshot);
1052+
ktime_get_snapshot_id(adapter->snapshot_clock_id, &adapter->snapshot);
10531053

10541054
igc_ptm_trigger(hw);
10551055

@@ -1103,6 +1103,8 @@ static int igc_ptp_getcrosststamp(struct ptp_clock_info *ptp,
11031103
/* This blocks until any in progress PTM transactions complete */
11041104
mutex_lock(&adapter->ptm_lock);
11051105

1106+
adapter->snapshot_clock_id = cts->clock_id;
1107+
11061108
ret = get_device_system_crosststamp(igc_phc_get_syncdevicetime,
11071109
adapter, &adapter->snapshot, cts);
11081110
mutex_unlock(&adapter->ptm_lock);

drivers/net/ethernet/mellanox/mlx5/core/lib/clock.c

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -340,7 +340,7 @@ static int mlx5_ptp_getcrosststamp(struct ptp_clock_info *ptp,
340340
goto unlock;
341341
}
342342

343-
ktime_get_snapshot(&history_begin);
343+
ktime_get_snapshot_id(cts->clock_id, &history_begin);
344344

345345
err = get_device_system_crosststamp(mlx5_mtctr_syncdevicetime, mdev,
346346
&history_begin, cts);
@@ -366,7 +366,7 @@ static int mlx5_ptp_getcrosscycles(struct ptp_clock_info *ptp,
366366
goto unlock;
367367
}
368368

369-
ktime_get_snapshot(&history_begin);
369+
ktime_get_snapshot_id(cts->clock_id, &history_begin);
370370

371371
err = get_device_system_crosststamp(mlx5_mtctr_syncdevicecyclestime,
372372
mdev, &history_begin, cts);

drivers/net/wireless/intel/iwlwifi/mld/ptp.c

Lines changed: 3 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -250,7 +250,8 @@ iwl_mld_phc_get_crosstimestamp(struct ptp_clock_info *ptp,
250250
/* System (wall) time */
251251
ktime_t sys_time;
252252

253-
memset(xtstamp, 0, sizeof(struct system_device_crosststamp));
253+
if (xtstamp->clock_id != CLOCK_REALTIME)
254+
return -ENOTSUPP;
254255

255256
ret = iwl_mld_get_crosstimestamp_fw(mld, &gp2, &sys_time);
256257
if (ret) {
@@ -270,7 +271,7 @@ iwl_mld_phc_get_crosstimestamp(struct ptp_clock_info *ptp,
270271

271272
/* System monotonic raw time is not used */
272273
xtstamp->device = ns_to_ktime(gp2_ns);
273-
xtstamp->sys_realtime = sys_time;
274+
xtstamp->sys_systime = sys_time;
274275

275276
return ret;
276277
}

0 commit comments

Comments
 (0)