Embedded Linux development
 help / color / mirror / Atom feed
* Re: Call for Participation: Embedded & IoT micro-conference at Linux Plumbers 2025
From: Sebastian Reichel @ 2025-09-24  0:33 UTC (permalink / raw)
  To: Brian Masney
  Cc: Stefan Schmidt, Jan Lubbe, stefan.schmidt, linux-embedded,
	linux-usb, linux-rockchip, Heikki Krogerus, Greg Kroah-Hartman,
	RD Babiera, Amit Sunil Dhamne, kernel
In-Reply-To: <CABx5tq+U_hcmxXDCGpTawsu5C0bDknC=p1Rq3FrtVuJq9gj2Pw@mail.gmail.com>

Hi Brian,

On Tue, Sep 23, 2025 at 07:38:14PM -0400, Brian Masney wrote:
> Hi Sebastian,
> 
> On Tue, Sep 23, 2025 at 7:03 PM Sebastian Reichel <sre@kernel.org> wrote:
> > I would like to present / discuss fusb302 (or other chips handled via
> > the TCPM framework) using boards that are mainly powered via USB-C and
> > not having any backup power source. This kind of setup is often found
> > on Rockchip boards (e.g. Libre Computer ROC-RK3399-PC, Radxa ROCK 5B
> > or ArmSoM Sige 5) and quite a pain, because a hard-reset effectively
> > kills the board power.
> >
> > I would present the problem(s), what I've done so far to get it working
> > to some degree with the upstream kernel and then discuss how to improve
> > the situation.
> >
> > I think to become a worthwhile discussion the session would need some
> > people that know the USB-PD specification and kernel subsystem, such as:
> >
> >  * Heikki Krogerus (USB-C maintainer)
> >  * Greg Kroah-Hartman (USB maintainer)
> >  * RD Babiera or Amit Sunil Dhamne (Google is actively working on
> >    ensuring TCPM code being compatible with the USB-PD specification
> >    and they were unhappy about some of my changes :))
> >
> > P.S.: I'm not sure how the CfP for the LPC micro-conferences works.
> > Please tell me if this mail is not good enough and I need to insert
> > something into some system.
> 
> You need to submit a proposal to
> https://lpc.events/event/19/abstracts/. You'll have to create an
> account, and there will be a "Submit new abstract" button at the
> bottom right of the page.

Ah, I was confused by the page not listing the embedded MC. I see
it appears in the drop down when trying to submit a new abstract.
Thanks for the hint - DONE.

> I went through the process for a talk that I submitted: "Fixing Clock
> Tree Propagation in the Common Clk Framework". It's related to this
> work:
> https://lore.kernel.org/linux-clk/20250923-clk-tests-docs-v4-0-9205cb3d3cba@redhat.com/T/

On most platforms I worked on we tried to have an exclusive PLL root
clock for DRM to avoid these issues. But sounds like a good topic!

Greetings,

-- Sebastian

^ permalink raw reply

* Re: Call for Participation: Embedded & IoT micro-conference at Linux Plumbers 2025
From: Brian Masney @ 2025-09-23 23:38 UTC (permalink / raw)
  To: Sebastian Reichel
  Cc: Stefan Schmidt, Jan Lubbe, stefan.schmidt, linux-embedded,
	linux-usb, linux-rockchip, Heikki Krogerus, Greg Kroah-Hartman,
	RD Babiera, Amit Sunil Dhamne, Sebastian Reichel, kernel
In-Reply-To: <j5dtkmnu55ycmqpaseazots7mevqyt5lafclvguxj6oz5r5cts@n563dsnvwuu7>

Hi Sebastian,

On Tue, Sep 23, 2025 at 7:03 PM Sebastian Reichel <sre@kernel.org> wrote:
> I would like to present / discuss fusb302 (or other chips handled via
> the TCPM framework) using boards that are mainly powered via USB-C and
> not having any backup power source. This kind of setup is often found
> on Rockchip boards (e.g. Libre Computer ROC-RK3399-PC, Radxa ROCK 5B
> or ArmSoM Sige 5) and quite a pain, because a hard-reset effectively
> kills the board power.
>
> I would present the problem(s), what I've done so far to get it working
> to some degree with the upstream kernel and then discuss how to improve
> the situation.
>
> I think to become a worthwhile discussion the session would need some
> people that know the USB-PD specification and kernel subsystem, such as:
>
>  * Heikki Krogerus (USB-C maintainer)
>  * Greg Kroah-Hartman (USB maintainer)
>  * RD Babiera or Amit Sunil Dhamne (Google is actively working on
>    ensuring TCPM code being compatible with the USB-PD specification
>    and they were unhappy about some of my changes :))
>
> P.S.: I'm not sure how the CfP for the LPC micro-conferences works.
> Please tell me if this mail is not good enough and I need to insert
> something into some system.

You need to submit a proposal to
https://lpc.events/event/19/abstracts/. You'll have to create an
account, and there will be a "Submit new abstract" button at the
bottom right of the page.

I went through the process for a talk that I submitted: "Fixing Clock
Tree Propagation in the Common Clk Framework". It's related to this
work:
https://lore.kernel.org/linux-clk/20250923-clk-tests-docs-v4-0-9205cb3d3cba@redhat.com/T/

Brian


^ permalink raw reply

* Re: Call for Participation: Embedded & IoT micro-conference at Linux Plumbers 2025
From: Sebastian Reichel @ 2025-09-23 23:02 UTC (permalink / raw)
  To: Stefan Schmidt, Jan Lubbe, stefan.schmidt, linux-embedded,
	linux-usb, linux-rockchip
  Cc: Heikki Krogerus, Greg Kroah-Hartman, RD Babiera,
	Amit Sunil Dhamne, Sebastian Reichel, kernel
In-Reply-To: <2a353817-f1da-4e7c-8b2c-0853779ec054@datenfreihafen.org>

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

Hi,

On Fri, Sep 05, 2025 at 09:45:26AM +0200, Stefan Schmidt wrote:
> We are happy to announce that the Embedded & IoT micro-conference was
> again accepted for Linux Plumbers this year. Hosted in beautiful Tokyo,
> Japan December 11-13. https://lpc.events/event/19/contributions/2005/
> 
> Topics cover all things embedded and IoT. Boot time to kernel size, low
> power communication, telemetry and also RTOS. Devicetree and build
> system have their own MC and we can move sessions between them as needed.

I would like to present / discuss fusb302 (or other chips handled via
the TCPM framework) using boards that are mainly powered via USB-C and
not having any backup power source. This kind of setup is often found
on Rockchip boards (e.g. Libre Computer ROC-RK3399-PC, Radxa ROCK 5B
or ArmSoM Sige 5) and quite a pain, because a hard-reset effectively
kills the board power.

I would present the problem(s), what I've done so far to get it working
to some degree with the upstream kernel and then discuss how to improve
the situation.

I think to become a worthwhile discussion the session would need some
people that know the USB-PD specification and kernel subsystem, such as:

 * Heikki Krogerus (USB-C maintainer)
 * Greg Kroah-Hartman (USB maintainer)
 * RD Babiera or Amit Sunil Dhamne (Google is actively working on
   ensuring TCPM code being compatible with the USB-PD specification
   and they were unhappy about some of my changes :))

P.S.: I'm not sure how the CfP for the LPC micro-conferences works.
Please tell me if this mail is not good enough and I need to insert
something into some system.

Greetings,

-- Sebastian

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

^ permalink raw reply

* [PATCH PREVIEW RFC 6/6] dt-bindings: bootcache: Add bindings for bootcache backend
From: acampanella-thegoodpenguin @ 2025-09-23 14:23 UTC (permalink / raw)
  To: linux-embedded
In-Reply-To: <20250923-bootcache-v1-0-4f86fdc38b4e@thegoodpenguin.co.uk>

From: Marc Kelly <mkelly@thegoodpenguin.co.uk>

Add device tree bindings for the bootcache_backend_memory.

Signed-off-by: Marc Kelly <mkelly@thegoodpenguin.co.uk>
---
 .../bootcache/linux,bootcache-backend-memory.yaml  | 67 ++++++++++++++++++++++
 MAINTAINERS                                        |  1 +
 2 files changed, 68 insertions(+)

diff --git a/Documentation/devicetree/bindings/bootcache/linux,bootcache-backend-memory.yaml b/Documentation/devicetree/bindings/bootcache/linux,bootcache-backend-memory.yaml
new file mode 100644
index 0000000000000000000000000000000000000000..cf46bf4c513e263f67cdf2323349fa16837c8d22
--- /dev/null
+++ b/Documentation/devicetree/bindings/bootcache/linux,bootcache-backend-memory.yaml
@@ -0,0 +1,67 @@
+# SPDX-License-Identifier: (GPL-2.0-only OR BSD-2-Clause)
+%YAML 1.2
+---
+$id: http://devicetree.org/schemas/bootcache/linux,bootcache-backend-memory.yaml#
+$schema: http://devicetree.org/meta-schemas/core.yaml#
+
+title: Bootcache Framework reserved memory backend
+
+maintainers:
+  - Marc Kelly <mkelly@thegoodpenguin.co.uk>
+  - Andrea Campenella <acampenella@thegoodpenguin.co.uk>
+
+description:
+  This bootcache backend adds support for using reserved memory
+  for the storage location for bootcache data. On initialization this
+  memory is read and any bootcache entries found are added to the
+  bootcache framework.
+  Data is inserted into these memory locations via the bootloader
+  or other means before the kernel boots.
+
+properties:
+  compatible:
+    enum:
+      - linux,backend-backend-memory
+
+  reg:
+    maxItems: 2
+
+  memory-region:
+    maxItems: 1
+    description:
+      Contains the bootcache reserved memory.
+      Data format is a binary block of packed cache data consisting
+      of a selection of key and value pairs, along with size indicators.
+      The format should be considered private to the driver and should
+      not be interpreted outside of the drivers context.
+
+required:
+  - compatible
+  - reg
+  - memory-region
+
+unevaluatedProperties: false
+
+examples:
+  - |
+    /*
+     * The bootcache-backend is placed in the in the main domain
+     * of the SOC, with the reserved memory location defined as
+     * follows.
+     * This defines 64kBytes in the upper 2GBytes.
+     *
+     * The size
+     * reserved-memory {
+     *     bootcache_reserved: bootcache-reserved@BFFF0000 {
+     *         no-map;
+     *         reg = <0x00 0xBFFF0000 0x00 0x10000>;
+     *         label = "bootcache_backend_memory";
+     *     };
+     * }
+     */
+
+    bootcache-backend@BFFF0000 {
+        compatible = "linux,backend-backend-memory";
+        reg = <0x00 0xBFFF0000 0x00 0x10000>;
+        memory-region = <&bootcache_reserved>;
+    };
diff --git a/MAINTAINERS b/MAINTAINERS
index 73679686d49ac653382ecb32b9b3b500a4509383..d547fe2fa77f6fabdd19be3c0a68526d2f6d2d4d 100644
--- a/MAINTAINERS
+++ b/MAINTAINERS
@@ -4422,6 +4422,7 @@ BOOT CACHE
 M:	Andrea Campanella <acampanella@thegoodpenguin.co.uk>
 M:	Marc Kelly <mkelly@thegoodpenguin.co.uk>
 S:	Maintained
+F:	Documentation/devicetree/bindings/bootcache/linux,bootcache-backend-memory.yaml
 F:	drivers/base/bootcache.c
 F:	drivers/base/bootcache_*
 F:	include/linux/bootcache.h

-- 
2.48.1


^ permalink raw reply related

* [PATCH PREVIEW RFC 5/6] base: bootcache: Add bootcache memory backend
From: acampanella-thegoodpenguin @ 2025-09-23 14:23 UTC (permalink / raw)
  To: linux-embedded
In-Reply-To: <20250923-bootcache-v1-0-4f86fdc38b4e@thegoodpenguin.co.uk>

From: Marc Kelly <mkelly@thegoodpenguin.co.uk>

bootcache_backend_memory provides a simple memory based backend that can
inject data found stored in a reserved-memory block into the bootcache
framework.

Signed-off-by: Marc Kelly <mkelly@thegoodpenguin.co.uk>
---
 drivers/base/Kconfig                    |   7 +
 drivers/base/Makefile                   |   1 +
 drivers/base/bootcache_backend_memory.c | 220 ++++++++++++++++++++++++++++++++
 3 files changed, 228 insertions(+)

diff --git a/drivers/base/Kconfig b/drivers/base/Kconfig
index 1303364993ff4bf7fbbc210243dc6dc48fb1bd83..00c0ea6fa31f2d9a8863c93218a4db7ff87f9c0a 100644
--- a/drivers/base/Kconfig
+++ b/drivers/base/Kconfig
@@ -95,6 +95,13 @@ config BOOTCACHE
 		  A simple backend for testing and development.
 		  It does not persist any data externally.
 
+	config BOOTCACHE_BACKEND_MEMORY
+		bool "Memory backend"
+		help
+		  A backend that reads the cache data from reserved system memory.
+		  The reserved memory block is defined in the device tree and is
+		  assumed to be populated by the bootloader.
+
 	endchoice
 	endif
 
diff --git a/drivers/base/Makefile b/drivers/base/Makefile
index dc87c21cd79468045878c4b3cef5714c12f65ec4..d818e72df290e6772297345efc71082adc04e1f2 100644
--- a/drivers/base/Makefile
+++ b/drivers/base/Makefile
@@ -10,6 +10,7 @@ obj-y			:= component.o core.o bus.o dd.o syscore.o \
 obj-$(CONFIG_AUXILIARY_BUS) += auxiliary.o
 obj-$(CONFIG_BOOTCACHE)    += bootcache.o
 obj-$(CONFIG_BOOTCACHE_BACKEND_TEST)    += bootcache_backend_test.o
+obj-$(CONFIG_BOOTCACHE_BACKEND_MEMORY)    += bootcache_backend_memory.o
 obj-$(CONFIG_DEVTMPFS)	+= devtmpfs.o
 obj-y			+= power/
 obj-$(CONFIG_ISA_BUS_API)	+= isa.o
diff --git a/drivers/base/bootcache_backend_memory.c b/drivers/base/bootcache_backend_memory.c
new file mode 100644
index 0000000000000000000000000000000000000000..d7a83ce2725bc7aa5f37d5fc3dcd7bea753e4d68
--- /dev/null
+++ b/drivers/base/bootcache_backend_memory.c
@@ -0,0 +1,220 @@
+// SPDX-License-Identifier: GPL-2.0
+#define DEBUG 1
+#include <linux/unaligned.h>
+#include <linux/init.h>
+#include <linux/io.h>
+#include <linux/kernel.h>
+#include <linux/slab.h>
+#include <linux/hashtable.h>
+#include <linux/of.h>
+#include <linux/of_device.h>
+#include <linux/of_reserved_mem.h>
+#include <linux/platform_device.h>
+#include <linux/string.h>
+#include <linux/types.h>
+#include <linux/errno.h>
+#include <linux/kobject.h>
+#include <linux/sysfs.h>
+
+#include <linux/bootcache.h>
+
+#define DRIVER_NAME "bootcache_memory_backend"
+#define BOOTCACHE_MAGIC ('B' << 24 | 'C' << 16 | 'H' << 8 | 'E')
+#define BOOTCACHE_MINSIZE 4096
+
+/*
+ * This defines a cache entry as stored.
+ */
+struct cache_memory_store_entry {
+	u32 key_length;
+	u32 data_length;
+	u8 data_type;
+	u8 data[];
+} __packed;
+
+/*
+ * The in memory store of multiple cache entries.
+ */
+struct cache_memory_store {
+	u32 magic;
+	u32 entry_count;
+	struct cache_memory_store_entry entries[];
+} __packed;
+
+struct reserved_mem *rmem;
+
+/*
+ * This function processes the loaded data and adds each entry to the
+ * system cache via the callbck.
+ */
+static int memory_backend_load_cache(void)
+{
+	const struct cache_memory_store *store;
+	const u8 *current_ptr;
+	const void *max_address;
+	u32 entry_count;
+	int i;
+	int ret;
+
+	if (!rmem) {
+		pr_warn("%s: No bootcache was found\n", DRIVER_NAME);
+		return 0;
+	}
+
+	store = ioremap(rmem->base, rmem->size);
+	if (!store) {
+		pr_warn("%s: Unable to map reserved memory 0x%llx\n", DRIVER_NAME, rmem->base);
+		return -ENOMEM;
+	}
+	max_address = store + rmem->size;
+	current_ptr = (const unsigned char *)store->entries;
+	entry_count = get_unaligned(&store->entry_count);
+
+	for (i = 0; i < entry_count; i++) {
+		struct cache_memory_store_entry *entry;
+		struct bootcache_entry *new_entry = NULL;
+		size_t data_length, key_length;
+		u8 *src, *dest;
+		int j;
+
+		entry = (struct cache_memory_store_entry *)current_ptr;
+		data_length = get_unaligned(&entry->data_length);
+		key_length = get_unaligned(&entry->key_length);
+
+		/* Check if will go outside the bounds */
+		if ((current_ptr + sizeof(struct cache_memory_store_entry) +
+				data_length + key_length + 1) > max_address) {
+			ret = -ENOMEM;
+			goto error;
+		}
+
+		new_entry = kzalloc(sizeof(*new_entry), GFP_KERNEL);
+		if (!new_entry) {
+			ret = -ENOMEM;
+			goto error;
+		}
+
+		new_entry->len = data_length;
+		new_entry->key = kzalloc(key_length+1, GFP_KERNEL);
+		new_entry->data = kzalloc(data_length, GFP_KERNEL);
+
+		if (!new_entry->key || !new_entry->data) {
+			pr_err("%s: Memory Allocation error creating new_entry data\n",
+				DRIVER_NAME);
+			kfree(new_entry->key);
+			kfree(new_entry->data);
+			kfree(new_entry);
+			ret = -ENOMEM;
+			goto error;
+		}
+		/*
+		 * Source data is potentially unaligned, so we copy it with the correct
+		 * access functions
+		 */
+		src = &entry->data[0];
+		dest = new_entry->key;
+		for (j = 0; j < key_length; j++)
+			*dest++ = get_unaligned(src++);
+
+		src = &entry->data[key_length+1];
+		dest = new_entry->data;
+		for (j = 0; j < data_length; j++)
+			*dest++ = get_unaligned(src++);
+
+		pr_debug("%s: Setting up Entry (%d) with key: %s, data length is %zu\n",
+			DRIVER_NAME, i, new_entry->key, new_entry->len);
+
+		/* call the framework provided function */
+		ret = bootcache_add_entry(new_entry);
+		if (ret) {
+			kfree(new_entry->key);
+			kfree(new_entry->data);
+			kfree(new_entry);
+			ret = 0;
+		}
+
+		/* Sanity check we've got space for the next extry */
+
+		current_ptr += sizeof(struct cache_memory_store_entry) +
+			data_length + key_length + 1;
+		if (current_ptr + sizeof(struct cache_memory_store_entry)
+				> max_address) {
+			ret = ret = -ENOMEM;
+			goto error;
+		}
+	}
+
+error:
+	if (store)
+		iounmap((void *)store);
+
+	return ret;
+}
+
+static struct bootcache_info cache_info = {
+	.name = "memory",
+	.load_cache = memory_backend_load_cache,
+};
+
+static int bootcache_backend_probe(struct platform_device *pdev)
+{
+	int ret;
+	size_t table_size;
+	struct cache_memory_store *temp_store;
+	struct device_node *reserved_mem_node;
+
+	/* Check for the front end being ready */
+
+	pr_debug("%s: %s\n", DRIVER_NAME, __func__);
+
+	reserved_mem_node = of_parse_phandle(pdev->dev.of_node, "memory-region", 0);
+	if (reserved_mem_node) {
+		rmem = of_reserved_mem_lookup(reserved_mem_node);
+		of_node_put(reserved_mem_node);
+	}
+
+	if (!rmem) {
+		pr_err("%s: Failed to find reserved memory region.\n", DRIVER_NAME);
+		return -ENOMEM;
+	}
+	pr_debug("%s: Found reserved cache memory block (%s):\n", DRIVER_NAME, rmem->name);
+	pr_debug("%s:  Physical Address: 0x%llx\n", DRIVER_NAME, rmem->base);
+	pr_debug("%s:  Size: 0x%llx (%llu bytes)\n", DRIVER_NAME, rmem->size,
+		rmem->size);
+
+	if (rmem->size < BOOTCACHE_MINSIZE) {
+		pr_err("%s: reserved memory too small (%llu bytes)\n", DRIVER_NAME, rmem->size);
+		return -ENOMEM;
+	}
+
+	ret = bootcache_register_backend(&cache_info);
+
+	if (ret < 0) {
+		pr_err("%s: bootcache_register_backend() failed with error %d\n",
+			DRIVER_NAME, ret);
+		return ret;
+	}
+	pr_info("%s: Backend loaded\n", DRIVER_NAME);
+
+	return 0;
+}
+
+static const struct of_device_id bootcache_backend_driver_dt_ids[] = {
+	{ .compatible = "linux,backend-backend-memory", },
+	{ }
+};
+
+static struct platform_driver bootcache_memory_platform_driver = {
+	.probe		= bootcache_backend_probe,
+	.driver		= {
+		.name	= DRIVER_NAME,
+		.of_match_table = of_match_ptr(bootcache_backend_driver_dt_ids),
+	},
+};
+
+static int __init bootcache_backend_init(void)
+{
+	return platform_driver_register(&bootcache_memory_platform_driver);
+}
+
+core_initcall(bootcache_backend_init);

-- 
2.48.1


^ permalink raw reply related

* [PATCH PREVIEW RFC 4/6] base: bootcache: Add bootcache test backend
From: acampanella-thegoodpenguin @ 2025-09-23 14:23 UTC (permalink / raw)
  To: linux-embedded
In-Reply-To: <20250923-bootcache-v1-0-4f86fdc38b4e@thegoodpenguin.co.uk>

From: Marc Kelly <mkelly@thegoodpenguin.co.uk>

bootcache_backend_test provides a simple test backend of API
demonstration and testing purposes.

Signed-off-by: Marc Kelly <mkelly@thegoodpenguin.co.uk>
---
 MAINTAINERS                           |   2 +
 drivers/base/Kconfig                  |  14 ++++
 drivers/base/Makefile                 |   1 +
 drivers/base/bootcache_backend_test.c | 119 ++++++++++++++++++++++++++++++++++
 4 files changed, 136 insertions(+)

diff --git a/MAINTAINERS b/MAINTAINERS
index 4bf3766b30bbf75214911bd4ce5256a066f05726..73679686d49ac653382ecb32b9b3b500a4509383 100644
--- a/MAINTAINERS
+++ b/MAINTAINERS
@@ -4420,8 +4420,10 @@ F:	drivers/iio/imu/bmi323/
 
 BOOT CACHE
 M:	Andrea Campanella <acampanella@thegoodpenguin.co.uk>
+M:	Marc Kelly <mkelly@thegoodpenguin.co.uk>
 S:	Maintained
 F:	drivers/base/bootcache.c
+F:	drivers/base/bootcache_*
 F:	include/linux/bootcache.h
 
 BPF JIT for ARC
diff --git a/drivers/base/Kconfig b/drivers/base/Kconfig
index da02f95948d880da83c3025addc1e111dbce339a..1303364993ff4bf7fbbc210243dc6dc48fb1bd83 100644
--- a/drivers/base/Kconfig
+++ b/drivers/base/Kconfig
@@ -84,6 +84,20 @@ config BOOTCACHE
 
 	  If unsure, say N.
 
+	if BOOTCACHE
+	choice
+		prompt "Boot-time cache backend"
+		depends on BOOTCACHE
+
+	config BOOTCACHE_BACKEND_TEST
+		bool "Test backend"
+		help
+		  A simple backend for testing and development.
+		  It does not persist any data externally.
+
+	endchoice
+	endif
+
 config STANDALONE
 	bool "Select only drivers that don't need compile-time external firmware"
 	default y
diff --git a/drivers/base/Makefile b/drivers/base/Makefile
index 10a16e6c2ea1ad778fb7793583b9ee54d2498b2b..dc87c21cd79468045878c4b3cef5714c12f65ec4 100644
--- a/drivers/base/Makefile
+++ b/drivers/base/Makefile
@@ -9,6 +9,7 @@ obj-y			:= component.o core.o bus.o dd.o syscore.o \
 			   swnode.o faux.o
 obj-$(CONFIG_AUXILIARY_BUS) += auxiliary.o
 obj-$(CONFIG_BOOTCACHE)    += bootcache.o
+obj-$(CONFIG_BOOTCACHE_BACKEND_TEST)    += bootcache_backend_test.o
 obj-$(CONFIG_DEVTMPFS)	+= devtmpfs.o
 obj-y			+= power/
 obj-$(CONFIG_ISA_BUS_API)	+= isa.o
diff --git a/drivers/base/bootcache_backend_test.c b/drivers/base/bootcache_backend_test.c
new file mode 100644
index 0000000000000000000000000000000000000000..b44b4802fb99aa70c731017c503c6084796e90ae
--- /dev/null
+++ b/drivers/base/bootcache_backend_test.c
@@ -0,0 +1,119 @@
+// SPDX-License-Identifier: GPL-2.0
+#include <linux/init.h>
+#include <linux/kernel.h>
+#include <linux/slab.h>
+#include <linux/hashtable.h>
+#include <linux/string.h>
+#include <linux/types.h>
+#include <linux/errno.h>
+#include <linux/kobject.h>
+#include <linux/sysfs.h>
+
+#include <linux/bootcache.h>
+
+#define DRIVER_NAME "bootcache_test_backend"
+
+struct test_data {
+	const char *name;
+	u32 value;
+	size_t data_length;
+};
+
+static struct test_data test_data_array[] = {
+	{
+		.name = "Bootcache Test One",
+		.value = 1234,
+		.data_length = sizeof(u32),
+	},
+	{
+		.name = "Bootcache Test Two",
+		.value = 5678,
+		.data_length = sizeof(u32),
+	},
+	{
+		.name = "Bootcache Test Three",
+		.value = 9012,
+		.data_length = sizeof(u32),
+	},
+	{
+		.name = "Bootcache Test Four",
+		.value = 0xDEADBEEF,
+		.data_length = sizeof(u32),
+	},
+	{
+		.name = "Bootcache Test Five",
+		.value = 0xC0DEBAD0,
+		.data_length = sizeof(u32),
+	}
+};
+
+static int test_backend_load_cache(void)
+{
+
+	struct bootcache_entry *new_entry = NULL;
+	int i;
+	int ret;
+
+	pr_info("%s: Backend local_cache callback\n", DRIVER_NAME);
+
+	/*
+	 * We want to load a bunch of fake data into the cache here
+	 * so that it can be used for testing purposes
+	 */
+	for (i = 0; i < ARRAY_SIZE(test_data_array); i++) {
+		/*
+		 * Print the name and value of the current element.
+		 * Use pr_info for a standard kernel log message.
+		 */
+		new_entry = kzalloc(sizeof(*new_entry), GFP_KERNEL);
+		if (!new_entry)
+			return -ENOMEM;
+
+		new_entry->key = kstrdup(test_data_array[i].name, GFP_KERNEL);
+		if (!new_entry->key) {
+			kfree(new_entry);
+			return -ENOMEM;
+		}
+		new_entry->len = test_data_array[i].data_length;
+		new_entry->data = kmemdup(&test_data_array[i].value,
+			test_data_array[i].data_length, GFP_KERNEL);
+		if (!new_entry->data) {
+			kfree(new_entry->key);
+			kfree(new_entry);
+			return -ENOMEM;
+		}
+
+		/* call the framework provided function */
+		ret = bootcache_add_entry(new_entry);
+		if (ret) {
+			kfree(new_entry->key);
+			kfree(new_entry->data);
+			kfree(new_entry);
+			ret = 0;
+		}
+	}
+	return 0;
+}
+
+static struct bootcache_info cache_info = {
+	.name = "test",
+	.load_cache = test_backend_load_cache,
+};
+
+static int __init bootcache_backend_init(void)
+{
+	int ret;
+
+	ret = bootcache_register_backend(&cache_info);
+
+	if (ret < 0) {
+		pr_err("%s: bootcache_register_backend() failed with error %d\n",
+			DRIVER_NAME, ret);
+		return ret;
+	}
+	pr_info("%s: Backend loaded\n", DRIVER_NAME);
+
+	return 0;
+}
+
+core_initcall(bootcache_backend_init);

-- 
2.48.1


^ permalink raw reply related

* [PATCH PREVIEW RFC 3/6] crypto: use bootcache to cache fastest algorithm
From: acampanella-thegoodpenguin @ 2025-09-23 14:23 UTC (permalink / raw)
  To: linux-embedded
In-Reply-To: <20250923-bootcache-v1-0-4f86fdc38b4e@thegoodpenguin.co.uk>

From: Andrew Murray <amurray@thegoodpenguin.co.uk>

During boot xor_blocks may determine the fastest xor algorithm
by using do_xor_speed to perform a speed test on available
algorithms. This process can increase the overall boot time.

Let's make use of bootcache to cache the result of the speed
test for subsequent boots.

Signed-off-by: Andrew Murray <amurray@thegoodpenguin.co.uk>
---
 crypto/xor.c | 29 ++++++++++++++++++++++++++++-
 1 file changed, 28 insertions(+), 1 deletion(-)

diff --git a/crypto/xor.c b/crypto/xor.c
index f39621a57bb33c4015c06dff00e03a07716618f6..3457df0414064758a1923752e91642d2237af7b3 100644
--- a/crypto/xor.c
+++ b/crypto/xor.c
@@ -14,6 +14,7 @@
 #include <linux/raid/xor.h>
 #include <linux/jiffies.h>
 #include <linux/preempt.h>
+#include <linux/bootcache.h>
 #include <asm/xor.h>
 
 #ifndef XOR_SELECT_TEMPLATE
@@ -54,13 +55,13 @@ EXPORT_SYMBOL(xor_blocks);
 /* Set of all registered templates.  */
 static struct xor_block_template *__initdata template_list;
 
-#ifndef MODULE
 static void __init do_xor_register(struct xor_block_template *tmpl)
 {
 	tmpl->next = template_list;
 	template_list = tmpl;
 }
 
+#ifndef MODULE
 static int __init register_xor_blocks(void)
 {
 	active_template = XOR_SELECT_TEMPLATE(NULL);
@@ -79,6 +80,21 @@ static int __init register_xor_blocks(void)
 #define BENCH_SIZE	4096
 #define REPS		800U
 
+static struct xor_block_template * __init
+xor_get_template_by_name(char *fastest_name)
+{
+	struct xor_block_template *f;
+
+#define xor_speed	do_xor_register
+	// build a list of templates
+	XOR_TRY_TEMPLATES;
+#undef xor_speed
+	for (f = template_list; f; f = f->next)
+		if (!strcmp(f->name, fastest_name))
+			return f;
+	return NULL;
+}
+
 static void __init
 do_xor_speed(struct xor_block_template *tmpl, void *b1, void *b2)
 {
@@ -117,9 +133,18 @@ calibrate_xor_blocks(void)
 {
 	void *b1, *b2;
 	struct xor_block_template *f, *fastest;
+	char cached_name[32];
+	int ret;
 
 	fastest = XOR_SELECT_TEMPLATE(NULL);
 
+	if (!fastest) {
+		ret = bootcache_get_string("xor_blocks_fastest",
+				cached_name, sizeof(cached_name));
+		if (!ret)
+			fastest = xor_get_template_by_name(cached_name);
+	}
+
 	if (fastest) {
 		printk(KERN_INFO "xor: automatically using best "
 				 "checksumming function   %-10s\n",
@@ -149,6 +174,8 @@ calibrate_xor_blocks(void)
 		if (f->speed > fastest->speed)
 			fastest = f;
 
+	bootcache_set_string("xor_blocks_fastest", fastest->name);
+
 	pr_info("xor: using function: %s (%d MB/sec)\n",
 	       fastest->name, fastest->speed);
 

-- 
2.48.1


^ permalink raw reply related

* [PATCH PREVIEW RFC 1/6] base: bootcache: initial commit
From: acampanella-thegoodpenguin @ 2025-09-23 14:23 UTC (permalink / raw)
  To: linux-embedded
In-Reply-To: <20250923-bootcache-v1-0-4f86fdc38b4e@thegoodpenguin.co.uk>

bootcache provides boot-time key-value cache to help improve
boot performance by allowing drivers to cache expensive computations.

Simple API are provided:
- bootcache_get_u16()/bootcache_set_u16() - retrieve/store u16 values
- bootcache_get_u32()/bootcache_set_u32() - retrieve/store u32 values
- bootcache_get_u64()/bootcache_set_u64() - retrieve/store u64 values
- bootcache_get_string()/bootcache_set_string() - retrieve/store strings
- bootcache_register_backend() - Backend registration
- bootcache_add_entry() - Add cache entry into framework

Signed-off-by: Marc Kelly <mkelly@thegoodpenguin.co.uk>
Signed-off-by: Andrea Campanella <acampanella@thegoodpenguin.co.uk>
---
 MAINTAINERS               |   6 ++
 drivers/base/Kconfig      |  11 +++
 drivers/base/Makefile     |   1 +
 drivers/base/bootcache.c  | 179 +++++++++++++++++++++++++++++++++++++
 include/linux/bootcache.h | 219 ++++++++++++++++++++++++++++++++++++++++++++++
 5 files changed, 416 insertions(+)

diff --git a/MAINTAINERS b/MAINTAINERS
index daf520a13bdf6a991c0160a96620f40308c29ee0..4bf3766b30bbf75214911bd4ce5256a066f05726 100644
--- a/MAINTAINERS
+++ b/MAINTAINERS
@@ -4418,6 +4418,12 @@ S:	Maintained
 F:	Documentation/devicetree/bindings/iio/imu/bosch,bmi323.yaml
 F:	drivers/iio/imu/bmi323/
 
+BOOT CACHE
+M:	Andrea Campanella <acampanella@thegoodpenguin.co.uk>
+S:	Maintained
+F:	drivers/base/bootcache.c
+F:	include/linux/bootcache.h
+
 BPF JIT for ARC
 M:	Shahab Vahedi <list+bpf@vahedi.org>
 L:	bpf@vger.kernel.org
diff --git a/drivers/base/Kconfig b/drivers/base/Kconfig
index 064eb52ff7e2d4d8745e9c39882b41dc4cf02a89..da02f95948d880da83c3025addc1e111dbce339a 100644
--- a/drivers/base/Kconfig
+++ b/drivers/base/Kconfig
@@ -73,6 +73,17 @@ config DEVTMPFS_SAFE
 	  with the PROT_EXEC flag. This can break, for example, non-KMS
 	  video drivers.
 
+config BOOTCACHE
+	bool "Boot-time cache for the kernel"
+	help
+	  Enable a simple key-value cache subsystem for storing boot-time
+	  configuration data. This allows drivers and kernel subsystems to
+	  cache expensive computations during boot, potentially improving
+	  boot performance on subsequent reboots by avoiding redundant
+	  hardware detection and initialization work
+
+	  If unsure, say N.
+
 config STANDALONE
 	bool "Select only drivers that don't need compile-time external firmware"
 	default y
diff --git a/drivers/base/Makefile b/drivers/base/Makefile
index 8074a10183dcb720a6b820b8476b230716b37f01..10a16e6c2ea1ad778fb7793583b9ee54d2498b2b 100644
--- a/drivers/base/Makefile
+++ b/drivers/base/Makefile
@@ -8,6 +8,7 @@ obj-y			:= component.o core.o bus.o dd.o syscore.o \
 			   topology.o container.o property.o cacheinfo.o \
 			   swnode.o faux.o
 obj-$(CONFIG_AUXILIARY_BUS) += auxiliary.o
+obj-$(CONFIG_BOOTCACHE)    += bootcache.o
 obj-$(CONFIG_DEVTMPFS)	+= devtmpfs.o
 obj-y			+= power/
 obj-$(CONFIG_ISA_BUS_API)	+= isa.o
diff --git a/drivers/base/bootcache.c b/drivers/base/bootcache.c
new file mode 100644
index 0000000000000000000000000000000000000000..d74ead796b0f50ca9a90e84e7230b9ad6ca896d8
--- /dev/null
+++ b/drivers/base/bootcache.c
@@ -0,0 +1,179 @@
+// SPDX-License-Identifier: GPL-2.0
+#include <linux/init.h>
+#include <linux/kernel.h>
+#include <linux/slab.h>
+#include <linux/hashtable.h>
+#include <linux/string.h>
+#include <linux/stringhash.h>
+#include <linux/types.h>
+#include <linux/spinlock.h>
+#include <linux/errno.h>
+#include <linux/kobject.h>
+#include <linux/sysfs.h>
+#include <linux/bootcache.h>
+
+static DEFINE_HASHTABLE(bootcache_table, BOOTCACHE_HASH_BITS);
+static DEFINE_SPINLOCK(bootcache_lock);
+static struct kobject *bootcache_kobj;
+static struct bootcache_info *bootcache_backend;
+static bool bootcache_initilized;
+
+int bootcache_register_backend(struct bootcache_info *bci)
+{
+	int ret;
+
+	if (!bci)
+		return -EINVAL;
+	if (!bci->name)
+		return -EINVAL;
+
+	/* If we're not ready, tell backend to try again later */
+	if (!bootcache_initilized)
+		return -EPROBE_DEFER;
+
+	if (bootcache_backend) {
+		pr_warn("bootcache: Backend '%s' is already registered, cannot register '%s'\n",
+		bootcache_backend->name, bci->name);
+		return -EBUSY;
+	}
+	pr_info("bootcache: Registering backend '%s'\n",
+		bci->name);
+
+	/* Have the backend load and populate the cache store */
+	ret = bci->load_cache();
+
+	if (ret)
+		goto failed_initilize;
+
+	bootcache_backend = bci;
+	return 0;
+
+failed_initilize:
+	return ret;
+}
+EXPORT_SYMBOL(bootcache_register_backend);
+
+int bootcache_get(const char *name, void *buf, size_t *len)
+{
+	struct bootcache_entry *entry;
+	u32 hash;
+	int ret = -ENOENT;
+
+	if (!name || !buf || !len)
+		return -EINVAL;
+
+	hash = full_name_hash(NULL, name, strlen(name));
+
+	spin_lock(&bootcache_lock);
+	hash_for_each_possible(bootcache_table, entry, node, hash) {
+		if (strcmp(entry->key, name) == 0) {
+			if (*len < entry->len) {
+				*len = entry->len;
+				ret = -ENOSPC;
+				goto unlock;
+			}
+			memcpy(buf, entry->data, entry->len);
+			*len = entry->len;
+			ret = 0;
+			goto unlock;
+		}
+	}
+
+unlock:
+	spin_unlock(&bootcache_lock);
+	return ret;
+}
+EXPORT_SYMBOL(bootcache_get);
+
+int bootcache_add_entry(struct bootcache_entry *entry)
+{
+	u32 hash;
+	struct bootcache_entry *existing_entry;
+	int ret = 0;
+
+	hash = full_name_hash(NULL, entry->key, strlen(entry->key));
+
+	spin_lock(&bootcache_lock);
+
+	hash_for_each_possible(bootcache_table, existing_entry, node, hash) {
+		if (strcmp(existing_entry->key, entry->key) == 0) {
+			ret = -EEXIST;  // Key already exists
+			goto unlock;
+		}
+	}
+
+	hash_add(bootcache_table, &entry->node, hash);
+
+unlock:
+	spin_unlock(&bootcache_lock);
+	return ret;
+}
+EXPORT_SYMBOL(bootcache_add_entry);
+
+int bootcache_set(const char *name, const void *data, size_t len)
+{
+	struct bootcache_entry *new_entry;
+	u32 hash;
+	int ret = 0;
+
+	if (!name || !data || !len)
+		return -EINVAL;
+
+	new_entry = kzalloc(sizeof(*new_entry), GFP_KERNEL);
+	if (!new_entry)
+		return -ENOMEM;
+
+	new_entry->key = kstrdup(name, GFP_KERNEL);
+	if (!new_entry->key) {
+		ret = -ENOMEM;
+		goto free;
+	}
+
+	new_entry->data = kmemdup(data, len, GFP_KERNEL);
+	if (!new_entry->data) {
+		ret = -ENOMEM;
+		goto free;
+	}
+
+	new_entry->len = len;
+	ret = bootcache_add_entry(new_entry);
+	if (!ret)
+		return 0;
+
+free:
+	kfree(new_entry->data);
+	kfree(new_entry->key);
+	kfree(new_entry);
+	return ret;
+}
+EXPORT_SYMBOL(bootcache_set);
+
+static ssize_t writeout_store(struct kobject *kobj, struct kobj_attribute *attr,
+			    const char *buf, size_t count)
+{
+	/*Implement persistent storage backend */
+	return count;
+}
+
+static struct kobj_attribute writeout_attr = __ATTR_WO(writeout);
+
+static int __init bootcache_init(void)
+{
+	int ret;
+
+	pr_info("bootcache: backend loaded\n");
+
+	/* Create /sys/kernel/bootcache/writeout */
+	bootcache_kobj = kobject_create_and_add("bootcache", kernel_kobj);
+	if (!bootcache_kobj)
+		return -ENOMEM;
+
+	ret = sysfs_create_file(bootcache_kobj, &writeout_attr.attr);
+	if (ret) {
+		kobject_put(bootcache_kobj);
+		return ret;
+	}
+	bootcache_initilized = true;
+	return 0;
+}
+core_initcall(bootcache_init);
diff --git a/include/linux/bootcache.h b/include/linux/bootcache.h
new file mode 100644
index 0000000000000000000000000000000000000000..52c07cf09bb87fc6c305485e5409bd235ede4e6e
--- /dev/null
+++ b/include/linux/bootcache.h
@@ -0,0 +1,219 @@
+/* SPDX-License-Identifier: GPL-2.0 */
+#ifndef _LINUX_BOOTCACHE_H
+#define _LINUX_BOOTCACHE_H
+
+#include <linux/types.h>
+
+#ifdef CONFIG_BOOTCACHE
+
+#define BOOTCACHE_HASH_BITS 6  /* 64 buckets */
+
+struct bootcache_entry {
+	struct hlist_node node;
+	char *key;
+	void *data;
+	size_t len;
+};
+
+/**
+ * struct bootcache_info - Structure for registering a boot cache backend.
+ *
+ * @name:   The name of the backend.
+ *
+ * Callbacks:
+ * @load_cache: Callback function to read and populate the framework from the cache.
+ */
+
+struct bootcache_info {
+	const char *name;
+	/* Callback Function Pointers */
+	int (*load_cache)(void);
+};
+
+/**
+ * bootcache_add_entry - Add an entry directly into the hash table
+ * @entry: bootcache_entry structure
+ *
+ * Returns: 0 on success, entry was added, do not free it.
+ *          1 on success but an existing entry was updated,
+ *            free to deallocate entry.
+ */
+int bootcache_add_entry(struct bootcache_entry *entry);
+
+/**
+ * bootcache_register_backend - Register a backend provider with the framework
+ * @bci: bootcache_info structure
+ *
+ * Returns: 0 on success, -EPROBE_DEFER if the frontend is not ready,
+ *          -EBUSY if another backend is already registered,
+ *          -EINVAL on invalid registration information.
+ */
+int bootcache_register_backend(struct bootcache_info *bci);
+
+/**
+ * bootcache_get - Retrieve arbitrary data from the cache
+ * @name: Key to look up
+ * @buf: Buffer to store retrieved data
+ * @len: On input, size of buffer; on output, actual data size
+ *
+ * Returns: 0 on success, -EINVAL for invalid parameters,
+ *          -ENOENT if not found, -ENOSPC if buffer too small
+ */
+int bootcache_get(const char *name, void *buf, size_t *len);
+
+/**
+ * bootcache_set - Store arbitrary data in the cache
+ * @name: Key to store under
+ * @data: Data to store
+ * @len: Length of data
+ *
+ * Returns: 0 on success, -EINVAL for invalid parameters, -ENOMEM on allocation failure
+ */
+int bootcache_set(const char *name, const void *data, size_t len);
+
+#else /* !CONFIG_BOOTCACHE */
+
+static inline int bootcache_get(const char *name, void *buf, size_t *len)
+{
+	return -ENOENT;
+}
+
+static inline int bootcache_set(const char *name, const void *data, size_t len)
+{
+	return -EOPNOTSUPP;
+}
+
+/**
+ * bootcache_get_u16 - Retrieve a u16 value from the cache
+ * @name: Key to look up
+ * @out_val: Pointer to store the retrieved value
+ *
+ * Returns: 0 on success, -EINVAL for invalid parameters, -ENOENT if not found
+ */
+static inline int bootcache_get_u16(const char *name, u16 *out_val)
+{
+	size_t len = sizeof(u16);
+
+	if (IS_ENABLED(CONFIG_BOOTCACHE))
+		return bootcache_get(name, out_val, &len);
+	else
+		return -ENOENT;
+}
+
+/**
+ * bootcache_set_u16 - Store a u16 value in the cache
+ * @name: Key to store under
+ * @val: Value to store
+ *
+ * Returns: 0 on success, -EINVAL for invalid parameters, -ENOMEM on allocation failure
+ */
+static inline int bootcache_set_u16(const char *name, u16 val)
+{
+	if (IS_ENABLED(CONFIG_BOOTCACHE))
+		return bootcache_set(name, &val, sizeof(u16));
+	else
+		return -EOPNOTSUPP;
+}
+
+/**
+ * bootcache_get_u32 - Retrieve a u32 value from the cache
+ * @name: Key to look up
+ * @out_val: Pointer to store the retrieved value
+ *
+ * Returns: 0 on success, -EINVAL for invalid parameters, -ENOENT if not found
+ */
+static inline int bootcache_get_u32(const char *name, u32 *out_val)
+{
+	size_t len = sizeof(u32);
+
+	if (IS_ENABLED(CONFIG_BOOTCACHE))
+		return bootcache_get(name, out_val, &len);
+	else
+		return -ENOENT;
+}
+
+/**
+ * bootcache_set_u32 - Store a u32 value in the cache
+ * @name: Key to store under
+ * @val: Value to store
+ *
+ * Returns: 0 on success, -EINVAL for invalid parameters, -ENOMEM on allocation failure
+ */
+static inline int bootcache_set_u32(const char *name, u32 val)
+{
+	if (IS_ENABLED(CONFIG_BOOTCACHE))
+		return bootcache_set(name, &val, sizeof(u32));
+	else
+		return -EOPNOTSUPP;
+}
+
+/**
+ * bootcache_get_u64 - Retrieve a u64 value from the cache
+ * @name: Key to look up
+ * @out_val: Pointer to store the retrieved value
+ *
+ * Returns: 0 on success, -EINVAL for invalid parameters, -ENOENT if not found
+ */
+static inline int bootcache_get_u64(const char *name, u64 *out_val)
+{
+	size_t len = sizeof(u64);
+
+	if (IS_ENABLED(CONFIG_BOOTCACHE))
+		return bootcache_get(name, out_val, &len);
+	else
+		return -ENOENT;
+}
+
+/**
+ * bootcache_set_u64 - Store a u64 value in the cache
+ * @name: Key to store under
+ * @val: Value to store
+ *
+ * Returns: 0 on success, -EINVAL for invalid parameters, -ENOMEM on allocation failure
+ */
+static inline int bootcache_set_u64(const char *name, u64 val)
+{
+	if (IS_ENABLED(CONFIG_BOOTCACHE))
+		return bootcache_set(name, &val, sizeof(u64));
+	else
+		return -EOPNOTSUPP;
+}
+
+/**
+ * bootcache_get_string - Retrieve a string from the cache
+ * @name: Key to look up
+ * @buf: Buffer to store retrieved string
+ * @buflen: Size of buffer
+ *
+ * Returns: 0 on success, -EINVAL for invalid parameters,
+ *          -ENOENT if not found, -ENOSPC if buffer too small
+ */
+static inline int bootcache_get_string(const char *name, char *buf, size_t buflen)
+{
+	size_t len = buflen;
+
+	if (IS_ENABLED(CONFIG_BOOTCACHE))
+		return bootcache_get(name, buf, &len);
+	else
+		return -ENOENT;
+}
+
+/**
+ * bootcache_set_string - Store a string in the cache
+ * @name: Key to store under
+ * @str: Null-terminated string to store
+ *
+ * Returns: 0 on success, -EINVAL for invalid parameters, -ENOMEM on allocation failure
+ */
+static inline int bootcache_set_string(const char *name, const char *str)
+{
+	if (IS_ENABLED(CONFIG_BOOTCACHE)) {
+		if (!str)
+			return -EINVAL;
+		return bootcache_set(name, str, strlen(str) + 1);
+	} else {
+		return -EOPNOTSUPP;
+	}
+}
+
+#endif /* _LINUX_BOOTCACHE_H */

-- 
2.48.1


^ permalink raw reply related

* [PATCH PREVIEW RFC 2/6] raid6: Add bootcache
From: acampanella-thegoodpenguin @ 2025-09-23 14:23 UTC (permalink / raw)
  To: linux-embedded
In-Reply-To: <20250923-bootcache-v1-0-4f86fdc38b4e@thegoodpenguin.co.uk>

Check for previously cached results before benchmark

Signed-off-by: Andrea Campanella <acampanella@thegoodpenguin.co.uk>
---
 lib/raid6/algos.c | 21 +++++++++++++++++++++
 1 file changed, 21 insertions(+)

diff --git a/lib/raid6/algos.c b/lib/raid6/algos.c
index 799e0e5eac26db3d10c07e79f46537af4ec6f182..fc69d94afdb4fc153626a3e21c506eda57540618 100644
--- a/lib/raid6/algos.c
+++ b/lib/raid6/algos.c
@@ -19,6 +19,7 @@
 #include <linux/module.h>
 #include <linux/gfp.h>
 #endif
+#include <linux/bootcache.h>
 
 struct raid6_calls raid6_call;
 EXPORT_SYMBOL_GPL(raid6_call);
@@ -159,6 +160,24 @@ static inline const struct raid6_calls *raid6_choose_gen(
 	int start = (disks>>1)-1, stop = disks-3;	/* work on the second half of the disks */
 	const struct raid6_calls *const *algo;
 	const struct raid6_calls *best;
+	char cached_algo_name[32];
+
+	/* Try to get cached algorithm by name */
+	if (bootcache_get_string("raid6_best_algo", cached_algo_name,
+		sizeof(cached_algo_name)) == 0) {
+		/* Find algorithm by name */
+		for (algo = raid6_algos; *algo; algo++) {
+			if (strcmp((*algo)->name, cached_algo_name) == 0) {
+				if (!(*algo)->valid || (*algo)->valid()) {
+					raid6_call = *algo;
+					pr_info("raid6: using algorithm %s (from cache)\n",
+						(*algo)->name);
+					return best;
+				}
+				break;
+			}
+		}
+	}
 
 	for (bestgenperf = 0, best = NULL, algo = raid6_algos; *algo; algo++) {
 		if (!best || (*algo)->priority >= best->priority) {
@@ -198,6 +217,8 @@ static inline const struct raid6_calls *raid6_choose_gen(
 		goto out;
 	}
 
+	bootcache_set_string("raid6_best_algo", best->name);
+
 	raid6_call = *best;
 
 	if (!IS_ENABLED(CONFIG_RAID6_PQ_BENCHMARK)) {

-- 
2.48.1


^ permalink raw reply related

* [PATCH PREVIEW RFC 0/6] Add support for boot-time caching
From: acampanella-thegoodpenguin @ 2025-09-23 14:23 UTC (permalink / raw)
  To: linux-embedded

This patch series provides a simple key-value cache for storing boot-time
configuration data. The goal is to allow kernel components and drivers to
cache time-consuming-to-compute values during boot, enabling faster
subsequent boots by avoiding redundant initialization work.

During kernel boot, many subsystems perform expensive operations like:

- Hardware detection and configuration
- Performance tuning calculations
- Resource allocation decisions
- Driver initialization parameters

These operations often produce the same results across boots on the same
hardware, making them good candidates for caching.

Signed-off-by: acampanella-thegoodpenguin <acampanella@thegoodpenguin.co.uk>
---
Andrew Murray (1):
      crypto: use bootcache to cache fastest algorithm

Marc Kelly (3):
      base: bootcache: Add bootcache test backend
      base: bootcache: Add bootcache memory backend
      dt-bindings: bootcache: Add bindings for bootcache backend

acampanella-thegoodpenguin (2):
      base: bootcache: initial commit
      raid6: Add bootcache

 .../bootcache/linux,bootcache-backend-memory.yaml  |  67 +++++++
 MAINTAINERS                                        |   9 +
 crypto/xor.c                                       |  29 ++-
 drivers/base/Kconfig                               |  32 +++
 drivers/base/Makefile                              |   3 +
 drivers/base/bootcache.c                           | 179 +++++++++++++++++
 drivers/base/bootcache_backend_memory.c            | 220 +++++++++++++++++++++
 drivers/base/bootcache_backend_test.c              | 119 +++++++++++
 include/linux/bootcache.h                          | 219 ++++++++++++++++++++
 lib/raid6/algos.c                                  |  21 ++
 10 files changed, 897 insertions(+), 1 deletion(-)
---
base-commit: c17b750b3ad9f45f2b6f7e6f7f4679844244f0b9
change-id: 20250915-bootcache-1bcf0ee0d7b0

Best regards,
-- 
acampanella-thegoodpenguin <acampanella@thegoodpenguin.co.uk>


^ permalink raw reply

* [boot-time] Reminder of Boot-Time SIG meeting (Sep 23)
From: Bird, Tim @ 2025-09-18 19:43 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, September 23, at 9:00 am Mountain Daylight Time.
See this link for other time zones:
https://www.timeanddate.com/worldclock/meetingdetails.html?year=2025&month=09&day=23&hour=15&min=0&sec=0&p1=220&p2=137&p3=195&p4=771
(That makes it 8:00 am Pacific, 15:00 UTC, 17:00 CET, and 20: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 agenda for the September 23 meeting will be available in the above document before the call.
This is what I've got so far:

- ELC Europe boot-time discussions post-mortem
   - what's next for UBL (Unified Boot Log)?
      - discuss Kevin Hillman's feedback
- Round table of ongoing work
  - What's in-progress for:
     - instrumentation, reduction, testing, automation, tooling
  - Status of patches or docs being considered for upstream, or recently upstreamed
 - elinux wiki Boot-Time pages
      - https://elinux.org/Boot_Time_Project_Ideas
 - Conference and meetups:
    - LPC 2026 - December 11-13, 2025, Tokyo, Japan
       - System Boot and Security Microconference
       - Embedded and IOT Microconference

Next meeting: October 28th
--------

If you have items you'd like to cover, please e-mail me or put them in the document.

Thanks,
 -- Tim

^ permalink raw reply

* Call for Participation: Embedded & IoT micro-conference at Linux Plumbers 2025
From: Stefan Schmidt @ 2025-09-05  7:45 UTC (permalink / raw)
  To: linux-arm-kernel, linux-embedded, linux-arm-msm,
	linux-wpan@vger.kernel.org, BlueZ development, linux-can,
	devicetree, yocto@lists.yoctoproject.org, openembeded-devel,
	boot-architecture
  Cc: Jan Lubbe, stefan.schmidt

We are happy to announce that the Embedded & IoT micro-conference was
again accepted for Linux Plumbers this year. Hosted in beautiful Tokyo,
Japan December 11-13.
https://lpc.events/event/19/contributions/2005/

Topics cover all things embedded and IoT. Boot time to kernel size, low
power communication, telemetry and also RTOS. Devicetree and build
system have their own MC and we can move sessions between them as needed.

As with all MC's at Plumbers we are not looking for talks, but rather
discussing current problems and working towards their solution. If your
proposal has a specific stakeholder (maintainer, developer, company)
that would be needed for a fruitful discussion, please mention it in
your submission.

The CfP is open now and will run until October 3rd. Please do not wait
until the end with your submissions as we are going to accept good
proposals even before the end, so the MC might be filled up before 
October 3rd.

Jan & Stefan

^ permalink raw reply

* RE: [boot-time] New page for tracking boot-time activities
From: Bird, Tim @ 2025-08-04 21:14 UTC (permalink / raw)
  To: Rob Landley, Linux Embedded
In-Reply-To: <56e24313-cb40-445e-b2e2-900fe7e27b33@landley.net>



> -----Original Message-----
> From: Rob Landley <rob@landley.net>
> Sent: Monday, August 4, 2025 12:06 PM
> To: Bird, Tim <Tim.Bird@sony.com>; Linux Embedded <linux-embedded@vger.kernel.org>
> Subject: Re: [boot-time] New page for tracking boot-time activities
> 
> On 6/19/25 14: 06, Bird, Tim wrote: > Hey kernel boot-time developers, > > This month, I'm replacing our regular Boot-time SIG meeting
> (which normally > happens on the 4th Tuesday of every month), with a Birds-of-a-Feather (BoF) >
> 
> On 6/19/25 14:06, Bird, Tim wrote:
> > Hey kernel boot-time developers,
> >
> > This month, I'm replacing our regular Boot-time SIG meeting (which normally
> > happens on the 4th Tuesday of every month), with a Birds-of-a-Feather (BoF)
> > session at Open Source Summit North America, as part of the Embedded
> > Linux Conference track.
> >
> > Tthe BOF is Tuesday, June 24.
> > See here for session details: https://ossna2025.sched.com/event/1zfle?iframe=no
> 
> Was there a recording or minutes of this meeting for those who couldn't
> attend?

Here a link to a recording of this session:
https://youtu.be/qcotfSsrtnk

 -- Tim


^ permalink raw reply

* Re: [boot-time] New page for tracking boot-time activities
From: Rob Landley @ 2025-08-04 18:05 UTC (permalink / raw)
  To: Bird, Tim, Linux Embedded
In-Reply-To: <MW5PR13MB5632D3415109C228182DF2F3FD7DA@MW5PR13MB5632.namprd13.prod.outlook.com>

On 6/19/25 14:06, Bird, Tim wrote:
> Hey kernel boot-time developers,
> 
> This month, I'm replacing our regular Boot-time SIG meeting (which normally
> happens on the 4th Tuesday of every month), with a Birds-of-a-Feather (BoF)
> session at Open Source Summit North America, as part of the Embedded
> Linux Conference track.
> 
> Tthe BOF is Tuesday, June 24.
> See here for session details: https://ossna2025.sched.com/event/1zfle?iframe=no

Was there a recording or minutes of this meeting for those who couldn't 
attend?

Rob

^ permalink raw reply

* [boot-time] Reminder of Boot-Time SIG meeting (July 22)
From: Bird, Tim @ 2025-07-17 22:56 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, July 22, at 9:00 am Mountain Daylight Time.
See this link for other time zones:
https://www.timeanddate.com/worldclock/meetingdetails.html?year=2025&month=07&day=22&hour=15&min=0&sec=0&p1=220&p2=137&p3=195&p4=771
(That makes it 8:00 am Pacific, 15:00 UTC, 17:00 CET, and 20: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 agenda for the July 22 meeting will be available in the above document before the call.
This is what I've got so far:

- ELC boot-time post-mortem
   - What ideas should we follow up on to advance upstream?

  - Status of patches or docs being considered for upstream
    - print initlevel
    - bootstage stash driver
    - show_delta 2.0
    - deferred initcalls
    - better probe details (function name, to map to source line)
    - pre-timer init cycle count durations (and tool)
    - anything outstanding for deferred memory init?
    - documentation or tuning guide?

- Round-table of on-going work
     - Tim currently working on:
         - boot time early cycle counts (Tim)
         - boot-time regression test
         - mapping printks and initcalls to source lines, to accumulate boot time per Linux sub-system
   - boot caching (The Good Penguin work)
   - boot-time data wiki (Tim)
   - Unified Boot Log (Vishnu, TI)
   - elinux wiki Boot-Time pages
      - https://elinux.org/Boot_Time_Project_Ideas
    - Automatically reducing kernel configuration (Michael)
    - Android working on parallelized module loading (Saravana)
    - some udev integration with systemd (Federico)
     
 - Conference and meetups:
   - ELC 2025 - June 23-25, Denver, USA - pretty good lineup of boot-time topics
     - presentations and videos are now available: https://elinux.org/ELC_2025_Presentations
   - ELCE 2025 - August 25-27, Amsterdam, The Netherlands
   - LPC 2026 - December 11-13, 2025, Tokyo, Japan

Next meeting: August 26th falls during Embedded Linux Conference Europe 2025,
so we'll skip that as a call.  If there's enough interest, we might be able to schedule an unconference
session for boot-time discussions in Amsterdam, for those present.
Our next call will likely be September 23rd.

--------

If you have items you'd like to cover, please e-mail me or put them in the document.

Thanks,
 -- Tim


^ permalink raw reply

* [boot-time] New page for tracking boot-time activities
From: Bird, Tim @ 2025-06-19 19:06 UTC (permalink / raw)
  To: Linux Embedded

Hey kernel boot-time developers,

This month, I'm replacing our regular Boot-time SIG meeting (which normally
happens on the 4th Tuesday of every month), with a Birds-of-a-Feather (BoF)
session at Open Source Summit North America, as part of the Embedded
Linux Conference track.

Tthe BOF is Tuesday, June 24.
See here for session details: https://ossna2025.sched.com/event/1zfle?iframe=no

I've made a wiki page to keep track of some of the things that SIG participants
have mentioned that they have recently worked on, or are currently working on,
here:
https://elinux.org/Boot-Time_Activities

The page is not exhaustive.  I plan to review this page during the BoF.
If you have a project or work that you'd like to let others know about,
please email me, or add it to the page yourself.

Let's keep each other informed of the boot-time work we're doing!
 -- Tim


^ permalink raw reply

* Re: Deferred probe times
From: Federico Giovanardi @ 2025-05-26  8:14 UTC (permalink / raw)
  To: Bird, Tim; +Cc: Linux Embedded
In-Reply-To: <MW5PR13MB56324F6600F6844DB8A6FCD5FD9BA@MW5PR13MB5632.namprd13.prod.outlook.com>

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


Well, the comment about the giant block was not a complaint, of course.

With both patches, I used to get the attached image, so the 
deferred_probe slot it's separated into its constituents.


Thanks

Federico


On 2025-05-24 02:16, Bird, Tim wrote:
>> -----Original Message-----
>> From: Federico Giovanardi <federico@giovanardi.dev>
>> Hello,
>> 
>> I was poking around the boot data database while I noticed that the
>> deferred_probe initicalls are considered as a giant block;
> 
> Hmm.  I didn't think anyone was looking at this data besides myself.
> The site is really still under construction, so I apologize for missing
> and mis-formatted data.  But thanks for looking at
> the data and finding something that needs attention upstream!!
> 
>> 
>> There is a patch that looks never went upstream to measure them:
>> https://lkml.iu.edu/1707.3/02349.html
> 
> Wow, that's interesting.  Here's the lore link for this thread:
> https://lore.kernel.org/lkml/20170725233159.89543-1-toddpoynor@google.com/#t
> 
> It doesn't look like there were (after discussion) objections to 
> accepting upstream.
> I wonder what happened.
> 
> ...
> It looks like it was superceded by this patch:
> https://lore.kernel.org/lkml/20180620023903.242758-1-toddpoynor@gmail.com/
> which may provide some of the data necessary.
> 
> The thing missing there are some (IMHO) better name lookups for the 
> probe function.
> I wrote a patch for that, but didn't persist in trying to upstream it.  
> Maybe I should
> dust that off and send it again.
> 
>> 
>> And another one from me to print the result in the .svg.
>> 
>> 
>> Have a nice day
>> Federico

[-- Attachment #2: image.png --]
[-- Type: image/png, Size: 73235 bytes --]

^ permalink raw reply

* Re: [PATCH 1/1] drivers: misc: add driver for bootstage stash
From: kernel test robot @ 2025-05-24  7:18 UTC (permalink / raw)
  To: Francesco Valla, linux-embedded; +Cc: llvm, oe-kbuild-all
In-Reply-To: <20250522224223.358881-3-francesco@valla.it>

Hi Francesco,

kernel test robot noticed the following build warnings:

[auto build test WARNING on char-misc/char-misc-linus]
[also build test WARNING on robh/for-next linus/master v6.15-rc7]
[cannot apply to char-misc/char-misc-testing char-misc/char-misc-next next-20250523]
[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/Francesco-Valla/drivers-misc-add-driver-for-bootstage-stash/20250523-122757
base:   char-misc/char-misc-linus
patch link:    https://lore.kernel.org/r/20250522224223.358881-3-francesco%40valla.it
patch subject: [PATCH 1/1] drivers: misc: add driver for bootstage stash
config: hexagon-allyesconfig (https://download.01.org/0day-ci/archive/20250524/202505241547.wVTtLz71-lkp@intel.com/config)
compiler: clang version 21.0.0git (https://github.com/llvm/llvm-project f819f46284f2a79790038e1f6649172789734ae8)
reproduce (this is a W=1 build): (https://download.01.org/0day-ci/archive/20250524/202505241547.wVTtLz71-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/202505241547.wVTtLz71-lkp@intel.com/

All warnings (new ones prefixed by >>):

>> drivers/misc/bootstage.c:164:24: warning: format specifies type 'unsigned long long' but the argument has type 'resource_size_t' (aka 'unsigned int') [-Wformat]
     163 |                 dev_err(dev, "invalid declared stash size %u (expected: <= %llu)\n",
         |                                                                            ~~~~
         |                                                                            %u
     164 |                         drvdata->hdr->size, size);
         |                                             ^~~~
   include/linux/dev_printk.h:154:65: note: expanded from macro 'dev_err'
     154 |         dev_printk_index_wrap(_dev_err, KERN_ERR, dev, dev_fmt(fmt), ##__VA_ARGS__)
         |                                                                ~~~     ^~~~~~~~~~~
   include/linux/dev_printk.h:110:23: note: expanded from macro 'dev_printk_index_wrap'
     110 |                 _p_func(dev, fmt, ##__VA_ARGS__);                       \
         |                              ~~~    ^~~~~~~~~~~
   drivers/misc/bootstage.c:168:4: warning: format specifies type 'unsigned long long' but the argument has type 'resource_size_t' (aka 'unsigned int') [-Wformat]
     167 |                 dev_err(dev, "invalid calculated stash size %llu (expected: <= %llu)\n",
         |                                                             ~~~~
         |                                                             %u
     168 |                         calc_size, size);
         |                         ^~~~~~~~~
   include/linux/dev_printk.h:154:65: note: expanded from macro 'dev_err'
     154 |         dev_printk_index_wrap(_dev_err, KERN_ERR, dev, dev_fmt(fmt), ##__VA_ARGS__)
         |                                                                ~~~     ^~~~~~~~~~~
   include/linux/dev_printk.h:110:23: note: expanded from macro 'dev_printk_index_wrap'
     110 |                 _p_func(dev, fmt, ##__VA_ARGS__);                       \
         |                              ~~~    ^~~~~~~~~~~
   drivers/misc/bootstage.c:168:15: warning: format specifies type 'unsigned long long' but the argument has type 'resource_size_t' (aka 'unsigned int') [-Wformat]
     167 |                 dev_err(dev, "invalid calculated stash size %llu (expected: <= %llu)\n",
         |                                                                                ~~~~
         |                                                                                %u
     168 |                         calc_size, size);
         |                                    ^~~~
   include/linux/dev_printk.h:154:65: note: expanded from macro 'dev_err'
     154 |         dev_printk_index_wrap(_dev_err, KERN_ERR, dev, dev_fmt(fmt), ##__VA_ARGS__)
         |                                                                ~~~     ^~~~~~~~~~~
   include/linux/dev_printk.h:110:23: note: expanded from macro 'dev_printk_index_wrap'
     110 |                 _p_func(dev, fmt, ##__VA_ARGS__);                       \
         |                              ~~~    ^~~~~~~~~~~
   3 warnings generated.


vim +164 drivers/misc/bootstage.c

   143	
   144	static int bootstage_parse(struct device *dev, struct bootstage_drvdata *drvdata,
   145				   resource_size_t size)
   146	{
   147		const char *str_ptr = (const char *)(drvdata->records + drvdata->hdr->count);
   148		const resource_size_t calc_size = (resource_size_t)((void *)str_ptr - (void *)drvdata->hdr);
   149		struct bootstage_record *rec;
   150		u32 r;
   151	
   152		// Sanity checks on bootstage header
   153		if (drvdata->hdr->magic != BOOTSTAGE_MAGIC) {
   154			dev_err(dev, "wrong bootstage magic number %08Xh\n", drvdata->hdr->magic);
   155			return -EINVAL;
   156		} else if (drvdata->hdr->version > BOOTSTAGE_MAX_VERSION) {
   157			dev_err(dev, "bootstage version %u not supported\n", drvdata->hdr->version);
   158			return -EOPNOTSUPP;
   159		} else if (drvdata->hdr->size == 0) {
   160			dev_err(dev, "invalid bootstage stash (declared size is zero)\n");
   161			return -EINVAL;
   162		} else if (drvdata->hdr->size > size) {
   163			dev_err(dev, "invalid declared stash size %u (expected: <= %llu)\n",
 > 164				drvdata->hdr->size, size);
   165			return -EINVAL;
   166		} else if (calc_size > size) {
   167			dev_err(dev, "invalid calculated stash size %llu (expected: <= %llu)\n",
   168				calc_size, size);
   169			return -EINVAL;
   170		} else if (drvdata->hdr->count == 0) {
   171			dev_info(dev, "bootstage stash has no records\n");
   172			return 0;
   173		}
   174	
   175		// Set start time to invalid
   176		drvdata->start_time_us = 0xFFFFFFFF;
   177	
   178		// Associate names to records, which are placed at the end of the record area
   179		for (r = 0, rec = drvdata->records; r < drvdata->hdr->count; r++, rec++) {
   180			// Save minimum time, will be used as bootloader enter time
   181			if (rec->start_us < drvdata->start_time_us)
   182				drvdata->start_time_us = rec->time_us;
   183	
   184			// Save maximum time, will be used as bootloader exit time
   185			if (rec->time_us > drvdata->end_time_us)
   186				drvdata->end_time_us = rec->time_us;
   187	
   188			if (str_ptr > ((const char *)drvdata->hdr + size)) {
   189				dev_err(dev, "name for record %u is corrupted\n", r);
   190				return -ENODATA;
   191			}
   192	
   193			rec->name = str_ptr;
   194			str_ptr += strlen(rec->name) + 1;
   195		}
   196	
   197		return 0;
   198	}
   199	

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

^ permalink raw reply

* Re: [PATCH 1/1] drivers: misc: add driver for bootstage stash
From: Krzysztof Kozlowski @ 2025-05-24  6:16 UTC (permalink / raw)
  To: Rob Landley, Francesco Valla, linux-embedded
In-Reply-To: <ad98c8d5-dc2e-4f52-9835-e15d9f3a94fd@landley.net>

On 23/05/2025 21:34, Rob Landley wrote:
> On 5/23/25 01:29, Krzysztof Kozlowski wrote:
>> On 23/05/2025 00:42, Francesco Valla wrote:
>>> Add support for bootstage stash areas containing boot time data
>>> created by some bootloader (e.g. U-Boot). The driver provides generic
>>> time information through sysfs and platform-specific one through
>>> debugfs.
>>>
>>> Signed-off-by: Francesco Valla <francesco@valla.it>
>>
>> Your Cc list is so incomplete I really do not understand which project
>> you target and this popped up in my lei filters. If this is not for
>> Linux kernel, please ignore the rest.
> 
> The discussion is happening on the linux-embedded list you cc'd in your 
> reply.
> 
> https://www.spinics.net/lists/linux-embedded/msg04429.html
> 
> https://www.spinics.net/lists/linux-embedded/msg04435.html

No, that's not the place where we discuss patches. Use
get_maintainers.pl to find the right place.

Best regards,
Krzysztof

^ permalink raw reply

* Re: [PATCH 1/1] drivers: misc: add driver for bootstage stash
From: Krzysztof Kozlowski @ 2025-05-24  6:15 UTC (permalink / raw)
  To: Francesco Valla, linux-embedded
In-Reply-To: <3107514.XAFRqVoOGU@fedora.fritz.box>

On 23/05/2025 21:43, Francesco Valla wrote:
>> tested by automated tooling. Performing review on untested code might be
>> a waste of time.
>>
>> Please kindly resend and include all necessary To/Cc entries.
>>
> 
> 
> I did not want to unnecessary bother people that might not be interested,
> as the current form is not intended for mainline. I'll however be more
> scrupulous in the future.

Then mark your patches clearly like that. Usually this is RFC with
explanation what you mean by that in cover letter.


Best regards,
Krzysztof

^ permalink raw reply

* Re: Reminder of Boot-Time SIG meeting - May 27
From: Rob Landley @ 2025-05-23 19:31 UTC (permalink / raw)
  To: Linux Embedded
In-Reply-To: <MW5PR13MB5632B8EE9EC410B617304A3BFD99A@MW5PR13MB5632.namprd13.prod.outlook.com>

On 5/22/25 18:33, Bird, Tim wrote:
> 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.

Is there a git for 
https://birdcloud.org/boot-time-files/grab-boot-data.sh or just a 
snapshot of the file with no history?

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

I keep forgetting the project web page(s) and having to dig for them, 
and modern google does _not_ find them.

Also, https://elinux.org/Unified_Boot_Log does not link to 
https://elinux.org/Boot_Time and the only link back the other way is the 
"special topic meeting" note...

Rob

^ permalink raw reply

* RE: [RFC PATCH 0/1] Add driver for bootstage stash
From: Bird, Tim @ 2025-05-24  0:28 UTC (permalink / raw)
  To: Bird, Tim, Federico Giovanardi, linux-embedded@vger.kernel.org
In-Reply-To: <MW5PR13MB5632A2522BFAF3066DCC57CDFD9BA@MW5PR13MB5632.namprd13.prod.outlook.com>

Correction...

> -----Original Message-----
> From: Bird, Tim <Tim.Bird@sony.com>
> One counter_id could be 0 - indicating that the counter is time in microseconds
> (for U-boot bootstage data, where the values are already converted to microseconds).
> I would prefer doing that counter conversion at boot-time, when the cycle counter
I would prefer NOT doing that counter conversion at boot-time...

> values can (almost) as easily be normalized to microseconds at report time.
> 

^ permalink raw reply

* RE: Deferred probe times
From: Bird, Tim @ 2025-05-24  0:16 UTC (permalink / raw)
  To: Federico Giovanardi, Linux Embedded
In-Reply-To: <cd10fd7ee9a3b0ce61cf3c1ea3805fbd@giovanardi.dev>

> -----Original Message-----
> From: Federico Giovanardi <federico@giovanardi.dev>
> Hello,
> 
> I was poking around the boot data database while I noticed that the
> deferred_probe initicalls are considered as a giant block;

Hmm.  I didn't think anyone was looking at this data besides myself.
The site is really still under construction, so I apologize for missing
and mis-formatted data.  But thanks for looking at
the data and finding something that needs attention upstream!!

> 
> There is a patch that looks never went upstream to measure them:
> https://lkml.iu.edu/1707.3/02349.html

Wow, that's interesting.  Here's the lore link for this thread:
https://lore.kernel.org/lkml/20170725233159.89543-1-toddpoynor@google.com/#t

It doesn't look like there were (after discussion) objections to accepting upstream.
I wonder what happened.

...
It looks like it was superceded by this patch:
https://lore.kernel.org/lkml/20180620023903.242758-1-toddpoynor@gmail.com/
which may provide some of the data necessary.

The thing missing there are some (IMHO) better name lookups for the probe function.
I wrote a patch for that, but didn't persist in trying to upstream it.  Maybe I should
dust that off and send it again.

> 
> And another one from me to print the result in the .svg.
> 
> 
> Have a nice day
> Federico


^ permalink raw reply

* RE: [RFC PATCH 0/1] Add driver for bootstage stash
From: Bird, Tim @ 2025-05-24  0:07 UTC (permalink / raw)
  To: Federico Giovanardi, linux-embedded@vger.kernel.org
In-Reply-To: <473a062e4f939bc58a5c0e636569b826@giovanardi.dev>

> -----Original Message-----
> From: Federico Giovanardi <fede.dev@giovanardi.dev>
> Hello,
> 
> The note about the data format also was my initial thought, by just
> copying a C structure we might have issues as soon one party changes it,
> and they might not be perfectly aligned.
> 
> To avoid inventing yet-another-data-format I've used msgpack in the past
> for that (the format
> https://github.com/msgpack/msgpack/blob/master/spec.md, not the library
> ); because the specs are so simple they can be implemented in a few
> lines, and it's something with a reference. But I don't have a lot of
> experience in upstreaming stuff on the kernel, so I don't know if it
> might cause someone to don't be happy. Anyway, I can contribute the
> implementation if needed.
> 
> Something as simple as an array of fixarray will give extensibility with
> only a few bytes of overhead.
> 
> Which gets encoded as:
> 
> 0xdc # lenght 16 bit << array header
>       # 0xB << 4 | ( array_size & 0xF) << fixarray header ( 3 elements,
> simplest case)
>             # 0xce # time_us
>             # 0xce # start_us
>             # 0xc << 4 | strlen(name) # name
>             /*no flags, no id*/
>       # 0xB << 4 | ( array_size & 0xF) << fixarray header ( 5 elements
> bigger case)
>             # 0xce # time_us
>             # 0xce # start_us
>             # 0xc << 4 | strlen(name) # name
>             # 0xcc # flags
>             # 0xcc # id
>       .. repeat ...
> 
> 
> Since the goal is to use that in many different contexts, defining the
> fields that we need early is important.

My own opinion is that the current bootstash format is too complicated, and that the
Unified Boot Log record format should be simplified to just
name, counter_id, and counter value, with fixed limits on the size of each.

struct UBL_entry {
  char name[7];
  u8 counter_id;
  u64 counter_value;
}

None of this looking up names in a separate table business.

One counter_id could be 0 - indicating that the counter is time in microseconds
(for U-boot bootstage data, where the values are already converted to microseconds).
I would prefer doing that counter conversion at boot-time, when the cycle counter
values can (almost) as easily be normalized to microseconds at report time.

That is, other cycle-counters used in a single Unified Boot Log could be used, and
instrumentation can just store their value, without doing the conversion.  The reporting
tool would need to know the conversion rate for each counter_id.  But it
should be able to calculate that at report time.

It would be good to discuss whether that reporting (and conversion) should be in the kernel
or a separate user-space tool.  The current patch puts reporting into the kernel.
   -- Tim


^ permalink raw reply

* RE: [PATCH 1/1] drivers: misc: add driver for bootstage stash
From: Bird, Tim @ 2025-05-23 23:43 UTC (permalink / raw)
  To: Francesco Valla, linux-embedded@vger.kernel.org
In-Reply-To: <20250522224223.358881-3-francesco@valla.it>

Francesco,

Thanks for this prototype!!

> -----Original Message-----
> From: Francesco Valla <francesco@valla.it>
> Add support for bootstage stash areas containing boot time data
> created by some bootloader (e.g. U-Boot). The driver provides generic
> time information through sysfs and platform-specific one through
> debugfs.
> 
> Signed-off-by: Francesco Valla <francesco@valla.it>
> ---
>  .../bindings/reserved-memory/bootstage.yaml   |  44 +++
>  Documentation/misc-devices/bootstage.rst      |  53 ++++
>  Documentation/misc-devices/index.rst          |   1 +
>  MAINTAINERS                                   |   7 +
>  drivers/misc/Kconfig                          |  10 +
>  drivers/misc/Makefile                         |   1 +
>  drivers/misc/bootstage.c                      | 292 ++++++++++++++++++
>  drivers/of/platform.c                         |   1 +
>  8 files changed, 409 insertions(+)
>  create mode 100644 Documentation/devicetree/bindings/reserved-memory/bootstage.yaml
>  create mode 100644 Documentation/misc-devices/bootstage.rst
>  create mode 100644 drivers/misc/bootstage.c
> 
> diff --git a/Documentation/devicetree/bindings/reserved-memory/bootstage.yaml b/Documentation/devicetree/bindings/reserved-
> memory/bootstage.yaml
> new file mode 100644
> index 000000000000..e71d85c5c2ce
> --- /dev/null
> +++ b/Documentation/devicetree/bindings/reserved-memory/bootstage.yaml
> @@ -0,0 +1,44 @@
> +# SPDX-License-Identifier: GPL-2.0-only OR BSD-2-Clause
> +%YAML 1.2
> +---
> +$id: http://devicetree.org/schemas/reserved-memory/bootstage.yaml#
> +$schema: http://devicetree.org/meta-schemas/core.yaml#
> +
> +title: Bootstage stash
> +
> +description: |
> +  This binding represents a reserved memory region containing bootstage stash
> +  data generated by a previous bootloader stage.
> +
> +maintainers:
> +  - Francesco Valla <francesco@valla.it>
> +
> +allOf:
> +  - $ref: reserved-memory.yaml
> +
> +properties:
> +  compatible:
> +    const: bootstage
> +
> +  reg:
> +    description: page-aligned region of memory containing bootstage stash data
> +
> +required:
> +  - compatible
> +  - reg
> +  - no-map
> +
> +unevaluatedProperties: false
> +
> +examples:
> +  - |
> +    reserved-memory {
> +        #address-cells = <2>;
> +        #size-cells = <1>;
> +
> +        bootstage: bootstage@12340000 {
> +            compatible = "bootstage";
> +            reg = <0x00 0x12340000 0x2000>;
> +            no-map;
> +        };
> +    };
> diff --git a/Documentation/misc-devices/bootstage.rst b/Documentation/misc-devices/bootstage.rst
> new file mode 100644
> index 000000000000..2e1bbd31aab8
> --- /dev/null
> +++ b/Documentation/misc-devices/bootstage.rst
> @@ -0,0 +1,53 @@
> +.. SPDX-License-Identifier: GPL-2.0
> +
> +================
> +Bootstage driver
> +================
> +
> +The bootstage driver exports interfaces to read from a bootstage stash area
> +saved by a bootloader (e.g.: U-Boot) that ran before the Linux kernel.
> +
> +Two kind of interfaces are exported:
> +
> +- a sysfs interface for bootloader- and platform-agnostic data
> +- a debugfs interface for bootloader- and platform-specific data
> +
> +
> +The sysfs interface
> +-------------------
> +
> +Following sysfs attributes can be found at /sys/devices/platform/<device-name>/:
> +
> +- start_time_us: bootloader start time in microseconds
> +- end_time_us: bootloader end time in microseconds
> +
> +
> +The debugfs interface
> +---------------------
> +
> +Following debugfs interfaces can be found at
> +/sys/kernel/debug/bootstage/<device-name>/:
> +
> +- stages: details on staged bootloader stages, with start time and duration.
> +  Example output::
> +
> +    Mark (us)  Elapsed (us)  Stage
> +            0             0  reset
> +       183689        183689  SPL
> +       489247        305558  end phase
> +       506987         17740  board_init_f
> +      1257880        750893  board_init_r
> +      1622303        364423  eth_common_init
> +      1888033        265730  eth_initialize
> +      1893077          5044  main_loop
> +      4204282       2311205  cli_loop
> +
> +- accumulated_time: time accumulated during certain bootloader stages.
> +  Example output::
> +
> +    Time (us)  Stage
> +         4902  dm_spl
> +       322719  dm_f
> +         9527  dm_r
> +
> +The number and type of staged stages are bootloader- and platform-specific.

I think it would be good to indicate in this document the required U-Boot CONFIG
settings for bootstage to be enabled.  We don't need to replicate detailed U-Boot
documentation, but maybe just refer to the required configs.  (e.g. CONFIG_BOOTSTAGE,
CONFIG_BOOTSTAGE_STASH, etc.)

Note: I looked in the U-boot documentation for documentation about Bootstage,
and I couldn't find much.  There might be an opportunity to add some documentation
there as well.

> diff --git a/Documentation/misc-devices/index.rst b/Documentation/misc-devices/index.rst
> index 8c5b226d8313..c5ebb3d44505 100644
> --- a/Documentation/misc-devices/index.rst
> +++ b/Documentation/misc-devices/index.rst
> @@ -28,3 +28,4 @@ fit into other categories.
>     tps6594-pfsm
>     uacce
>     xilinx_sdfec
> +   bootstage
> diff --git a/MAINTAINERS b/MAINTAINERS
> index f21f1dabb5fe..0bdecd07023a 100644
> --- a/MAINTAINERS
> +++ b/MAINTAINERS
> @@ -4203,6 +4203,13 @@ F:	Documentation/ABI/stable/sysfs-class-bluetooth
>  F:	include/net/bluetooth/
>  F:	net/bluetooth/
> 
> +BOOTSTAGE DRIVER
> +M:	Francesco Valla <francesco@valla.it>
> +L:	linux-embedded@vger.kernel.org
> +S:	Maintained
> +F:	Documentation/devicetree/bindings/reserved-memory/bootstage.yaml
> +F:	drivers/misc/bootstage.c
> +
>  BONDING DRIVER
>  M:	Jay Vosburgh <jv@jvosburgh.net>
>  L:	netdev@vger.kernel.org
> diff --git a/drivers/misc/Kconfig b/drivers/misc/Kconfig
> index 6b37d61150ee..97cdfa241c0c 100644
> --- a/drivers/misc/Kconfig
> +++ b/drivers/misc/Kconfig
> @@ -632,6 +632,16 @@ config MCHP_LAN966X_PCI
>  	    - lan966x-miim (MDIO_MSCC_MIIM)
>  	    - lan966x-switch (LAN966X_SWITCH)
> 
> +config BOOTSTAGE
> +	tristate "Bootstage stash support"
> +	depends on OF_RESERVED_MEM
> +	help
> +	  This enables the support for a bootstage stash.
> +
> +	  A bootstage stash can be created by some bootloaders (e.g.: U-Boot) to
> +	  store information on its boot timings. This driver provides access to
> +	  these information through sysfs and debugsfs interfaces.
> +
>  source "drivers/misc/c2port/Kconfig"
>  source "drivers/misc/eeprom/Kconfig"
>  source "drivers/misc/cb710/Kconfig"
> diff --git a/drivers/misc/Makefile b/drivers/misc/Makefile
> index d6c917229c45..3562c1bf701f 100644
> --- a/drivers/misc/Makefile
> +++ b/drivers/misc/Makefile
> @@ -74,3 +74,4 @@ lan966x-pci-objs		:= lan966x_pci.o
>  lan966x-pci-objs		+= lan966x_pci.dtbo.o
>  obj-$(CONFIG_MCHP_LAN966X_PCI)	+= lan966x-pci.o
>  obj-y				+= keba/
> +obj-$(CONFIG_BOOTSTAGE)		+= bootstage.o
> diff --git a/drivers/misc/bootstage.c b/drivers/misc/bootstage.c
> new file mode 100644
> index 000000000000..a106410a56ee
> --- /dev/null
> +++ b/drivers/misc/bootstage.c
> @@ -0,0 +1,292 @@
> +// SPDX-License-Identifier: GPL-2.0-only
> +/*
> + * Copyright (C) 2025 - Francesco Valla <francesco@valla.it>
> + *
> + * Driver for bootstage stash.
> + *
> + * This driver exposes bootstage stash generated by bootloader and/or firmware
> + * stages that run before the Linux kernel.
> + *
> + */
> +
> +#include <linux/debugfs.h>
> +#include <linux/io.h>
> +#include <linux/mm.h>
> +#include <linux/module.h>
> +#include <linux/of_reserved_mem.h>
> +#include <linux/platform_device.h>
> +#include <linux/seq_file.h>
> +
> +#define BOOTSTAGE_MAGIC		0xb00757a3
> +#define BOOTSTAGE_MAX_VERSION	0
> +
> +enum bootstage_id {
> +	BOOTSTAGE_ID_START = 0,
> +};
> +
> +enum bootstage_flags {
> +	BOOTSTAGEF_ERROR	= 1 << 0,	/* Error record */
> +	BOOTSTAGEF_ALLOC	= 1 << 1,	/* Allocate an id */
> +};
> +
> +struct bootstage_record {
> +	ulong time_us;
> +	u32 start_us;
> +	const char *name;
> +	int flags;
> +	enum bootstage_id id;
> +};
> +
> +struct bootstage_hdr {
> +	u32 version;		/* Boostage stash version */
> +	u32 count;		/* Number of records */
> +	u32 size;		/* Total data size (non-zero if valid) */
> +	u32 magic;		/* Magic number */
> +	u32 next_id;		/* Next ID to use for bootstage */
> +};
> +
> +struct bootstage_drvdata {
> +	struct bootstage_hdr *hdr;
> +	struct bootstage_record *records;
> +
> +	u32 start_time_us;
> +	u32 end_time_us;
> +
> +	struct dentry *debugfs_dir;
> +};
> +
> +static struct dentry *bootstage_debugfs_dir;
> +
> +static int stages_show(struct seq_file *m, void *d)
> +{
> +	struct bootstage_drvdata *drvdata = m->private;
> +	struct bootstage_hdr *hdr = drvdata->hdr;
> +	struct bootstage_record *rec;
> +	u32 prev = 0;
> +	int i;
> +
> +	seq_printf(m, "%13s %13s  %s\n", "Mark (us)", "Elapsed (us)", "Stage");
> +
> +	for (i = 0, rec = drvdata->records; i < hdr->count; i++, rec++) {
> +		if ((rec->id && !rec->start_us) || (i == 0)) {
> +			if (prev > rec->time_us)
> +				prev = 0;
> +			seq_printf(m, "%13lu %13lu  %s\n", rec->time_us,
> +				   rec->time_us - prev, rec->name);
> +			prev = rec->time_us;
> +		}
> +	}
> +
> +	return 0;
> +}
> +DEFINE_SHOW_ATTRIBUTE(stages);
> +
> +static int accumulated_time_show(struct seq_file *m, void *d)
> +{
> +	struct bootstage_drvdata *drvdata = m->private;
> +	struct bootstage_hdr *hdr = drvdata->hdr;
> +	struct bootstage_record *rec;
> +	int i;
> +
> +	seq_printf(m, "%13s  %s\n", "Time (us)", "Stage");
> +
> +	for (i = 0, rec = drvdata->records; i < hdr->count; i++, rec++) {
> +		if (rec->start_us)
> +			seq_printf(m, "%13lu  %s\n", rec->time_us, rec->name);
> +	}
> +
> +	return 0;
> +}
> +DEFINE_SHOW_ATTRIBUTE(accumulated_time);
> +
> +static void bootstage_debugfs_init(struct device *dev, struct bootstage_drvdata *drvdata)
> +{
> +	drvdata->debugfs_dir = debugfs_create_dir(dev_name(dev), bootstage_debugfs_dir);
> +	if (IS_ERR(drvdata->debugfs_dir))
> +		return;
> +
> +	debugfs_create_file("stages", 0444, drvdata->debugfs_dir, drvdata, &stages_fops);
> +	debugfs_create_file("accumulated_time", 0444, drvdata->debugfs_dir, drvdata,
> +			    &accumulated_time_fops);
> +}
> +
> +static void bootstage_debugfs_exit(struct device *dev, struct bootstage_drvdata *drvdata)
> +{
> +	debugfs_remove_recursive(drvdata->debugfs_dir);
> +}
> +
> +static ssize_t start_time_us_show(struct device *dev, struct device_attribute *attr, char *buf)
> +{
> +	struct bootstage_drvdata *drvdata = dev_get_drvdata(dev);
> +
> +	return sprintf(buf, "%u\n", drvdata->start_time_us);
> +}
> +static DEVICE_ATTR_RO(start_time_us);
> +
> +static ssize_t end_time_us_show(struct device *dev, struct device_attribute *attr, char *buf)
> +{
> +	struct bootstage_drvdata *drvdata = dev_get_drvdata(dev);
> +
> +	return sprintf(buf, "%u\n", drvdata->end_time_us);
> +}
> +static DEVICE_ATTR_RO(end_time_us);
> +
> +static struct attribute *bootstage_attrs[] = {
> +	&dev_attr_start_time_us.attr,
> +	&dev_attr_end_time_us.attr,
> +	NULL,
> +};
> +
> +static const struct attribute_group bootstage_attr_group = {
> +	.attrs = bootstage_attrs,
> +};
> +
> +static int bootstage_parse(struct device *dev, struct bootstage_drvdata *drvdata,
> +			   resource_size_t size)
> +{
> +	const char *str_ptr = (const char *)(drvdata->records + drvdata->hdr->count);
> +	const resource_size_t calc_size = (resource_size_t)((void *)str_ptr - (void *)drvdata->hdr);
> +	struct bootstage_record *rec;
> +	u32 r;
> +
> +	// Sanity checks on bootstage header
> +	if (drvdata->hdr->magic != BOOTSTAGE_MAGIC) {
> +		dev_err(dev, "wrong bootstage magic number %08Xh\n", drvdata->hdr->magic);
> +		return -EINVAL;
> +	} else if (drvdata->hdr->version > BOOTSTAGE_MAX_VERSION) {
> +		dev_err(dev, "bootstage version %u not supported\n", drvdata->hdr->version);
> +		return -EOPNOTSUPP;
> +	} else if (drvdata->hdr->size == 0) {
> +		dev_err(dev, "invalid bootstage stash (declared size is zero)\n");
> +		return -EINVAL;
> +	} else if (drvdata->hdr->size > size) {
> +		dev_err(dev, "invalid declared stash size %u (expected: <= %llu)\n",
> +			drvdata->hdr->size, size);
> +		return -EINVAL;
> +	} else if (calc_size > size) {
> +		dev_err(dev, "invalid calculated stash size %llu (expected: <= %llu)\n",
> +			calc_size, size);
> +		return -EINVAL;
> +	} else if (drvdata->hdr->count == 0) {
> +		dev_info(dev, "bootstage stash has no records\n");
> +		return 0;
> +	}
> +
> +	// Set start time to invalid
> +	drvdata->start_time_us = 0xFFFFFFFF;
> +
> +	// Associate names to records, which are placed at the end of the record area
> +	for (r = 0, rec = drvdata->records; r < drvdata->hdr->count; r++, rec++) {
> +		// Save minimum time, will be used as bootloader enter time
> +		if (rec->start_us < drvdata->start_time_us)
> +			drvdata->start_time_us = rec->time_us;
> +
> +		// Save maximum time, will be used as bootloader exit time
> +		if (rec->time_us > drvdata->end_time_us)
> +			drvdata->end_time_us = rec->time_us;
> +
> +		if (str_ptr > ((const char *)drvdata->hdr + size)) {
> +			dev_err(dev, "name for record %u is corrupted\n", r);
> +			return -ENODATA;
> +		}
> +
> +		rec->name = str_ptr;
> +		str_ptr += strlen(rec->name) + 1;
> +	}
> +
> +	return 0;
> +}
> +
> +static int bootstage_probe(struct platform_device *pdev)
> +{
> +	struct device *dev = &pdev->dev;
> +	struct reserved_mem *rmem;
> +	struct bootstage_drvdata *drvdata;
> +	int ret;
> +
> +	rmem = of_reserved_mem_lookup(dev->of_node);
> +	if (!rmem) {
> +		dev_err(dev, "failed to lookup reserved memory\n");
> +		return -EINVAL;
> +	}
> +
> +	if (!rmem->size || (rmem->size > ULONG_MAX) ||
> +	    (rmem->size < sizeof(struct bootstage_hdr))) {
> +		dev_err(dev, "invalid memory region size\n");
> +		return -EINVAL;
> +	}
> +
> +	if (!PAGE_ALIGNED(rmem->base) || !PAGE_ALIGNED(rmem->size)) {
> +		dev_err(dev, "memory region must be page-aligned\n");
> +		return -EINVAL;
> +	}
> +
> +	drvdata = devm_kmalloc(dev, sizeof(*drvdata), GFP_KERNEL);
> +	if (!drvdata)
> +		return -ENOMEM;
> +
> +	platform_set_drvdata(pdev, drvdata);
> +
> +	drvdata->hdr = devm_memremap(dev, rmem->base, rmem->size, MEMREMAP_WB);
> +	if (IS_ERR(drvdata->hdr)) {
> +		dev_err(dev, "failed to remap bootstage region\n");
> +		return PTR_ERR(drvdata->hdr);
> +	}
> +
> +	drvdata->records =
> +		(struct bootstage_record *)((void *)drvdata->hdr + sizeof(struct bootstage_hdr));
> +
> +	ret = bootstage_parse(dev, drvdata, rmem->size);
> +	if (ret)
> +		return ret;
> +
> +	ret = sysfs_create_group(&pdev->dev.kobj, &bootstage_attr_group);
> +	if (ret) {
> +		dev_err(dev, "failed to create sysfs group\n");
> +		return ret;
> +	}
> +
> +	bootstage_debugfs_init(dev, drvdata);
> +
> +	return 0;
> +}
> +
> +static void bootstage_remove(struct platform_device *pdev)
> +{
> +	struct bootstage_drvdata *drvdata = platform_get_drvdata(pdev);
> +
> +	bootstage_debugfs_exit(&pdev->dev, drvdata);
> +	sysfs_remove_group(&pdev->dev.kobj, &bootstage_attr_group);
> +}
> +
> +static const struct of_device_id bootstage_of_match[] = {
> +	{ .compatible = "bootstage" },
> +	{},
> +};
> +
> +static struct platform_driver bootstage_driver = {
> +	.probe = bootstage_probe,
> +	.remove = bootstage_remove,
> +	.driver = {
> +		.name = "bootstage",
> +		.of_match_table = bootstage_of_match,
> +	},
> +};
> +
> +static int __init bootstage_init(void)
> +{
> +	bootstage_debugfs_dir = debugfs_create_dir(bootstage_driver.driver.name, NULL);
> +	return platform_driver_register(&bootstage_driver);
> +}
> +arch_initcall(bootstage_init);
> +
> +static void __exit bootstage_exit(void)
> +{
> +	debugfs_remove_recursive(bootstage_debugfs_dir);
> +	platform_driver_unregister(&bootstage_driver);
> +}
> +module_exit(bootstage_exit)
> +
> +MODULE_DESCRIPTION("Driver for Bootstage stash.");
> +MODULE_LICENSE("GPL");
> +MODULE_AUTHOR("Francesco Valla <francesco@valla.it>");

OK - I have to admit now that I am confused.  I haven't actually run this code,
or the U-boot code, but in examining the code at:
https://elixir.bootlin.com/u-boot/v2025.04/source/common/bootstage.c#L269
it seems like U-boot adds each individual record as a device tree property.

If that code (add_bootstage_devicetree) is putting info in the device tree as properties,
why is this kernel code reading bootstage stash entries as binary structured data
from the bootstage stash memory.

I see the 'bootstage_stash()' function in that same U-boot code, which presumably
is storing U-boot entries into the stash area, to be passed to the kernel.
Is there code in U-boot to add the stash element address property to the flattened
device tree that it passes to the kernel, or is this just manually configured
in 1) the U-boot config, and 2) the kernel device tree file?

Or maybe, the bootstage_stash() in the U-boot source code is there to copy
records from a secondary bootloader into the primary U-boot bootstage
stash?  I can't figure out what's going on.

Are these two things related or completely separate?  (That is, if the flattened
device tree has a bootstage node with sub-notes having 'name' and either 'accum' or 'mark'
records with a time_us element, is that completely different from the bootstage stash
memory area?

Just trying to get a handle on what's going on here and how the data is being transferred.

> diff --git a/drivers/of/platform.c b/drivers/of/platform.c
> index f77cb19973a5..e19b04733584 100644
> --- a/drivers/of/platform.c
> +++ b/drivers/of/platform.c
> @@ -496,6 +496,7 @@ static const struct of_device_id reserved_mem_matches[] = {
>  	{ .compatible = "ramoops" },
>  	{ .compatible = "nvmem-rmem" },
>  	{ .compatible = "google,open-dice" },
> +	{ .compatible = "bootstage" },
>  	{}
>  };
> 
> --
> 2.49.0
> 


^ 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