From nobody Mon Jun 8 03:21:17 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 4B42C3E0245; Tue, 2 Jun 2026 09:46:21 +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=1780393582; cv=none; b=cAwAMXIbcga81exE45yGVl7jKYoXnXYX6KuNkDR9KszmUQcMWrQkCraLXYDoP32LuifDCAG4p4KAAc5TnW9fOWHDX48QrVJvd18E3tKKYC+IWqb9hh5DsarohpxFp0YaWu+qXJy9d8lSDgoqCJvuTMzmzPo3bD3s7E8KquTUKlU= ARC-Message-Signature: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1780393582; c=relaxed/simple; bh=qVY4o/8FGCCDcKcZWuAvdFV3+W2G9uWC2JhA/6i1cLk=; h=Date:From:To:Subject:Cc:In-Reply-To:References:MIME-Version: Message-ID:Content-Type; b=L3g3Kq+zBHF6LUYR12l8KDIdbYyLStIbkyJEzRld1JvSf0oG8xPZ31rrkdC/+2a5YCkFzrqRwNZUyPD76TZJ3yq/QqAurtB6cPdTsMZ7wY9EKbLRRUCY8k+uyYvmuOTOizwcK44RT/tAly8OkwWBUBR8KeB8MxhzXKsDQG1xUNw= 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=rvdMnVHr; dkim=permerror (0-bit key) header.d=linutronix.de header.i=@linutronix.de header.b=I+HUiGgD; 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="rvdMnVHr"; dkim=permerror (0-bit key) header.d=linutronix.de header.i=@linutronix.de header.b="I+HUiGgD" Date: Tue, 02 Jun 2026 09:46:18 -0000 DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=linutronix.de; s=2020; t=1780393579; 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=exX0s8aLeBNYANtvAWlfGiN+bN6jvPUubsDWrSW0YH0=; b=rvdMnVHrG0UL2L1J9jOoNwQBQ+sq7rrk+JS0wni0CBTXswUu+wRPSsNMkbpFZrmXBG/Ubq BsvGh4f7lxvB2PFq2QeK4+K3r3n/F7LrjEsliryq/O5xYzZhf2kYy+BRx43/15k1/63erZ LlhkIwn6Y08fiozyMV/5FJr0A0O/LEhNFN3RQlad/F+XRAyq0Gxe2/Ff9fgQP+eaot9Rzn sH4puJ8DHQlnd4Tv/HFbEY7OvJVRGsMEVXL221eRpjgUb1ni3Gw7mT/LwpY6l6lN31YlJg 7K1Bs3qkjsDRE40IwTiHMS0Vye1e/fIBkVbOoWMX9GHQAQNX6vu0SqUbTyrYUQ== DKIM-Signature: v=1; a=ed25519-sha256; c=relaxed/relaxed; d=linutronix.de; s=2020e; t=1780393579; 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=exX0s8aLeBNYANtvAWlfGiN+bN6jvPUubsDWrSW0YH0=; b=I+HUiGgDjDHjfpAee1AIBbBHTNW+P4vzWy+2M4t7DnfAjyRzke9qzxp+DCUdNGBKP6jvaq SE8wmCi8OC9zRYAg== From: "tip-bot2 for Thomas Gleixner" Sender: tip-bot2@linutronix.de Reply-to: linux-kernel@vger.kernel.org To: linux-tip-commits@vger.kernel.org Subject: [tip: timers/ptp] timekeeping: Provide ktime_get_snapshot_id() Cc: Thomas Gleixner , David Woodhouse , Arthur Kiyanovski , thomas.weissschuh@linutronix.de, Jacob Keller , x86@kernel.org, linux-kernel@vger.kernel.org In-Reply-To: <20260529195556.971591633@kernel.org> References: <20260529195556.971591633@kernel.org> Precedence: bulk X-Mailing-List: linux-kernel@vger.kernel.org List-Id: List-Subscribe: List-Unsubscribe: MIME-Version: 1.0 Message-ID: <178039357848.2140988.13747404251861669420.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: eba302268a019275fd6ff452d4ff0b94fef11c76 Gitweb: https://git.kernel.org/tip/eba302268a019275fd6ff452d4ff0b94f= ef11c76 Author: Thomas Gleixner AuthorDate: Fri, 29 May 2026 21:59:51 +02:00 Committer: Thomas Gleixner CommitterDate: Tue, 02 Jun 2026 11:39:57 +02:00 timekeeping: Provide ktime_get_snapshot_id() ktime_get_snapshot() provides a snapshot of the underlying clocksource counter value and the corresponding CLOCK_MONOTONIC_RAW, CLOCK_REALTIME and CLOCK_BOOTTIME timestamps. There is no usage of CLOCK_REALTIME and CLOCK_BOOTTIME at the same time and CLOCK_BOOTTIME support was just added for the ARM64 KVM tracing mechanism, which needs CLOCK_BOOTTIME and the underlying clocksource counter value. ktime_get_snapshot() is also not suitable for usage with CLOCK_AUX, but that's a prerequisite to support PTP hardware timestamping for CLOCK_AUX steering. As a first step, rename ktime_get_snapshot() to ktime_get_snapshot_id(), which now takes a clockid argument to select the clock which needs to be captured. The result is stored in system_time_snapshot::systime, which will replace the system_time_snapshot::real/boot members once all usage sites have been converted. ktime_get_snapshot() is a simple wrapper which hands in CLOCK_REALTIME as clockid argument for the conversion period. That means CLOCK_REALTIME is now captured twice, but that redunancy is only temporary. As all usage sites of struct system_time_snapshot has to be updated anyway, rename the 'raw' member to 'monoraw' for clarity. No functional change vs. current users of ktime_get_snapshot() Signed-off-by: Thomas Gleixner Tested-by: David Woodhouse Tested-by: Arthur Kiyanovski Reviewed-by: David Woodhouse Reviewed-by: Thomas Wei=C3=9Fschuh Reviewed-by: Jacob Keller Link: https://patch.msgid.link/20260529195556.971591633@kernel.org --- include/linux/timekeeping.h | 34 +++++++++----- kernel/time/timekeeping.c | 89 ++++++++++++++++++++++++++---------- 2 files changed, 90 insertions(+), 33 deletions(-) diff --git a/include/linux/timekeeping.h b/include/linux/timekeeping.h index aee2c1a..161157c 100644 --- a/include/linux/timekeeping.h +++ b/include/linux/timekeeping.h @@ -276,24 +276,32 @@ static inline bool ktime_get_aux_ts64(clockid_t id, s= truct timespec64 *kt) { ret #endif =20 /** - * struct system_time_snapshot - simultaneous raw/real time capture with - * counter value - * @cycles: Clocksource counter value to produce the system times - * @real: Realtime system time - * @boot: Boot time - * @raw: Monotonic raw system time - * @cs_id: Clocksource ID + * 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 + * @systime: The system time of the selected CLOCK ID + * @real: Realtime system time + * @boot: Boot time + * @raw: Monotonic raw system time + * @monoraw: Monotonic raw system time + * @cs_id: Clocksource ID * @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 systime; ktime_t real; ktime_t boot; - ktime_t raw; + union { + ktime_t raw; + ktime_t monoraw; + }; enum clocksource_ids cs_id; unsigned int clock_was_set_seq; u8 cs_was_changed_seq; + u8 valid; }; =20 /** @@ -341,9 +349,15 @@ extern int get_device_system_crosststamp( struct system_device_crosststamp *xtstamp); =20 /* - * Simultaneously snapshot realtime and monotonic raw clocks + * Simultaneously snapshot a given clock with MONOTONIC_RAW and the underl= ying + * clocksource counter value. */ -extern void ktime_get_snapshot(struct system_time_snapshot *systime_snapsh= ot); +extern void ktime_get_snapshot_id(clockid_t clock_id, struct system_time_s= napshot *systime_snapshot); + +static inline void ktime_get_snapshot(struct system_time_snapshot *systime= _snapshot) +{ + ktime_get_snapshot_id(CLOCK_REALTIME, systime_snapshot); +} =20 /* * Persistent clock related interfaces diff --git a/kernel/time/timekeeping.c b/kernel/time/timekeeping.c index c493a40..0053dc0 100644 --- a/kernel/time/timekeeping.c +++ b/kernel/time/timekeeping.c @@ -1183,43 +1183,86 @@ noinstr time64_t __ktime_get_real_seconds(void) } =20 /** - * ktime_get_snapshot - snapshots the realtime/monotonic raw clocks with c= ounter - * @systime_snapshot: pointer to struct receiving the system time snapshot - */ -void ktime_get_snapshot(struct system_time_snapshot *systime_snapshot) -{ - struct timekeeper *tk =3D &tk_core.timekeeper; + * ktime_get_snapshot_id - Simultaneously snapshot a given clock ID with + * CLOCK_MONOTONIC_RAW and the underlying + * clocksource counter value. + * @clock_id: The clock ID to snapshot + * @systime_snapshot: Pointer to struct receiving the system time snapshot + */ +void ktime_get_snapshot_id(clockid_t clock_id, struct system_time_snapshot= *systime_snapshot) +{ + ktime_t base_raw, base_sys, offs_sys, *offs, offs_zero =3D 0; + u64 nsec_raw, nsec_sys, now; + struct timekeeper *tk; + struct tk_data *tkd; unsigned int seq; - ktime_t base_raw; ktime_t base_real; ktime_t base_boot; - u64 nsec_raw; - u64 nsec_real; - u64 now; =20 - WARN_ON_ONCE(timekeeping_suspended); + /* Invalidate the snapshot for all failure cases */ + systime_snapshot->valid =3D false; + + if (WARN_ON_ONCE(timekeeping_suspended)) + return; + + switch (clock_id) { + case CLOCK_REALTIME: + tkd =3D &tk_core; + offs =3D &tk_core.timekeeper.offs_real; + break; + /* Map RAW to MONOTONIC so the loop below is trivial */ + case CLOCK_MONOTONIC_RAW: + case CLOCK_MONOTONIC: + tkd =3D &tk_core; + offs =3D &offs_zero; + break; + case CLOCK_BOOTTIME: + tkd =3D &tk_core; + offs =3D &tk_core.timekeeper.offs_boot; + break; + default: + WARN_ON_ONCE(1); + return; + } + + tk =3D &tkd->timekeeper; =20 do { - seq =3D read_seqcount_begin(&tk_core.seq); + seq =3D read_seqcount_begin(&tkd->seq); + now =3D tk_clock_read(&tk->tkr_mono); systime_snapshot->cs_id =3D tk->tkr_mono.clock->id; systime_snapshot->cs_was_changed_seq =3D tk->cs_was_changed_seq; systime_snapshot->clock_was_set_seq =3D tk->clock_was_set_seq; - base_real =3D ktime_add(tk->tkr_mono.base, - tk_core.timekeeper.offs_real); - base_boot =3D ktime_add(tk->tkr_mono.base, - tk_core.timekeeper.offs_boot); + + base_sys =3D tk->tkr_mono.base; + offs_sys =3D *offs; base_raw =3D tk->tkr_raw.base; - nsec_real =3D timekeeping_cycles_to_ns(&tk->tkr_mono, now); - nsec_raw =3D timekeeping_cycles_to_ns(&tk->tkr_raw, now); - } while (read_seqcount_retry(&tk_core.seq, seq)); + + /* Kept around until the callers are fixed up */ + base_real =3D ktime_add(base_sys, tk_core.timekeeper.offs_real); + base_boot =3D ktime_add(base_sys, tk_core.timekeeper.offs_boot); + + nsec_sys =3D timekeeping_cycles_to_ns(&tk->tkr_mono, now); + nsec_raw =3D timekeeping_cycles_to_ns(&tk->tkr_raw, now); + } while (read_seqcount_retry(&tkd->seq, seq)); =20 systime_snapshot->cycles =3D now; - systime_snapshot->real =3D ktime_add_ns(base_real, nsec_real); - systime_snapshot->boot =3D ktime_add_ns(base_boot, nsec_real); - systime_snapshot->raw =3D ktime_add_ns(base_raw, nsec_raw); + systime_snapshot->systime =3D ktime_add_ns(base_sys, offs_sys + nsec_sys); + systime_snapshot->real =3D ktime_add_ns(base_real, nsec_sys); + systime_snapshot->boot =3D ktime_add_ns(base_boot, nsec_sys); + systime_snapshot->monoraw =3D ktime_add_ns(base_raw, nsec_raw); + + /* + * Special case for PTP. Just transfer the raw time into sys, + * so the call sites can consistently use snap::systime. + */ + if (clock_id =3D=3D CLOCK_MONOTONIC_RAW) + systime_snapshot->systime =3D systime_snapshot->monoraw; + /* Tell the consumer that this snapshot is valid */ + systime_snapshot->valid =3D true; } -EXPORT_SYMBOL_GPL(ktime_get_snapshot); +EXPORT_SYMBOL_GPL(ktime_get_snapshot_id); =20 /* Scale base by mult/div checking for overflow */ static int scale64_check_overflow(u64 mult, u64 div, u64 *base)