From nobody Mon Jun 8 03:20:28 2026 Received: from galois.linutronix.de (Galois.linutronix.de [193.142.43.55]) (using TLSv1.2 with cipher ECDHE-RSA-AES256-GCM-SHA384 (256/256 bits)) (No client certificate requested) by smtp.subspace.kernel.org (Postfix) with ESMTPS id EE3B43C8C56; Thu, 4 Jun 2026 09:07:38 +0000 (UTC) Authentication-Results: smtp.subspace.kernel.org; arc=none smtp.client-ip=193.142.43.55 ARC-Seal: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1780564060; cv=none; b=PGqS/qWEm37p8xO2wxYHTsAY63hlkUXEN8JyyO6umyfYXk3yMiKKn2Qa/og+HVflqh8Mg231pg+D4wWYjNnJWUVn2hzL+9GVtZ+VIeQHH6IpTUbMIXWExvO10a8/R+e4a+FVhiFw03XuwLgmlrKFl6McRB90RtNq/qqsqHJoALw= ARC-Message-Signature: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1780564060; c=relaxed/simple; bh=uPxhwqCNlZhyDozmd0cW4MlOZWap6oOjT1WxUosaQ2E=; h=Date:From:To:Subject:Cc:In-Reply-To:References:MIME-Version: Message-ID:Content-Type; b=XYUA7tByH5Yx3qYGPeqlgkL6MdCzj5jEKshYuSiKvX//wjJH3I2+JiJ9WxU+UGpEooe+6nI8fYvbiPr5Q/q4A1PItC9XYMxVLXwhuIqwQIh/utuxSL6T6JEJQkuS4+kB2gFRaJRd0qqeRodS69mvgLL9GEfneTJLji2m5LOXlHI= ARC-Authentication-Results: i=1; smtp.subspace.kernel.org; dmarc=pass (p=none dis=none) header.from=linutronix.de; spf=pass smtp.mailfrom=linutronix.de; dkim=pass (2048-bit key) header.d=linutronix.de header.i=@linutronix.de header.b=rqvcQiDC; dkim=permerror (0-bit key) header.d=linutronix.de header.i=@linutronix.de header.b=DpCzbErQ; arc=none smtp.client-ip=193.142.43.55 Authentication-Results: smtp.subspace.kernel.org; dmarc=pass (p=none dis=none) header.from=linutronix.de Authentication-Results: smtp.subspace.kernel.org; spf=pass smtp.mailfrom=linutronix.de Authentication-Results: smtp.subspace.kernel.org; dkim=pass (2048-bit key) header.d=linutronix.de header.i=@linutronix.de header.b="rqvcQiDC"; dkim=permerror (0-bit key) header.d=linutronix.de header.i=@linutronix.de header.b="DpCzbErQ" Date: Thu, 04 Jun 2026 09:07:35 -0000 DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=linutronix.de; s=2020; t=1780564057; h=from:from:sender:sender:reply-to:reply-to:subject:subject:date:date: message-id:message-id:to:to:cc:cc:mime-version:mime-version: content-type:content-type: content-transfer-encoding:content-transfer-encoding: in-reply-to:in-reply-to:references:references; bh=+QQD2pke8/vigBROVOLqypem3qSItngJ2S3A1u/BHbU=; b=rqvcQiDCOE/2QiD6hDT1Y5VdffkpQFff11gnenvlJnBPydQi2lqQZ0MK9/tFEr/TdPoZak Y9MMpd/QCyxTOnl4bXjhts9y8zVN9Qu+CCKJeQW5g74UZyb8swUDQJJXgfEiiAjnio/rA3 Nvk2EvDN1kKvDuh+pfiJaEyo2F+cYEnmjnMl99YA7SPurSBFzLTR71yNBCycc/IKScLlvC oPyZhaSxJkZgFYDLObiJfTlsoRlbdrgqAwUUEhtznPiYIPosxvdqJd/e1DvJPubUOahIq4 GsOh0dzWEyN61DbASPvor7CikYOydu0drlY7TTHyN3vNuPwxix2eT0khTh1Vyg== DKIM-Signature: v=1; a=ed25519-sha256; c=relaxed/relaxed; d=linutronix.de; s=2020e; t=1780564057; h=from:from:sender:sender:reply-to:reply-to:subject:subject:date:date: message-id:message-id:to:to:cc:cc:mime-version:mime-version: content-type:content-type: content-transfer-encoding:content-transfer-encoding: in-reply-to:in-reply-to:references:references; bh=+QQD2pke8/vigBROVOLqypem3qSItngJ2S3A1u/BHbU=; b=DpCzbErQUluyydC20TE37lKPxUw71uDPOi9g0EHzH9EtDI8nxadcbWW4rRfPMCBI7EuGmU OKLMp0swcyk/8BAw== From: "tip-bot2 for David Woodhouse" Sender: tip-bot2@linutronix.de Reply-to: linux-kernel@vger.kernel.org To: linux-tip-commits@vger.kernel.org Subject: [tip: timers/ptp] timekeeping: Add clocksource read_snapshot() method and hw_cycles to snapshot Cc: David Woodhouse , Thomas Gleixner , Jacob Keller , x86@kernel.org, linux-kernel@vger.kernel.org In-Reply-To: <20260529195558.202568489@kernel.org> References: <20260529195558.202568489@kernel.org> Precedence: bulk X-Mailing-List: linux-kernel@vger.kernel.org List-Id: List-Subscribe: List-Unsubscribe: MIME-Version: 1.0 Message-ID: <178056405583.710.1391677868447342868.tip-bot2@tip-bot2> Robot-ID: Robot-Unsubscribe: Contact to get blacklisted from these emails Precedence: bulk Content-Type: text/plain; charset="utf-8" Content-Transfer-Encoding: quoted-printable The following commit has been merged into the timers/ptp branch of tip: Commit-ID: ca1ec8bfac8c95d0fed9e3611ea21400d1f37262 Gitweb: https://git.kernel.org/tip/ca1ec8bfac8c95d0fed9e3611ea21400d= 1f37262 Author: David Woodhouse AuthorDate: Fri, 29 May 2026 22:01:29 +02:00 Committer: Thomas Gleixner CommitterDate: Thu, 04 Jun 2026 11:04:18 +02:00 timekeeping: Add clocksource read_snapshot() method and hw_cycles to snapsh= ot Add a read_snapshot() callback to struct clocksource which returns the derived clocksource value while also providing the underlying hardware counter reading and the related clocksource ID. This allows ktime_get_snapshot_id() to populate new hw_cycles and hw_csid fields in struct system_time_snapshot. For clocksources that are derived from an underlying counter (e.g., Hyper-V TSC page scales TSC to 10MHz, kvmclock scales TSC to 1GHz), this provides atomic access to both the derived value needed for timekeeping calculations, and the raw hardware counter needed by consumers like KVM's master clock and the vmclock PTP driver. [ tglx: Reworked it slightly ] Signed-off-by: David Woodhouse Signed-off-by: Thomas Gleixner Reviewed-by: Jacob Keller Assisted-by: Kiro:claude-opus-4.6-1m Link: https://patch.msgid.link/20260526230635.136914-1-dwmw2@infradead.org Link: https://patch.msgid.link/20260529195558.202568489@kernel.org --- include/linux/clocksource.h | 24 ++++++++++++++++++++++++ include/linux/timekeeping.h | 6 ++++++ kernel/time/timekeeping.c | 21 ++++++++++++++++++++- 3 files changed, 50 insertions(+), 1 deletion(-) diff --git a/include/linux/clocksource.h b/include/linux/clocksource.h index 7c38190..6d9ddf1 100644 --- a/include/linux/clocksource.h +++ b/include/linux/clocksource.h @@ -32,6 +32,21 @@ struct module; #include =20 /** + * struct clocksource_hw_snapshot - Snapshot for the underlying hardware c= ounter 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 snap= shot + */ +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. * This is the structure used for system time. @@ -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; =20 + u64 (*read_snapshot)(struct clocksource *cs, struct clocksource_hw_snap= shot *chs); int (*enable)(struct clocksource *cs); void (*disable)(struct clocksource *cs); void (*suspend)(struct clocksource *cs); diff --git a/include/linux/timekeeping.h b/include/linux/timekeeping.h index 7f03e1c..984a866 100644 --- a/include/linux/timekeeping.h +++ b/include/linux/timekeeping.h @@ -279,18 +279,24 @@ static inline bool ktime_get_aux_ts64(clockid_t id, s= truct timespec64 *kt) { ret * struct system_time_snapshot - Simultaneous time capture of CLOCK_MONOTO= NIC_RAW, * a selected CLOCK_* and the clocksource counter value * @cycles: Clocksource counter value to produce the system times + * @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; + 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; diff --git a/kernel/time/timekeeping.c b/kernel/time/timekeeping.c index 65d870c..0d5b67f 100644 --- a/kernel/time/timekeeping.c +++ b/kernel/time/timekeeping.c @@ -320,6 +320,7 @@ static __always_inline u64 tk_clock_read(const struct t= k_read_base *tkr) =20 return clock->read(clock); } + static inline void clocksource_disable_inline_read(void) { } static inline void clocksource_enable_inline_read(void) { } #endif @@ -1187,6 +1188,18 @@ noinstr time64_t __ktime_get_real_seconds(void) return tk->xtime_sec; } =20 +static inline u64 tk_clock_read_snapshot(const struct tk_read_base *tkr, + struct clocksource_hw_snapshot *chs) +{ + struct clocksource *clock =3D READ_ONCE(tkr->clock); + + if (unlikely(clock->read_snapshot)) + return clock->read_snapshot(clock, chs); + + return clock->read(clock); +} + + /** * ktime_get_snapshot_id - Simultaneously snapshot a given clock ID with * CLOCK_MONOTONIC_RAW and the underlying @@ -1237,14 +1250,20 @@ void ktime_get_snapshot_id(clockid_t clock_id, stru= ct system_time_snapshot *syst tk =3D &tkd->timekeeper; =20 do { + struct clocksource_hw_snapshot chs =3D { }; + seq =3D read_seqcount_begin(&tkd->seq); =20 /* Aux clocks can be invalid */ if (!tk->clock_valid) return; =20 - now =3D tk_clock_read(&tk->tkr_mono); + now =3D tk_clock_read_snapshot(&tk->tkr_mono, &chs); systime_snapshot->cs_id =3D tk->tkr_mono.clock->id; + + systime_snapshot->hw_cycles =3D chs.hw_cycles; + systime_snapshot->hw_csid =3D chs.hw_csid; + systime_snapshot->cs_was_changed_seq =3D tk->cs_was_changed_seq; systime_snapshot->clock_was_set_seq =3D tk->clock_was_set_seq; =20