RE: [PATCH v6 08/11] timekeeping: Add function to convert realtime to base clock

From: D, Lakshmi Sowjanya
Date: Tue Apr 16 2024 - 06:17:51 EST




> -----Original Message-----
> From: Thomas Gleixner <tglx@xxxxxxxxxxxxx>
> Sent: Thursday, April 11, 2024 3:46 AM
> To: D, Lakshmi Sowjanya <lakshmi.sowjanya.d@xxxxxxxxx>;
> jstultz@xxxxxxxxxx; giometti@xxxxxxxxxxxx; corbet@xxxxxxx; linux-
> kernel@xxxxxxxxxxxxxxx
> Cc: x86@xxxxxxxxxx; netdev@xxxxxxxxxxxxxxx; linux-doc@xxxxxxxxxxxxxxx; intel-
> wired-lan@xxxxxxxxxxxxxxxx; andriy.shevchenko@xxxxxxxxxxxxxxx; Dong, Eddie
> <eddie.dong@xxxxxxxxx>; Hall, Christopher S <christopher.s.hall@xxxxxxxxx>;
> Brandeburg, Jesse <jesse.brandeburg@xxxxxxxxx>; davem@xxxxxxxxxxxxx;
> alexandre.torgue@xxxxxxxxxxx; joabreu@xxxxxxxxxxxx;
> mcoquelin.stm32@xxxxxxxxx; perex@xxxxxxxx; linux-sound@xxxxxxxxxxxxxxx;
> Nguyen, Anthony L <anthony.l.nguyen@xxxxxxxxx>;
> peter.hilber@xxxxxxxxxxxxxxx; N, Pandith <pandith.n@xxxxxxxxx>; Mohan,
> Subramanian <subramanian.mohan@xxxxxxxxx>; T R, Thejesh Reddy
> <thejesh.reddy.t.r@xxxxxxxxx>; D, Lakshmi Sowjanya
> <lakshmi.sowjanya.d@xxxxxxxxx>
> Subject: Re: [PATCH v6 08/11] timekeeping: Add function to convert realtime to
> base clock
>
> On Wed, Apr 10 2024 at 17:18, lakshmi.sowjanya.d@xxxxxxxxx wrote:
> > From: Lakshmi Sowjanya D <lakshmi.sowjanya.d@xxxxxxxxx>
> >
> > PPS(Pulse Per Second) generates signals in realtime, but Timed IO
>
> ... generates signals based on CLOCK_REALTIME, but ...
>
> > hardware understands time in base clock reference.
>
> The hardware does not understand anything.
>
> > Add an interface,
> > ktime_real_to_base_clock() to convert realtime to base clock.
> >
> > Add the helper function timekeeping_clocksource_has_base(), to check
> > whether the current clocksource has the same base clock. This will be
> > used by Timed IO device to check if the base clock is X86_ART(Always
> > Running Timer).
>
> Again this fails to explain the rationale and as this is a core change which is
> hardware agnostic the whole Timed IO and ART reference is not really helpful.
> Something like this:
>
> "PPS (Pulse Per Second) generates a hardware pulse every second based
> on CLOCK_REALTIME. This works fine when the pulse is generated in
> software from a hrtimer callback function.
>
> For hardware which generates the pulse by programming a timer it's
> required to convert CLOCK_REALTIME to the underlying hardware clock.
>
> The X86 Timed IO device is based on the Always Running Timer (ART),
> which is the base clock of the TSC, which is usually the system
> clocksource on X86.
>
> The core code already has functionality to convert base clock
> timestamps to system clocksource timestamps, but there is no support
> for converting the other way around.
>
> Provide the required functionality to support such devices in a
> generic way to avoid code duplication in drivers:
>
> 1) ktime_real_to_base_clock() to convert a CLOCK_REALTIME
> timestamp to a base clock timestamp
>
> 2) timekeeping_clocksource_has_base() to allow drivers to validate
> that the system clocksource is based on a particular
> clocksource ID.

Thanks for the commit message.
I will update as suggested.

>
> > +static bool convert_cs_to_base(u64 *cycles, enum clocksource_ids
> > +base_id) {
> > + struct clocksource *cs = tk_core.timekeeper.tkr_mono.clock;
> > + struct clocksource_base *base = cs->base;
> > +
> > + /* Check whether base_id matches the base clock */
> > + if (!base || base->id != base_id)
> > + return false;
> > +
> > + *cycles -= base->offset;
> > + if (!convert_clock(cycles, base->denominator, base->numerator))
> > + return false;
> > + return true;
> > +}
> > +
> > +static u64 convert_ns_to_cs(u64 delta) {
> > + struct tk_read_base *tkr = &tk_core.timekeeper.tkr_mono;
> > +
> > + return div_u64((delta << tkr->shift) - tkr->xtime_nsec, tkr->mult);
> > +}
>
> > +bool ktime_real_to_base_clock(ktime_t treal, enum clocksource_ids
> > +base_id, u64 *cycles)
>
> As this is a kernel API function it really wants kernel-doc comment to explain the
> functionality, the arguments and the return value.

Will add the following documentation:

" ktime_real_to_base_clock()- Convert CLOCK_REALTIME timestamp to a base clock timestamp.
@treal: CLOCK_REALTIME timestamp to convert.
@base_id: base clocksource id.
@*cycles: pointer to store the converted base clock timestamp.

Converts a supplied, future realtime clock value to the corresponding base clock value.

Return: true if the conversion is successful, false otherwise."

>
> > +{
> > + struct timekeeper *tk = &tk_core.timekeeper;
> > + unsigned int seq;
> > + u64 delta;
> > +
> > + do {
> > + seq = read_seqcount_begin(&tk_core.seq);
> > + if ((u64)treal < tk->tkr_mono.base_real)
> > + return false;
> > + delta = (u64)treal - tk->tkr_mono.base_real;
>
> In the previous version you had a sanity check on delta:
>
> >>> + if (delta > tk->tkr_mono.clock->max_idle_ns)
> >>> + return false;
>
> And I told you:
>
> >> I don't think this cutoff is valid. There is no guarantee that this
> >> is linear unless:
> >>
> >> Treal[last timekeeper update] <= treal < Treal[next timekeeper
> >> update]
> >>
> >> Look at the dance in get_device_system_crosststamp() and
> >> adjust_historical_crosststamp() to see why.
>
> So now there is not even a check anymore whether the delta conversion can
> overflow.
>
> There is zero explanation why this conversion is considered to be correct.

Adding the following check for delta overflow in convert_ns_to_cs function.

if (BITS_TO_BYTES(fls64(*delta) + tkr->shift) >= sizeof(*delta))
return false;

>
> > + *cycles = tk->tkr_mono.cycle_last + convert_ns_to_cs(delta);
> > + if (!convert_cs_to_base(cycles, base_id))
> > + return false;
> > + } while (read_seqcount_retry(&tk_core.seq, seq));
> > +
> > + return true;
> > +}
>
> > +/**
> > + * timekeeping_clocksource_has_base - Check whether the current
> clocksource
> > + * has a base clock
>
> s/has a base clock/is based on a given base clock
>
> > + * @id: The clocksource ID to check for
>
> base clocksource ID
>
> > + *
> > + * Note: The return value is a snapshot which can become invalid right
> > + * after the function returns.
> > + *
> > + * Return: true if the timekeeper clocksource has a base clock with @id,
> > + * false otherwise
> > + */
>
> Thanks,
>
> tglx