[<prev] [next>] [thread-next>] [day] [month] [year] [list]
Message-ID: <20250724115657.150-1-darinzon@amazon.com>
Date: Thu, 24 Jul 2025 14:56:56 +0300
From: David Arinzon <darinzon@...zon.com>
To: David Miller <davem@...emloft.net>, Jakub Kicinski <kuba@...nel.org>,
Richard Cochran <richardcochran@...il.com>, Eric Dumazet
<edumazet@...gle.com>, Paolo Abeni <pabeni@...hat.com>, "Woodhouse, David"
<dwmw@...zon.com>, Andrew Lunn <andrew@...n.ch>, Miroslav Lichvar
<mlichvar@...hat.com>, David Woodhouse <dwmw2@...radead.org>, Thomas Gleixner
<tglx@...utronix.de>, <netdev@...r.kernel.org>
CC: David Arinzon <darinzon@...zon.com>, "Machulsky, Zorik"
<zorik@...zon.com>, "Matushevsky, Alexander" <matua@...zon.com>, Saeed Bshara
<saeedb@...zon.com>, "Wilson, Matt" <msw@...zon.com>, "Liguori, Anthony"
<aliguori@...zon.com>, "Bshara, Nafea" <nafea@...zon.com>, "Schmeilin,
Evgeny" <evgenys@...zon.com>, "Belgazal, Netanel" <netanel@...zon.com>,
"Saidi, Ali" <alisaidi@...zon.com>, "Herrenschmidt, Benjamin"
<benh@...zon.com>, "Kiyanovski, Arthur" <akiyano@...zon.com>, "Dagan, Noam"
<ndagan@...zon.com>, "Bernstein, Amit" <amitbern@...zon.com>, "Ostrovsky,
Evgeny" <evostrov@...zon.com>, "Tabachnik, Ofir" <ofirt@...zon.com>, "Julien
Ridoux" <ridouxj@...zon.com>, Josh Levinson <joshlev@...zon.com>
Subject: [RFC PATCH net-next] ptp: Introduce PTP_SYS_OFFSET_EXTENDED_TRUSTED ioctl
This patch introduces a new ioctl command,
PTP_SYS_OFFSET_EXTENDED_TRUSTED, to the Linux PTP subsystem.
The existing PTP_SYS_OFFSET_EXTENDED ioctl enables user-space
applications to correlate timestamps between system and PTP clocks
using raw measurements. These timestamps are used, for example,
by applications such as phc2sys to synchronize the system clock
from a PHC device.
The existing PTP APIs lack information about the synchronization
status and the quality of time offered by the PHC device. This
limitation is commonly circumvented by user-space tools such as
ptp4l. These tools implement the synchronization logic and can
export their measurement of clock accuracy and report on
synchronization status, and possible failures.
The proposed PTP_SYS_OFFSET_EXTENDED_TRUSTED ioctl offers the
same timestamps as the PTP_SYS_OFFSET_EXTENDED ioctl, but extends
it with a measurement of the PHC device clock accuracy and the
synchronization status. This supports two objectives.
The first objective focuses on the use case where the PHC device
is fully managed. The ENA driver, for example, exposes a PHC
device, whose synchronization status and quality is maintained
without any user-space application. This new ioctl reports on the
clock accuracy and status of the PHC device to user-space
applications, where ptp4l and similar are not available.
The second objective is to provide user-space applications with a
complete view of the current time and associated quality of the
PHC device in one-single call. This objective benefits the
consumers of time offered by the PHC device, independent from how
it is kept in sync (using ptp4l or being a managed device).
The proposed PTP_SYS_OFFSET_EXTENDED_TRUSTED ioctl fulfills both
objectives by extending each PHC timestamp with two quality
indicators:
- error_bound: a device-calculated value (in nanoseconds)
reflecting the maximum possible deviation of the timestamp from
the true time, based on internal clock state.
- clock_status: a qualitative state of the clock, with defined
values including:
1. Unknown: the clock's synchronization status cannot be
reliably determined.
2. Initializing: the clock is acquiring synchronization.
3. Synchronized: The clock is actively being synchronized and
maintained accurately by the device.
4. FreeRunning: the clock is drifting and not being
synchronized and updated by the device.
5. Unreliable: the clock is known to be unreliable, the
error_bound value cannot be trusted.
Note that the value taken by the clock status aligns with the
definition of the ptp_vmclock device and has the same semantic.
The status value are meant to be vendor-agnostic, and generic
enough to be mapped to specific protocols, including the
clockAccuracy and clockClass concepts defined within the IEEE
1588 standard.
This ioctl enables applications to directly obtain clock quality
metrics from the device, reducing the need for indirect inference
and simplifying clock monitoring.
Signed-off-by: Amit Bernstein <amitbern@...zon.com>
Signed-off-by: David Arinzon <darinzon@...zon.com>
---
drivers/ptp/ptp_chardev.c | 61 ++++++++++++++++++++++++++
include/linux/ptp_clock_kernel.h | 19 +++++++++
include/uapi/linux/ptp_clock.h | 73 ++++++++++++++++++++++++++++++++
3 files changed, 153 insertions(+)
diff --git a/drivers/ptp/ptp_chardev.c b/drivers/ptp/ptp_chardev.c
index 4ca5a464..12fef95c 100644
--- a/drivers/ptp/ptp_chardev.c
+++ b/drivers/ptp/ptp_chardev.c
@@ -365,6 +365,64 @@ static long ptp_sys_offset_extended(struct ptp_clock *ptp, void __user *arg)
return copy_to_user(arg, extoff, sizeof(*extoff)) ? -EFAULT : 0;
}
+static long ptp_sys_offset_extended_trusted(struct ptp_clock *ptp,
+ void __user *arg)
+{
+ struct ptp_sys_offset_extended_trusted *extofftrst __free(kfree) = NULL;
+ struct ptp_system_timestamp sts;
+ struct ptp_clock_attributes att;
+
+ if (!ptp->info->gettimextrusted64)
+ return -EOPNOTSUPP;
+
+ extofftrst = memdup_user(arg, sizeof(*extofftrst));
+ if (IS_ERR(extofftrst))
+ return PTR_ERR(extofftrst);
+
+ if (extofftrst->n_samples > PTP_MAX_SAMPLES ||
+ extofftrst->rsv[0] ||
+ extofftrst->rsv[1])
+ return -EINVAL;
+
+ switch (extofftrst->clockid) {
+ case CLOCK_REALTIME:
+ case CLOCK_MONOTONIC:
+ case CLOCK_MONOTONIC_RAW:
+ break;
+ case CLOCK_AUX ... CLOCK_AUX_LAST:
+ if (IS_ENABLED(CONFIG_POSIX_AUX_CLOCKS))
+ break;
+ fallthrough;
+ default:
+ return -EINVAL;
+ }
+
+ sts.clockid = extofftrst->clockid;
+ for (unsigned int i = 0; i < extofftrst->n_samples; i++) {
+ struct timespec64 ts;
+ int err;
+
+ err = ptp->info->gettimextrusted64(ptp->info, &ts, &sts, &att);
+ if (err)
+ return err;
+
+ /* Filter out disabled or unavailable clocks */
+ if (sts.pre_ts.tv_sec < 0 || sts.post_ts.tv_sec < 0)
+ return -EINVAL;
+
+ extofftrst->ts[i][0].pct.sec = sts.pre_ts.tv_sec;
+ extofftrst->ts[i][0].pct.nsec = sts.pre_ts.tv_nsec;
+ extofftrst->ts[i][1].pct.sec = ts.tv_sec;
+ extofftrst->ts[i][1].pct.nsec = ts.tv_nsec;
+ extofftrst->ts[i][1].att.error_bound = att.error_bound;
+ extofftrst->ts[i][1].att.clock_status = att.clock_status;
+ extofftrst->ts[i][2].pct.sec = sts.post_ts.tv_sec;
+ extofftrst->ts[i][2].pct.nsec = sts.post_ts.tv_nsec;
+ }
+
+ return copy_to_user(arg, extofftrst, sizeof(*extofftrst)) ? -EFAULT : 0;
+}
+
static long ptp_sys_offset(struct ptp_clock *ptp, void __user *arg)
{
struct ptp_sys_offset *sysoff __free(kfree) = NULL;
@@ -503,6 +561,9 @@ long ptp_ioctl(struct posix_clock_context *pccontext, unsigned int cmd,
case PTP_SYS_OFFSET_EXTENDED2:
return ptp_sys_offset_extended(ptp, argptr);
+ case PTP_SYS_OFFSET_EXTENDED_TRUSTED:
+ return ptp_sys_offset_extended_trusted(ptp, argptr);
+
case PTP_SYS_OFFSET:
case PTP_SYS_OFFSET2:
return ptp_sys_offset(ptp, argptr);
diff --git a/include/linux/ptp_clock_kernel.h b/include/linux/ptp_clock_kernel.h
index 3d089bd4..cd74e32f 100644
--- a/include/linux/ptp_clock_kernel.h
+++ b/include/linux/ptp_clock_kernel.h
@@ -120,6 +120,21 @@ struct ptp_system_timestamp {
* reading the lowest bits of the PHC timestamp and the second
* reading immediately follows that.
*
+ * @gettimextrusted64: Reads the current time from the hardware clock and
+ * optionally also the system clock with additional data on
+ * hardware clock accuracy and reliability.
+ * parameter ts: Holds the PHC timestamp.
+ * parameter sts: If not NULL, it holds a pair of
+ * timestamps from the system clock. The first reading is
+ * made right before reading the lowest bits of the PHC
+ * timestamp and the second reading immediately follows
+ * that.
+ * parameter error_bound: If not NULL, it holds the maximum
+ * error bound for the PHC timestamp in nanoseconds.
+ * parameter clock_status: If not NULL, it holds
+ * qualitative clock states indicating its synchronization
+ * status and reliability.
+ *
* @getcrosststamp: Reads the current time from the hardware clock and
* system clock simultaneously.
* parameter cts: Contains timestamp (device,system) pair,
@@ -200,6 +215,10 @@ struct ptp_clock_info {
int (*gettime64)(struct ptp_clock_info *ptp, struct timespec64 *ts);
int (*gettimex64)(struct ptp_clock_info *ptp, struct timespec64 *ts,
struct ptp_system_timestamp *sts);
+ int (*gettimextrusted64)(struct ptp_clock_info *ptp,
+ struct timespec64 *ts,
+ struct ptp_system_timestamp *sts,
+ struct ptp_clock_attributes *att);
int (*getcrosststamp)(struct ptp_clock_info *ptp,
struct system_device_crosststamp *cts);
int (*settime64)(struct ptp_clock_info *p, const struct timespec64 *ts);
diff --git a/include/uapi/linux/ptp_clock.h b/include/uapi/linux/ptp_clock.h
index 18eefa6d..bb22ed61 100644
--- a/include/uapi/linux/ptp_clock.h
+++ b/include/uapi/linux/ptp_clock.h
@@ -76,6 +76,26 @@
*/
#define PTP_PEROUT_V1_VALID_FLAGS (0)
+/*
+ * Clock status values for struct ptp_clock_attributes.clock_status
+ */
+enum ptp_clock_status {
+ /* clock synchronization status cannot be reliably determined */
+ PTP_CLOCK_STATUS_UNKNOWN = 0,
+
+ /* clock is acquiring synchronization */
+ PTP_CLOCK_STATUS_INITIALIZING = 1,
+
+ /* clock is synchronized and maintained accurately by the device */
+ PTP_CLOCK_STATUS_SYNCED = 2,
+
+ /* clock is drifting and not being synchronized by the device */
+ PTP_CLOCK_STATUS_FREE_RUNNING = 3,
+
+ /* clock is unreliable, the error_bound value cannot be trusted */
+ PTP_CLOCK_STATUS_UNRELIABLE = 4
+};
+
/*
* struct ptp_clock_time - represents a time value
*
@@ -91,6 +111,33 @@ struct ptp_clock_time {
__u32 reserved;
};
+/*
+ * struct ptp_clock_attributes - describes additional data for a PTP clock
+ * timestamp
+ *
+ * @error_bound: The maximum possible error (in nanoseconds) associated with
+ * the reported timestamp, this value quantifies the inaccuracy
+ * of the clock at the time of reading.
+ * @clock_status: Qualitative state of the clock (enum ptp_clock_status)
+ * @rsv: Reserved for future use, should be set to zero.
+ */
+struct ptp_clock_attributes {
+ __u32 error_bound;
+ __u8 clock_status;
+ __u8 rsv[3];
+};
+
+/*
+ * struct ptp_clock_time_trusted - PTP timestamp with its associated attributes
+ *
+ * @pct: The PTP clock timestamp value.
+ * @att: PTP clock attributes about the timestamp
+ */
+struct ptp_clock_time_trusted {
+ struct ptp_clock_time pct;
+ struct ptp_clock_attributes att;
+};
+
struct ptp_clock_caps {
int max_adj; /* Maximum frequency adjustment in parts per billon. */
int n_alarm; /* Number of programmable alarms. */
@@ -177,6 +224,30 @@ struct ptp_sys_offset_extended {
struct ptp_clock_time ts[PTP_MAX_SAMPLES][3];
};
+/*
+ * ptp_sys_offset_extended_trusted - data structure for IOCTL operation
+ * PTP_SYS_OFFSET_EXTENDED_TRUSTED
+ *
+ * @n_samples: Desired number of measurements.
+ * @clockid: clockid of a clock-base used for pre/post timestamps.
+ * @rsv: Reserved for future use.
+ * @ts: Array of samples in the form [pre-TS, PHC, post-TS].
+ * Each sample consists of timestamp in the form [sec, nsec],
+ * while the PHC sample also includes clock attributes in the form
+ * [error_bound, clock_status],
+ *
+ * Starting from kernel 6.12 and onwards, the first word of the reserved-field
+ * is used for @clockid. That's backward compatible since previous kernel
+ * expect all three reserved words (@rsv[3]) to be 0 while the clockid (first
+ * word in the new structure) for CLOCK_REALTIME is '0'.
+ */
+struct ptp_sys_offset_extended_trusted {
+ unsigned int n_samples;
+ __kernel_clockid_t clockid;
+ unsigned int rsv[2];
+ struct ptp_clock_time_trusted ts[PTP_MAX_SAMPLES][3];
+};
+
struct ptp_sys_offset_precise {
struct ptp_clock_time device;
struct ptp_clock_time sys_realtime;
@@ -231,6 +302,8 @@ struct ptp_pin_desc {
_IOWR(PTP_CLK_MAGIC, 8, struct ptp_sys_offset_precise)
#define PTP_SYS_OFFSET_EXTENDED \
_IOWR(PTP_CLK_MAGIC, 9, struct ptp_sys_offset_extended)
+#define PTP_SYS_OFFSET_EXTENDED_TRUSTED \
+ _IOWR(PTP_CLK_MAGIC, 10, struct ptp_sys_offset_extended_trusted)
#define PTP_CLOCK_GETCAPS2 _IOR(PTP_CLK_MAGIC, 10, struct ptp_clock_caps)
#define PTP_EXTTS_REQUEST2 _IOW(PTP_CLK_MAGIC, 11, struct ptp_extts_request)
--
2.47.1
Powered by blists - more mailing lists