RE: [PATCH v3] printk: fix zero-valued printk timestamps in early boot

Bird, Tim
2026-03-24T20:23:37Z

Hey Shashank,

Thanks for looking into this, and providing some ideas. See my responses below.

> -----Original Message-----
> From: Shashank Balaji <shashankbalaji02@gmail.com>
>
> Hi Tim, Petr,
>
> On Fri, Mar 13, 2026 at 11:45:02AM +0100, Petr Mladek wrote:
> > Finally added timekeeping maintainers and John into Cc.
> > We should have added time since v1.
> >
> > Anyway, you might see the entire history at
> > https://lore.kernel.org/all/39b09edb-8998-4ebd-a564-7d594434a981@bird.org/
> >
> >
...

>
> Based on the discussions thus far, I see three problems currently:
>
> 1. Three phases of timestamps on consoles printing synchronously is awkward
Agreed.

> 2. Possible userspace breakage:
>
> I don't know how big of a concern this is, but if the timestamps were to not start at zero, any
> tools expecting them to, would be shocked. printk timestamp comparison with CLOCK_BOOTTIME
> wouldn't work anymore.
>
> 3. Counter frequency constancy requirement:
>
> For the early time calibration to be accurate, the counter frequency should be constant from
> processor power on to the end of the calibration. We don't know what the firmware or the bootloader
> may do in-between. If the counter frequency depends on cpu frequency or is just unstable, then we
> should err on the side of caution and bail out of early times. On the other hand, if constant counter
> frequency is architecturally guaranteed or if the cpu advertises so, then we should be good. Like,
> x86 has one only if boot_cpu_has(X86_FEATURE_CONSTANT_TSC), rest are dubious.

I'll need to check when the data for boot_cpu_has() is initialized. I believe it's not available
from the very first kernel instruction, but I may be misremembering. I think almost all
x86_64 processors have invariant TSCs since about 2008, so it might be better to just
document this issue in the config. I don't think a lot of people are optimizing this
100ms to 400ms region of early boot (that this patch is targeted at) on older processors.

>
> Idea: Making the early timestamps start at 0 would partially address these problems:
>
> 1. No awkward three phases of timestamps:
>
> The only difference would be that serial would have a number of timestamps exactly at 0, while userspace
> wouldn't. The early time calibration data would only be used for userspace to convert the counter values
> to timestamps with a zero origin.
>
> 2. Userspace breakage:
>
> CLOCK_BOOTTIME's origin is timekeeping init. So relative to that, the origin of early timestamps would be
> closer, but still different.
>
> Making the early timestamps start at 0 would also lower counter frequency constancy requirement. Now the constancy
> requirement would only be between the period of kernel start to calibration end, a phase in which the kernel is
> in full control. Maybe even if !boot_cpu_has(X86_FEATURE_CONSTANT_TSC), the calibration data would be fine to use?
> This is debatable.
>
> A disadvantage of this method is that visibility into per-kernel duration is lost. But that can be made up for by
> adding something like:
>
> pr_info("Pre-kernel duration: %llu ms\n", pre_kernel_time);
>
> But this information should be taken with a grain of salt if constant counter frequency is not guaranteed.
>
> Another point, since constancy of counter frequency is being relied upon anyway, conversion of counter value to
> timestamp can be done later once counter frequency calibration is complete, instead of doing our own calibration.
> An arch hook like arch_counter_freq() could be provided from which we can get this info. On x86, it would be wired
> up to tsc_khz. If arch_counter_freq() returns 0, that means constant frequency is not guaranteed, so we'd bail
> out of the counter value to timestamp conversion.

Interesting. If I can validate that local_clock() is using the same clock source (TSC) as my early_times calibration,
maybe I *can* just steal the calibration already done when initializing that clock. I'm using the same
routine 'clocks_calc_mult_shift', and maybe it would be better to just grab the numbers that result from
the TSC clock initialization, rather than calling it again (with different numbers) myself. I'll look into this.

Thanks very much for the feedback and ideas.
-- Tim