Embedded Linux development
 help / color / mirror / Atom feed
* hello
From: zh yon @ 2025-12-27 11:55 UTC (permalink / raw)
  To: linux-embedded

subscribe linux-embedded

^ permalink raw reply

* hello
From: zh yon @ 2025-12-27 11:52 UTC (permalink / raw)
  To: linux-embedded

subscrube linux-embedded

^ permalink raw reply

* Re: [PATCH] printk: add early_counter_ns routine for printk blind spot
From: Petr Mladek @ 2025-11-27 16:16 UTC (permalink / raw)
  To: Bird, Tim
  Cc: Geert Uytterhoeven, Francesco Valla, Tim Bird, Steve Rostedt,
	john.ogness@linutronix.de, senozhatsky@chromium.org,
	Andrew Morton, LKML, Linux Embedded
In-Reply-To: <MW5PR13MB5632A34DAEDD321E9813F997FDDFA@MW5PR13MB5632.namprd13.prod.outlook.com>

On Thu 2025-11-27 00:16:23, Bird, Tim wrote:
> 
> 
> > -----Original Message-----
> > From: Geert Uytterhoeven <geert@linux-m68k.org>
> > Hi all,
> > 
> > On Wed, 26 Nov 2025 at 03:24, Francesco Valla <francesco@valla.it> wrote:
> > > On Mon, Nov 24, 2025 at 10:30:52PM -0700, Tim Bird wrote:
> > > > From: Tim Bird <tim.bird@sony.com>
> > > >
> > > > During early boot, printk timestamps are reported as zero,
> > > > which creates a blind spot in early boot timings.  This blind
> > > > spot hinders timing and optimization efforts for code that
> > > > executes before time_init(), which is when local_clock() is
> > > > initialized sufficiently to start returning non-zero timestamps.
> > > > This period is about 400 milliseconds for many current desktop
> > > > and embedded machines running Linux.
> > > >
> > > > Add an early_counter_ns function that returns nanosecond
> > > > timestamps based on get_cycles().  get_cycles() is operational
> > > > on arm64 and x86_64 from kernel start.  Add some calibration
> > > > printks to allow setting configuration variables that are used
> > > > to convert cycle counts to nanoseconds (which are then used
> > > > in early printks).  Add CONFIG_EARLY_COUNTER_NS, as well as
> > > > some associated conversion variables, as new kernel config
> > > > variables.
> > > >
> > > > After proper configuration, this yields non-zero timestamps for
> > > > printks from the very start of kernel execution.  The timestamps
> > > > are relative to the start of the architecture-specific counter
> > > > used in get_cycles (e.g. the TSC on x86_64 and cntvct_el0 on arm64).
> > > > This means that the time reported reflects time-from-power-on for
> > > > most embedded products.  This is also a useful data point for
> > > > boot-time optimization work.
> > > >
> > > > Note that there is a discontinuity in the timestamp sequencing
> > > > when standard clocks are finally initialized in time_init().
> > > > The printk timestamps are thus not monotonically increasing
> > > > through the entire boot.
> > >
> > > This is... not going to work, IMO, and might lead to breakages in
> > > userspace tools (are printk timings a userspace API?).
> > 
> > I think they are.
> > 
> > Another approach would be to defer the calibration/conversion to
> > userspace, and make sure the early part stands out.
> > I.e. when real timekeeping is available, kernel messages are prefixed by
> > "[%5lu.%06lu]".  Early messages could be prefixed by a plain integer
> > "[%12u]", containing the raw cycle counter value.
> > The presence of the decimal point would make the difference obvious.
> 
> I thought about this while I was creating this.
> It wouldn't require the extra configuration for MULT and SHIFT (which would be nice),
> and it would be, as you say, very obvious that this was not a regular timestamp. 
> This means it could be enabled on a generic kernel (making more likely it could be
> enabled by default). And really only boot-time optimizers would care enough to
> decode the data, so the onus would be on them to run the tool.  Everyone else
> could ignore them.
> 
> I'm not sure if it would break existing printk-processing tools.  I suspect it would.

I guess that it might break even basic tools, like dmesg, journalctl,
or crash.

A solution might be to pass it as an extra information to the official
timestamp, for example:

  + on console:

      <level>[timestamp][callerid][cl cycles] message
      <6>[    0.000000][    T0][cl  345678] BIOS-provided physical RAM map:
      <6>[    0.000000][    T0][cl 1036890] BIOS-e820: [mem 0x0000000000000000-0x000000000009fbff] usable
      <6>[    0.000000][    T0][cl 1129452] BIOS-e820: [mem 0x000000000009fc00-0x000000000009ffff] reserved

  + via /dev/kmsg

     <level>,<sequnum>,<timestamp>,<contflag>[,additional_values, ... ];<message text>
     6,2,0,-,caller=T0,cycle=345678;BIOS-provided physical RAM map:
     6,3,0,-,caller=T0,cycle=1036890;BIOS-e820: [mem 0x0000000000000000-0x000000000009fbff] usable
     6,4,0,-,caller=T0,cycle=1129452;BIOS-e820: [mem 0x000000000009fc00-0x000000000009ffff] reserved

The extra field would disappear after time_init().

The value might be stored in struct printk_info in the same field .ts_nsec.
It might be distinguished from a real timestamp using a flag in
enum printk_info_flags. The official timestamp would be zero when
this flag is set.

It will not require the two CONFIG_ values for calibrating the
computation.

The output on the console is a bit messy. But I guess that this
feature is rather for tuning and it won't be enabled on production
systems. So it might be acceptable.

time_init() might even print a message with the cycle value
and the official timestamp on the same line. It can be used
for post-processing and translating cycles back to ns.

> Also,  I find that post-processing tools often get overlooked.
> I asked at ELC this year how many people are using show_delta, which 
> has been upstream for years, and can do a few neat things with printk timestamps,
> and not a single person had even heard of it.

Yeah. We need to make sure that the post processing tool won't get mad,
for example, crash or show garbage.

Best Regards,
Petr

^ permalink raw reply

* Re: [PATCH] printk: add early_counter_ns routine for printk blind spot
From: kernel test robot @ 2025-11-27  9:13 UTC (permalink / raw)
  To: Tim Bird, pmladek, Steve Rostedt, john.ogness, senozhatsky
  Cc: oe-kbuild-all, Tim Bird, Andrew Morton,
	Linux Memory Management List, Francesco Valla, LKML,
	Linux Embedded
In-Reply-To: <39b09edb-8998-4ebd-a564-7d594434a981@bird.org>

Hi Tim,

kernel test robot noticed the following build errors:

[auto build test ERROR on linus/master]
[also build test ERROR on v6.18-rc7]
[cannot apply to akpm-mm/mm-everything next-20251127]
[If your patch is applied to the wrong git tree, kindly drop us a note.
And when submitting patch, we suggest to use '--base' as documented in
https://git-scm.com/docs/git-format-patch#_base_tree_information]

url:    https://github.com/intel-lab-lkp/linux/commits/Tim-Bird/printk-add-early_counter_ns-routine-for-printk-blind-spot/20251125-133242
base:   linus/master
patch link:    https://lore.kernel.org/r/39b09edb-8998-4ebd-a564-7d594434a981%40bird.org
patch subject: [PATCH] printk: add early_counter_ns routine for printk blind spot
config: i386-randconfig-2006-20250825 (https://download.01.org/0day-ci/archive/20251127/202511271051.yfp2O98B-lkp@intel.com/config)
compiler: gcc-14 (Debian 14.2.0-19) 14.2.0
reproduce (this is a W=1 build): (https://download.01.org/0day-ci/archive/20251127/202511271051.yfp2O98B-lkp@intel.com/reproduce)

If you fix the issue in a separate patch/commit (i.e. not just a new version of
the same patch/commit), kindly add following tags
| Reported-by: kernel test robot <lkp@intel.com>
| Closes: https://lore.kernel.org/oe-kbuild-all/202511271051.yfp2O98B-lkp@intel.com/

All errors (new ones prefixed by >>):

   ld: init/main.o: in function `kernel_init':
>> init/main.c:1522:(.ref.text+0x201): undefined reference to `__udivdi3'


vim +1522 init/main.c

  1481	
  1482	static int __ref kernel_init(void *unused)
  1483	{
  1484		int ret;
  1485		u64 end_cycles, end_ns;
  1486		u32 early_mult, early_shift;
  1487	
  1488		/*
  1489		 * Wait until kthreadd is all set-up.
  1490		 */
  1491		wait_for_completion(&kthreadd_done);
  1492	
  1493		kernel_init_freeable();
  1494		/* need to finish all async __init code before freeing the memory */
  1495		async_synchronize_full();
  1496	
  1497		system_state = SYSTEM_FREEING_INITMEM;
  1498		kprobe_free_init_mem();
  1499		ftrace_free_init_mem();
  1500		kgdb_free_init_mem();
  1501		exit_boot_config();
  1502		free_initmem();
  1503		mark_readonly();
  1504	
  1505		/*
  1506		 * Kernel mappings are now finalized - update the userspace page-table
  1507		 * to finalize PTI.
  1508		 */
  1509		pti_finalize();
  1510	
  1511		system_state = SYSTEM_RUNNING;
  1512		numa_default_policy();
  1513	
  1514		rcu_end_inkernel_boot();
  1515	
  1516		do_sysctl_args();
  1517	
  1518		/* show calibration data for early_counter_ns */
  1519		end_cycles = get_cycles();
  1520		end_ns = local_clock();
  1521		clocks_calc_mult_shift(&early_mult, &early_shift,
> 1522			((end_cycles - start_cycles) * NSEC_PER_SEC)/(end_ns - start_ns),
  1523			NSEC_PER_SEC, 50);
  1524	

-- 
0-DAY CI Kernel Test Service
https://github.com/intel/lkp-tests/wiki

^ permalink raw reply

* [PATCH DISCUSSION 5/8] gpio: davinci: reset initcall level
From: Francesco Valla @ 2025-11-26 22:54 UTC (permalink / raw)
  To: linux-embedded, Tim Bird
  Cc: Federico Giovanardi, Michael Opdenacker, Saravana Kannan,
	Nishanth Menon, Vignesh Raghavendra, Tero Kristo, Francesco Valla
In-Reply-To: <20251126-beagleplay-probes-v1-0-c833defd4c9b@valla.it>

With the fw_devlink infrastracture in place, a custom initcall level is
doing more harm than good, especially in arm64 platforms that use the
(quite old) davinci gpio driver but relies on firmware for power
management and clock setup. Reset the initcall level to the default.

Signed-off-by: Francesco Valla <francesco@valla.it>
---
 drivers/gpio/gpio-davinci.c | 17 +----------------
 1 file changed, 1 insertion(+), 16 deletions(-)

diff --git a/drivers/gpio/gpio-davinci.c b/drivers/gpio/gpio-davinci.c
index 538f27209ce718ae49820c6429e3ab9342006825..fd937b07bc52f7dac437ba0503e6013af3196a1b 100644
--- a/drivers/gpio/gpio-davinci.c
+++ b/drivers/gpio/gpio-davinci.c
@@ -663,22 +663,7 @@ static struct platform_driver davinci_gpio_driver = {
 		.of_match_table	= davinci_gpio_ids,
 	},
 };
-
-/*
- * GPIO driver registration needs to be done before machine_init functions
- * access GPIO. Hence davinci_gpio_drv_reg() is a postcore_initcall.
- */
-static int __init davinci_gpio_drv_reg(void)
-{
-	return platform_driver_register(&davinci_gpio_driver);
-}
-postcore_initcall(davinci_gpio_drv_reg);
-
-static void __exit davinci_gpio_exit(void)
-{
-	platform_driver_unregister(&davinci_gpio_driver);
-}
-module_exit(davinci_gpio_exit);
+module_platform_driver(davinci_gpio_driver);
 
 MODULE_AUTHOR("Jan Kotas <jank@cadence.com>");
 MODULE_DESCRIPTION("DAVINCI GPIO driver");

-- 
2.52.0


^ permalink raw reply related

* [PATCH DISCUSSION 3/8] arm64: dts: ti: k3-am625-beagleplay: remove inter-regulator dependency
From: Francesco Valla @ 2025-11-26 22:54 UTC (permalink / raw)
  To: linux-embedded, Tim Bird
  Cc: Federico Giovanardi, Michael Opdenacker, Saravana Kannan,
	Nishanth Menon, Vignesh Raghavendra, Tero Kristo, Francesco Valla
In-Reply-To: <20251126-beagleplay-probes-v1-0-c833defd4c9b@valla.it>

The dependency between vsys_5v0 (supplier) and vdd_3v3 (consumer)
describes the hardware well, but causes delays during boot, since
the kernel is trying to probe vdd_3v3 before vsys_5v0, causing a
boot deferral chain for it and all the dependent devices.

The dependency is not functionally required, as both regulators are
fixed, not controllable and always ON, and is thus removed.

Signed-off-by: Francesco Valla <francesco@valla.it>
---
 arch/arm64/boot/dts/ti/k3-am625-beagleplay.dts | 1 -
 1 file changed, 1 deletion(-)

diff --git a/arch/arm64/boot/dts/ti/k3-am625-beagleplay.dts b/arch/arm64/boot/dts/ti/k3-am625-beagleplay.dts
index 60e2c86ab197e348bf941e30c2641a26cd940d82..3a96d76db0fbf7be68884c130ecb9e5c1c06d834 100644
--- a/arch/arm64/boot/dts/ti/k3-am625-beagleplay.dts
+++ b/arch/arm64/boot/dts/ti/k3-am625-beagleplay.dts
@@ -118,7 +118,6 @@ vdd_3v3: regulator-2 {
 		regulator-name = "vdd_3v3";
 		regulator-min-microvolt = <3300000>;
 		regulator-max-microvolt = <3300000>;
-		vin-supply = <&vsys_5v0>;
 		regulator-always-on;
 		regulator-boot-on;
 	};

-- 
2.52.0


^ permalink raw reply related

* [PATCH DISCUSSION 0/8] Reducing probe deferral - for profit and fun
From: Francesco Valla @ 2025-11-26 22:54 UTC (permalink / raw)
  To: linux-embedded, Tim Bird
  Cc: Federico Giovanardi, Michael Opdenacker, Saravana Kannan,
	Nishanth Menon, Vignesh Raghavendra, Tero Kristo, Francesco Valla

Hello,

this patchset is meant as a continuation of the discussion done during
the last Boot Time SIG meeting [1] and not as something that can be
applied as-is. The maintainers for most (if not all) the involved
subsystems are not Cc'd for this reason - if anything useful will come
out of the discussion, a proper submission process will be followed.

I Cc'd the Beagleplay (well, K3 platform) maintainers because they might
be interested, but hey: feel free to ignore the thread.

== TL;DR ==

A probe deferral optimization was attemped on the Beagleplay, leading to
a reduction of 240ms of pre-init boot time and a set of techniques that
can be re-used on other platforms. Patches included.

== Introduction ==

The questions this work arose from were related to the probe deferral
process that happens during boot, and in particular:

  - how much time is "lost" doing probes that don't complete and are
    deferred?
  - is the current infrastructure good at deferring probes in an
    efficient way?
  - what can be done to enhance the current infrastructure?

They pretty much all generated doing boot time characterization on a
Beagleplay, where the probe deferral mechanism is triggered many times
during boot - half of the pre-init time of a vanilla system is spent
inside the deferred_probe_initcall() function, which is the point in
which probes that were deferred is performed.

== Status quo ==

On a Beagleplay booting the mainline kernel (v6.18-rc7) with the default
configuration (arm64 defconfig), the pre-init time is around 1080ms;
during this time span, 89 probe deferrals are triggered. This can be
easily verified using the initcall_debug command line option and
counting the occurrences of a driver returning 517 (or -517, this uneven
behavior bothers me, but I'll keep it for another time). Some example
follows:

[    0.060228] probe of 4201000.gpio returned -517 after 0 usecs
[    0.192159] probe of 2b300050.target-module returned -517 after 12 usecs
[    0.269648] probe of 2850000.serial returned -517 after 18 usecs
[    0.688228] probe of 8000f00.mdio returned 517 after 36137 usecs
[    0.959488] probe of fa20000.mmc returned 517 after 17380 usecs

It shall be noted that most of the deferral events lasts less than 10
microseconds; this is due to the excellent work the fw_devlink
infrastructure is doing under the hood to prevent the probes to even
happen if all the identified suppliers are not already present (that is,
probed) themselves. However, some other are non-negligible at all, like
the mdio friend above, which takes a whopping 36-milliseconds chunk of
time to decide that it's not the time for them to probe.

On this vanilla system, deferred_probe_initcall() takes 504765us to
complete - thats is roughly half of the entire boot process. This is not
unexpected, and not necessarily the sign that something is not working -
but let's investigate a bit.

== The investigation method ==

To investigate the reasons behind the probe deferral, two main tools
can used:

  - the initcall_debug command line option, that without any
    modification to the code offers a nice detailed view of the boot
    process (with initcall levels too, thanks to yours truly [2]);
  - the extensive debug prints that the core driver infrastructure is
    providing; this has to be enabled manually, either with
    CONFIG_DEBUG_DRIVER=y or with the plain old '#define DEBUG' inside
    drivers/base/core.c.

Combining the two, it can be seen what are the consumers and suppliers
for each peripheral and how they interact during boot; for example:

[    0.080959] platform fa00000.mmc: Linked as a consumer to 601000.gpio
[    0.089809] platform fa00000.mmc: Linked as a consumer to regulator-4
[    0.090502] platform fa00000.mmc: Linked as a consumer to regulator-5
[    0.194678] platform fa00000.mmc: Linked as a consumer to 44043000.system-controller:power-controller
[    0.198904] platform fa00000.mmc: Linked as a consumer to 44043000.system-controller:clock-controller
[    0.324348] platform fa00000.mmc: Linked as a consumer to f4000.pinctrl
[    0.720843] platform fa00000.mmc: error -EPROBE_DEFER: supplier regulator-5 not ready

This is a long - and maybe tedious, for someone - work, but in my
experience it helps to truly know a platform; if working more as an
integrator than a developer, this can be a game changer. At least, it
was for me - YMMV.

== Some possible ways out ==

Several methodologies can be exploited to "solve" the probe deferral
problem - assuming it is a problem. The ones that have been used to
obtain the results presented later - and thus covered by the patchset -
are here presented:

1) Ensure that the fw_devlink infrastructure is working correctly
   (spoiler: it is, most of the time) and close the gaps, if any; one
   of such gaps is covered in patch 1 (that was also already submitted
   [3] and will probably see a resend).

2) Help the aforementioned fw_devlink to break the cycles, because this
   might not be straightforward for its logic; this is what is done in
   patch 2 with the introduction of post-init-providers properties.
   It shall be noted that such property is not at the moment working
   with the DTB checker, because it is not considered in any schema.

3) Remove unnecessary dependencies between devices, like it is done in
   patch 3; this can happen in particular with regulators, which are
   often inserted to properly model the hardware but might not really
   be required.

4) Tune the kernel configuration - this can be done extensively with
   excellent results, but something might not be so obvious - see patch
   4 for a particularly sneaky condition that was encountered.

(Beware, from now on be dragons - you have been warned)

5) Change initcall levels. Old drivers for proven IPs - like I2C or SPI
   or GPIO controllers - might have been configured for a specific
   platform to initialize at a odd initcall level and then blindly
   re-used for new platforms. This is not always working well with
   modern systems with a System Management processor - like the
   Beagleplay - where more or less any device depends on a firmware
   interface like SCMI to be present. Some examples can be found in
   patches 5, 6 and 7.

6) Move things around inside the drivers Makefile. This is probably one
   of the most effective AND controversial thing to do, especially if
   coupled with 5), as it changes the init ordering of the various
   subsystems. Patch 8 shows what has been done for the Beagleplay, to
   ensure the SCMI firmware interface and all the services it provide
   (clocks, power domains and so on) are initialized before the drivers.
   Of course a single configuration that can be suitable for all
   platforms cannot be found, but maybe this aspect can be tackled from
   another direction, (mis-)using the LTO support that is already there.
   More work is required on this point, of course. 

== Results ==

With all the patches applied, I was able to reduce the overall pre-init
time to around 840ms, ~240ms less than the original system.

The duration of deferred_probe_initcall() lowered to ~18ms and the
number of pre-init probe deferrals to only 4 - these are not really
avoidable, as there are fixed regulators that depend on the PMIC.

Considering that no driver behavior has been modified... not bad, at
least IMO (but I'm the author and thus don't count).

== Bonus track: deferred probes of modules ==

With the discussion above focused on the pre-init time, nothing has been
said about what happens where the userspace of choice loads modules. The
answer is: a lot of deferrals can take place also there, but the
solution might however be simpler; in fact, the modprobe infrastructure
already supports soft dependencies between modules.

For the Beagleplay, probe deferrals hit the display (tidss) and sound
areas; this is the content I used inside /etc/modprobe.d/beagle.conf: 

softdep ite_it66121 pre: display_connector
softdep tidss pre: ite_it66121
softdep snd_soc_simple_card pre: ite_it66121 snd_soc_davinci_mcasp snd_soc_hdmi_codec

This solved all of the issues and ensured a smooth module experience.

== References == 

[1] https://lore.kernel.org/linux-embedded/MW5PR13MB5632E0103356DB6C0B330FCCFDD5A@MW5PR13MB5632.namprd13.prod.outlook.com/
[2] https://lore.kernel.org/linux-embedded/20250316205014.2830071-2-francesco@valla.it/
[3] https://lore.kernel.org/all/20250930-mmc_pwrseq-v2-1-80a8c6be0fb0@valla.it/

Cheers,
Francesco

Signed-off-by: Francesco Valla <francesco@valla.it>
---
Francesco Valla (8):
      of: property: fw_devlink: Add support for "mmc-pwrseq"
      arm64: dts: ti: k3-am625-beagleplay: set post-init-providers
      arm64: dts: ti: k3-am625-beagleplay: remove inter-regulator dependency
      arm64: defconfig: compile reset-gpio as built-in
      gpio: davinci: reset initcall level
      i2c: omap: reset initcall level
      regulator: fixed: reset initcall level
      drivers: Makefile: reorder driver initialization

 arch/arm64/boot/dts/ti/k3-am625-beagleplay.dts | 12 ++++++++++-
 arch/arm64/configs/defconfig                   |  2 +-
 drivers/Makefile                               | 30 ++++++++++++++------------
 drivers/gpio/gpio-davinci.c                    | 17 +--------------
 drivers/i2c/busses/i2c-omap.c                  | 15 +------------
 drivers/of/property.c                          |  2 ++
 drivers/regulator/fixed.c                      | 13 +----------
 7 files changed, 33 insertions(+), 58 deletions(-)
---
base-commit: 30f09200cc4aefbd8385b01e41bde2e4565a6f0e
change-id: 20251126-beagleplay-probes-f14e5941de10

Best regards,
-- 
Francesco Valla <francesco@valla.it>


^ permalink raw reply

* RE: [PATCH] printk: add early_counter_ns routine for printk blind spot
From: Bird, Tim @ 2025-11-27  0:16 UTC (permalink / raw)
  To: Geert Uytterhoeven, Francesco Valla
  Cc: Tim Bird, pmladek@suse.com, Steve Rostedt,
	john.ogness@linutronix.de, senozhatsky@chromium.org,
	Andrew Morton, LKML, Linux Embedded
In-Reply-To: <CAMuHMdXvQtCyqSN37QYWCL2T2sz7r-S2Cy7MySn59F3qn5vsZA@mail.gmail.com>



> -----Original Message-----
> From: Geert Uytterhoeven <geert@linux-m68k.org>
> Hi all,
> 
> On Wed, 26 Nov 2025 at 03:24, Francesco Valla <francesco@valla.it> wrote:
> > On Mon, Nov 24, 2025 at 10:30:52PM -0700, Tim Bird wrote:
> > > From: Tim Bird <tim.bird@sony.com>
> > >
> > > During early boot, printk timestamps are reported as zero,
> > > which creates a blind spot in early boot timings.  This blind
> > > spot hinders timing and optimization efforts for code that
> > > executes before time_init(), which is when local_clock() is
> > > initialized sufficiently to start returning non-zero timestamps.
> > > This period is about 400 milliseconds for many current desktop
> > > and embedded machines running Linux.
> > >
> > > Add an early_counter_ns function that returns nanosecond
> > > timestamps based on get_cycles().  get_cycles() is operational
> > > on arm64 and x86_64 from kernel start.  Add some calibration
> > > printks to allow setting configuration variables that are used
> > > to convert cycle counts to nanoseconds (which are then used
> > > in early printks).  Add CONFIG_EARLY_COUNTER_NS, as well as
> > > some associated conversion variables, as new kernel config
> > > variables.
> > >
> > > After proper configuration, this yields non-zero timestamps for
> > > printks from the very start of kernel execution.  The timestamps
> > > are relative to the start of the architecture-specific counter
> > > used in get_cycles (e.g. the TSC on x86_64 and cntvct_el0 on arm64).
> > > This means that the time reported reflects time-from-power-on for
> > > most embedded products.  This is also a useful data point for
> > > boot-time optimization work.
> > >
> > > Note that there is a discontinuity in the timestamp sequencing
> > > when standard clocks are finally initialized in time_init().
> > > The printk timestamps are thus not monotonically increasing
> > > through the entire boot.
> >
> > This is... not going to work, IMO, and might lead to breakages in
> > userspace tools (are printk timings a userspace API?).
> 
> I think they are.
> 
> Another approach would be to defer the calibration/conversion to
> userspace, and make sure the early part stands out.
> I.e. when real timekeeping is available, kernel messages are prefixed by
> "[%5lu.%06lu]".  Early messages could be prefixed by a plain integer
> "[%12u]", containing the raw cycle counter value.
> The presence of the decimal point would make the difference obvious.

I thought about this while I was creating this.
It wouldn't require the extra configuration for MULT and SHIFT (which would be nice),
and it would be, as you say, very obvious that this was not a regular timestamp. 
This means it could be enabled on a generic kernel (making more likely it could be
enabled by default). And really only boot-time optimizers would care enough to
decode the data, so the onus would be on them to run the tool.  Everyone else
could ignore them.

I'm not sure if it would break existing printk-processing tools.  I suspect it would.

Also,  I find that post-processing tools often get overlooked.
I asked at ELC this year how many people are using show_delta, which 
has been upstream for years, and can do a few neat things with printk timestamps,
and not a single person had even heard of it.

In this scenario, you would still need to have the calibration printks in
the code so that the tool could pull them out to then convert the cycle-valued
printks into printks with regular timestamps.

I could see doing this if people object to the non-genericity of the current
solution.

> 
> > I actually have a counter-proposal: the time obtained through cycle
> > evaluation is used as an offset to be added to the printk time after
> > time_init() is called. A (working, but maybe sub-optimal) patch to
> > obtain this is attached at the end.
> 
> Oh, that's a nice idea, too!

Thanks for the feedback!
 -- Tim


^ permalink raw reply

* RE: [PATCH] printk: add early_counter_ns routine for printk blind spot
From: Bird, Tim @ 2025-11-27  0:03 UTC (permalink / raw)
  To: Petr Mladek, Francesco Valla
  Cc: Tim Bird, Steve Rostedt, john.ogness@linutronix.de,
	senozhatsky@chromium.org, Andrew Morton, LKML, Anna-Maria Behnsen,
	Frederic Weisbecker, Thomas Gleixner, Linux Embedded
In-Reply-To: <aSb4xHCB6i_Q6JpC@pathway.suse.cz>

> -----Original Message-----
> From: Petr Mladek <pmladek@suse.com>
> On Tue 2025-11-25 14:08:40, Francesco Valla wrote:
> > Hi Tim,
> >
> > I tested this on my i.MX93 FRDM (arm64) board and after a bit of
> > fiddling with the MULT/SHIFT values I got it working. It can be a very
> > valuable addition.
> >
> > Some comments follow.
> >
> > On Mon, Nov 24, 2025 at 10:30:52PM -0700, Tim Bird wrote:
> > > From: Tim Bird <tim.bird@sony.com>
> > >
> > > During early boot, printk timestamps are reported as zero,
> > > which creates a blind spot in early boot timings.  This blind
> > > spot hinders timing and optimization efforts for code that
> > > executes before time_init(), which is when local_clock() is
> > > initialized sufficiently to start returning non-zero timestamps.
> > > This period is about 400 milliseconds for many current desktop
> > > and embedded machines running Linux.
> > >
> > > Add an early_counter_ns function that returns nanosecond
> > > timestamps based on get_cycles().  get_cycles() is operational
> > > on arm64 and x86_64 from kernel start.  Add some calibration
> > > printks to allow setting configuration variables that are used
> > > to convert cycle counts to nanoseconds (which are then used
> > > in early printks).  Add CONFIG_EARLY_COUNTER_NS, as well as
> > > some associated conversion variables, as new kernel config
> > > variables.
> > >
> > > After proper configuration, this yields non-zero timestamps for
> > > printks from the very start of kernel execution.  The timestamps
> > > are relative to the start of the architecture-specific counter
> > > used in get_cycles (e.g. the TSC on x86_64 and cntvct_el0 on arm64).
> > > This means that the time reported reflects time-from-power-on for
> > > most embedded products.  This is also a useful data point for
> > > boot-time optimization work.
> > >
> > > Note that there is a discontinuity in the timestamp sequencing
> > > when standard clocks are finally initialized in time_init().
> > > The printk timestamps are thus not monotonically increasing
> > > through the entire boot.
> >
> > This is... not going to work, IMO, and might lead to breakages in
> > userspace tools (are printk timings a userspace API?).
> 
> Honestly, I am not sure if it would break anything. The fact is
> that printk() always used monotonic timers. And it is possible
> that some userspace depends on it.
> 
> I personally thing that non-monotonic time stamps might be confusing
> but they should not cause any serious breakage. But I might be wrong.
> People are creative...

I worried about this, but I'm skeptical it's a big deal.  Humans might be
a little confused, but it's not difficult to see what's going on just by looking
at the timestamps.   If a tool breaks, especially something that's used
in automation, e.g. it's used to report results, or is in some sort of CI
loop where the break will cascade into a test failure, then that's a bigger issue. 
But right now I'm not aware of any boot-time tests where that would be the case.

I'll comment more on different fixes for this below.

> 
> > I actually have a counter-proposal: the time obtained through cycle
> > evaluation is used as an offset to be added to the printk time after
> > time_init() is called. A (working, but maybe sub-optimal) patch to
> > obtain this is attached at the end.
> 
> I am not sure if this is a good idea. The offset would cause
> that all post-timer-init printk timestamps differ from values
> provided by the timer API. And it might cause confusion,
> for example, when they are printed as part of the message,
> or when analyzing a crash dump.
> 
> On the other hand, there are various clock sources in the kernel
> which are not comparable anyway. So maybe I am too cautious.

I thought of adding an offset, but I didn't want to disturb anything past
the time_init() call.  As it is now, the early_counter_ns feature only
changes the zero-valued timestamps.  So anything relying on the absolute
value of an existing timestamp later in the boot would not be affected.
I thought that if people suddenly saw the timestamps jump by 10 to 30 seconds
(since they are now relative to machine start instead of to kernel clock start
(time_init()), it would be very jarring.  I suppose they would get used to it,
though, and all relative timings should stay the same.

I also didn't want to add additional overhead (even a single add) in the case
where CONFIG_EARLY_COUNTER_NS was disabled.  But, realistically, I
don't think an additional add in the printk path is not going to be noticeable,
and I can probably structure it so that there's absolutely no overhead when
CONFIG_EARLY_COUNTER_NS is disabled.

I considered embedding an early counter offset into local_clock(), and thus
not modifying the printk code at all.  This would have the benefit
of keeping the printk timestamps consistent with other uses of local_clock()
data (such as crash dumps or inside other messages). But then that would embed the
early_counter overhead into every user of local_clock() (whether humans
saw the timestamp values or not). And some of those users might be more
performance sensitive than printk is.

Finally, I considered adding another config option to control adding the offset,
but at 3 configs for this fairly niche functionality, I thought I was already
pushing my luck.  But a new config would be easy to add.

My plan is to add an offset for the early_counter_ns value to printk, without
a config, in the next patch version, and see what people think.

> 
> > > --- a/init/Kconfig
> > > +++ b/init/Kconfig
> > > @@ -770,6 +770,53 @@ config IKHEADERS
> > >  	  or similar programs.  If you build the headers as a module, a module called
> > >  	  kheaders.ko is built which can be loaded on-demand to get access to headers.
> > >
> > > +config EARLY_COUNTER_NS
> > > +	bool "Use counter for early printk timestamps"
> > > +	default y
> > > +	depends on PRINTK
> > > +	help
> > > +	  Use a cycle-counter to provide printk timestamps during early
> > > +	  boot.  This allows seeing timing information that would
> > > +	  otherwise be displayed with 0-valued timestamps.
> > > +
> > > +	  In order for this to work, you need to specify values for
> > > +	  EARLY_COUNTER_MULT and EARLY_COUNTER_SHIFT, used to convert
> > > +	  from the cycle count to nanoseconds.
> > > +
> > > +config EARLY_COUNTER_MULT
> > > +	int "Multiplier for early cycle counter"
> > > +	depends on PRINTK && EARLY_COUNTER_NS
> > > +	default 1
> > > +	help
> > > +	  This value specifies a multiplier to be used when converting
> > > +	  cycle counts to nanoseconds.  The formula used is:
> > > +		  ns = (cycles * mult) >> shift
> > > +
> > > +	  Use a multiplier that will bring the value of (cycles * mult)
> > > +	  to near a power of two, that is greater than 1000.  The
> > > +	  nanoseconds returned by this conversion are divided by 1000
> > > +	  to be used as the printk timestamp counter (with resolution
> > > +	  of microseconds).
> > > +
> > > +	  As an example, for a cycle-counter with a frequency of 200 Mhz,
> > > +	  the multiplier would be: 10485760, and the shift would be 21.
> > > +
> >
> > If I got this correclty:
> >
> > 	EARLY_COUNTER_MULT = (10^9 / freq) << EARLY_COUNTER_SHIFT
> >
> > where EARLY_COUNTER_SHIFT can be chosen at will, provided it is big
> > enough to survice the ns->us conversion but small enough not to overflow
> > the u64 container.

Yeah, I was worried about these Kconfig explanations.  I think it will be easier
to just explain how I recommend this should be configured, which is something like:

Turn on CONFIG_EARLY_COUNTER_NS, run the kernel once, get the values for MULT
and SHIFT (printed by the calibration code), enter them in the appropriate configs, and
then build and run the kernel again.  This only needs to be done once per platform,
and could even be put into the defconfig (or a config fragment) for a platform.
(More on having hardcoded config for this below).  It was not my intent to have
kernel developers doing weird (shift) math to enable this feature.  Note that I can't
get the values from devicetree or the kernel command line, as this is used before
either of those is initialized or parsed.

> >
> > > +config EARLY_COUNTER_SHIFT
> > > +	int "Shift value for early cycle counter"
> > > +	range 0 63
> > > +	depends on PRINTK && EARLY_COUNTER_NS
> > > +	default 0
> > > +	help
> > > +	  This value specifies a shift value to be used when converting
> > > +	  cycle counts to nanoseconds.  The formula used is:
> > > +		  ns = (cycles * mult) >> shift
> > > +
> > > +	  Use a shift that will bring the result to a value
> > > +	  in nanoseconds.
> > > +
> > > +	  As an example, for a cycle-counter with a frequency of 200 Mhz,
> > > +	  the multiplier would be: 10485760, and the shift would be 21.
> > > +
> > >  config LOG_BUF_SHIFT
> > >  	int "Kernel log buffer size (16 => 64KB, 17 => 128KB)"
> > >  	range 12 25
> 
> So, it is usable only for a particular HW. It is not usable for a
> generic kernel which is supposed to run on misc HW.

That's correct.  It is mostly targeted at embedded products,
where shaving off 10 to 200 milliseconds in the pre-clock-initialization
region of boot would be valuable.  For people doing aggressive
boot time optimization, they will have a custom kernel anyway
(and probably a custom bootloader, device tree, initramfs, udev rules,
SE linux rules, module load ordering, systemd config, etc.)

Basically, if you're optimizing the code in this kernel boot time blind
spot, you are very likely not using a generic kernel.  (That's not to
say that the optimizations made won't ultimately be valuable to people using
generic kernels).

> 
> I guess that there is no way to detect the CPU frequency at runtime?
This "feature" is used before clock initialization, which is what
would be used to calibrate the CPU frequency at runtime.  This runs so 
early that doing the calibration inline doesn't work.  Not enough kernel
services are available (Actually, zero services are available, as this
can be used in the very first printk in start_kernel.)

Plan from here...

I got a compile error from 0-day on powerpc, so I need to re-spin to fix that.
I'll address the other issues raised and submit a new version when I can.
I'm off to Japan this week, and between business travel and the holidays,
and being away from my lab where I can do hardware testing, it will
probably be some time in January before I send the next version.

Thanks very much for the feedback!
 -- Tim


^ permalink raw reply

* [PATCH DISCUSSION 8/8] drivers: Makefile: reorder driver initialization
From: Francesco Valla @ 2025-11-26 22:54 UTC (permalink / raw)
  To: linux-embedded, Tim Bird
  Cc: Federico Giovanardi, Michael Opdenacker, Saravana Kannan,
	Nishanth Menon, Vignesh Raghavendra, Tero Kristo, Francesco Valla
In-Reply-To: <20251126-beagleplay-probes-v1-0-c833defd4c9b@valla.it>

Reorder drivers at Makefile level to have the critical ones (fot the
platform in exam, i.e. AM62x) to ptobe and initialize early. This avoids
useless deferrals and saves some milliseconds.

Signed-off-by: Francesco Valla <francesco@valla.it>
---
 drivers/Makefile | 30 ++++++++++++++++--------------
 1 file changed, 16 insertions(+), 14 deletions(-)

diff --git a/drivers/Makefile b/drivers/Makefile
index 8e1ffa4358d5f1aadb0b1559ba3b41b44de6daa4..7dccffff7a126e2b1983467875d6b24ae7156075 100644
--- a/drivers/Makefile
+++ b/drivers/Makefile
@@ -7,14 +7,30 @@
 #
 
 obj-y				+= cache/
+obj-$(CONFIG_MAILBOX)		+= mailbox/
+obj-y				+= firmware/
 obj-y				+= irqchip/
 obj-y				+= bus/
 
 obj-$(CONFIG_GENERIC_PHY)	+= phy/
 
+# SOC specific infrastructure drivers.
+obj-y				+= soc/
+obj-$(CONFIG_PM_GENERIC_DOMAINS)	+= pmdomain/
+
+obj-y				+= clk/
+# Many drivers will want to use DMA so this has to be made available
+# really early.
+obj-$(CONFIG_DMADEVICES)	+= dma/
+
+
 # GPIO must come after pinctrl as gpios may need to mux pins etc
 obj-$(CONFIG_PINCTRL)		+= pinctrl/
 obj-$(CONFIG_GPIOLIB)		+= gpio/
+
+# regulators early, since some subsystems rely on them to initialize
+obj-$(CONFIG_REGULATOR)		+= regulator/
+
 obj-y				+= pwm/
 
 # LEDs must come before PCI, it is needed by NPEM driver
@@ -37,22 +53,10 @@ obj-$(CONFIG_ACPI)		+= acpi/
 obj-$(CONFIG_PNP)		+= pnp/
 obj-y				+= amba/
 
-obj-y				+= clk/
-# Many drivers will want to use DMA so this has to be made available
-# really early.
-obj-$(CONFIG_DMADEVICES)	+= dma/
-
-# SOC specific infrastructure drivers.
-obj-y				+= soc/
-obj-$(CONFIG_PM_GENERIC_DOMAINS)	+= pmdomain/
-
 obj-y				+= virtio/
 obj-$(CONFIG_VDPA)		+= vdpa/
 obj-$(CONFIG_XEN)		+= xen/
 
-# regulators early, since some subsystems rely on them to initialize
-obj-$(CONFIG_REGULATOR)		+= regulator/
-
 # reset controllers early, since gpu drivers might rely on them to initialize
 obj-$(CONFIG_RESET_CONTROLLER)	+= reset/
 
@@ -134,7 +138,6 @@ obj-y				+= mmc/
 obj-y				+= ufs/
 obj-$(CONFIG_MEMSTICK)		+= memstick/
 obj-$(CONFIG_INFINIBAND)	+= infiniband/
-obj-y				+= firmware/
 obj-$(CONFIG_FWCTL)		+= fwctl/
 obj-$(CONFIG_CRYPTO)		+= crypto/
 obj-$(CONFIG_SUPERH)		+= sh/
@@ -153,7 +156,6 @@ obj-$(CONFIG_COMEDI)		+= comedi/
 obj-$(CONFIG_STAGING)		+= staging/
 obj-y				+= platform/
 
-obj-$(CONFIG_MAILBOX)		+= mailbox/
 obj-$(CONFIG_HWSPINLOCK)	+= hwspinlock/
 obj-$(CONFIG_REMOTEPROC)	+= remoteproc/
 obj-$(CONFIG_RPMSG)		+= rpmsg/

-- 
2.52.0


^ permalink raw reply related

* [PATCH DISCUSSION 6/8] i2c: omap: reset initcall level
From: Francesco Valla @ 2025-11-26 22:54 UTC (permalink / raw)
  To: linux-embedded, Tim Bird
  Cc: Federico Giovanardi, Michael Opdenacker, Saravana Kannan,
	Nishanth Menon, Vignesh Raghavendra, Tero Kristo, Francesco Valla
In-Reply-To: <20251126-beagleplay-probes-v1-0-c833defd4c9b@valla.it>

With the fw_devlink infrastracture in place, a custom initcall level is
doing more harm than good, especially in arm64 platforms that use the
(quite old) omap i2c driver but relies on firmware for power management
and clock setup. Reset the initcall level to the default.

Signed-off-by: Francesco Valla <francesco@valla.it>
---
 drivers/i2c/busses/i2c-omap.c | 15 +--------------
 1 file changed, 1 insertion(+), 14 deletions(-)

diff --git a/drivers/i2c/busses/i2c-omap.c b/drivers/i2c/busses/i2c-omap.c
index d9f590f0c384340dd31308bdf9ed0cb1a1a2ba8b..081b472ec99a271521cbbbc21b8462c3a69d13cf 100644
--- a/drivers/i2c/busses/i2c-omap.c
+++ b/drivers/i2c/busses/i2c-omap.c
@@ -1625,20 +1625,7 @@ static struct platform_driver omap_i2c_driver = {
 		.of_match_table = of_match_ptr(omap_i2c_of_match),
 	},
 };
-
-/* I2C may be needed to bring up other drivers */
-static int __init
-omap_i2c_init_driver(void)
-{
-	return platform_driver_register(&omap_i2c_driver);
-}
-subsys_initcall(omap_i2c_init_driver);
-
-static void __exit omap_i2c_exit_driver(void)
-{
-	platform_driver_unregister(&omap_i2c_driver);
-}
-module_exit(omap_i2c_exit_driver);
+module_platform_driver(omap_i2c_driver);
 
 MODULE_AUTHOR("MontaVista Software, Inc. (and others)");
 MODULE_DESCRIPTION("TI OMAP I2C bus adapter");

-- 
2.52.0


^ permalink raw reply related

* [PATCH DISCUSSION 7/8] regulator: fixed: reset initcall level
From: Francesco Valla @ 2025-11-26 22:54 UTC (permalink / raw)
  To: linux-embedded, Tim Bird
  Cc: Federico Giovanardi, Michael Opdenacker, Saravana Kannan,
	Nishanth Menon, Vignesh Raghavendra, Tero Kristo, Francesco Valla
In-Reply-To: <20251126-beagleplay-probes-v1-0-c833defd4c9b@valla.it>

With the fw_devlink infrastracture in place, a custom initcall level is
doing more harm than good, especially in arm64 platforms that relies on
firmware for power management and clock setup.

Reset the initcall level to the default.

Signed-off-by: Francesco Valla <francesco@valla.it>
---
 drivers/regulator/fixed.c | 13 +------------
 1 file changed, 1 insertion(+), 12 deletions(-)

diff --git a/drivers/regulator/fixed.c b/drivers/regulator/fixed.c
index a2d16e9abfb58dc3ebd1c1c612fe699ae3487d95..36e70e70ab2d19818b90d9ca72e615bd6cdfe800 100644
--- a/drivers/regulator/fixed.c
+++ b/drivers/regulator/fixed.c
@@ -390,18 +390,7 @@ static struct platform_driver regulator_fixed_voltage_driver = {
 		.of_match_table = of_match_ptr(fixed_of_match),
 	},
 };
-
-static int __init regulator_fixed_voltage_init(void)
-{
-	return platform_driver_register(&regulator_fixed_voltage_driver);
-}
-subsys_initcall(regulator_fixed_voltage_init);
-
-static void __exit regulator_fixed_voltage_exit(void)
-{
-	platform_driver_unregister(&regulator_fixed_voltage_driver);
-}
-module_exit(regulator_fixed_voltage_exit);
+module_platform_driver(regulator_fixed_voltage_driver);
 
 MODULE_AUTHOR("Mark Brown <broonie@opensource.wolfsonmicro.com>");
 MODULE_DESCRIPTION("Fixed voltage regulator");

-- 
2.52.0


^ permalink raw reply related

* [PATCH DISCUSSION 4/8] arm64: defconfig: compile reset-gpio as built-in
From: Francesco Valla @ 2025-11-26 22:54 UTC (permalink / raw)
  To: linux-embedded, Tim Bird
  Cc: Federico Giovanardi, Michael Opdenacker, Saravana Kannan,
	Nishanth Menon, Vignesh Raghavendra, Tero Kristo, Francesco Valla
In-Reply-To: <20251126-beagleplay-probes-v1-0-c833defd4c9b@valla.it>

Having the reset-gpio driver as module interferes with the fw_devlink
mechanism, since all reset-gpios appears to probe correctly but cannot
then be used right away because the underlying reset controller is not
yet registered. This leads to wasted probe time, as fw_devlink cannot
really prevent the probe due to a missing supplier.

On a Beagleplay, this leads to multiple non-negligible probe deferrals
before userspace:

[    0.878651] probe of sdio-pwrseq returned 517 after 1726 usecds
[    0.891927] probe of sdio-pwrseq returned 517 after 238 usecs
[    0.897796] probe of sdio-pwrseq returned 517 after 234 usecs
[    0.933930] probe of sdio-pwrseq returned 517 after 277 usecs
[    0.979049] probe of sdio-pwrseq returned 517 after 252 usecs

Set CONFIG_RESET_GPIO=y to have the driver built-in.

Signed-off-by: Francesco Valla <francesco@valla.it>
---
 arch/arm64/configs/defconfig | 2 +-
 1 file changed, 1 insertion(+), 1 deletion(-)

diff --git a/arch/arm64/configs/defconfig b/arch/arm64/configs/defconfig
index 1a48faad2473a9b8f1c87567f38fedc7b703b44d..4879aec0b2d70e3b8fe6636c14e68ecdf023e625 100644
--- a/arch/arm64/configs/defconfig
+++ b/arch/arm64/configs/defconfig
@@ -1607,7 +1607,7 @@ CONFIG_QCOM_PDC=y
 CONFIG_QCOM_MPM=y
 CONFIG_TI_SCI_INTR_IRQCHIP=y
 CONFIG_TI_SCI_INTA_IRQCHIP=y
-CONFIG_RESET_GPIO=m
+CONFIG_RESET_GPIO=y
 CONFIG_RESET_IMX7=y
 CONFIG_RESET_QCOM_AOSS=y
 CONFIG_RESET_QCOM_PDC=m

-- 
2.52.0


^ permalink raw reply related

* [PATCH DISCUSSION 1/8] of: property: fw_devlink: Add support for "mmc-pwrseq"
From: Francesco Valla @ 2025-11-26 22:54 UTC (permalink / raw)
  To: linux-embedded, Tim Bird
  Cc: Federico Giovanardi, Michael Opdenacker, Saravana Kannan,
	Nishanth Menon, Vignesh Raghavendra, Tero Kristo, Francesco Valla
In-Reply-To: <20251126-beagleplay-probes-v1-0-c833defd4c9b@valla.it>

Add support for parsing MMC power sequencing (pwrseq) binding so that
fw_devlink can enforce the dependency.

Signed-off-by: Francesco Valla <francesco@valla.it>
---
 drivers/of/property.c | 2 ++
 1 file changed, 2 insertions(+)

diff --git a/drivers/of/property.c b/drivers/of/property.c
index c1feb631e3831d7d5ec23c606af31731bfc2f8b8..fcf10c4f02dcf879e1f25e4fa97b25152d58bacb 100644
--- a/drivers/of/property.c
+++ b/drivers/of/property.c
@@ -1377,6 +1377,7 @@ DEFINE_SIMPLE_PROP(post_init_providers, "post-init-providers", NULL)
 DEFINE_SIMPLE_PROP(access_controllers, "access-controllers", "#access-controller-cells")
 DEFINE_SIMPLE_PROP(pses, "pses", "#pse-cells")
 DEFINE_SIMPLE_PROP(power_supplies, "power-supplies", NULL)
+DEFINE_SIMPLE_PROP(mmc_pwrseq, "mmc-pwrseq", NULL)
 DEFINE_SUFFIX_PROP(regulators, "-supply", NULL)
 DEFINE_SUFFIX_PROP(gpio, "-gpio", "#gpio-cells")
 
@@ -1524,6 +1525,7 @@ static const struct supplier_bindings of_supplier_bindings[] = {
 	{ .parse_prop = parse_msi_parent, },
 	{ .parse_prop = parse_pses, },
 	{ .parse_prop = parse_power_supplies, },
+	{ .parse_prop = parse_mmc_pwrseq, },
 	{ .parse_prop = parse_gpio_compat, },
 	{ .parse_prop = parse_interrupts, },
 	{ .parse_prop = parse_interrupt_map, },

-- 
2.52.0


^ permalink raw reply related

* [PATCH DISCUSSION 2/8] arm64: dts: ti: k3-am625-beagleplay: set post-init-providers
From: Francesco Valla @ 2025-11-26 22:54 UTC (permalink / raw)
  To: linux-embedded, Tim Bird
  Cc: Federico Giovanardi, Michael Opdenacker, Saravana Kannan,
	Nishanth Menon, Vignesh Raghavendra, Tero Kristo, Francesco Valla
In-Reply-To: <20251126-beagleplay-probes-v1-0-c833defd4c9b@valla.it>

Add the post-init-providers property where reasonable:

  - the gic500 is depending on itself, but that is taken care during
    probe;
  - the TPS65219 PMIC is depending on one of its regulators, but also
    that is considered during probe;
  - the DRM endpoints causes mutual dependencies between componets, but
    only one way is an actual init dependency for each couple.

This solves the following cycles found by the fw_devlink infrastructure
during initialization:

[    0.056895] /bus@f0000/interrupt-controller@1800000: Fixed dependency cycle(s) with /bus@f0000/interrupt-controller@1800000
[    0.057072] /bus@f0000/i2c@20020000/bridge-hdmi@4c: Fixed dependency cycle(s) with /bus@f0000/dss@30200000
[    0.057218] /bus@f0000/dss@30200000: Fixed dependency cycle(s) with /bus@f0000/i2c@20020000/bridge-hdmi@4c
[    0.073755] /bus@f0000/i2c@20020000/bridge-hdmi@4c: Fixed dependency cycle(s) with /bus@f0000/dss@30200000
[    0.079458] /bus@f0000/i2c@20020000/bridge-hdmi@4c: Fixed dependency cycle(s) with /bus@f0000/dss@30200000
[    0.079567] /bus@f0000/dss@30200000: Fixed dependency cycle(s) with /bus@f0000/i2c@20020000/bridge-hdmi@4c
[    0.086984] /bus@f0000/i2c@20020000/bridge-hdmi@4c: Fixed dependency cycle(s) with /connector-hdmi
[    0.087088] /connector-hdmi: Fixed dependency cycle(s) with /bus@f0000/i2c@20020000/bridge-hdmi@4c
[    0.573947] /bus@f0000/i2c@20000000/pmic@30: Fixed dependency cycle(s) with /bus@f0000/i2c@20000000/pmic@30/regulators/buck2
[    0.598398] /connector-hdmi: Fixed dependency cycle(s) with /bus@f0000/i2c@20020000/bridge-hdmi@4c
[    0.598494] /bus@f0000/dss@30200000: Fixed dependency cycle(s) with /bus@f0000/i2c@20020000/bridge-hdmi@4c
[    0.598675] /bus@f0000/i2c@20020000/bridge-hdmi@4c: Fixed dependency cycle(s) with /connector-hdmi
[    0.598734] /bus@f0000/i2c@20020000/bridge-hdmi@4c: Fixed dependency cycle(s) with /bus@f0000/dss@30200000

Signed-off-by: Francesco Valla <francesco@valla.it>
---
 arch/arm64/boot/dts/ti/k3-am625-beagleplay.dts | 11 +++++++++++
 1 file changed, 11 insertions(+)

diff --git a/arch/arm64/boot/dts/ti/k3-am625-beagleplay.dts b/arch/arm64/boot/dts/ti/k3-am625-beagleplay.dts
index 7028d9835c4a89cc3f5ca17543b18d3419751f0a..60e2c86ab197e348bf941e30c2641a26cd940d82 100644
--- a/arch/arm64/boot/dts/ti/k3-am625-beagleplay.dts
+++ b/arch/arm64/boot/dts/ti/k3-am625-beagleplay.dts
@@ -211,6 +211,9 @@ hdmi0: connector-hdmi {
 		compatible = "hdmi-connector";
 		label = "hdmi";
 		type = "a";
+
+		post-init-providers = <&it66121>;
+
 		port {
 			hdmi_connector_in: endpoint {
 				remote-endpoint = <&it66121_out>;
@@ -622,6 +625,10 @@ cpsw3g_phy1: ethernet-phy@1 {
 	};
 };
 
+&gic500 {
+	post-init-providers = <&gic500>;
+};
+
 &main_gpio0 {
 	bootph-all;
 	pinctrl-names = "default";
@@ -701,6 +708,8 @@ tps65219: pmic@30 {
 		system-power-controller;
 		ti,power-button;
 
+		post-init-providers = <&buck2_reg>;
+
 		regulators {
 			buck1_reg: buck1 {
 				regulator-name = "VDD_CORE";
@@ -793,6 +802,8 @@ it66121: bridge-hdmi@4c {
 		interrupts = <36 IRQ_TYPE_EDGE_FALLING>;
 		#sound-dai-cells = <0>;
 
+		post-init-providers = <&dss>;
+
 		ports {
 			#address-cells = <1>;
 			#size-cells = <0>;

-- 
2.52.0


^ permalink raw reply related

* Re: [PATCH] printk: add early_counter_ns routine for printk blind spot
From: Petr Mladek @ 2025-11-26 12:55 UTC (permalink / raw)
  To: Francesco Valla
  Cc: Tim Bird, Steve Rostedt, john.ogness, senozhatsky, Tim Bird,
	Andrew Morton, LKML, Anna-Maria Behnsen, Frederic Weisbecker,
	Thomas Gleixner, Linux Embedded
In-Reply-To: <aSWqWD1BQ-m-Zy9C@bywater>

On Tue 2025-11-25 14:08:40, Francesco Valla wrote:
> Hi Tim,
> 
> I tested this on my i.MX93 FRDM (arm64) board and after a bit of
> fiddling with the MULT/SHIFT values I got it working. It can be a very
> valuable addition.
> 
> Some comments follow.
> 
> On Mon, Nov 24, 2025 at 10:30:52PM -0700, Tim Bird wrote:
> > From: Tim Bird <tim.bird@sony.com>
> > 
> > During early boot, printk timestamps are reported as zero,
> > which creates a blind spot in early boot timings.  This blind
> > spot hinders timing and optimization efforts for code that
> > executes before time_init(), which is when local_clock() is
> > initialized sufficiently to start returning non-zero timestamps.
> > This period is about 400 milliseconds for many current desktop
> > and embedded machines running Linux.
> > 
> > Add an early_counter_ns function that returns nanosecond
> > timestamps based on get_cycles().  get_cycles() is operational
> > on arm64 and x86_64 from kernel start.  Add some calibration
> > printks to allow setting configuration variables that are used
> > to convert cycle counts to nanoseconds (which are then used
> > in early printks).  Add CONFIG_EARLY_COUNTER_NS, as well as
> > some associated conversion variables, as new kernel config
> > variables.
> > 
> > After proper configuration, this yields non-zero timestamps for
> > printks from the very start of kernel execution.  The timestamps
> > are relative to the start of the architecture-specific counter
> > used in get_cycles (e.g. the TSC on x86_64 and cntvct_el0 on arm64).
> > This means that the time reported reflects time-from-power-on for
> > most embedded products.  This is also a useful data point for
> > boot-time optimization work.
> > 
> > Note that there is a discontinuity in the timestamp sequencing
> > when standard clocks are finally initialized in time_init().
> > The printk timestamps are thus not monotonically increasing
> > through the entire boot.
> 
> This is... not going to work, IMO, and might lead to breakages in
> userspace tools (are printk timings a userspace API?).

Honestly, I am not sure if it would break anything. The fact is
that printk() always used monotonic timers. And it is possible
that some userspace depends on it.

I personally thing that non-monotonic time stamps might be confusing
but they should not cause any serious breakage. But I might be wrong.
People are creative...

> I actually have a counter-proposal: the time obtained through cycle
> evaluation is used as an offset to be added to the printk time after
> time_init() is called. A (working, but maybe sub-optimal) patch to
> obtain this is attached at the end.

I am not sure if this is a good idea. The offset would cause
that all post-timer-init printk timestamps differ from values
provided by the timer API. And it might cause confusion,
for example, when they are printed as part of the message,
or when analyzing a crash dump.

On the other hand, there are various clock sources in the kernel
which are not comparable anyway. So maybe I am too cautious.

> > --- a/init/Kconfig
> > +++ b/init/Kconfig
> > @@ -770,6 +770,53 @@ config IKHEADERS
> >  	  or similar programs.  If you build the headers as a module, a module called
> >  	  kheaders.ko is built which can be loaded on-demand to get access to headers.
> >  
> > +config EARLY_COUNTER_NS
> > +	bool "Use counter for early printk timestamps"
> > +	default y
> > +	depends on PRINTK
> > +	help
> > +	  Use a cycle-counter to provide printk timestamps during early
> > +	  boot.  This allows seeing timing information that would
> > +	  otherwise be displayed with 0-valued timestamps.
> > +
> > +	  In order for this to work, you need to specify values for
> > +	  EARLY_COUNTER_MULT and EARLY_COUNTER_SHIFT, used to convert
> > +	  from the cycle count to nanoseconds.
> > +
> > +config EARLY_COUNTER_MULT
> > +	int "Multiplier for early cycle counter"
> > +	depends on PRINTK && EARLY_COUNTER_NS
> > +	default 1
> > +	help
> > +	  This value specifies a multiplier to be used when converting
> > +	  cycle counts to nanoseconds.  The formula used is:
> > +		  ns = (cycles * mult) >> shift
> > +
> > +	  Use a multiplier that will bring the value of (cycles * mult)
> > +	  to near a power of two, that is greater than 1000.  The
> > +	  nanoseconds returned by this conversion are divided by 1000
> > +	  to be used as the printk timestamp counter (with resolution
> > +	  of microseconds).
> > +
> > +	  As an example, for a cycle-counter with a frequency of 200 Mhz,
> > +	  the multiplier would be: 10485760, and the shift would be 21.
> > +
> 
> If I got this correclty:
> 
> 	EARLY_COUNTER_MULT = (10^9 / freq) << EARLY_COUNTER_SHIFT
> 
> where EARLY_COUNTER_SHIFT can be chosen at will, provided it is big
> enough to survice the ns->us conversion but small enough not to overflow
> the u64 container. 
> 
> > +config EARLY_COUNTER_SHIFT
> > +	int "Shift value for early cycle counter"
> > +	range 0 63
> > +	depends on PRINTK && EARLY_COUNTER_NS
> > +	default 0
> > +	help
> > +	  This value specifies a shift value to be used when converting
> > +	  cycle counts to nanoseconds.  The formula used is:
> > +		  ns = (cycles * mult) >> shift
> > +
> > +	  Use a shift that will bring the result to a value
> > +	  in nanoseconds.
> > +
> > +	  As an example, for a cycle-counter with a frequency of 200 Mhz,
> > +	  the multiplier would be: 10485760, and the shift would be 21.
> > +
> >  config LOG_BUF_SHIFT
> >  	int "Kernel log buffer size (16 => 64KB, 17 => 128KB)"
> >  	range 12 25

So, it is usable only for a particular HW. It is not usable for a
generic kernel which is supposed to run on misc HW.

I guess that there is no way to detect the CPU frequency at runtime?

Best Regards,
Petr

^ permalink raw reply

* Re: [PATCH] printk: add early_counter_ns routine for printk blind spot
From: Petr Mladek @ 2025-11-26 11:13 UTC (permalink / raw)
  To: Tim Bird
  Cc: Steve Rostedt, john.ogness, senozhatsky, Tim Bird, Andrew Morton,
	Francesco Valla, LKML, Anna-Maria Behnsen, Frederic Weisbecker,
	Thomas Gleixner, Linux Embedded
In-Reply-To: <39b09edb-8998-4ebd-a564-7d594434a981@bird.org>

Adding some people from the time subsystem into Cc.
Please, keep them in the loop in the eventual next version of the
patch.

For the new people, please note the discussion has already started,
see
https://lore.kernel.org/r/39b09edb-8998-4ebd-a564-7d594434a981@bird.org

Best Regards,
Petr

On Mon 2025-11-24 22:30:52, Tim Bird wrote:
> From: Tim Bird <tim.bird@sony.com>
> 
> During early boot, printk timestamps are reported as zero,
> which creates a blind spot in early boot timings.  This blind
> spot hinders timing and optimization efforts for code that
> executes before time_init(), which is when local_clock() is
> initialized sufficiently to start returning non-zero timestamps.
> This period is about 400 milliseconds for many current desktop
> and embedded machines running Linux.
> 
> Add an early_counter_ns function that returns nanosecond
> timestamps based on get_cycles().  get_cycles() is operational
> on arm64 and x86_64 from kernel start.  Add some calibration
> printks to allow setting configuration variables that are used
> to convert cycle counts to nanoseconds (which are then used
> in early printks).  Add CONFIG_EARLY_COUNTER_NS, as well as
> some associated conversion variables, as new kernel config
> variables.
> 
> After proper configuration, this yields non-zero timestamps for
> printks from the very start of kernel execution.  The timestamps
> are relative to the start of the architecture-specific counter
> used in get_cycles (e.g. the TSC on x86_64 and cntvct_el0 on arm64).
> This means that the time reported reflects time-from-power-on for
> most embedded products.  This is also a useful data point for
> boot-time optimization work.
> 
> Note that there is a discontinuity in the timestamp sequencing
> when standard clocks are finally initialized in time_init().
> The printk timestamps are thus not monotonically increasing
> through the entire boot.
> 
> Signed-off-by: Tim Bird <tim.bird@sony.com>
> ---
>  init/Kconfig           | 47 ++++++++++++++++++++++++++++++++++++++++++
>  init/main.c            | 25 ++++++++++++++++++++++
>  kernel/printk/printk.c | 15 ++++++++++++++
>  3 files changed, 87 insertions(+)
> 
> diff --git a/init/Kconfig b/init/Kconfig
> index cab3ad28ca49..5352567c43ed 100644
> --- a/init/Kconfig
> +++ b/init/Kconfig
> @@ -770,6 +770,53 @@ config IKHEADERS
>  	  or similar programs.  If you build the headers as a module, a module called
>  	  kheaders.ko is built which can be loaded on-demand to get access to headers.
>  
> +config EARLY_COUNTER_NS
> +	bool "Use counter for early printk timestamps"
> +	default y
> +	depends on PRINTK
> +	help
> +	  Use a cycle-counter to provide printk timestamps during early
> +	  boot.  This allows seeing timing information that would
> +	  otherwise be displayed with 0-valued timestamps.
> +
> +	  In order for this to work, you need to specify values for
> +	  EARLY_COUNTER_MULT and EARLY_COUNTER_SHIFT, used to convert
> +	  from the cycle count to nanoseconds.
> +
> +config EARLY_COUNTER_MULT
> +	int "Multiplier for early cycle counter"
> +	depends on PRINTK && EARLY_COUNTER_NS
> +	default 1
> +	help
> +	  This value specifies a multiplier to be used when converting
> +	  cycle counts to nanoseconds.  The formula used is:
> +		  ns = (cycles * mult) >> shift
> +
> +	  Use a multiplier that will bring the value of (cycles * mult)
> +	  to near a power of two, that is greater than 1000.  The
> +	  nanoseconds returned by this conversion are divided by 1000
> +	  to be used as the printk timestamp counter (with resolution
> +	  of microseconds).
> +
> +	  As an example, for a cycle-counter with a frequency of 200 Mhz,
> +	  the multiplier would be: 10485760, and the shift would be 21.
> +
> +config EARLY_COUNTER_SHIFT
> +	int "Shift value for early cycle counter"
> +	range 0 63
> +	depends on PRINTK && EARLY_COUNTER_NS
> +	default 0
> +	help
> +	  This value specifies a shift value to be used when converting
> +	  cycle counts to nanoseconds.  The formula used is:
> +		  ns = (cycles * mult) >> shift
> +
> +	  Use a shift that will bring the result to a value
> +	  in nanoseconds.
> +
> +	  As an example, for a cycle-counter with a frequency of 200 Mhz,
> +	  the multiplier would be: 10485760, and the shift would be 21.
> +
>  config LOG_BUF_SHIFT
>  	int "Kernel log buffer size (16 => 64KB, 17 => 128KB)"
>  	range 12 25
> diff --git a/init/main.c b/init/main.c
> index 07a3116811c5..587aaaad22d1 100644
> --- a/init/main.c
> +++ b/init/main.c
> @@ -105,6 +105,8 @@
>  #include <linux/ptdump.h>
>  #include <linux/time_namespace.h>
>  #include <net/net_namespace.h>
> +#include <linux/timex.h>
> +#include <linux/sched/clock.h>
>  
>  #include <asm/io.h>
>  #include <asm/setup.h>
> @@ -906,6 +908,8 @@ static void __init early_numa_node_init(void)
>  #endif
>  }
>  
> +static u64 start_cycles, start_ns;
> +
>  asmlinkage __visible __init __no_sanitize_address __noreturn __no_stack_protector
>  void start_kernel(void)
>  {
> @@ -1023,6 +1027,10 @@ void start_kernel(void)
>  	timekeeping_init();
>  	time_init();
>  
> +	/* used to calibrate early_counter_ns */
> +	start_cycles = get_cycles();
> +	start_ns = local_clock();
> +
>  	/* This must be after timekeeping is initialized */
>  	random_init();
>  
> @@ -1474,6 +1482,8 @@ void __weak free_initmem(void)
>  static int __ref kernel_init(void *unused)
>  {
>  	int ret;
> +	u64 end_cycles, end_ns;
> +	u32 early_mult, early_shift;
>  
>  	/*
>  	 * Wait until kthreadd is all set-up.
> @@ -1505,6 +1515,21 @@ static int __ref kernel_init(void *unused)
>  
>  	do_sysctl_args();
>  
> +	/* show calibration data for early_counter_ns */
> +	end_cycles = get_cycles();
> +	end_ns = local_clock();
> +	clocks_calc_mult_shift(&early_mult, &early_shift,
> +		((end_cycles - start_cycles) * NSEC_PER_SEC)/(end_ns - start_ns),
> +		NSEC_PER_SEC, 50);
> +
> +#ifdef CONFIG_EARLY_COUNTER_NS
> +	pr_info("Early Counter: start_cycles=%llu, end_cycles=%llu, cycles=%llu\n",
> +		start_cycles, end_cycles, (end_cycles - start_cycles));
> +	pr_info("Early Counter: start_ns=%llu, end_ns=%llu, ns=%llu\n",
> +		start_ns, end_ns, (end_ns - start_ns));
> +	pr_info("Early Counter: MULT=%u, SHIFT=%u\n", early_mult, early_shift);
> +#endif
> +
>  	if (ramdisk_execute_command) {
>  		ret = run_init_process(ramdisk_execute_command);
>  		if (!ret)
> diff --git a/kernel/printk/printk.c b/kernel/printk/printk.c
> index 5aee9ffb16b9..522dd24cd534 100644
> --- a/kernel/printk/printk.c
> +++ b/kernel/printk/printk.c
> @@ -2210,6 +2210,19 @@ static u16 printk_sprint(char *text, u16 size, int facility,
>  	return text_len;
>  }
>  
> +#ifdef CONFIG_EARLY_COUNTER_NS
> +static inline u64 early_counter_ns(void)
> +{
> +	return ((u64)get_cycles() * CONFIG_EARLY_COUNTER_MULT)
> +		>> CONFIG_EARLY_COUNTER_SHIFT;
> +}
> +#else
> +static inline u64 early_counter_ns(void)
> +{
> +	return 0;
> +}
> +#endif
> +
>  __printf(4, 0)
>  int vprintk_store(int facility, int level,
>  		  const struct dev_printk_info *dev_info,
> @@ -2239,6 +2252,8 @@ int vprintk_store(int facility, int level,
>  	 * timestamp with respect to the caller.
>  	 */
>  	ts_nsec = local_clock();
> +	if (!ts_nsec)
> +		ts_nsec = early_counter_ns();
>  
>  	caller_id = printk_caller_id();
>  
> -- 
> 2.43.0

^ permalink raw reply

* Re: [PATCH] printk: add early_counter_ns routine for printk blind spot
From: Geert Uytterhoeven @ 2025-11-26  7:38 UTC (permalink / raw)
  To: Francesco Valla
  Cc: Tim Bird, pmladek, Steve Rostedt, john.ogness, senozhatsky,
	Tim Bird, Andrew Morton, LKML, Linux Embedded
In-Reply-To: <aSWqWD1BQ-m-Zy9C@bywater>

Hi all,

On Wed, 26 Nov 2025 at 03:24, Francesco Valla <francesco@valla.it> wrote:
> On Mon, Nov 24, 2025 at 10:30:52PM -0700, Tim Bird wrote:
> > From: Tim Bird <tim.bird@sony.com>
> >
> > During early boot, printk timestamps are reported as zero,
> > which creates a blind spot in early boot timings.  This blind
> > spot hinders timing and optimization efforts for code that
> > executes before time_init(), which is when local_clock() is
> > initialized sufficiently to start returning non-zero timestamps.
> > This period is about 400 milliseconds for many current desktop
> > and embedded machines running Linux.
> >
> > Add an early_counter_ns function that returns nanosecond
> > timestamps based on get_cycles().  get_cycles() is operational
> > on arm64 and x86_64 from kernel start.  Add some calibration
> > printks to allow setting configuration variables that are used
> > to convert cycle counts to nanoseconds (which are then used
> > in early printks).  Add CONFIG_EARLY_COUNTER_NS, as well as
> > some associated conversion variables, as new kernel config
> > variables.
> >
> > After proper configuration, this yields non-zero timestamps for
> > printks from the very start of kernel execution.  The timestamps
> > are relative to the start of the architecture-specific counter
> > used in get_cycles (e.g. the TSC on x86_64 and cntvct_el0 on arm64).
> > This means that the time reported reflects time-from-power-on for
> > most embedded products.  This is also a useful data point for
> > boot-time optimization work.
> >
> > Note that there is a discontinuity in the timestamp sequencing
> > when standard clocks are finally initialized in time_init().
> > The printk timestamps are thus not monotonically increasing
> > through the entire boot.
>
> This is... not going to work, IMO, and might lead to breakages in
> userspace tools (are printk timings a userspace API?).

I think they are.

Another approach would be to defer the calibration/conversion to
userspace, and make sure the early part stands out.
I.e. when real timekeeping is available, kernel messages are prefixed by
"[%5lu.%06lu]".  Early messages could be prefixed by a plain integer
"[%12u]", containing the raw cycle counter value.
The presence of the decimal point would make the difference obvious.

> I actually have a counter-proposal: the time obtained through cycle
> evaluation is used as an offset to be added to the printk time after
> time_init() is called. A (working, but maybe sub-optimal) patch to
> obtain this is attached at the end.

Oh, that's a nice idea, too!

Gr{oetje,eeting}s,

                        Geert

-- 
Geert Uytterhoeven -- There's lots of Linux beyond ia32 -- geert@linux-m68k.org

In personal conversations with technical people, I call myself a hacker. But
when I'm talking to journalists I just say "programmer" or something like that.
                                -- Linus Torvalds

^ permalink raw reply

* Re: [PATCH] printk: add early_counter_ns routine for printk blind spot
From: Francesco Valla @ 2025-11-25 13:08 UTC (permalink / raw)
  To: Tim Bird
  Cc: pmladek, Steve Rostedt, john.ogness, senozhatsky, Tim Bird,
	Andrew Morton, LKML, Linux Embedded
In-Reply-To: <39b09edb-8998-4ebd-a564-7d594434a981@bird.org>

Hi Tim,

I tested this on my i.MX93 FRDM (arm64) board and after a bit of
fiddling with the MULT/SHIFT values I got it working. It can be a very
valuable addition.

Some comments follow.

On Mon, Nov 24, 2025 at 10:30:52PM -0700, Tim Bird wrote:
> From: Tim Bird <tim.bird@sony.com>
> 
> During early boot, printk timestamps are reported as zero,
> which creates a blind spot in early boot timings.  This blind
> spot hinders timing and optimization efforts for code that
> executes before time_init(), which is when local_clock() is
> initialized sufficiently to start returning non-zero timestamps.
> This period is about 400 milliseconds for many current desktop
> and embedded machines running Linux.
> 
> Add an early_counter_ns function that returns nanosecond
> timestamps based on get_cycles().  get_cycles() is operational
> on arm64 and x86_64 from kernel start.  Add some calibration
> printks to allow setting configuration variables that are used
> to convert cycle counts to nanoseconds (which are then used
> in early printks).  Add CONFIG_EARLY_COUNTER_NS, as well as
> some associated conversion variables, as new kernel config
> variables.
> 
> After proper configuration, this yields non-zero timestamps for
> printks from the very start of kernel execution.  The timestamps
> are relative to the start of the architecture-specific counter
> used in get_cycles (e.g. the TSC on x86_64 and cntvct_el0 on arm64).
> This means that the time reported reflects time-from-power-on for
> most embedded products.  This is also a useful data point for
> boot-time optimization work.
> 
> Note that there is a discontinuity in the timestamp sequencing
> when standard clocks are finally initialized in time_init().
> The printk timestamps are thus not monotonically increasing
> through the entire boot.

This is... not going to work, IMO, and might lead to breakages in
userspace tools (are printk timings a userspace API?).

I actually have a counter-proposal: the time obtained through cycle
evaluation is used as an offset to be added to the printk time after
time_init() is called. A (working, but maybe sub-optimal) patch to
obtain this is attached at the end.

> 
> Signed-off-by: Tim Bird <tim.bird@sony.com>
> ---
>  init/Kconfig           | 47 ++++++++++++++++++++++++++++++++++++++++++
>  init/main.c            | 25 ++++++++++++++++++++++
>  kernel/printk/printk.c | 15 ++++++++++++++
>  3 files changed, 87 insertions(+)
> 
> diff --git a/init/Kconfig b/init/Kconfig
> index cab3ad28ca49..5352567c43ed 100644
> --- a/init/Kconfig
> +++ b/init/Kconfig
> @@ -770,6 +770,53 @@ config IKHEADERS
>  	  or similar programs.  If you build the headers as a module, a module called
>  	  kheaders.ko is built which can be loaded on-demand to get access to headers.
>  
> +config EARLY_COUNTER_NS
> +	bool "Use counter for early printk timestamps"
> +	default y
> +	depends on PRINTK
> +	help
> +	  Use a cycle-counter to provide printk timestamps during early
> +	  boot.  This allows seeing timing information that would
> +	  otherwise be displayed with 0-valued timestamps.
> +
> +	  In order for this to work, you need to specify values for
> +	  EARLY_COUNTER_MULT and EARLY_COUNTER_SHIFT, used to convert
> +	  from the cycle count to nanoseconds.
> +
> +config EARLY_COUNTER_MULT
> +	int "Multiplier for early cycle counter"
> +	depends on PRINTK && EARLY_COUNTER_NS
> +	default 1
> +	help
> +	  This value specifies a multiplier to be used when converting
> +	  cycle counts to nanoseconds.  The formula used is:
> +		  ns = (cycles * mult) >> shift
> +
> +	  Use a multiplier that will bring the value of (cycles * mult)
> +	  to near a power of two, that is greater than 1000.  The
> +	  nanoseconds returned by this conversion are divided by 1000
> +	  to be used as the printk timestamp counter (with resolution
> +	  of microseconds).
> +
> +	  As an example, for a cycle-counter with a frequency of 200 Mhz,
> +	  the multiplier would be: 10485760, and the shift would be 21.
> +

If I got this correclty:

	EARLY_COUNTER_MULT = (10^9 / freq) << EARLY_COUNTER_SHIFT

where EARLY_COUNTER_SHIFT can be chosen at will, provided it is big
enough to survice the ns->us conversion but small enough not to overflow
the u64 container. 

> +config EARLY_COUNTER_SHIFT
> +	int "Shift value for early cycle counter"
> +	range 0 63
> +	depends on PRINTK && EARLY_COUNTER_NS
> +	default 0
> +	help
> +	  This value specifies a shift value to be used when converting
> +	  cycle counts to nanoseconds.  The formula used is:
> +		  ns = (cycles * mult) >> shift
> +
> +	  Use a shift that will bring the result to a value
> +	  in nanoseconds.
> +
> +	  As an example, for a cycle-counter with a frequency of 200 Mhz,
> +	  the multiplier would be: 10485760, and the shift would be 21.
> +
>  config LOG_BUF_SHIFT
>  	int "Kernel log buffer size (16 => 64KB, 17 => 128KB)"
>  	range 12 25
> diff --git a/init/main.c b/init/main.c
> index 07a3116811c5..587aaaad22d1 100644
> --- a/init/main.c
> +++ b/init/main.c
> @@ -105,6 +105,8 @@
>  #include <linux/ptdump.h>
>  #include <linux/time_namespace.h>
>  #include <net/net_namespace.h>
> +#include <linux/timex.h>
> +#include <linux/sched/clock.h>
>  
>  #include <asm/io.h>
>  #include <asm/setup.h>
> @@ -906,6 +908,8 @@ static void __init early_numa_node_init(void)
>  #endif
>  }
>  
> +static u64 start_cycles, start_ns;
> +
>  asmlinkage __visible __init __no_sanitize_address __noreturn __no_stack_protector
>  void start_kernel(void)
>  {
> @@ -1023,6 +1027,10 @@ void start_kernel(void)
>  	timekeeping_init();
>  	time_init();
>  
> +	/* used to calibrate early_counter_ns */
> +	start_cycles = get_cycles();
> +	start_ns = local_clock();
> +
>  	/* This must be after timekeeping is initialized */
>  	random_init();
>  
> @@ -1474,6 +1482,8 @@ void __weak free_initmem(void)
>  static int __ref kernel_init(void *unused)
>  {
>  	int ret;
> +	u64 end_cycles, end_ns;
> +	u32 early_mult, early_shift;
>  
>  	/*
>  	 * Wait until kthreadd is all set-up.
> @@ -1505,6 +1515,21 @@ static int __ref kernel_init(void *unused)
>  
>  	do_sysctl_args();
>  
> +	/* show calibration data for early_counter_ns */
> +	end_cycles = get_cycles();
> +	end_ns = local_clock();
> +	clocks_calc_mult_shift(&early_mult, &early_shift,
> +		((end_cycles - start_cycles) * NSEC_PER_SEC)/(end_ns - start_ns),
> +		NSEC_PER_SEC, 50);
> +
> +#ifdef CONFIG_EARLY_COUNTER_NS
> +	pr_info("Early Counter: start_cycles=%llu, end_cycles=%llu, cycles=%llu\n",
> +		start_cycles, end_cycles, (end_cycles - start_cycles));
> +	pr_info("Early Counter: start_ns=%llu, end_ns=%llu, ns=%llu\n",
> +		start_ns, end_ns, (end_ns - start_ns));
> +	pr_info("Early Counter: MULT=%u, SHIFT=%u\n", early_mult, early_shift);
> +#endif
> +

I don't get the need to have these here - should they be an help for the
integrator to calibrate and choose EARLY_COUNTER_MULT and
EARLY_COUNTER_SHIFT? The ns values printed here have some meaning only if
these two parameters are already set correctly in the first place -
what's the foreseen calibration procedure?

Moreover, if they are only required for calibration, maybe pr_debugi()
would be a better choice?

>  	if (ramdisk_execute_command) {
>  		ret = run_init_process(ramdisk_execute_command);
>  		if (!ret)
> diff --git a/kernel/printk/printk.c b/kernel/printk/printk.c
> index 5aee9ffb16b9..522dd24cd534 100644
> --- a/kernel/printk/printk.c
> +++ b/kernel/printk/printk.c
> @@ -2210,6 +2210,19 @@ static u16 printk_sprint(char *text, u16 size, int facility,
>  	return text_len;
>  }
>  
> +#ifdef CONFIG_EARLY_COUNTER_NS
> +static inline u64 early_counter_ns(void)
> +{
> +	return ((u64)get_cycles() * CONFIG_EARLY_COUNTER_MULT)
> +		>> CONFIG_EARLY_COUNTER_SHIFT;
> +}
> +#else
> +static inline u64 early_counter_ns(void)
> +{
> +	return 0;
> +}
> +#endif
> +
>  __printf(4, 0)
>  int vprintk_store(int facility, int level,
>  		  const struct dev_printk_info *dev_info,
> @@ -2239,6 +2252,8 @@ int vprintk_store(int facility, int level,
>  	 * timestamp with respect to the caller.
>  	 */
>  	ts_nsec = local_clock();
> +	if (!ts_nsec)
> +		ts_nsec = early_counter_ns();
>  
>  	caller_id = printk_caller_id();
>  
> -- 
> 2.43.0
> 
> 

Best regards,

Francesco

---

diff --git a/kernel/printk/printk.c b/kernel/printk/printk.c
index 522dd24cd534..b4108f215c5e 100644
--- a/kernel/printk/printk.c
+++ b/kernel/printk/printk.c
@@ -2216,11 +2216,26 @@ static inline u64 early_counter_ns(void)
 	return ((u64)get_cycles() * CONFIG_EARLY_COUNTER_MULT)
 		>> CONFIG_EARLY_COUNTER_SHIFT;
 }
+
+static u64 early_counter_ns_offset(void)
+{
+	static u64 early_counter_ns_start = 0;
+
+	if (!early_counter_ns_start)
+		early_counter_ns_start = early_counter_ns();
+
+	return early_counter_ns_start;
+}
 #else
 static inline u64 early_counter_ns(void)
 {
 	return 0;
 }
+
+static inline u64 early_counter_ns_offset(void)
+{
+	return 0;
+}
 #endif
 
 __printf(4, 0)
@@ -2254,6 +2269,8 @@ int vprintk_store(int facility, int level,
 	ts_nsec = local_clock();
 	if (!ts_nsec)
 		ts_nsec = early_counter_ns();
+	else
+		ts_nsec += early_counter_ns_offset();
 
 	caller_id = printk_caller_id();


^ permalink raw reply related

* Re: [PATCH] printk: add early_counter_ns routine for printk blind spot
From: kernel test robot @ 2025-11-25  7:52 UTC (permalink / raw)
  To: Tim Bird, pmladek, Steve Rostedt, john.ogness, senozhatsky
  Cc: oe-kbuild-all, Tim Bird, Andrew Morton,
	Linux Memory Management List, Francesco Valla, LKML,
	Linux Embedded
In-Reply-To: <39b09edb-8998-4ebd-a564-7d594434a981@bird.org>

Hi Tim,

kernel test robot noticed the following build errors:

[auto build test ERROR on linus/master]
[also build test ERROR on v6.18-rc7]
[cannot apply to akpm-mm/mm-everything next-20251124]
[If your patch is applied to the wrong git tree, kindly drop us a note.
And when submitting patch, we suggest to use '--base' as documented in
https://git-scm.com/docs/git-format-patch#_base_tree_information]

url:    https://github.com/intel-lab-lkp/linux/commits/Tim-Bird/printk-add-early_counter_ns-routine-for-printk-blind-spot/20251125-133242
base:   linus/master
patch link:    https://lore.kernel.org/r/39b09edb-8998-4ebd-a564-7d594434a981%40bird.org
patch subject: [PATCH] printk: add early_counter_ns routine for printk blind spot
config: powerpc-allnoconfig (https://download.01.org/0day-ci/archive/20251125/202511251534.9kMSsAH6-lkp@intel.com/config)
compiler: powerpc-linux-gcc (GCC) 15.1.0
reproduce (this is a W=1 build): (https://download.01.org/0day-ci/archive/20251125/202511251534.9kMSsAH6-lkp@intel.com/reproduce)

If you fix the issue in a separate patch/commit (i.e. not just a new version of
the same patch/commit), kindly add following tags
| Reported-by: kernel test robot <lkp@intel.com>
| Closes: https://lore.kernel.org/oe-kbuild-all/202511251534.9kMSsAH6-lkp@intel.com/

All errors (new ones prefixed by >>):

   powerpc-linux-ld: init/main.o: in function `kernel_init':
>> main.c:(.ref.text+0x144): undefined reference to `__udivdi3'

-- 
0-DAY CI Kernel Test Service
https://github.com/intel/lkp-tests/wiki

^ permalink raw reply

* [PATCH] printk: add early_counter_ns routine for printk blind spot
From: Tim Bird @ 2025-11-25  5:30 UTC (permalink / raw)
  To: pmladek, Steve Rostedt, john.ogness, senozhatsky
  Cc: Tim Bird, Andrew Morton, Francesco Valla, LKML, Linux Embedded

From: Tim Bird <tim.bird@sony.com>

During early boot, printk timestamps are reported as zero,
which creates a blind spot in early boot timings.  This blind
spot hinders timing and optimization efforts for code that
executes before time_init(), which is when local_clock() is
initialized sufficiently to start returning non-zero timestamps.
This period is about 400 milliseconds for many current desktop
and embedded machines running Linux.

Add an early_counter_ns function that returns nanosecond
timestamps based on get_cycles().  get_cycles() is operational
on arm64 and x86_64 from kernel start.  Add some calibration
printks to allow setting configuration variables that are used
to convert cycle counts to nanoseconds (which are then used
in early printks).  Add CONFIG_EARLY_COUNTER_NS, as well as
some associated conversion variables, as new kernel config
variables.

After proper configuration, this yields non-zero timestamps for
printks from the very start of kernel execution.  The timestamps
are relative to the start of the architecture-specific counter
used in get_cycles (e.g. the TSC on x86_64 and cntvct_el0 on arm64).
This means that the time reported reflects time-from-power-on for
most embedded products.  This is also a useful data point for
boot-time optimization work.

Note that there is a discontinuity in the timestamp sequencing
when standard clocks are finally initialized in time_init().
The printk timestamps are thus not monotonically increasing
through the entire boot.

Signed-off-by: Tim Bird <tim.bird@sony.com>
---
 init/Kconfig           | 47 ++++++++++++++++++++++++++++++++++++++++++
 init/main.c            | 25 ++++++++++++++++++++++
 kernel/printk/printk.c | 15 ++++++++++++++
 3 files changed, 87 insertions(+)

diff --git a/init/Kconfig b/init/Kconfig
index cab3ad28ca49..5352567c43ed 100644
--- a/init/Kconfig
+++ b/init/Kconfig
@@ -770,6 +770,53 @@ config IKHEADERS
 	  or similar programs.  If you build the headers as a module, a module called
 	  kheaders.ko is built which can be loaded on-demand to get access to headers.
 
+config EARLY_COUNTER_NS
+	bool "Use counter for early printk timestamps"
+	default y
+	depends on PRINTK
+	help
+	  Use a cycle-counter to provide printk timestamps during early
+	  boot.  This allows seeing timing information that would
+	  otherwise be displayed with 0-valued timestamps.
+
+	  In order for this to work, you need to specify values for
+	  EARLY_COUNTER_MULT and EARLY_COUNTER_SHIFT, used to convert
+	  from the cycle count to nanoseconds.
+
+config EARLY_COUNTER_MULT
+	int "Multiplier for early cycle counter"
+	depends on PRINTK && EARLY_COUNTER_NS
+	default 1
+	help
+	  This value specifies a multiplier to be used when converting
+	  cycle counts to nanoseconds.  The formula used is:
+		  ns = (cycles * mult) >> shift
+
+	  Use a multiplier that will bring the value of (cycles * mult)
+	  to near a power of two, that is greater than 1000.  The
+	  nanoseconds returned by this conversion are divided by 1000
+	  to be used as the printk timestamp counter (with resolution
+	  of microseconds).
+
+	  As an example, for a cycle-counter with a frequency of 200 Mhz,
+	  the multiplier would be: 10485760, and the shift would be 21.
+
+config EARLY_COUNTER_SHIFT
+	int "Shift value for early cycle counter"
+	range 0 63
+	depends on PRINTK && EARLY_COUNTER_NS
+	default 0
+	help
+	  This value specifies a shift value to be used when converting
+	  cycle counts to nanoseconds.  The formula used is:
+		  ns = (cycles * mult) >> shift
+
+	  Use a shift that will bring the result to a value
+	  in nanoseconds.
+
+	  As an example, for a cycle-counter with a frequency of 200 Mhz,
+	  the multiplier would be: 10485760, and the shift would be 21.
+
 config LOG_BUF_SHIFT
 	int "Kernel log buffer size (16 => 64KB, 17 => 128KB)"
 	range 12 25
diff --git a/init/main.c b/init/main.c
index 07a3116811c5..587aaaad22d1 100644
--- a/init/main.c
+++ b/init/main.c
@@ -105,6 +105,8 @@
 #include <linux/ptdump.h>
 #include <linux/time_namespace.h>
 #include <net/net_namespace.h>
+#include <linux/timex.h>
+#include <linux/sched/clock.h>
 
 #include <asm/io.h>
 #include <asm/setup.h>
@@ -906,6 +908,8 @@ static void __init early_numa_node_init(void)
 #endif
 }
 
+static u64 start_cycles, start_ns;
+
 asmlinkage __visible __init __no_sanitize_address __noreturn __no_stack_protector
 void start_kernel(void)
 {
@@ -1023,6 +1027,10 @@ void start_kernel(void)
 	timekeeping_init();
 	time_init();
 
+	/* used to calibrate early_counter_ns */
+	start_cycles = get_cycles();
+	start_ns = local_clock();
+
 	/* This must be after timekeeping is initialized */
 	random_init();
 
@@ -1474,6 +1482,8 @@ void __weak free_initmem(void)
 static int __ref kernel_init(void *unused)
 {
 	int ret;
+	u64 end_cycles, end_ns;
+	u32 early_mult, early_shift;
 
 	/*
 	 * Wait until kthreadd is all set-up.
@@ -1505,6 +1515,21 @@ static int __ref kernel_init(void *unused)
 
 	do_sysctl_args();
 
+	/* show calibration data for early_counter_ns */
+	end_cycles = get_cycles();
+	end_ns = local_clock();
+	clocks_calc_mult_shift(&early_mult, &early_shift,
+		((end_cycles - start_cycles) * NSEC_PER_SEC)/(end_ns - start_ns),
+		NSEC_PER_SEC, 50);
+
+#ifdef CONFIG_EARLY_COUNTER_NS
+	pr_info("Early Counter: start_cycles=%llu, end_cycles=%llu, cycles=%llu\n",
+		start_cycles, end_cycles, (end_cycles - start_cycles));
+	pr_info("Early Counter: start_ns=%llu, end_ns=%llu, ns=%llu\n",
+		start_ns, end_ns, (end_ns - start_ns));
+	pr_info("Early Counter: MULT=%u, SHIFT=%u\n", early_mult, early_shift);
+#endif
+
 	if (ramdisk_execute_command) {
 		ret = run_init_process(ramdisk_execute_command);
 		if (!ret)
diff --git a/kernel/printk/printk.c b/kernel/printk/printk.c
index 5aee9ffb16b9..522dd24cd534 100644
--- a/kernel/printk/printk.c
+++ b/kernel/printk/printk.c
@@ -2210,6 +2210,19 @@ static u16 printk_sprint(char *text, u16 size, int facility,
 	return text_len;
 }
 
+#ifdef CONFIG_EARLY_COUNTER_NS
+static inline u64 early_counter_ns(void)
+{
+	return ((u64)get_cycles() * CONFIG_EARLY_COUNTER_MULT)
+		>> CONFIG_EARLY_COUNTER_SHIFT;
+}
+#else
+static inline u64 early_counter_ns(void)
+{
+	return 0;
+}
+#endif
+
 __printf(4, 0)
 int vprintk_store(int facility, int level,
 		  const struct dev_printk_info *dev_info,
@@ -2239,6 +2252,8 @@ int vprintk_store(int facility, int level,
 	 * timestamp with respect to the caller.
 	 */
 	ts_nsec = local_clock();
+	if (!ts_nsec)
+		ts_nsec = early_counter_ns();
 
 	caller_id = printk_caller_id();
 
-- 
2.43.0


^ permalink raw reply related

* [boot-time] Reminder of Boot-Time SIG meeting (Nov 25)
From: Bird, Tim @ 2025-11-21  2:34 UTC (permalink / raw)
  To: Linux Embedded

Hey Linux Boot-Time SIG interested parties (and other interested Linux kernel developers),

Here is the information for the next Linux Boot-Time SIG conference call.

The meeting will be held via the Jitsi online meeting platform.
To Join the meeting via web, click on:
https://meet.jit.si/LinuxBootTimeSIG

----
Our next meeting is Tuesday, November 25, at 9:00 am Mountain Standard Time.
See this link for other time zones:
https://www.timeanddate.com/worldclock/meetingdetails.html?year=2025&month=11&day=25&hour=16&min=0&sec=0&p1=220&p2=137&p3=195&p4=771
(That makes it 8:00 am Pacific, 16:00 UTC, 17:00 CET, and 21:30 IST)

I'm planning on 1 hour for this meeting.

The agenda for the meeting (and where we'll keep the minutes) is here:
https://docs.google.com/document/d/1XAufoTT6VVJOTMzKMoz8SyOss-JA9H4J1_yVXQq5mN0/edit?usp=sharing

The full  agenda for the October 28 meeting will be available in the above document before the call.
Below is what I've got so far.

I look forward to talking with you on Tuesday,
 -- Tim


Preliminary agenda:
  - items in flight status update:
    - bootcache - Ideas on Board
    - early_counter (printk 0-timestamp fix) - Sony/Tim
    - Unified Boot Log (UBL) - Texas Instruments

- testing/tools
   - status of boot time regression test?

- want to start:
   - boot-time tuning tool (wizard)

- elinux wiki
   - updated https://elinux.org/Boot_Time_Presentations with talks from ELC 2025
      - still need to add talks from ELC Europe 2025
   - added https://elinux.org/ELC_2025_Boot_Time_Presentations
      - was produced by Sidharth Seela using AI (Tim converted to MediaWiki markdown)
      - please check for accuracy
   - I still want to work on a boot delay taxonomy document, but it will have to wait until January

- Conferences:
  - Linux Plumbers Conference (Dec 11-13, Tokyo)
     - 3 topics at Embedded micro-conference
       - Reducing Android Boot Times: Evaluating Proactive File Prefetching
       - Boot time optimization for embedded devices
       - Fixing clock tree Propagation in the common clk framework?
     - see https://lpc.events/event/19/sessions/232/#20251211

Next call: January 20 (No call in December)

^ permalink raw reply

* Re: [PATCH RFC 0/3] Add splash DRM client
From: Maxime Ripard @ 2025-10-29  8:36 UTC (permalink / raw)
  To: Francesco Valla
  Cc: Mario Limonciello, Thomas Zimmermann, Maarten Lankhorst,
	David Airlie, Simona Vetter, Jonathan Corbet, Jocelyn Falempe,
	Javier Martinez Canillas, Sam Ravnborg, linux-kernel, dri-devel,
	linux-doc, linux-embedded
In-Reply-To: <4497733.UPlyArG6xL@fedora.fritz.box>

[-- Attachment #1: Type: text/plain, Size: 2660 bytes --]

On Tue, Oct 28, 2025 at 09:09:06AM +0100, Francesco Valla wrote:
> Hi,
> 
> On Monday, 27 October 2025 at 18:19:12 Maxime Ripard <mripard@kernel.org> wrote:
> > On Mon, Oct 27, 2025 at 11:31:06AM -0500, Mario Limonciello wrote:
> > > On 10/27/25 11:28 AM, Maxime Ripard wrote:
> > > > On Mon, Oct 27, 2025 at 11:01:55AM -0500, Mario Limonciello wrote:
> > > > > On 10/27/25 7:35 AM, Thomas Zimmermann wrote:
> > > > > > > >     - a very simple progress bar, which can be driven through sysfs;
> > > > > > 
> > > > > > Once you have options to control these settings from user space, you
> > > > > > should do it in user space entirely. As Maxime suggested, please improve
> > > > > > plymouth for anything with animation.
> > > > > > 
> > > > > > > >     - a static image (optional).
> > > > > > 
> > > > > > Board vendors often provide an image, see /sys/firmware/acpi/bgrt/. This
> > > > > > is a candidate for display, or the penguin or a custom image. Please
> > > > > > make it configurable by Kconfig. Again, if you need policy and
> > > > > > heuristics for deciding what to display, you better do this in user
> > > > > > space.
> > > > > 
> > > > > I'd actually argue that the static image from BGRT should be the preferred
> > > > > priority.  This can make for a nice hand off to Plymouth.
> > > > > 
> > > > > The (UEFI) BIOS already will show this image as soon as the GOP driver is
> > > > > loaded.  Bootloaders like GRUB by default will avoid showing anything or
> > > > > will overwrite with the exact same image in the same location.  This can let
> > > > > the kernel do the same, and then the moment Plymouth takes over it could do
> > > > > the same.
> > > > 
> > > > And BGRT isn't typically found on embedded systems at all, so I'm not
> > > > sure it's a sensible default, let alone a priority. At most a possible
> > > 
> > > There are certainly embedded machines using UEFI and that have a BGRT.
> > 
> > Yes, indeed, hence the "typically".
> > 
> > > How about "Sensible default the top of the priority list if it exists"
> > 
> > How about we don't tell contributors what their priorities must be?
> > 
> > Maxime
> > 
> 
> I'm not familiar at all with BGRT, I'll study a bit about it.
> 
> A build-time configuration could then let the user select:
> 
> - a plain solid color
> - a custom static image
> - the penguin logo (?)
> - (on UEFI systems) BGRT source

It wouldn't work for generic distros that would run with the same config
on systems with and without BGRT.

Again, that whole discussion around BGRT is very premature, I'd suggest
to drop it for now.

Maxime

[-- Attachment #2: signature.asc --]
[-- Type: application/pgp-signature, Size: 273 bytes --]

^ permalink raw reply

* Re: [PATCH RFC 0/3] Add splash DRM client
From: Maxime Ripard @ 2025-10-29  8:34 UTC (permalink / raw)
  To: Francesco Valla
  Cc: Maarten Lankhorst, Thomas Zimmermann, David Airlie, Simona Vetter,
	Jonathan Corbet, Jocelyn Falempe, Javier Martinez Canillas,
	Sam Ravnborg, linux-kernel, dri-devel, linux-doc, linux-embedded
In-Reply-To: <2756316.lGaqSPkdTl@fedora.fritz.box>

[-- Attachment #1: Type: text/plain, Size: 5171 bytes --]

On Tue, Oct 28, 2025 at 08:58:05AM +0100, Francesco Valla wrote:
> On Monday, 27 October 2025 at 11:09:56 Maxime Ripard <mripard@kernel.org> wrote:
> > > Once compiled inside the kernel, the client can be enabled through the
> > > command line specifying the drm_client_lib.active=splash parameter.
> > > 
> > > == Motivation ==
> > > 
> > > The motivation behind this work is to offer to embedded system
> > > developers a new path for a simple activation of the display(s)
> > > connected to their system, with the following usecases:
> > > 
> > >   - bootsplash - possibly displaying even before init;
> > >   - early activation of the display pipeline, in particular whenever one
> > >     component of the pipeline (e.g.: a panel) takes a non-negligible
> > >     time to initialize;
> > >   - recovery systems, where the splash client can offer a simple feedback
> > >     for unattended recovery tasks;
> > >   - update systems, where the splash client can offer a simple feedback
> > >     for unattended update tasks.
> > 
> > If plymouth cannot be used by embedded systems for some reason, then you
> > should work on a plymouth alternative.
>
> Thing is: any possible alternative would still start after userspace has
> been loaded, checked (in case of secure boot, which is ubiquitous now)
> and initialized. This means, at least in my usecases, several hundreds of
> milliseconds after userspace start, to be summed to the panel initialization
> time.

Yeah, but you have a *lot* of policies even for something as simple as a
bootsplash:

  * Do you want it on all your screens or just one, if so, which one?

  * If the bootsplash image doesn't fit the screen you chose, what
    should you do? stretch, crop, keep the same resolution? If the image
    is smaller than the screen, where do you want to put it? Top left
    corner? In the center?

  * If there's BGRT, do you want to have BGRT always, bootsplash always,
    compose the bootsplash with BGRT? If so, same questions than before.

etc.

The kernel can't answer all these questions, and can't address every
possible use case. Userspace can, and that's largely why plymouth
exists.

But If the main thing you care about is boot time, U-Boot has everything
needed to setup a bootsplash early.

> > > While the first seems the most obvious one, it was the second that acted
> > > as the driver, as in the past I had to implement a ugly workaround using
> > > a systemd generator to kickstart the initialization of a display and
> > > shave ~400ms of boot time.
> > > 
> > > The last 2 usecase, instead, are the reason I dropped the "boot" part
> > > from bootsplash.
> > > 
> > > == Implementation details ==
> > > 
> > > The design is quite simple, with a kernel thread doing the heavylifting
> > > for the rendering part and some locking to protect interactions with it.
> > > 
> > > The splash image is loaded using the firmware framework, with the client
> > > expecting to find a binary dump having the right dimensions (width and
> > > height) and FOURCC format for each modeset. Given a 1920x1080 RGB888
> > > modeset, the client will for example search for a firmware named:
> > > 
> > >    drm_splash_1920x1080_RG24.raw
> > > 
> > > If the firmware cannot be loaded directly, the NOUEVENT sysfs fallback
> > > mechanism is used to let userspace load the appropriate image.
> > > 
> > > == Testing ==
> > > 
> > > Testing was done on qemu (both with vkms and bochs drivers), on a HDMI
> > > display connected to a Beagleplay and on a ILI9341 SPI display connected
> > > to a i.MX93 FRDM board. All these platforms revealed different
> > > weaknesses that were hopefully removed.
> > > 
> > > == Open points / issues ==
> > > 
> > > The reason for this being an RFC is that there are several open points:
> > > 
> > >   - Support for tiled connectors should be there, but has not been
> > >     tested. Any idea on how to test it?
> > 
> > Did you mean tiled formats?
> > 
> 
> No, AFAIU the tiled connectors are different connectors that feed different
> panels, which however are part of a single logical screen. Support for this
> setup is present at drm level [1], but I'm not familiar with it.
> 
> I've only found this used inside the i915 Intel driver [2].

TIL, thanks.

> > >   - I'm not entirely convinced that using the firmware framework to load
> > >     the images is the right path. The idea behind it was to re-use the
> > >     compressed firmware support, but then I discovered it is not there
> > >     for built-in firmware.
> > 
> > Yeah, firmware loading for this has a few issues (being tedious to setup
> > for when built-in being one). I think just going the fbdev penguin road
> > is a better choice: you provide the path, and it's embedded in the
> > kernel directly.
> > 
> 
> Yes, this is already working, but if large-ish images are used, the loading
> time for them defeats the entire purpose of an in-kernel splash.

The loading time of what exactly? If the image is in some section of the
binary, you wouldn't have to load anything.

Maxime

[-- Attachment #2: signature.asc --]
[-- Type: application/pgp-signature, Size: 273 bytes --]

^ permalink raw reply

* Re: [PATCH RFC 0/3] Add splash DRM client
From: Mario Limonciello @ 2025-10-28 13:39 UTC (permalink / raw)
  To: Francesco Valla, Maxime Ripard
  Cc: Thomas Zimmermann, Maarten Lankhorst, David Airlie, Simona Vetter,
	Jonathan Corbet, Jocelyn Falempe, Javier Martinez Canillas,
	Sam Ravnborg, linux-kernel, dri-devel, linux-doc, linux-embedded
In-Reply-To: <4497733.UPlyArG6xL@fedora.fritz.box>

On 10/28/25 3:09 AM, Francesco Valla wrote:
> Hi,
> 
> On Monday, 27 October 2025 at 18:19:12 Maxime Ripard <mripard@kernel.org> wrote:
>> On Mon, Oct 27, 2025 at 11:31:06AM -0500, Mario Limonciello wrote:
>>> On 10/27/25 11:28 AM, Maxime Ripard wrote:
>>>> On Mon, Oct 27, 2025 at 11:01:55AM -0500, Mario Limonciello wrote:
>>>>> On 10/27/25 7:35 AM, Thomas Zimmermann wrote:
>>>>>>>>      - a very simple progress bar, which can be driven through sysfs;
>>>>>>
>>>>>> Once you have options to control these settings from user space, you
>>>>>> should do it in user space entirely. As Maxime suggested, please improve
>>>>>> plymouth for anything with animation.
>>>>>>
>>>>>>>>      - a static image (optional).
>>>>>>
>>>>>> Board vendors often provide an image, see /sys/firmware/acpi/bgrt/. This
>>>>>> is a candidate for display, or the penguin or a custom image. Please
>>>>>> make it configurable by Kconfig. Again, if you need policy and
>>>>>> heuristics for deciding what to display, you better do this in user
>>>>>> space.
>>>>>
>>>>> I'd actually argue that the static image from BGRT should be the preferred
>>>>> priority.  This can make for a nice hand off to Plymouth.
>>>>>
>>>>> The (UEFI) BIOS already will show this image as soon as the GOP driver is
>>>>> loaded.  Bootloaders like GRUB by default will avoid showing anything or
>>>>> will overwrite with the exact same image in the same location.  This can let
>>>>> the kernel do the same, and then the moment Plymouth takes over it could do
>>>>> the same.
>>>>
>>>> And BGRT isn't typically found on embedded systems at all, so I'm not
>>>> sure it's a sensible default, let alone a priority. At most a possible
>>>
>>> There are certainly embedded machines using UEFI and that have a BGRT.
>>
>> Yes, indeed, hence the "typically".
>>
>>> How about "Sensible default the top of the priority list if it exists"
>>
>> How about we don't tell contributors what their priorities must be?
>>
>> Maxime
>>
> 
> I'm not familiar at all with BGRT, I'll study a bit about it.
> 
> A build-time configuration could then let the user select:
> 
> - a plain solid color
> - a custom static image
> - the penguin logo (?)
> - (on UEFI systems) BGRT source

Thanks!

What I had in mind (which feel free to disagree - it's an RC afterall):

User can pick one of these:

CONFIG_SPLASH_IMAGE
CONFIG_SPLASH_COLOR

If user picks CONFIG_SPLASH_IMAGE then the default behavior would be 
UEFI BGRT with a fallback to a Linux penguin.

Additionally there could be a

CONFIG_SPLASH_CUSTOM_IMAGE

This would populate the path to a custom image at build time.

If user picks this then it would override both UEFI BGRT and Linux penguin.

> 
> 
> 
> Thank you
> 
> Regards,
> Francesco


^ permalink raw reply


This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox