Skip to contentSkip to conversation

liveupdate: Rework KHO for in-kernel users

PATCH In review Pasha Tatashin 6 participants 42 messages Nov 1, 2025 – Nov 13, 2025

Subsystems (8)
lore
Share & tools
lore

Pasha Tatashin

author maintainer
#0 lore raw

v9 cover liveupdate: Rework KHO for in-kernel users

Changelog:
v9:
Added review-bys and addressed comments from Mike Rapoport and Pratyush Yadav.
Dropped patch that moves abort/finalize to public header per Mike's request.
Added patch from Zhu Yanjun to output errors by name.

This series appliyes against akpm's mm-unstable branch.

This series refactors the KHO framework to better support in-kernel users like the upcoming LUO. The current design, which relies on a notifier chain and debugfs for control, is too restrictive for direct programmatic use.

The core of this rework is the removal of the notifier chain in favor of a direct registration API. This decouples clients from the shutdown-time finalization sequence, allowing them to manage their preserved state more flexibly and at any time.

In support of this new model, this series also:
- Makes the debugfs interface optional.
- Introduces APIs to unpreserve memory and fixes a bug in the abort path where client state was being incorrectly discarded. Note that this is an interim step, as a more comprehensive fix is planned as part of the stateless KHO work [1].
- Moves all KHO code into a new kernel/liveupdate/ directory to consolidate live update components.

[1] https://lore.kernel.org/all/[email protected]

Mike Rapoport (Microsoft) (1):
kho: drop notifiers

Pasha Tatashin (7):
kho: make debugfs interface optional
kho: add interfaces to unpreserve folios, page ranges, and vmalloc
memblock: Unpreserve memory in case of error
test_kho: Unpreserve memory in case of error
kho: don't unpreserve memory during abort
liveupdate: kho: move to kernel/liveupdate
MAINTAINERS: update KHO maintainers

Zhu Yanjun (1):
liveupdate: kho: Use %pe format specifier for error pointer printing

 Documentation/core-api/kho/concepts.rst       |   2 +-
 MAINTAINERS                                   |   4 +-
 include/linux/kexec_handover.h                |  46 +-
 init/Kconfig                                  |   2 +
 kernel/Kconfig.kexec                          |  24 -
 kernel/Makefile                               |   3 +-
 kernel/kexec_handover_internal.h              |  16 -
 kernel/liveupdate/Kconfig                     |  39 ++
 kernel/liveupdate/Makefile                    |   5 +
 kernel/{ => liveupdate}/kexec_handover.c      | 532 +++++++-----------
 .../{ => liveupdate}/kexec_handover_debug.c   |   0
 kernel/liveupdate/kexec_handover_debugfs.c    | 221 ++++++++
 kernel/liveupdate/kexec_handover_internal.h   |  56 ++
 lib/test_kho.c                                | 128 +++--
 mm/memblock.c                                 |  93 +--
 tools/testing/selftests/kho/vmtest.sh         |   1 +
 16 files changed, 690 insertions(+), 482 deletions(-)
 delete mode 100644 kernel/kexec_handover_internal.h
 create mode 100644 kernel/liveupdate/Kconfig
 create mode 100644 kernel/liveupdate/Makefile
 rename kernel/{ => liveupdate}/kexec_handover.c (80%)
 rename kernel/{ => liveupdate}/kexec_handover_debug.c (100%)
 create mode 100644 kernel/liveupdate/kexec_handover_debugfs.c
 create mode 100644 kernel/liveupdate/kexec_handover_internal.h

base-commit: 9ef7b034116354ee75502d1849280a4d2ff98a7c

Signature · 1 line
2.51.1.930.gacf6e81ea2-goog
author maintainer
#1 lore raw

PATCH v9 1/9 kho: make debugfs interface optional

Currently, KHO is controlled via debugfs interface, but once LUO is introduced, it can control KHO, and the debug interface becomes optional.

Add a separate config CONFIG_KEXEC_HANDOVER_DEBUGFS that enables the debugfs interface, and allows to inspect the tree.

Move all debugfs related code to a new file to keep the .c files clear of ifdefs.

---
 MAINTAINERS                           |   2 +-
 kernel/Kconfig.kexec                  |  12 +-
 kernel/Makefile                       |   1 +
 kernel/kexec_handover.c               | 273 +++++---------------------
 kernel/kexec_handover_debugfs.c       | 216 ++++++++++++++++++++
 kernel/kexec_handover_internal.h      |  39 ++++
 tools/testing/selftests/kho/vmtest.sh |   1 +
 7 files changed, 320 insertions(+), 224 deletions(-)
 create mode 100644 kernel/kexec_handover_debugfs.c
MAINTAINERS +1 -1
index 2628431dcdfe..bdd0a1260421 100644
@@ -13795,7 +13795,7 @@ S:	Maintained
 F:	Documentation/admin-guide/mm/kho.rst
 F:	Documentation/core-api/kho/*
 F:	include/linux/kexec_handover.h
-F:	kernel/kexec_handover.c
+F:	kernel/kexec_handover*
 F:	tools/testing/selftests/kho/
 
 KEYS-ENCRYPTED
kernel/Kconfig.kexec +11 -1
index 54e581072617..cc6743137946 100644
@@ -100,7 +100,6 @@ config KEXEC_HANDOVER
 	depends on !DEFERRED_STRUCT_PAGE_INIT
 	select MEMBLOCK_KHO_SCRATCH
 	select KEXEC_FILE
-	select DEBUG_FS
 	select LIBFDT
 	select CMA
 	help
@@ -118,6 +117,17 @@ config KEXEC_HANDOVER_DEBUG
 	  scenarios and the extra code might be adding overhead it is
 	  only optionally enabled.
 
+config KEXEC_HANDOVER_DEBUGFS
+	bool "kexec handover debugfs interface"
+	default KEXEC_HANDOVER
+	depends on KEXEC_HANDOVER
+	select DEBUG_FS
+	help
+	  Allow to control kexec handover device tree via debugfs
+	  interface, i.e. finalize the state or aborting the finalization.
+	  Also, enables inspecting the KHO fdt trees with the debugfs binary
+	  blobs.
+
 config CRASH_DUMP
 	bool "kernel crash dumps"
 	default ARCH_DEFAULT_CRASH_DUMP
kernel/Makefile +1 -0
index 9fe722305c9b..2cf7909a74e5 100644
@@ -84,6 +84,7 @@ obj-$(CONFIG_KEXEC_FILE) += kexec_file.o
 obj-$(CONFIG_KEXEC_ELF) += kexec_elf.o
 obj-$(CONFIG_KEXEC_HANDOVER) += kexec_handover.o
 obj-$(CONFIG_KEXEC_HANDOVER_DEBUG) += kexec_handover_debug.o
+obj-$(CONFIG_KEXEC_HANDOVER_DEBUGFS) += kexec_handover_debugfs.o
 obj-$(CONFIG_BACKTRACE_SELF_TEST) += backtracetest.o
 obj-$(CONFIG_COMPAT) += compat.o
 obj-$(CONFIG_CGROUPS) += cgroup/
kernel/kexec_handover.c +51 -222

389 lines not on this page · raw message

kernel/kexec_handover_debugfs.c new file +216 -0

216 lines not on this page · raw message

kernel/kexec_handover_internal.h +39 -0
index 05e9720ba7b9..217b8b25a542 100644
@@ -2,8 +2,47 @@
 #ifndef LINUX_KEXEC_HANDOVER_INTERNAL_H
 #define LINUX_KEXEC_HANDOVER_INTERNAL_H
 
+#include <linux/kexec_handover.h>
+#include <linux/list.h>
 #include <linux/types.h>
 
+#ifdef CONFIG_KEXEC_HANDOVER_DEBUGFS
+#include <linux/debugfs.h>
+
+struct kho_debugfs {
+	struct dentry *dir;
+	struct dentry *sub_fdt_dir;
+	struct list_head fdt_list;
+};
+
+#else
+struct kho_debugfs {};
+#endif
+
+extern struct kho_scratch *kho_scratch;
+extern unsigned int kho_scratch_cnt;
+
+bool kho_finalized(void);
+int kho_finalize(void);
+int kho_abort(void);
+
+#ifdef CONFIG_KEXEC_HANDOVER_DEBUGFS
+int kho_debugfs_init(void);
+void kho_in_debugfs_init(struct kho_debugfs *dbg, const void *fdt);
+int kho_out_debugfs_init(struct kho_debugfs *dbg);
+int kho_debugfs_fdt_add(struct kho_debugfs *dbg, const char *name,
+			const void *fdt, bool root);
+void kho_debugfs_cleanup(struct kho_debugfs *dbg);
+#else
+static inline int kho_debugfs_init(void) { return 0; }
+static inline void kho_in_debugfs_init(struct kho_debugfs *dbg,
+				       const void *fdt) { }
+static inline int kho_out_debugfs_init(struct kho_debugfs *dbg) { return 0; }
+static inline int kho_debugfs_fdt_add(struct kho_debugfs *dbg, const char *name,
+				      const void *fdt, bool root) { return 0; }
+static inline void kho_debugfs_cleanup(struct kho_debugfs *dbg) {}
+#endif /* CONFIG_KEXEC_HANDOVER_DEBUGFS */
+
 #ifdef CONFIG_KEXEC_HANDOVER_DEBUG
 bool kho_scratch_overlap(phys_addr_t phys, size_t size);
 #else
tools/testing/selftests/kho/vmtest.sh +1 -0
index 3f6c17166846..49fdac8e8b15 100755
@@ -59,6 +59,7 @@ function build_kernel() {
 	tee "$kconfig" > "$kho_config" <<EOF
 CONFIG_BLK_DEV_INITRD=y
 CONFIG_KEXEC_HANDOVER=y
+CONFIG_KEXEC_HANDOVER_DEBUGFS=y
 CONFIG_TEST_KEXEC_HANDOVER=y
 CONFIG_DEBUG_KERNEL=y
 CONFIG_DEBUG_VM=y
Signature · 1 line
2.51.1.930.gacf6e81ea2-goog
#2 lore raw

Re: [PATCH v9 1/9] kho: make debugfs interface optional

Quoted 54 lines · Pasha Tatashin

Currently, KHO is controlled via debugfs interface, but once LUO is introduced, it can control KHO, and the debug interface becomes optional.

Add a separate config CONFIG_KEXEC_HANDOVER_DEBUGFS that enables the debugfs interface, and allows to inspect the tree.

Move all debugfs related code to a new file to keep the .c files clear of ifdefs.

---
  MAINTAINERS                           |   2 +-
  kernel/Kconfig.kexec                  |  12 +-
  kernel/Makefile                       |   1 +
  kernel/kexec_handover.c               | 273 +++++---------------------
  kernel/kexec_handover_debugfs.c       | 216 ++++++++++++++++++++
  kernel/kexec_handover_internal.h      |  39 ++++
  tools/testing/selftests/kho/vmtest.sh |   1 +
  7 files changed, 320 insertions(+), 224 deletions(-)

create mode 100644 kernel/kexec_handover_debugfs.c

MAINTAINERS +1 -1
index 2628431dcdfe..bdd0a1260421 100644
@@ -13795,7 +13795,7 @@ S:	Maintained
  F:	Documentation/admin-guide/mm/kho.rst
  F:	Documentation/core-api/kho/*
  F:	include/linux/kexec_handover.h
-F:	kernel/kexec_handover.c
+F:	kernel/kexec_handover*
  F:	tools/testing/selftests/kho/
 
  KEYS-ENCRYPTED
kernel/Kconfig.kexec +0 -1
index 54e581072617..cc6743137946 100644
@@ -100,7 +100,6 @@ config KEXEC_HANDOVER
  	depends on !DEFERRED_STRUCT_PAGE_INIT
  	select MEMBLOCK_KHO_SCRATCH
  	select KEXEC_FILE
-	select DEBUG_FS
  	select LIBFDT
  	select CMA
  	help
@@ -118,6 +117,17 @@ config KEXEC_HANDOVER_DEBUG
  	  scenarios and the extra code might be adding overhead it is
  	  only optionally enabled.
 

kernel/Kconfig.kexec config KEXEC_HANDOVER_DEBUG · line 129

Quoted 10 lines
kernel/Kconfig.kexec +10 -0
+config KEXEC_HANDOVER_DEBUGFS
+	bool "kexec handover debugfs interface"
+	default KEXEC_HANDOVER
+	depends on KEXEC_HANDOVER
+	select DEBUG_FS
+	help
+	  Allow to control kexec handover device tree via debugfs
+	  interface, i.e. finalize the state or aborting the finalization.
+	  Also, enables inspecting the KHO fdt trees with the debugfs binary
+	  blobs.

Hi, Pasha

In our previous discussion, we talked about counting the number of times the kernel is rebooted via kexec. At that time, you suggested adding a variable in debugfs to keep track of this count. However, since debugfs is now optional, where would be an appropriate place to store this variable?

BR,
Yanjun.Zhu

Quoted 708 lines
kernel/Kconfig.kexec +1 -0
+
  config CRASH_DUMP
  	bool "kernel crash dumps"
  	default ARCH_DEFAULT_CRASH_DUMP
kernel/Makefile +1 -0
index 9fe722305c9b..2cf7909a74e5 100644
@@ -84,6 +84,7 @@ obj-$(CONFIG_KEXEC_FILE) += kexec_file.o
  obj-$(CONFIG_KEXEC_ELF) += kexec_elf.o
  obj-$(CONFIG_KEXEC_HANDOVER) += kexec_handover.o
  obj-$(CONFIG_KEXEC_HANDOVER_DEBUG) += kexec_handover_debug.o
+obj-$(CONFIG_KEXEC_HANDOVER_DEBUGFS) += kexec_handover_debugfs.o
  obj-$(CONFIG_BACKTRACE_SELF_TEST) += backtracetest.o
  obj-$(CONFIG_COMPAT) += compat.o
  obj-$(CONFIG_CGROUPS) += cgroup/
kernel/kexec_handover.c +51 -222
index de4466b47455..da071277d85e 100644
@@ -11,7 +11,6 @@
  #include <linux/cleanup.h>
  #include <linux/cma.h>
  #include <linux/count_zeros.h>
-#include <linux/debugfs.h>
  #include <linux/kexec.h>
  #include <linux/kexec_handover.h>
  #include <linux/libfdt.h>
@@ -30,6 +29,7 @@
   */
  #include "../mm/internal.h"
  #include "kexec_internal.h"
+#include "kexec_handover_internal.h"
 
  #define KHO_FDT_COMPATIBLE "kho-v1"
  #define PROP_PRESERVED_MEMORY_MAP "preserved-memory-map"
@@ -105,8 +105,6 @@ struct khoser_mem_chunk;
 
  struct kho_serialization {
  	struct page *fdt;
-	struct list_head fdt_list;
-	struct dentry *sub_fdt_dir;
  	struct kho_mem_track track;
  	/* First chunk of serialized preserved memory map */
  	struct khoser_mem_chunk *preserved_mem_map;
@@ -114,20 +112,16 @@ struct kho_serialization {
 
  struct kho_out {
  	struct blocking_notifier_head chain_head;
-
-	struct dentry *dir;
-
  	struct mutex lock; /* protects KHO FDT finalization */
-
  	struct kho_serialization ser;
  	bool finalized;
+	struct kho_debugfs dbg;
  };
 
  static struct kho_out kho_out = {
  	.chain_head = BLOCKING_NOTIFIER_INIT(kho_out.chain_head),
  	.lock = __MUTEX_INITIALIZER(kho_out.lock),
  	.ser = {
-		.fdt_list = LIST_HEAD_INIT(kho_out.ser.fdt_list),
  		.track = {
  			.orders = XARRAY_INIT(kho_out.ser.track.orders, 0),
  		},
@@ -477,8 +471,8 @@ static void __init kho_mem_deserialize(const void *fdt)
   * area for early allocations that happen before page allocator is
   * initialized.
   */
-static struct kho_scratch *kho_scratch;
-static unsigned int kho_scratch_cnt;
+struct kho_scratch *kho_scratch;
+unsigned int kho_scratch_cnt;
 
  /*
   * The scratch areas are scaled by default as percent of memory allocated from
@@ -674,37 +668,6 @@ static void __init kho_reserve_scratch(void)
  	kho_enable = false;
  }
 
-struct fdt_debugfs {
-	struct list_head list;
-	struct debugfs_blob_wrapper wrapper;
-	struct dentry *file;
-};
-
-static int kho_debugfs_fdt_add(struct list_head *list, struct dentry *dir,
-			       const char *name, const void *fdt)
-{
-	struct fdt_debugfs *f;
-	struct dentry *file;
-
-	f = kmalloc(sizeof(*f), GFP_KERNEL);
-	if (!f)
-		return -ENOMEM;
-
-	f->wrapper.data = (void *)fdt;
-	f->wrapper.size = fdt_totalsize(fdt);
-
-	file = debugfs_create_blob(name, 0400, dir, &f->wrapper);
-	if (IS_ERR(file)) {
-		kfree(f);
-		return PTR_ERR(file);
-	}
-
-	f->file = file;
-	list_add(&f->list, list);
-
-	return 0;
-}
-
  /**
   * kho_add_subtree - record the physical address of a sub FDT in KHO root tree.
   * @ser: serialization control object passed by KHO notifiers.
@@ -716,7 +679,8 @@ static int kho_debugfs_fdt_add(struct list_head *list, struct dentry *dir,
   * by KHO for the new kernel to retrieve it after kexec.
   *
   * A debugfs blob entry is also created at
- * ``/sys/kernel/debug/kho/out/sub_fdts/@name``.
+ * ``/sys/kernel/debug/kho/out/sub_fdts/@name`` when kernel is configured with
+ * CONFIG_KEXEC_HANDOVER_DEBUGFS
   *
   * Return: 0 on success, error code on failure
   */
@@ -733,7 +697,7 @@ int kho_add_subtree(struct kho_serialization *ser, const char *name, void *fdt)
  	if (err)
  		return err;
 
-	return kho_debugfs_fdt_add(&ser->fdt_list, ser->sub_fdt_dir, name, fdt);
+	return kho_debugfs_fdt_add(&kho_out.dbg, name, fdt, false);
  }
  EXPORT_SYMBOL_GPL(kho_add_subtree);
 
@@ -1064,30 +1028,7 @@ void *kho_restore_vmalloc(const struct kho_vmalloc *preservation)
  }
  EXPORT_SYMBOL_GPL(kho_restore_vmalloc);
 
-/* Handling for debug/kho/out */
-
-static struct dentry *debugfs_root;
-
-static int kho_out_update_debugfs_fdt(void)
-{
-	int err = 0;
-	struct fdt_debugfs *ff, *tmp;
-
-	if (kho_out.finalized) {
-		err = kho_debugfs_fdt_add(&kho_out.ser.fdt_list, kho_out.dir,
-					  "fdt", page_to_virt(kho_out.ser.fdt));
-	} else {
-		list_for_each_entry_safe(ff, tmp, &kho_out.ser.fdt_list, list) {
-			debugfs_remove(ff->file);
-			list_del(&ff->list);
-			kfree(ff);
-		}
-	}
-
-	return err;
-}
-
-static int kho_abort(void)
+static int __kho_abort(void)
  {
  	int err;
  	unsigned long order;
@@ -1120,7 +1061,28 @@ static int kho_abort(void)
  	return err;
  }
 
-static int kho_finalize(void)
+int kho_abort(void)
+{
+	int ret = 0;
+
+	if (!kho_enable)
+		return -EOPNOTSUPP;
+
+	guard(mutex)(&kho_out.lock);
+	if (!kho_out.finalized)
+		return -ENOENT;
+
+	ret = __kho_abort();
+	if (ret)
+		return ret;
+
+	kho_out.finalized = false;
+	kho_debugfs_cleanup(&kho_out.dbg);
+
+	return 0;
+}
+
+static int __kho_finalize(void)
  {
  	int err = 0;
  	u64 *preserved_mem_map;
@@ -1163,118 +1125,46 @@ static int kho_finalize(void)
  abort:
  	if (err) {
  		pr_err("Failed to convert KHO state tree: %d\n", err);
-		kho_abort();
+		__kho_abort();
  	}
 
  	return err;
  }
 
-static int kho_out_finalize_get(void *data, u64 *val)
+int kho_finalize(void)
  {
-	mutex_lock(&kho_out.lock);
-	*val = kho_out.finalized;
-	mutex_unlock(&kho_out.lock);
-
-	return 0;
-}
-
-static int kho_out_finalize_set(void *data, u64 _val)
-{
-	int ret = 0;
-	bool val = !!_val;
-
-	mutex_lock(&kho_out.lock);
+	int ret;
 
-	if (val == kho_out.finalized) {
-		if (kho_out.finalized)
-			ret = -EEXIST;
-		else
-			ret = -ENOENT;
-		goto unlock;
-	}
+	if (!kho_enable)
+		return -EOPNOTSUPP;
 
-	if (val)
-		ret = kho_finalize();
-	else
-		ret = kho_abort();
+	guard(mutex)(&kho_out.lock);
+	if (kho_out.finalized)
+		return -EEXIST;
 
+	ret = __kho_finalize();
  	if (ret)
-		goto unlock;
-
-	kho_out.finalized = val;
-	ret = kho_out_update_debugfs_fdt();
-
-unlock:
-	mutex_unlock(&kho_out.lock);
-	return ret;
-}
-
-DEFINE_DEBUGFS_ATTRIBUTE(fops_kho_out_finalize, kho_out_finalize_get,
-			 kho_out_finalize_set, "%llu\n");
-
-static int scratch_phys_show(struct seq_file *m, void *v)
-{
-	for (int i = 0; i < kho_scratch_cnt; i++)
-		seq_printf(m, "0x%llx\n", kho_scratch[i].addr);
-
-	return 0;
-}
-DEFINE_SHOW_ATTRIBUTE(scratch_phys);
+		return ret;
 
-static int scratch_len_show(struct seq_file *m, void *v)
-{
-	for (int i = 0; i < kho_scratch_cnt; i++)
-		seq_printf(m, "0x%llx\n", kho_scratch[i].size);
+	kho_out.finalized = true;
 
-	return 0;
+	return kho_debugfs_fdt_add(&kho_out.dbg, "fdt",
+				   page_to_virt(kho_out.ser.fdt), true);
  }
-DEFINE_SHOW_ATTRIBUTE(scratch_len);
 
-static __init int kho_out_debugfs_init(void)
+bool kho_finalized(void)
  {
-	struct dentry *dir, *f, *sub_fdt_dir;
-
-	dir = debugfs_create_dir("out", debugfs_root);
-	if (IS_ERR(dir))
-		return -ENOMEM;
-
-	sub_fdt_dir = debugfs_create_dir("sub_fdts", dir);
-	if (IS_ERR(sub_fdt_dir))
-		goto err_rmdir;
-
-	f = debugfs_create_file("scratch_phys", 0400, dir, NULL,
-				&scratch_phys_fops);
-	if (IS_ERR(f))
-		goto err_rmdir;
-
-	f = debugfs_create_file("scratch_len", 0400, dir, NULL,
-				&scratch_len_fops);
-	if (IS_ERR(f))
-		goto err_rmdir;
-
-	f = debugfs_create_file("finalize", 0600, dir, NULL,
-				&fops_kho_out_finalize);
-	if (IS_ERR(f))
-		goto err_rmdir;
-
-	kho_out.dir = dir;
-	kho_out.ser.sub_fdt_dir = sub_fdt_dir;
-	return 0;
-
-err_rmdir:
-	debugfs_remove_recursive(dir);
-	return -ENOENT;
+	guard(mutex)(&kho_out.lock);
+	return kho_out.finalized;
  }
 
  struct kho_in {
-	struct dentry *dir;
  	phys_addr_t fdt_phys;
  	phys_addr_t scratch_phys;
-	struct list_head fdt_list;
+	struct kho_debugfs dbg;
  };
 
  static struct kho_in kho_in = {
-	.fdt_list = LIST_HEAD_INIT(kho_in.fdt_list),
  };
 
  static const void *kho_get_fdt(void)
@@ -1338,56 +1228,6 @@ int kho_retrieve_subtree(const char *name, phys_addr_t *phys)
  }
  EXPORT_SYMBOL_GPL(kho_retrieve_subtree);
 
-/* Handling for debugfs/kho/in */
-
-static __init int kho_in_debugfs_init(const void *fdt)
-{
-	struct dentry *sub_fdt_dir;
-	int err, child;
-
-	kho_in.dir = debugfs_create_dir("in", debugfs_root);
-	if (IS_ERR(kho_in.dir))
-		return PTR_ERR(kho_in.dir);
-
-	sub_fdt_dir = debugfs_create_dir("sub_fdts", kho_in.dir);
-	if (IS_ERR(sub_fdt_dir)) {
-		err = PTR_ERR(sub_fdt_dir);
-		goto err_rmdir;
-	}
-
-	err = kho_debugfs_fdt_add(&kho_in.fdt_list, kho_in.dir, "fdt", fdt);
-	if (err)
-		goto err_rmdir;
-
-	fdt_for_each_subnode(child, fdt, 0) {
-		int len = 0;
-		const char *name = fdt_get_name(fdt, child, NULL);
-		const u64 *fdt_phys;
-
-		fdt_phys = fdt_getprop(fdt, child, "fdt", &len);
-		if (!fdt_phys)
-			continue;
-		if (len != sizeof(*fdt_phys)) {
-			pr_warn("node `%s`'s prop `fdt` has invalid length: %d\n",
-				name, len);
-			continue;
-		}
-		err = kho_debugfs_fdt_add(&kho_in.fdt_list, sub_fdt_dir, name,
-					  phys_to_virt(*fdt_phys));
-		if (err) {
-			pr_warn("failed to add fdt `%s` to debugfs: %d\n", name,
-				err);
-			continue;
-		}
-	}
-
-	return 0;
-
-err_rmdir:
-	debugfs_remove_recursive(kho_in.dir);
-	return err;
-}
-
  static __init int kho_init(void)
  {
  	int err = 0;
@@ -1402,27 +1242,16 @@ static __init int kho_init(void)
  		goto err_free_scratch;
  	}
 
-	debugfs_root = debugfs_create_dir("kho", NULL);
-	if (IS_ERR(debugfs_root)) {
-		err = -ENOENT;
+	err = kho_debugfs_init();
+	if (err)
  		goto err_free_fdt;
-	}
 
-	err = kho_out_debugfs_init();
+	err = kho_out_debugfs_init(&kho_out.dbg);
  	if (err)
  		goto err_free_fdt;
 
  	if (fdt) {
-		err = kho_in_debugfs_init(fdt);
-		/*
-		 * Failure to create /sys/kernel/debug/kho/in does not prevent
-		 * reviving state from KHO and setting up KHO for the next
-		 * kexec.
-		 */
-		if (err)
-			pr_err("failed exposing handover FDT in debugfs: %d\n",
-			       err);
-
+		kho_in_debugfs_init(&kho_in.dbg, fdt);
  		return 0;
  	}
 
kernel/kexec_handover_debugfs.c new file +216 -0
new file mode 100644
index 000000000000..a91b279f1b23
@@ -0,0 +1,216 @@
+// SPDX-License-Identifier: GPL-2.0-only
+/*
+ * kexec_handover_debugfs.c - kexec handover debugfs interfaces
+ * Copyright (C) 2023 Alexander Graf <[email protected]>
+ * Copyright (C) 2025 Microsoft Corporation, Mike Rapoport <[email protected]>
+ * Copyright (C) 2025 Google LLC, Changyuan Lyu <[email protected]>
+ * Copyright (C) 2025 Google LLC, Pasha Tatashin <[email protected]>
+ */
+
+#define pr_fmt(fmt) "KHO: " fmt
+
+#include <linux/init.h>
+#include <linux/io.h>
+#include <linux/libfdt.h>
+#include <linux/mm.h>
+#include "kexec_handover_internal.h"
+
+static struct dentry *debugfs_root;
+
+struct fdt_debugfs {
+	struct list_head list;
+	struct debugfs_blob_wrapper wrapper;
+	struct dentry *file;
+};
+
+static int __kho_debugfs_fdt_add(struct list_head *list, struct dentry *dir,
+				 const char *name, const void *fdt)
+{
+	struct fdt_debugfs *f;
+	struct dentry *file;
+
+	f = kmalloc(sizeof(*f), GFP_KERNEL);
+	if (!f)
+		return -ENOMEM;
+
+	f->wrapper.data = (void *)fdt;
+	f->wrapper.size = fdt_totalsize(fdt);
+
+	file = debugfs_create_blob(name, 0400, dir, &f->wrapper);
+	if (IS_ERR(file)) {
+		kfree(f);
+		return PTR_ERR(file);
+	}
+
+	f->file = file;
+	list_add(&f->list, list);
+
+	return 0;
+}
+
+int kho_debugfs_fdt_add(struct kho_debugfs *dbg, const char *name,
+			const void *fdt, bool root)
+{
+	struct dentry *dir;
+
+	if (root)
+		dir = dbg->dir;
+	else
+		dir = dbg->sub_fdt_dir;
+
+	return __kho_debugfs_fdt_add(&dbg->fdt_list, dir, name, fdt);
+}
+
+void kho_debugfs_cleanup(struct kho_debugfs *dbg)
+{
+	struct fdt_debugfs *ff, *tmp;
+
+	list_for_each_entry_safe(ff, tmp, &dbg->fdt_list, list) {
+		debugfs_remove(ff->file);
+		list_del(&ff->list);
+		kfree(ff);
+	}
+}
+
+static int kho_out_finalize_get(void *data, u64 *val)
+{
+	*val = kho_finalized();
+
+	return 0;
+}
+
+static int kho_out_finalize_set(void *data, u64 val)
+{
+	if (val)
+		return kho_finalize();
+	else
+		return kho_abort();
+}
+
+DEFINE_DEBUGFS_ATTRIBUTE(kho_out_finalize_fops, kho_out_finalize_get,
+			 kho_out_finalize_set, "%llu\n");
+
+static int scratch_phys_show(struct seq_file *m, void *v)
+{
+	for (int i = 0; i < kho_scratch_cnt; i++)
+		seq_printf(m, "0x%llx\n", kho_scratch[i].addr);
+
+	return 0;
+}
+DEFINE_SHOW_ATTRIBUTE(scratch_phys);
+
+static int scratch_len_show(struct seq_file *m, void *v)
+{
+	for (int i = 0; i < kho_scratch_cnt; i++)
+		seq_printf(m, "0x%llx\n", kho_scratch[i].size);
+
+	return 0;
+}
+DEFINE_SHOW_ATTRIBUTE(scratch_len);
+
+__init void kho_in_debugfs_init(struct kho_debugfs *dbg, const void *fdt)
+{
+	struct dentry *dir, *sub_fdt_dir;
+	int err, child;
+
+	INIT_LIST_HEAD(&dbg->fdt_list);
+
+	dir = debugfs_create_dir("in", debugfs_root);
+	if (IS_ERR(dir)) {
+		err = PTR_ERR(dir);
+		goto err_out;
+	}
+
+	sub_fdt_dir = debugfs_create_dir("sub_fdts", dir);
+	if (IS_ERR(sub_fdt_dir)) {
+		err = PTR_ERR(sub_fdt_dir);
+		goto err_rmdir;
+	}
+
+	err = __kho_debugfs_fdt_add(&dbg->fdt_list, dir, "fdt", fdt);
+	if (err)
+		goto err_rmdir;
+
+	fdt_for_each_subnode(child, fdt, 0) {
+		int len = 0;
+		const char *name = fdt_get_name(fdt, child, NULL);
+		const u64 *fdt_phys;
+
+		fdt_phys = fdt_getprop(fdt, child, "fdt", &len);
+		if (!fdt_phys)
+			continue;
+		if (len != sizeof(*fdt_phys)) {
+			pr_warn("node %s prop fdt has invalid length: %d\n",
+				name, len);
+			continue;
+		}
+		err = __kho_debugfs_fdt_add(&dbg->fdt_list, sub_fdt_dir, name,
+					    phys_to_virt(*fdt_phys));
+		if (err) {
+			pr_warn("failed to add fdt %s to debugfs: %d\n", name,
+				err);
+			continue;
+		}
+	}
+
+	dbg->dir = dir;
+	dbg->sub_fdt_dir = sub_fdt_dir;
+
+	return;
+err_rmdir:
+	debugfs_remove_recursive(dir);
+err_out:
+	/*
+	 * Failure to create /sys/kernel/debug/kho/in does not prevent
+	 * reviving state from KHO and setting up KHO for the next
+	 * kexec.
+	 */
+	if (err)
+		pr_err("failed exposing handover FDT in debugfs: %d\n", err);
+}
+
+__init int kho_out_debugfs_init(struct kho_debugfs *dbg)
+{
+	struct dentry *dir, *f, *sub_fdt_dir;
+
+	INIT_LIST_HEAD(&dbg->fdt_list);
+
+	dir = debugfs_create_dir("out", debugfs_root);
+	if (IS_ERR(dir))
+		return -ENOMEM;
+
+	sub_fdt_dir = debugfs_create_dir("sub_fdts", dir);
+	if (IS_ERR(sub_fdt_dir))
+		goto err_rmdir;
+
+	f = debugfs_create_file("scratch_phys", 0400, dir, NULL,
+				&scratch_phys_fops);
+	if (IS_ERR(f))
+		goto err_rmdir;
+
+	f = debugfs_create_file("scratch_len", 0400, dir, NULL,
+				&scratch_len_fops);
+	if (IS_ERR(f))
+		goto err_rmdir;
+
+	f = debugfs_create_file("finalize", 0600, dir, NULL,
+				&kho_out_finalize_fops);
+	if (IS_ERR(f))
+		goto err_rmdir;
+
+	dbg->dir = dir;
+	dbg->sub_fdt_dir = sub_fdt_dir;
+	return 0;
+
+err_rmdir:
+	debugfs_remove_recursive(dir);
+	return -ENOENT;
+}
+
+__init int kho_debugfs_init(void)
+{
+	debugfs_root = debugfs_create_dir("kho", NULL);
+	if (IS_ERR(debugfs_root))
+		return -ENOENT;
+	return 0;
+}
kernel/kexec_handover_internal.h +39 -0
index 05e9720ba7b9..217b8b25a542 100644
@@ -2,8 +2,47 @@
  #ifndef LINUX_KEXEC_HANDOVER_INTERNAL_H
  #define LINUX_KEXEC_HANDOVER_INTERNAL_H
 
+#include <linux/kexec_handover.h>
+#include <linux/list.h>
  #include <linux/types.h>
 
+#ifdef CONFIG_KEXEC_HANDOVER_DEBUGFS
+#include <linux/debugfs.h>
+
+struct kho_debugfs {
+	struct dentry *dir;
+	struct dentry *sub_fdt_dir;
+	struct list_head fdt_list;
+};
+
+#else
+struct kho_debugfs {};
+#endif
+
+extern struct kho_scratch *kho_scratch;
+extern unsigned int kho_scratch_cnt;
+
+bool kho_finalized(void);
+int kho_finalize(void);
+int kho_abort(void);
+
+#ifdef CONFIG_KEXEC_HANDOVER_DEBUGFS
+int kho_debugfs_init(void);
+void kho_in_debugfs_init(struct kho_debugfs *dbg, const void *fdt);
+int kho_out_debugfs_init(struct kho_debugfs *dbg);
+int kho_debugfs_fdt_add(struct kho_debugfs *dbg, const char *name,
+			const void *fdt, bool root);
+void kho_debugfs_cleanup(struct kho_debugfs *dbg);
+#else
+static inline int kho_debugfs_init(void) { return 0; }
+static inline void kho_in_debugfs_init(struct kho_debugfs *dbg,
+				       const void *fdt) { }
+static inline int kho_out_debugfs_init(struct kho_debugfs *dbg) { return 0; }
+static inline int kho_debugfs_fdt_add(struct kho_debugfs *dbg, const char *name,
+				      const void *fdt, bool root) { return 0; }
+static inline void kho_debugfs_cleanup(struct kho_debugfs *dbg) {}
+#endif /* CONFIG_KEXEC_HANDOVER_DEBUGFS */
+
  #ifdef CONFIG_KEXEC_HANDOVER_DEBUG
  bool kho_scratch_overlap(phys_addr_t phys, size_t size);
  #else
tools/testing/selftests/kho/vmtest.sh +1 -0
index 3f6c17166846..49fdac8e8b15 100755
@@ -59,6 +59,7 @@ function build_kernel() {
  	tee "$kconfig" > "$kho_config" <<EOF
  CONFIG_BLK_DEV_INITRD=y
  CONFIG_KEXEC_HANDOVER=y
+CONFIG_KEXEC_HANDOVER_DEBUGFS=y
  CONFIG_TEST_KEXEC_HANDOVER=y
  CONFIG_DEBUG_KERNEL=y
  CONFIG_DEBUG_VM=y
author maintainer
#3 lore raw

Re: [PATCH v9 1/9] kho: make debugfs interface optional

Quoted 7 lines

Hi, Pasha

In our previous discussion, we talked about counting the number of times the kernel is rebooted via kexec. At that time, you suggested adding a variable in debugfs to keep track of this count.
However, since debugfs is now optional, where would be an appropriate place to store this variable?

It is an optional config and can still be enabled if the live update reboot number value needs to be accessed through debugfs. However, given that debugfs does not guarantee a stable interface, tooling should not be built to require these interfaces.

In the WIP LUO [1] I have, I pr_info() the live update number during boot and also store it in the incoming LUO FDT tree, which can also be accessed through this optional debugfs interface.

The pr_info message appears like this during boot:

[    0.000000] luo: Retrieved live update data, liveupdate number: 17

Pasha

author maintainer
#4 lore raw

Re: [PATCH v9 1/9] kho: make debugfs interface optional

Quoted 14 lines · Pasha Tatashin
Quoted 8 lines

Hi, Pasha

In our previous discussion, we talked about counting the number of times the kernel is rebooted via kexec. At that time, you suggested adding a variable in debugfs to keep track of this count.
However, since debugfs is now optional, where would be an appropriate place to store this variable?

It is an optional config and can still be enabled if the live update reboot number value needs to be accessed through debugfs. However, given that debugfs does not guarantee a stable interface, tooling should not be built to require these interfaces.

Quoted 8 lines

In the WIP LUO [1] I have, I pr_info() the live update number during boot and also store it in the incoming LUO FDT tree, which can also be accessed through this optional debugfs interface.

The pr_info message appears like this during boot:

[    0.000000] luo: Retrieved live update data, liveupdate number: 17

Pasha

Forgot to add link to WIP LUOv5:
[1] https://github.com/soleen/linux/tree/luo/v5rc04

#5 lore raw

Re: [PATCH v9 1/9] kho: make debugfs interface optional

Quoted 17 lines · Pasha Tatashin
Quoted 16 lines · Pasha Tatashin
Quoted 7 lines

Hi, Pasha

In our previous discussion, we talked about counting the number of times the kernel is rebooted via kexec. At that time, you suggested adding a variable in debugfs to keep track of this count.
However, since debugfs is now optional, where would be an appropriate place to store this variable?

It is an optional config and can still be enabled if the live update reboot number value needs to be accessed through debugfs. However, given that debugfs does not guarantee a stable interface, tooling should not be built to require these interfaces.

In the WIP LUO [1] I have, I pr_info() the live update number during boot and also store it in the incoming LUO FDT tree, which can also be accessed through this optional debugfs interface.

Quoted 6 lines
Quoted 4 lines

The pr_info message appears like this during boot:

[    0.000000] luo: Retrieved live update data, liveupdate number: 17

Pasha

Forgot to add link to WIP LUOv5:
[1] https://github.com/soleen/linux/tree/luo/v5rc04

Thanks a lot. I’ve carefully read this commit: https://github.com/soleen/linux/commit/60205b9a95c319dc9965f119303a1d83f0ff08fa.

To be honest, I’d like to run some tests with who/luo, including the selftest for kho/luo. Could you please share the steps with me?

If the testing steps have already been documented somewhere, could you please share the link?

Best Regards,

Yanjun.Zhu

author maintainer
#6 lore raw

Re: [PATCH v9 1/9] kho: make debugfs interface optional

Quoted 28 lines · Yanjun.Zhu
Quoted 17 lines · Pasha Tatashin
Quoted 16 lines · Pasha Tatashin
Quoted 7 lines

Hi, Pasha

In our previous discussion, we talked about counting the number of times the kernel is rebooted via kexec. At that time, you suggested adding a variable in debugfs to keep track of this count.
However, since debugfs is now optional, where would be an appropriate place to store this variable?

It is an optional config and can still be enabled if the live update reboot number value needs to be accessed through debugfs. However, given that debugfs does not guarantee a stable interface, tooling should not be built to require these interfaces.

In the WIP LUO [1] I have, I pr_info() the live update number during boot and also store it in the incoming LUO FDT tree, which can also be accessed through this optional debugfs interface.

Quoted 6 lines
Quoted 4 lines

The pr_info message appears like this during boot:

[    0.000000] luo: Retrieved live update data, liveupdate number: 17

Pasha

Forgot to add link to WIP LUOv5:
[1] https://github.com/soleen/linux/tree/luo/v5rc04

Quoted 8 lines

Thanks a lot. I’ve carefully read this commit:
https://github.com/soleen/linux/commit/60205b9a95c319dc9965f119303a1d83f0ff08fa.

To be honest, I’d like to run some tests with who/luo, including the selftest for kho/luo. Could you please share the steps with me?

If the testing steps have already been documented somewhere, could you please share the link?

Currently the test performs in-kernel tests for FLB data, it creates a number of FLB for every registered LUO file-handler, which at the moment is only memfd.

It works together with any of the kexec based live update tests. In v5, I introduce two tests:
luo_kexec_simple
luo_multi_session

For example, with luo_multi_session:

# ./luo_multi_session
# [STAGE 1] Starting pre-kexec setup for multi-session test...
# [STAGE 1] Creating state file for next stage (2)...
# [STAGE 1] Creating empty sessions 'multi-test-empty-1' and
'multi-test-empty-2'...
# [STAGE 1] Creating session 'multi-test-files-1' with one memfd...
# [STAGE 1] Creating session 'multi-test-files-2' with two memfds...
# [STAGE 1] Executing kexec...

... reboot ...
After reboot:

$ ./luo_multi_session
# [STAGE 2] Starting post-kexec verification...
# [STAGE 2] Retrieving all sessions...
# [STAGE 2] Verifying contents of session 'multi-test-files-1'...
# [STAGE 2] Verifying contents of session 'multi-test-files-2'...
# [STAGE 2] Test data verified successfully.
# [STAGE 2] Finalizing all test sessions...
# [STAGE 2] Finalizing state session...
#
--- MULTI-SESSION KEXEC TEST PASSED ---

Dmesg data, shows that in-kernel live update test was also successful:

[    0.000000] luo: Retrieved live update data, liveupdate number: 1
[    0.034513] liveupdate test: test-flb-v0: found flb data from the
previous boot
[    0.034517] liveupdate test: test-flb-v1: found flb data from the
previous boot
[    0.034518] liveupdate test: test-flb-v2: found flb data from the
previous boot
[    0.676891] liveupdate test: Registered 3 FLBs with file handler: [memfd-v1]

Pasha

Quoted 4 lines

Best Regards,

Yanjun.Zhu

#7 lore raw

Re: [PATCH v9 1/9] kho: make debugfs interface optional

Quoted 39 lines · Pasha Tatashin
Quoted 26 lines · Yanjun.Zhu
Quoted 17 lines · Pasha Tatashin
Quoted 16 lines · Pasha Tatashin
Quoted 7 lines

Hi, Pasha

In our previous discussion, we talked about counting the number of times the kernel is rebooted via kexec. At that time, you suggested adding a variable in debugfs to keep track of this count.
However, since debugfs is now optional, where would be an appropriate place to store this variable?

It is an optional config and can still be enabled if the live update reboot number value needs to be accessed through debugfs. However, given that debugfs does not guarantee a stable interface, tooling should not be built to require these interfaces.

In the WIP LUO [1] I have, I pr_info() the live update number during boot and also store it in the incoming LUO FDT tree, which can also be accessed through this optional debugfs interface.

Quoted 6 lines
Quoted 4 lines

The pr_info message appears like this during boot:

[    0.000000] luo: Retrieved live update data, liveupdate number: 17

Pasha

Forgot to add link to WIP LUOv5:
[1] https://github.com/soleen/linux/tree/luo/v5rc04

Quoted 8 lines

Thanks a lot. I’ve carefully read this commit:
https://github.com/soleen/linux/commit/60205b9a95c319dc9965f119303a1d83f0ff08fa.

To be honest, I’d like to run some tests with who/luo, including the selftest for kho/luo. Could you please share the steps with me?

If the testing steps have already been documented somewhere, could you please share the link?

Currently the test performs in-kernel tests for FLB data, it creates a number of FLB for every registered LUO file-handler, which at the moment is only memfd.

Quoted 6 lines

It works together with any of the kexec based live update tests. In v5, I introduce two tests:
luo_kexec_simple
luo_multi_session

For example, with luo_multi_session:

Hi, Pasha

I enabled "CONFIG_LIVEUPDATE=y"

# ./luo_multi_session
1..0 # SKIP Failed to open /dev/liveupdate. Is the luo module loaded?
# ls /dev/liveupdate
ls: cannot access '/dev/liveupdate': No such file or directory
# grep "LIVEUPDATE" -inrHI /boot/config-`uname -r`
/boot/config-next-20251107-luo+:349:CONFIG_LIVEUPDATE=y
/boot/config-next-20251107-luo+:11985:CONFIG_LIVEUPDATE_TEST=y

I made tests on FC42. But /dev/liveupdate is missing.

Thanks

Yanjun.Zhu

Quoted 40 lines
# ./luo_multi_session
# [STAGE 1] Starting pre-kexec setup for multi-session test...
# [STAGE 1] Creating state file for next stage (2)...
# [STAGE 1] Creating empty sessions 'multi-test-empty-1' and
'multi-test-empty-2'...
# [STAGE 1] Creating session 'multi-test-files-1' with one memfd...
# [STAGE 1] Creating session 'multi-test-files-2' with two memfds...
# [STAGE 1] Executing kexec...

... reboot ...
After reboot:

$ ./luo_multi_session
# [STAGE 2] Starting post-kexec verification...
# [STAGE 2] Retrieving all sessions...
# [STAGE 2] Verifying contents of session 'multi-test-files-1'...
# [STAGE 2] Verifying contents of session 'multi-test-files-2'...
# [STAGE 2] Test data verified successfully.
# [STAGE 2] Finalizing all test sessions...
# [STAGE 2] Finalizing state session...
#
--- MULTI-SESSION KEXEC TEST PASSED ---

Dmesg data, shows that in-kernel live update test was also successful:

[    0.000000] luo: Retrieved live update data, liveupdate number: 1
[    0.034513] liveupdate test: test-flb-v0: found flb data from the
previous boot
[    0.034517] liveupdate test: test-flb-v1: found flb data from the
previous boot
[    0.034518] liveupdate test: test-flb-v2: found flb data from the
previous boot
[    0.676891] liveupdate test: Registered 3 FLBs with file handler: [memfd-v1]

Pasha

Quoted 4 lines

Best Regards,

Yanjun.Zhu

Signature · 2 lines
Best Regards,
Yanjun.Zhu
maintainer
#8 lore raw

Re: [PATCH v9 1/9] kho: make debugfs interface optional

Quoted 54 lines · Zhu Yanjun
Quoted 39 lines · Pasha Tatashin
Quoted 26 lines · Yanjun.Zhu
Quoted 17 lines · Pasha Tatashin
Quoted 16 lines · Pasha Tatashin
Quoted 7 lines

Hi, Pasha

In our previous discussion, we talked about counting the number of times the kernel is rebooted via kexec. At that time, you suggested adding a variable in debugfs to keep track of this count.
However, since debugfs is now optional, where would be an appropriate place to store this variable?

It is an optional config and can still be enabled if the live update reboot number value needs to be accessed through debugfs. However, given that debugfs does not guarantee a stable interface, tooling should not be built to require these interfaces.

In the WIP LUO [1] I have, I pr_info() the live update number during boot and also store it in the incoming LUO FDT tree, which can also be accessed through this optional debugfs interface.

Quoted 6 lines
Quoted 4 lines

The pr_info message appears like this during boot:

[    0.000000] luo: Retrieved live update data, liveupdate number: 17

Pasha

Forgot to add link to WIP LUOv5:
[1] https://github.com/soleen/linux/tree/luo/v5rc04

Quoted 8 lines

Thanks a lot. I’ve carefully read this commit:
https://github.com/soleen/linux/commit/60205b9a95c319dc9965f119303a1d83f0ff08fa.

To be honest, I’d like to run some tests with who/luo, including the selftest for kho/luo. Could you please share the steps with me?

If the testing steps have already been documented somewhere, could you please share the link?

Currently the test performs in-kernel tests for FLB data, it creates a number of FLB for every registered LUO file-handler, which at the moment is only memfd.

Quoted 6 lines

It works together with any of the kexec based live update tests. In v5, I introduce two tests:
luo_kexec_simple
luo_multi_session

For example, with luo_multi_session:

Hi, Pasha

I enabled "CONFIG_LIVEUPDATE=y"

# ./luo_multi_session
1..0 # SKIP Failed to open /dev/liveupdate. Is the luo module loaded?
Quoted 8 lines
# ls /dev/liveupdate
ls: cannot access '/dev/liveupdate': No such file or directory
# grep "LIVEUPDATE" -inrHI /boot/config-`uname -r`
/boot/config-next-20251107-luo+:349:CONFIG_LIVEUPDATE=y
/boot/config-next-20251107-luo+:11985:CONFIG_LIVEUPDATE_TEST=y

I made tests on FC42. But /dev/liveupdate is missing.

You need to add liveupdate=1 to your kernel cmdline to enable LUO and get /dev/liveupdate.

Pasha, your LUO series doesn't add the liveupdate parameter to kernel-parameters.txt. I think it should be done in the next version to this parameter is discoverable.

Signature · 2 lines
Regards,
Pratyush Yadav
author maintainer
#9 lore raw

Re: [PATCH v9 1/9] kho: make debugfs interface optional

Quoted 60 lines · Pratyush Yadav
Quoted 57 lines · Zhu Yanjun
Quoted 39 lines · Pasha Tatashin
Quoted 26 lines · Yanjun.Zhu
Quoted 17 lines · Pasha Tatashin
Quoted 16 lines · Pasha Tatashin
Quoted 7 lines

Hi, Pasha

In our previous discussion, we talked about counting the number of times the kernel is rebooted via kexec. At that time, you suggested adding a variable in debugfs to keep track of this count.
However, since debugfs is now optional, where would be an appropriate place to store this variable?

It is an optional config and can still be enabled if the live update reboot number value needs to be accessed through debugfs. However, given that debugfs does not guarantee a stable interface, tooling should not be built to require these interfaces.

In the WIP LUO [1] I have, I pr_info() the live update number during boot and also store it in the incoming LUO FDT tree, which can also be accessed through this optional debugfs interface.

Quoted 6 lines
Quoted 4 lines

The pr_info message appears like this during boot:

[    0.000000] luo: Retrieved live update data, liveupdate number: 17

Pasha

Forgot to add link to WIP LUOv5:
[1] https://github.com/soleen/linux/tree/luo/v5rc04

Quoted 8 lines

Thanks a lot. I’ve carefully read this commit:
https://github.com/soleen/linux/commit/60205b9a95c319dc9965f119303a1d83f0ff08fa.

To be honest, I’d like to run some tests with who/luo, including the selftest for kho/luo. Could you please share the steps with me?

If the testing steps have already been documented somewhere, could you please share the link?

Currently the test performs in-kernel tests for FLB data, it creates a number of FLB for every registered LUO file-handler, which at the moment is only memfd.

Quoted 6 lines

It works together with any of the kexec based live update tests. In v5, I introduce two tests:
luo_kexec_simple
luo_multi_session

For example, with luo_multi_session:

Hi, Pasha

I enabled "CONFIG_LIVEUPDATE=y"

# ./luo_multi_session
1..0 # SKIP Failed to open /dev/liveupdate. Is the luo module loaded?
# ls /dev/liveupdate
ls: cannot access '/dev/liveupdate': No such file or directory
Quoted 8 lines
Quoted 5 lines
# grep "LIVEUPDATE" -inrHI /boot/config-`uname -r`
/boot/config-next-20251107-luo+:349:CONFIG_LIVEUPDATE=y
/boot/config-next-20251107-luo+:11985:CONFIG_LIVEUPDATE_TEST=y

I made tests on FC42. But /dev/liveupdate is missing.

You need to add liveupdate=1 to your kernel cmdline to enable LUO and get /dev/liveupdate.

+1, kernel parameters require: kho=1 liveupdate=1

Quoted 4 lines

Pasha, your LUO series doesn't add the liveupdate parameter to kernel-parameters.txt. I think it should be done in the next version to this parameter is discoverable.

Yeah, that is missing, I will update that in a standalone patch, or in a next version.

Thanks,
Pasha

#10 lore raw

Re: [PATCH v9 1/9] kho: make debugfs interface optional

In FC42, when I run "./luo_multi_session"

# ./luo_multi_session
# [STAGE 1] Starting pre-kexec setup for multi-session test...
# [STAGE 1] Creating state file for next stage (2)...
# [STAGE 1] Creating empty sessions 'multi-test-empty-1' and 'multi-test-empty-2'...
# [STAGE 1] Creating session 'multi-test-files-1' with one memfd...
# [STAGE 1] Creating session 'multi-test-files-2' with two memfds...
# [STAGE 1] Executing kexec...

Then the system hang. And via virt-viewer, a calltrace will appear.

The call trace is in the attachment.

Yanjun.Zhu

Quoted 74 lines · Pasha Tatashin
Quoted 56 lines · Pratyush Yadav
Quoted 54 lines · Zhu Yanjun
Quoted 37 lines · Pasha Tatashin
Quoted 24 lines · Yanjun.Zhu
Quoted 17 lines · Pasha Tatashin
Quoted 16 lines · Pasha Tatashin
Quoted 7 lines

Hi, Pasha

In our previous discussion, we talked about counting the number of times the kernel is rebooted via kexec. At that time, you suggested adding a variable in debugfs to keep track of this count.
However, since debugfs is now optional, where would be an appropriate place to store this variable?

It is an optional config and can still be enabled if the live update reboot number value needs to be accessed through debugfs. However, given that debugfs does not guarantee a stable interface, tooling should not be built to require these interfaces.

In the WIP LUO [1] I have, I pr_info() the live update number during boot and also store it in the incoming LUO FDT tree, which can also be accessed through this optional debugfs interface.

Quoted 6 lines
Quoted 4 lines

The pr_info message appears like this during boot:

[    0.000000] luo: Retrieved live update data, liveupdate number: 17

Pasha

Forgot to add link to WIP LUOv5:
[1] https://github.com/soleen/linux/tree/luo/v5rc04

Quoted 8 lines

Thanks a lot. I’ve carefully read this commit:
https://github.com/soleen/linux/commit/60205b9a95c319dc9965f119303a1d83f0ff08fa.

To be honest, I’d like to run some tests with who/luo, including the selftest for kho/luo. Could you please share the steps with me?

If the testing steps have already been documented somewhere, could you please share the link?

Currently the test performs in-kernel tests for FLB data, it creates a number of FLB for every registered LUO file-handler, which at the moment is only memfd.

Quoted 6 lines

It works together with any of the kexec based live update tests. In v5, I introduce two tests:
luo_kexec_simple
luo_multi_session

For example, with luo_multi_session:

Hi, Pasha

I enabled "CONFIG_LIVEUPDATE=y"

# ./luo_multi_session
1..0 # SKIP Failed to open /dev/liveupdate. Is the luo module loaded?
# ls /dev/liveupdate
ls: cannot access '/dev/liveupdate': No such file or directory
Quoted 7 lines
Quoted 5 lines
# grep "LIVEUPDATE" -inrHI /boot/config-`uname -r`
/boot/config-next-20251107-luo+:349:CONFIG_LIVEUPDATE=y
/boot/config-next-20251107-luo+:11985:CONFIG_LIVEUPDATE_TEST=y

I made tests on FC42. But /dev/liveupdate is missing.

You need to add liveupdate=1 to your kernel cmdline to enable LUO and get /dev/liveupdate.

+1, kernel parameters require: kho=1 liveupdate=1

Quoted 3 lines

Pasha, your LUO series doesn't add the liveupdate parameter to kernel-parameters.txt. I think it should be done in the next version to this parameter is discoverable.

Yeah, that is missing, I will update that in a standalone patch, or in a next version.

Thanks,
Pasha

Signature · 2 lines
Best Regards,
Yanjun.Zhu
author maintainer
#11 lore raw

Re: [PATCH v9 1/9] kho: make debugfs interface optional

Quoted 12 lines · Zhu Yanjun

In FC42, when I run "./luo_multi_session"

# ./luo_multi_session
# [STAGE 1] Starting pre-kexec setup for multi-session test...
# [STAGE 1] Creating state file for next stage (2)...
# [STAGE 1] Creating empty sessions 'multi-test-empty-1' and
'multi-test-empty-2'...
# [STAGE 1] Creating session 'multi-test-files-1' with one memfd...
# [STAGE 1] Creating session 'multi-test-files-2' with two memfds...
# [STAGE 1] Executing kexec...
Quoted 1 line

Then the system hang. And via virt-viewer, a calltrace will appear.

Looks like mountroot fails, are you passing the same kernel parameters as the during cold boot?
i.e. kexec -l -s --reuse-cmdline --initrd=[initramfs] [kernel]

Pasha

Quoted 84 lines

The call trace is in the attachment.

Yanjun.Zhu

Quoted 66 lines · Pasha Tatashin
Quoted 56 lines · Pratyush Yadav
Quoted 54 lines · Zhu Yanjun
Quoted 37 lines · Pasha Tatashin
Quoted 24 lines · Yanjun.Zhu
Quoted 17 lines · Pasha Tatashin
Quoted 16 lines · Pasha Tatashin
Quoted 7 lines

Hi, Pasha

In our previous discussion, we talked about counting the number of times the kernel is rebooted via kexec. At that time, you suggested adding a variable in debugfs to keep track of this count.
However, since debugfs is now optional, where would be an appropriate place to store this variable?

It is an optional config and can still be enabled if the live update reboot number value needs to be accessed through debugfs. However, given that debugfs does not guarantee a stable interface, tooling should not be built to require these interfaces.

In the WIP LUO [1] I have, I pr_info() the live update number during boot and also store it in the incoming LUO FDT tree, which can also be accessed through this optional debugfs interface.

Quoted 6 lines
Quoted 4 lines

The pr_info message appears like this during boot:

[    0.000000] luo: Retrieved live update data, liveupdate number: 17

Pasha

Forgot to add link to WIP LUOv5:
[1] https://github.com/soleen/linux/tree/luo/v5rc04

Quoted 8 lines

Thanks a lot. I’ve carefully read this commit:
https://github.com/soleen/linux/commit/60205b9a95c319dc9965f119303a1d83f0ff08fa.

To be honest, I’d like to run some tests with who/luo, including the selftest for kho/luo. Could you please share the steps with me?

If the testing steps have already been documented somewhere, could you please share the link?

Currently the test performs in-kernel tests for FLB data, it creates a number of FLB for every registered LUO file-handler, which at the moment is only memfd.

Quoted 6 lines

It works together with any of the kexec based live update tests. In v5, I introduce two tests:
luo_kexec_simple
luo_multi_session

For example, with luo_multi_session:

Hi, Pasha

I enabled "CONFIG_LIVEUPDATE=y"

# ./luo_multi_session
1..0 # SKIP Failed to open /dev/liveupdate. Is the luo module loaded?
# ls /dev/liveupdate
ls: cannot access '/dev/liveupdate': No such file or directory
Quoted 7 lines
Quoted 5 lines
# grep "LIVEUPDATE" -inrHI /boot/config-`uname -r`
/boot/config-next-20251107-luo+:349:CONFIG_LIVEUPDATE=y
/boot/config-next-20251107-luo+:11985:CONFIG_LIVEUPDATE_TEST=y

I made tests on FC42. But /dev/liveupdate is missing.

You need to add liveupdate=1 to your kernel cmdline to enable LUO and get /dev/liveupdate.

+1, kernel parameters require: kho=1 liveupdate=1

Quoted 8 lines
Quoted 3 lines

Pasha, your LUO series doesn't add the liveupdate parameter to kernel-parameters.txt. I think it should be done in the next version to this parameter is discoverable.

Yeah, that is missing, I will update that in a standalone patch, or in a next version.

Thanks,
Pasha

--
Best Regards,
Yanjun.Zhu

#12 lore raw

Re: [PATCH v9 1/9] kho: make debugfs interface optional

Quoted 12 lines · Pasha Tatashin
Quoted 11 lines · Zhu Yanjun

In FC42, when I run "./luo_multi_session"

# ./luo_multi_session
# [STAGE 1] Starting pre-kexec setup for multi-session test...
# [STAGE 1] Creating state file for next stage (2)...
# [STAGE 1] Creating empty sessions 'multi-test-empty-1' and
'multi-test-empty-2'...
# [STAGE 1] Creating session 'multi-test-files-1' with one memfd...
# [STAGE 1] Creating session 'multi-test-files-2' with two memfds...
# [STAGE 1] Executing kexec...
Quoted 4 lines
Quoted 1 line

Then the system hang. And via virt-viewer, a calltrace will appear.

Looks like mountroot fails, are you passing the same kernel parameters as the during cold boot?
i.e. kexec -l -s --reuse-cmdline --initrd=[initramfs] [kernel]

Thanks a lot. It can work now.  The logs are as below:

"

# [STAGE 2] Starting post-kexec verification...
# [STAGE 2] Retrieving all sessions...
# [STAGE 2] Verifying contents of session 'multi-test-files-1'... # [STAGE 2] Verifying contents of session 'multi-test-files-2'... # [STAGE 2] Test data verified successfully.
# [STAGE 2] Finalizing all test sessions...
# [STAGE 2] Finalizing state session...
#
--- MULTI-SESSION KEXEC TEST PASSED ---
"

Yanjun.Zhu

Quoted 85 lines

Pasha

Quoted 82 lines

The call trace is in the attachment.

Yanjun.Zhu

Quoted 66 lines · Pasha Tatashin
Quoted 56 lines · Pratyush Yadav
Quoted 54 lines · Zhu Yanjun
Quoted 37 lines · Pasha Tatashin
Quoted 24 lines · Yanjun.Zhu
Quoted 17 lines · Pasha Tatashin
Quoted 16 lines · Pasha Tatashin
Quoted 7 lines

Hi, Pasha

In our previous discussion, we talked about counting the number of times the kernel is rebooted via kexec. At that time, you suggested adding a variable in debugfs to keep track of this count.
However, since debugfs is now optional, where would be an appropriate place to store this variable?

It is an optional config and can still be enabled if the live update reboot number value needs to be accessed through debugfs. However, given that debugfs does not guarantee a stable interface, tooling should not be built to require these interfaces.

In the WIP LUO [1] I have, I pr_info() the live update number during boot and also store it in the incoming LUO FDT tree, which can also be accessed through this optional debugfs interface.

Quoted 6 lines
Quoted 4 lines

The pr_info message appears like this during boot:

[    0.000000] luo: Retrieved live update data, liveupdate number: 17

Pasha

Forgot to add link to WIP LUOv5:
[1] https://github.com/soleen/linux/tree/luo/v5rc04

Quoted 8 lines

Thanks a lot. I’ve carefully read this commit:
https://github.com/soleen/linux/commit/60205b9a95c319dc9965f119303a1d83f0ff08fa.

To be honest, I’d like to run some tests with who/luo, including the selftest for kho/luo. Could you please share the steps with me?

If the testing steps have already been documented somewhere, could you please share the link?

Currently the test performs in-kernel tests for FLB data, it creates a number of FLB for every registered LUO file-handler, which at the moment is only memfd.

Quoted 6 lines

It works together with any of the kexec based live update tests. In v5, I introduce two tests:
luo_kexec_simple
luo_multi_session

For example, with luo_multi_session:

Hi, Pasha

I enabled "CONFIG_LIVEUPDATE=y"

# ./luo_multi_session
1..0 # SKIP Failed to open /dev/liveupdate. Is the luo module loaded?
# ls /dev/liveupdate
ls: cannot access '/dev/liveupdate': No such file or directory
Quoted 7 lines
Quoted 5 lines
# grep "LIVEUPDATE" -inrHI /boot/config-`uname -r`
/boot/config-next-20251107-luo+:349:CONFIG_LIVEUPDATE=y
/boot/config-next-20251107-luo+:11985:CONFIG_LIVEUPDATE_TEST=y

I made tests on FC42. But /dev/liveupdate is missing.

You need to add liveupdate=1 to your kernel cmdline to enable LUO and get /dev/liveupdate.

+1, kernel parameters require: kho=1 liveupdate=1

Quoted 8 lines
Quoted 3 lines

Pasha, your LUO series doesn't add the liveupdate parameter to kernel-parameters.txt. I think it should be done in the next version to this parameter is discoverable.

Yeah, that is missing, I will update that in a standalone patch, or in a next version.

Thanks,
Pasha

--
Best Regards,
Yanjun.Zhu

#13 lore raw

Re: [PATCH v9 1/9] kho: make debugfs interface optional

Quoted 35 lines · Yanjun.Zhu
Quoted 12 lines · Pasha Tatashin
Quoted 11 lines · Zhu Yanjun

In FC42, when I run "./luo_multi_session"

# ./luo_multi_session
# [STAGE 1] Starting pre-kexec setup for multi-session test...
# [STAGE 1] Creating state file for next stage (2)...
# [STAGE 1] Creating empty sessions 'multi-test-empty-1' and
'multi-test-empty-2'...
# [STAGE 1] Creating session 'multi-test-files-1' with one memfd...
# [STAGE 1] Creating session 'multi-test-files-2' with two memfds...
# [STAGE 1] Executing kexec...
Quoted 4 lines
Quoted 1 line

Then the system hang. And via virt-viewer, a calltrace will appear.

Looks like mountroot fails, are you passing the same kernel parameters as the during cold boot?
i.e. kexec -l -s --reuse-cmdline --initrd=[initramfs] [kernel]

Thanks a lot. It can work now.  The logs are as below:

"

# [STAGE 2] Starting post-kexec verification...
# [STAGE 2] Retrieving all sessions...
# [STAGE 2] Verifying contents of session 'multi-test-files-1'... # [STAGE 2] Verifying contents of session 'multi-test-files-2'... # [STAGE 2] Test data verified successfully.
# [STAGE 2] Finalizing all test sessions...
# [STAGE 2] Finalizing state session...
#
--- MULTI-SESSION KEXEC TEST PASSED ---
"

Quoted 1 line

Yanjun.Zhu

Hi, Pasha

In my tests, I found that luo_kexec_simple and luo_multi_session currently depend on the glibc-static library.
If this library is not installed, build errors occur.
By making the following changes, luo_kexec_simple and luo_multi_session would no longer depend on glibc-static, reducing external library dependencies. I am not sure whether you agree with these proposed changes.

tools/testing/selftests/liveupdate/Makefile +0 -0
index 6ee6efeec62d..b226b9976150 100644
@@ -3,7 +3,6 @@

 KHDR_INCLUDES ?= -I../../../../usr/include
 CFLAGS += -Wall -O2 -Wno-unused-function
 CFLAGS += $(KHDR_INCLUDES)
-LDFLAGS += -static
 OUTPUT ?= .

 # --- Test Configuration (Edit this section when adding new tests) ---

Yanjun.Zhu

Quoted 88 lines
Quoted 88 lines

Pasha

Quoted 83 lines

The call trace is in the attachment.

Yanjun.Zhu

Quoted 75 lines · Pasha Tatashin
Quoted 57 lines · Pratyush Yadav
Quoted 55 lines · Zhu Yanjun
Quoted 38 lines · Pasha Tatashin
Quoted 28 lines · Yanjun.Zhu
Quoted 17 lines · Pasha Tatashin
Quoted 16 lines · Pasha Tatashin
Quoted 7 lines

Hi, Pasha

In our previous discussion, we talked about counting the number of times the kernel is rebooted via kexec. At that time, you suggested adding a variable in debugfs to keep track of this count.
However, since debugfs is now optional, where would be an appropriate place to store this variable?

It is an optional config and can still be enabled if the live update reboot number value needs to be accessed through debugfs. However, given that debugfs does not guarantee a stable interface, tooling should not be built to require these interfaces.

In the WIP LUO [1] I have, I pr_info() the live update number during boot and also store it in the incoming LUO FDT tree, which can also be accessed through this optional debugfs interface.

Quoted 6 lines
Quoted 4 lines

The pr_info message appears like this during boot:
[    0.000000] luo: Retrieved live update data, liveupdate number: 17

Pasha

Forgot to add link to WIP LUOv5:
[1] https://github.com/soleen/linux/tree/luo/v5rc04

Thanks a lot. I’ve carefully read this commit:
https://github.com/soleen/linux/commit/60205b9a95c319dc9965f119303a1d83f0ff08fa.

Quoted 5 lines

To be honest, I’d like to run some tests with who/luo, including the selftest for kho/luo. Could you please share the steps with me?

If the testing steps have already been documented somewhere, could you please share the link?

Currently the test performs in-kernel tests for FLB data, it creates a number of FLB for every registered LUO file-handler, which at the moment is only memfd.

Quoted 6 lines

It works together with any of the kexec based live update tests. In v5, I introduce two tests:
luo_kexec_simple
luo_multi_session

For example, with luo_multi_session:

Hi, Pasha

I enabled "CONFIG_LIVEUPDATE=y"

# ./luo_multi_session
1..0 # SKIP Failed to open /dev/liveupdate. Is the luo module loaded?
# ls /dev/liveupdate
ls: cannot access '/dev/liveupdate': No such file or directory
Quoted 7 lines
Quoted 5 lines
# grep "LIVEUPDATE" -inrHI /boot/config-`uname -r`
/boot/config-next-20251107-luo+:349:CONFIG_LIVEUPDATE=y
/boot/config-next-20251107-luo+:11985:CONFIG_LIVEUPDATE_TEST=y

I made tests on FC42. But /dev/liveupdate is missing.

You need to add liveupdate=1 to your kernel cmdline to enable LUO and get /dev/liveupdate.

+1, kernel parameters require: kho=1 liveupdate=1

Quoted 3 lines

Pasha, your LUO series doesn't add the liveupdate parameter to kernel-parameters.txt. I think it should be done in the next version to this parameter is discoverable.

Yeah, that is missing, I will update that in a standalone patch, or in a next version.

Thanks,
Pasha

Signature · 2 lines
Best Regards,
Yanjun.Zhu
author maintainer
#14 lore raw

Re: [PATCH v9 1/9] kho: make debugfs interface optional

Quoted 58 lines · Yanjun.Zhu
Quoted 36 lines · Yanjun.Zhu
Quoted 13 lines · Pasha Tatashin
Quoted 11 lines · Zhu Yanjun

In FC42, when I run "./luo_multi_session"

# ./luo_multi_session
# [STAGE 1] Starting pre-kexec setup for multi-session test...
# [STAGE 1] Creating state file for next stage (2)...
# [STAGE 1] Creating empty sessions 'multi-test-empty-1' and
'multi-test-empty-2'...
# [STAGE 1] Creating session 'multi-test-files-1' with one memfd...
# [STAGE 1] Creating session 'multi-test-files-2' with two memfds...
# [STAGE 1] Executing kexec...
Quoted 4 lines
Quoted 1 line

Then the system hang. And via virt-viewer, a calltrace will appear.

Looks like mountroot fails, are you passing the same kernel parameters as the during cold boot?
i.e. kexec -l -s --reuse-cmdline --initrd=[initramfs] [kernel]

Thanks a lot. It can work now. The logs are as below:

"

# [STAGE 2] Starting post-kexec verification...
# [STAGE 2] Retrieving all sessions...
# [STAGE 2] Verifying contents of session 'multi-test-files-1'... # [STAGE 2] Verifying contents of session 'multi-test-files-2'... # [STAGE 2] Test data verified successfully.
# [STAGE 2] Finalizing all test sessions...
# [STAGE 2] Finalizing state session...
#
--- MULTI-SESSION KEXEC TEST PASSED ---
"

Quoted 1 line

Yanjun.Zhu

Hi, Pasha

In my tests, I found that luo_kexec_simple and luo_multi_session currently depend on the glibc-static library.
If this library is not installed, build errors occur.
By making the following changes, luo_kexec_simple and luo_multi_session would no longer depend on glibc-static, reducing external library dependencies.
I am not sure whether you agree with these proposed changes.

tools/testing/selftests/liveupdate/Makefile +0 -0
index 6ee6efeec62d..b226b9976150 100644

tools/testing/selftests/liveupdate/Makefile line 6

Quoted 4 lines
tools/testing/selftests/liveupdate/Makefile +0 -1
@@ -3,7 +3,6 @@
  KHDR_INCLUDES ?= -I../../../../usr/include
  CFLAGS += -Wall -O2 -Wno-unused-function
  CFLAGS += $(KHDR_INCLUDES)
-LDFLAGS += -static

Hi Yanjun,

Thank you for testing. I prefer to keep the '-static' flag because these self-test files are not executed in the same environment where they are compiled but in a VM which might have a different userspace.

Thank you,
Pasha

Quoted 111 lines
tools/testing/selftests/liveupdate/Makefile +0 -0
  OUTPUT ?= .
 
  # --- Test Configuration (Edit this section when adding new tests) ---

Yanjun.Zhu

Quoted 105 lines
Quoted 105 lines

Pasha

Quoted 100 lines

The call trace is in the attachment.

Yanjun.Zhu

Quoted 87 lines · Pasha Tatashin
Quoted 72 lines · Pratyush Yadav
Quoted 70 lines · Zhu Yanjun
Quoted 52 lines · Pasha Tatashin
Quoted 38 lines · Yanjun.Zhu
Quoted 26 lines · Pasha Tatashin
Quoted 24 lines · Pasha Tatashin
Quoted 10 lines

Hi, Pasha

In our previous discussion, we talked about counting the number of times
the kernel is rebooted via kexec. At that time, you suggested adding a
variable in debugfs to keep track of this count. However, since debugfs is now optional, where would be an appropriate
place to store this variable?

It is an optional config and can still be enabled if the live update
reboot number value needs to be accessed through debugfs. However,
given that debugfs does not guarantee a stable interface, tooling
should not be built to require these interfaces.

In the WIP LUO [1] I have, I pr_info() the live update number during
boot and also store it in the incoming LUO FDT tree, which can also be
accessed through this optional debugfs interface.

Quoted 7 lines
Quoted 5 lines

The pr_info message appears like this during boot:

[    0.000000] luo: Retrieved live update data, liveupdate

number: 17

Pasha

Forgot to add link to WIP LUOv5:
[1] https://github.com/soleen/linux/tree/luo/v5rc04

Thanks a lot. I’ve carefully read this commit:
https://github.com/soleen/linux/commit/60205b9a95c319dc9965f119303a1d83f0ff08fa.

Quoted 7 lines

To be honest, I’d like to run some tests with who/luo, including the
selftest for kho/luo. Could you please share the steps with me?

If the testing steps have already been documented somewhere, could you
please share the link?

Currently the test performs in-kernel tests for FLB data, it creates a
number of FLB for every registered LUO file-handler, which at the moment is only memfd.

Quoted 6 lines

It works together with any of the kexec based live update tests. In v5, I introduce two tests:
luo_kexec_simple
luo_multi_session

For example, with luo_multi_session:

Hi, Pasha

I enabled "CONFIG_LIVEUPDATE=y"

# ./luo_multi_session
1..0 # SKIP Failed to open /dev/liveupdate. Is the luo module
loaded?
# ls /dev/liveupdate
ls: cannot access '/dev/liveupdate': No such file or directory
Quoted 7 lines
Quoted 5 lines
# grep "LIVEUPDATE" -inrHI /boot/config-`uname -r`
/boot/config-next-20251107-luo+:349:CONFIG_LIVEUPDATE=y
/boot/config-next-20251107-luo+:11985:CONFIG_LIVEUPDATE_TEST=y

I made tests on FC42. But /dev/liveupdate is missing.

You need to add liveupdate=1 to your kernel cmdline to enable LUO and get /dev/liveupdate.

+1, kernel parameters require: kho=1 liveupdate=1

Quoted 4 lines

Pasha, your LUO series doesn't add the liveupdate parameter to kernel-parameters.txt. I think it should be done in the next version to
this parameter is discoverable.

Quoted 5 lines

Yeah, that is missing, I will update that in a standalone patch, or in a next version.

Thanks,
Pasha

--
Best Regards,
Yanjun.Zhu

#15 lore raw

Re: [PATCH v9 1/9] kho: make debugfs interface optional

Quoted 61 lines · Pasha Tatashin
Quoted 54 lines · Yanjun.Zhu
Quoted 34 lines · Yanjun.Zhu
Quoted 13 lines · Pasha Tatashin
Quoted 11 lines · Zhu Yanjun

In FC42, when I run "./luo_multi_session"

# ./luo_multi_session
# [STAGE 1] Starting pre-kexec setup for multi-session test...
# [STAGE 1] Creating state file for next stage (2)...
# [STAGE 1] Creating empty sessions 'multi-test-empty-1' and
'multi-test-empty-2'...
# [STAGE 1] Creating session 'multi-test-files-1' with one memfd...
# [STAGE 1] Creating session 'multi-test-files-2' with two memfds...
# [STAGE 1] Executing kexec...
Quoted 4 lines
Quoted 1 line

Then the system hang. And via virt-viewer, a calltrace will appear.

Looks like mountroot fails, are you passing the same kernel parameters as the during cold boot?
i.e. kexec -l -s --reuse-cmdline --initrd=[initramfs] [kernel]

Thanks a lot. It can work now. The logs are as below:

"

# [STAGE 2] Starting post-kexec verification...
# [STAGE 2] Retrieving all sessions...
# [STAGE 2] Verifying contents of session 'multi-test-files-1'... # [STAGE 2] Verifying contents of session 'multi-test-files-2'... # [STAGE 2] Test data verified successfully.
# [STAGE 2] Finalizing all test sessions...
# [STAGE 2] Finalizing state session...
#
--- MULTI-SESSION KEXEC TEST PASSED ---
"

Quoted 1 line

Yanjun.Zhu

Hi, Pasha

In my tests, I found that luo_kexec_simple and luo_multi_session currently depend on the glibc-static library.
If this library is not installed, build errors occur.
By making the following changes, luo_kexec_simple and luo_multi_session would no longer depend on glibc-static, reducing external library dependencies.
I am not sure whether you agree with these proposed changes.

tools/testing/selftests/liveupdate/Makefile +0 -0
index 6ee6efeec62d..b226b9976150 100644

tools/testing/selftests/liveupdate/Makefile line 6

Quoted 4 lines
tools/testing/selftests/liveupdate/Makefile +0 -1
@@ -3,7 +3,6 @@
   KHDR_INCLUDES ?= -I../../../../usr/include
   CFLAGS += -Wall -O2 -Wno-unused-function
   CFLAGS += $(KHDR_INCLUDES)
-LDFLAGS += -static

Hi Yanjun,

Quoted 3 lines

Thank you for testing. I prefer to keep the '-static' flag because these self-test files are not executed in the same environment where they are compiled but in a VM which might have a different userspace.

Hi, Pasha

I agree with your reasoning. Given that the self-tests run in a different userspace, keeping the |-static| flag seems reasonable.

Best Regards,

Yanjun.Zhu

Quoted 113 lines

Thank you,
Pasha

Quoted 109 lines
tools/testing/selftests/liveupdate/Makefile +0 -0
   OUTPUT ?= .
 
   # --- Test Configuration (Edit this section when adding new tests) ---

Yanjun.Zhu

Quoted 103 lines
Quoted 103 lines

Pasha

Quoted 100 lines

The call trace is in the attachment.

Yanjun.Zhu

Quoted 87 lines · Pasha Tatashin
Quoted 72 lines · Pratyush Yadav
Quoted 70 lines · Zhu Yanjun
Quoted 52 lines · Pasha Tatashin
Quoted 38 lines · Yanjun.Zhu
Quoted 26 lines · Pasha Tatashin
Quoted 24 lines · Pasha Tatashin
Quoted 10 lines

Hi, Pasha

In our previous discussion, we talked about counting the
number of times
the kernel is rebooted via kexec. At that time, you
suggested adding a
variable in debugfs to keep track of this count.
However, since debugfs is now optional, where would be an
appropriate
place to store this variable?

It is an optional config and can still be enabled if the live update
reboot number value needs to be accessed through debugfs. However,
given that debugfs does not guarantee a stable interface, tooling
should not be built to require these interfaces.

In the WIP LUO [1] I have, I pr_info() the live update number during
boot and also store it in the incoming LUO FDT tree, which can also be
accessed through this optional debugfs interface.

Quoted 7 lines
Quoted 5 lines

The pr_info message appears like this during boot:

[    0.000000] luo: Retrieved live update data, liveupdate

number: 17

Pasha

Forgot to add link to WIP LUOv5:
[1]https://github.com/soleen/linux/tree/luo/v5rc04

Thanks a lot. I’ve carefully read this commit:
https://github.com/soleen/linux/commit/60205b9a95c319dc9965f119303a1d83f0ff08fa.

Quoted 7 lines

To be honest, I’d like to run some tests with who/luo, including the
selftest for kho/luo. Could you please share the steps with me?

If the testing steps have already been documented somewhere, could you
please share the link?

Currently the test performs in-kernel tests for FLB data, it creates a
number of FLB for every registered LUO file-handler, which at the moment is only memfd.

Quoted 6 lines

It works together with any of the kexec based live update tests. In v5, I introduce two tests:
luo_kexec_simple
luo_multi_session

For example, with luo_multi_session:

Hi, Pasha

I enabled "CONFIG_LIVEUPDATE=y"

# ./luo_multi_session
1..0 # SKIP Failed to open /dev/liveupdate. Is the luo module
loaded?
# ls /dev/liveupdate
ls: cannot access '/dev/liveupdate': No such file or directory
Quoted 7 lines
Quoted 5 lines
# grep "LIVEUPDATE" -inrHI /boot/config-`uname -r`
/boot/config-next-20251107-luo+:349:CONFIG_LIVEUPDATE=y
/boot/config-next-20251107-luo+:11985:CONFIG_LIVEUPDATE_TEST=y

I made tests on FC42. But /dev/liveupdate is missing.

You need to add liveupdate=1 to your kernel cmdline to enable LUO and get /dev/liveupdate.

+1, kernel parameters require: kho=1 liveupdate=1

Quoted 4 lines

Pasha, your LUO series doesn't add the liveupdate parameter to kernel-parameters.txt. I think it should be done in the next version to
this parameter is discoverable.

Quoted 5 lines

Yeah, that is missing, I will update that in a standalone patch, or in a next version.

Thanks,
Pasha

--
Best Regards,
Yanjun.Zhu

#16 lore raw

Re: [PATCH v9 1/9] kho: make debugfs interface optional

In reply to Pasha Tatashin
Quoted 12 lines · Pasha Tatashin
Quoted 11 lines · Zhu Yanjun

In FC42, when I run "./luo_multi_session"

# ./luo_multi_session
# [STAGE 1] Starting pre-kexec setup for multi-session test...
# [STAGE 1] Creating state file for next stage (2)...
# [STAGE 1] Creating empty sessions 'multi-test-empty-1' and
'multi-test-empty-2'...
# [STAGE 1] Creating session 'multi-test-files-1' with one memfd...
# [STAGE 1] Creating session 'multi-test-files-2' with two memfds...
# [STAGE 1] Executing kexec...
Quoted 6 lines
Quoted 1 line

Then the system hang. And via virt-viewer, a calltrace will appear.

Looks like mountroot fails, are you passing the same kernel parameters as the during cold boot?
i.e. kexec -l -s --reuse-cmdline --initrd=[initramfs] [kernel]

Pasha

Hi, Pasha

Following your advice, the following can work well.

I am not sure if we can merge this commit into selftests/liveupdate mainline?

commit 44764c48a658987b7729c5bc2be9fd87832cfbdf (HEAD -> linux-next/master)
Author: Zhu Yanjun <[email protected]>
Date:   Thu Nov 13 11:45:21 2025 -0800

    selftests/liveupdate: Fix the error "Unable to mount root fs on unknown-block"

    If the initrd is not provide, the followings will appear. "

    Call Trace:
    <TASK>
    dump_stack_lvl+0x5d/0x80
    vpanic+0x118/8x320
    panic+0x6b/0x6b
    ? do_mount_root+0x115/0x130
     mount_root_generic+0x1cf/0x270
     prepare_namespace+0x1e1/0x230
     kernel_init_freeable+0x136/8x140
    ?_pfx_kernel_init+0x10/0x10
     kernel_init+0x1a/0x140
     ret_from_fork+0x130/0x1a8
     ?_pfx_kernel_init+0x10/0x10
     ret_from_fork_asm+0x1a/0x30

     </ TASK>
     Kernel Offset: 0x3000000 from Oxffffffff81000000 "

tools/testing/selftests/liveupdate/do_kexec.sh +0 -0
index bb396a92c3b8..4ee59abd0dd4 100755
@@ -2,5 +2,5 @@

 # SPDX-License-Identifier: GPL-2.0
 set -e

-kexec -l -s --reuse-cmdline /boot/bzImage
+kexec -l -s --reuse-cmdline /boot/bzImage --initrd /boot/initramfs-uname -r.img kexec -e

Thanks a lot.

Yanjun.Zhu

Quoted 82 lines
Quoted 82 lines

The call trace is in the attachment.

Yanjun.Zhu

Quoted 66 lines · Pasha Tatashin
Quoted 56 lines · Pratyush Yadav
Quoted 54 lines · Zhu Yanjun
Quoted 37 lines · Pasha Tatashin
Quoted 24 lines · Yanjun.Zhu
Quoted 17 lines · Pasha Tatashin
Quoted 16 lines · Pasha Tatashin
Quoted 7 lines

Hi, Pasha

In our previous discussion, we talked about counting the number of times the kernel is rebooted via kexec. At that time, you suggested adding a variable in debugfs to keep track of this count.
However, since debugfs is now optional, where would be an appropriate place to store this variable?

It is an optional config and can still be enabled if the live update reboot number value needs to be accessed through debugfs. However, given that debugfs does not guarantee a stable interface, tooling should not be built to require these interfaces.

In the WIP LUO [1] I have, I pr_info() the live update number during boot and also store it in the incoming LUO FDT tree, which can also be accessed through this optional debugfs interface.

Quoted 6 lines
Quoted 4 lines

The pr_info message appears like this during boot:

[    0.000000] luo: Retrieved live update data, liveupdate number: 17

Pasha

Forgot to add link to WIP LUOv5:
[1] https://github.com/soleen/linux/tree/luo/v5rc04

Quoted 8 lines

Thanks a lot. I’ve carefully read this commit:
https://github.com/soleen/linux/commit/60205b9a95c319dc9965f119303a1d83f0ff08fa.

To be honest, I’d like to run some tests with who/luo, including the selftest for kho/luo. Could you please share the steps with me?

If the testing steps have already been documented somewhere, could you please share the link?

Currently the test performs in-kernel tests for FLB data, it creates a number of FLB for every registered LUO file-handler, which at the moment is only memfd.

Quoted 6 lines

It works together with any of the kexec based live update tests. In v5, I introduce two tests:
luo_kexec_simple
luo_multi_session

For example, with luo_multi_session:

Hi, Pasha

I enabled "CONFIG_LIVEUPDATE=y"

# ./luo_multi_session
1..0 # SKIP Failed to open /dev/liveupdate. Is the luo module loaded?
# ls /dev/liveupdate
ls: cannot access '/dev/liveupdate': No such file or directory
Quoted 7 lines
Quoted 5 lines
# grep "LIVEUPDATE" -inrHI /boot/config-`uname -r`
/boot/config-next-20251107-luo+:349:CONFIG_LIVEUPDATE=y
/boot/config-next-20251107-luo+:11985:CONFIG_LIVEUPDATE_TEST=y

I made tests on FC42. But /dev/liveupdate is missing.

You need to add liveupdate=1 to your kernel cmdline to enable LUO and get /dev/liveupdate.

+1, kernel parameters require: kho=1 liveupdate=1

Quoted 8 lines
Quoted 3 lines

Pasha, your LUO series doesn't add the liveupdate parameter to kernel-parameters.txt. I think it should be done in the next version to this parameter is discoverable.

Yeah, that is missing, I will update that in a standalone patch, or in a next version.

Thanks,
Pasha

--
Best Regards,
Yanjun.Zhu

author maintainer
#17 lore raw

Re: [PATCH v9 1/9] kho: make debugfs interface optional

Quoted 5 lines

set -e

(quoted diff) +1 -1
-kexec -l -s --reuse-cmdline /boot/bzImage
+kexec -l -s --reuse-cmdline /boot/bzImage --initrd

/boot/initramfs-uname -r.img

Thank you for your suggestion, in the next version, I am going to add initramfs optionally, I am thinking to update script to something like this:

#!/bin/sh
# SPDX-License-Identifier: GPL-2.0
set -e

# Use $KERNEL and $INITRAMFS to pass custom Kernel and optional initramfs

KERNEL="${KERNEL:-/boot/bzImage}"
set -- -l -s --reuse-cmdline "$KERNEL"

INITRAMFS="${INITRAMFS:-/boot/initramfs}"
if [ -f "$INITRAMFS" ]; then

    set -- "$@" --initrd="$INITRAMFS"

fi

kexec "$@"
kexec -e

author maintainer
#18 lore raw

Re: [PATCH v9 1/9] kho: make debugfs interface optional

Quoted 9 lines · Pasha Tatashin
Quoted 6 lines

set -e

(quoted diff) +1 -1
-kexec -l -s --reuse-cmdline /boot/bzImage
+kexec -l -s --reuse-cmdline /boot/bzImage --initrd

/boot/initramfs-uname -r.img

Thank you for your suggestion, in the next version, I am going to add initramfs optionally, I am thinking to update script to something like

Optionally, because in some environments (like in mine), it is built into bzImage.

Quoted 18 lines

this:

#!/bin/sh
# SPDX-License-Identifier: GPL-2.0
set -e

# Use $KERNEL and $INITRAMFS to pass custom Kernel and optional initramfs

KERNEL="${KERNEL:-/boot/bzImage}"
set -- -l -s --reuse-cmdline "$KERNEL"

INITRAMFS="${INITRAMFS:-/boot/initramfs}"
if [ -f "$INITRAMFS" ]; then

    set -- "$@" --initrd="$INITRAMFS"

fi

kexec "$@"
kexec -e

#19 lore raw

Re: [PATCH v9 1/9] kho: make debugfs interface optional

Quoted 11 lines · Pasha Tatashin
Quoted 7 lines · Pasha Tatashin
Quoted 5 lines

set -e

(quoted diff) +1 -1
-kexec -l -s --reuse-cmdline /boot/bzImage
+kexec -l -s --reuse-cmdline /boot/bzImage --initrd

/boot/initramfs-uname -r.img

Thank you for your suggestion, in the next version, I am going to add initramfs optionally, I am thinking to update script to something like

Optionally, because in some environments (like in mine), it is built into bzImage.

In my test hosts, the bzImage is vmlinuz-xxx. But with the help of "ln -sf ... ...",

this change can work well in my test environments, including x86_64 and arm64 hosts.

Br,

Yanjun.Zhu

Quoted 19 lines
Quoted 19 lines

this:

#!/bin/sh
# SPDX-License-Identifier: GPL-2.0
set -e

# Use $KERNEL and $INITRAMFS to pass custom Kernel and optional initramfs

KERNEL="${KERNEL:-/boot/bzImage}"
set -- -l -s --reuse-cmdline "$KERNEL"

INITRAMFS="${INITRAMFS:-/boot/initramfs}"
if [ -f "$INITRAMFS" ]; then

     set -- "$@" --initrd="$INITRAMFS"

fi

kexec "$@"
kexec -e

author maintainer
#20 lore raw

PATCH v9 2/9 kho: drop notifiers

In reply to Pasha Tatashin

From: "Mike Rapoport (Microsoft)" <[email protected]>

The KHO framework uses a notifier chain as the mechanism for clients to participate in the finalization process. While this works for a single, central state machine, it is too restrictive for kernel-internal components like pstore/reserve_mem or IMA. These components need a simpler, direct way to register their state for preservation (e.g., during their initcall) without being part of a complex, shutdown-time notifier sequence. The notifier model forces all participants into a single finalization flow and makes direct preservation from an arbitrary context difficult.
This patch refactors the client participation model by removing the notifier chain and introducing a direct API for managing FDT subtrees.

The core kho_finalize() and kho_abort() state machine remains, but clients now register their data with KHO beforehand.

---
 include/linux/kexec_handover.h   |  28 +-----
 kernel/kexec_handover.c          | 166 +++++++++++++++++--------------
 kernel/kexec_handover_debugfs.c  |  17 ++--
 kernel/kexec_handover_internal.h |   5 +-
 lib/test_kho.c                   |  35 +------
 mm/memblock.c                    |  62 +++---------
 6 files changed, 125 insertions(+), 188 deletions(-)
include/linux/kexec_handover.h +5 -23
index 25042c1d8d54..0d860d793b66 100644
@@ -10,14 +10,7 @@ struct kho_scratch {
 	phys_addr_t size;
 };
 
-/* KHO Notifier index */
-enum kho_event {
-	KEXEC_KHO_FINALIZE = 0,
-	KEXEC_KHO_ABORT = 1,
-};
-
 struct folio;
-struct notifier_block;
 struct page;
 
 #define DECLARE_KHOSER_PTR(name, type) \
@@ -37,8 +30,6 @@ struct page;
 		(typeof((s).ptr))((s).phys ? phys_to_virt((s).phys) : NULL); \
 	})
 
-struct kho_serialization;
-
 struct kho_vmalloc_chunk;
 struct kho_vmalloc {
 	DECLARE_KHOSER_PTR(first, struct kho_vmalloc_chunk *);
@@ -57,12 +48,10 @@ int kho_preserve_vmalloc(void *ptr, struct kho_vmalloc *preservation);
 struct folio *kho_restore_folio(phys_addr_t phys);
 struct page *kho_restore_pages(phys_addr_t phys, unsigned int nr_pages);
 void *kho_restore_vmalloc(const struct kho_vmalloc *preservation);
-int kho_add_subtree(struct kho_serialization *ser, const char *name, void *fdt);
+int kho_add_subtree(const char *name, void *fdt);
+void kho_remove_subtree(void *fdt);
 int kho_retrieve_subtree(const char *name, phys_addr_t *phys);
 
-int register_kho_notifier(struct notifier_block *nb);
-int unregister_kho_notifier(struct notifier_block *nb);
-
 void kho_memory_init(void);
 
 void kho_populate(phys_addr_t fdt_phys, u64 fdt_len, phys_addr_t scratch_phys,
@@ -110,23 +99,16 @@ static inline void *kho_restore_vmalloc(const struct kho_vmalloc *preservation)
 	return NULL;
 }
 
-static inline int kho_add_subtree(struct kho_serialization *ser,
-				  const char *name, void *fdt)
+static inline int kho_add_subtree(const char *name, void *fdt)
 {
 	return -EOPNOTSUPP;
 }
 
-static inline int kho_retrieve_subtree(const char *name, phys_addr_t *phys)
+static inline void kho_remove_subtree(void *fdt)
 {
-	return -EOPNOTSUPP;
 }
 
-static inline int register_kho_notifier(struct notifier_block *nb)
-{
-	return -EOPNOTSUPP;
-}
-
-static inline int unregister_kho_notifier(struct notifier_block *nb)
+static inline int kho_retrieve_subtree(const char *name, phys_addr_t *phys)
 {
 	return -EOPNOTSUPP;
 }
kernel/kexec_handover.c +91 -75

331 lines not on this page · raw message

kernel/kexec_handover_debugfs.c +10 -7
index a91b279f1b23..46e9e6c0791f 100644
@@ -61,14 +61,17 @@ int kho_debugfs_fdt_add(struct kho_debugfs *dbg, const char *name,
 	return __kho_debugfs_fdt_add(&dbg->fdt_list, dir, name, fdt);
 }
 
-void kho_debugfs_cleanup(struct kho_debugfs *dbg)
+void kho_debugfs_fdt_remove(struct kho_debugfs *dbg, void *fdt)
 {
-	struct fdt_debugfs *ff, *tmp;
-
-	list_for_each_entry_safe(ff, tmp, &dbg->fdt_list, list) {
-		debugfs_remove(ff->file);
-		list_del(&ff->list);
-		kfree(ff);
+	struct fdt_debugfs *ff;
+
+	list_for_each_entry(ff, &dbg->fdt_list, list) {
+		if (ff->wrapper.data == fdt) {
+			debugfs_remove(ff->file);
+			list_del(&ff->list);
+			kfree(ff);
+			break;
+		}
 	}
 }
 
kernel/kexec_handover_internal.h +3 -2
index 217b8b25a542..52ed73659fe6 100644
@@ -32,7 +32,7 @@ void kho_in_debugfs_init(struct kho_debugfs *dbg, const void *fdt);
 int kho_out_debugfs_init(struct kho_debugfs *dbg);
 int kho_debugfs_fdt_add(struct kho_debugfs *dbg, const char *name,
 			const void *fdt, bool root);
-void kho_debugfs_cleanup(struct kho_debugfs *dbg);
+void kho_debugfs_fdt_remove(struct kho_debugfs *dbg, void *fdt);
 #else
 static inline int kho_debugfs_init(void) { return 0; }
 static inline void kho_in_debugfs_init(struct kho_debugfs *dbg,
@@ -40,7 +40,8 @@ static inline void kho_in_debugfs_init(struct kho_debugfs *dbg,
 static inline int kho_out_debugfs_init(struct kho_debugfs *dbg) { return 0; }
 static inline int kho_debugfs_fdt_add(struct kho_debugfs *dbg, const char *name,
 				      const void *fdt, bool root) { return 0; }
-static inline void kho_debugfs_cleanup(struct kho_debugfs *dbg) {}
+static inline void kho_debugfs_fdt_remove(struct kho_debugfs *dbg,
+					  void *fdt) { }
 #endif /* CONFIG_KEXEC_HANDOVER_DEBUGFS */
 
 #ifdef CONFIG_KEXEC_HANDOVER_DEBUG
lib/test_kho.c +3 -32
index 60cd899ea745..9f7cfa6ac855 100644
@@ -39,33 +39,6 @@ struct kho_test_state {
 
 static struct kho_test_state kho_test_state;
 
-static int kho_test_notifier(struct notifier_block *self, unsigned long cmd,
-			     void *v)
-{
-	struct kho_test_state *state = &kho_test_state;
-	struct kho_serialization *ser = v;
-	int err = 0;
-
-	switch (cmd) {
-	case KEXEC_KHO_ABORT:
-		return NOTIFY_DONE;
-	case KEXEC_KHO_FINALIZE:
-		/* Handled below */
-		break;
-	default:
-		return NOTIFY_BAD;
-	}
-
-	err |= kho_preserve_folio(state->fdt);
-	err |= kho_add_subtree(ser, KHO_TEST_FDT, folio_address(state->fdt));
-
-	return err ? NOTIFY_BAD : NOTIFY_DONE;
-}
-
-static struct notifier_block kho_test_nb = {
-	.notifier_call = kho_test_notifier,
-};
-
 static int kho_test_save_data(struct kho_test_state *state, void *fdt)
 {
 	phys_addr_t *folios_info __free(kvfree) = NULL;
@@ -120,6 +93,7 @@ static int kho_test_prepare_fdt(struct kho_test_state *state)
 
 	fdt = folio_address(state->fdt);
 
+	err |= kho_preserve_folio(state->fdt);
 	err |= fdt_create(fdt, fdt_size);
 	err |= fdt_finish_reservemap(fdt);
 
@@ -131,6 +105,7 @@ static int kho_test_prepare_fdt(struct kho_test_state *state)
 
 	err |= fdt_finish(fdt);
 
+	err = kho_add_subtree(KHO_TEST_FDT, folio_address(state->fdt));
 	if (err)
 		folio_put(state->fdt);
 
@@ -203,10 +178,6 @@ static int kho_test_save(void)
 	if (err)
 		goto err_free_folios;
 
-	err = register_kho_notifier(&kho_test_nb);
-	if (err)
-		goto err_free_fdt;
-
 	return 0;
 
 err_free_fdt:
@@ -326,7 +297,7 @@ static void kho_test_cleanup(void)
 
 static void __exit kho_test_exit(void)
 {
-	unregister_kho_notifier(&kho_test_nb);
+	kho_remove_subtree(folio_address(kho_test_state.fdt));
 	kho_test_cleanup();
 }
 module_exit(kho_test_exit);
mm/memblock.c +13 -49

99 lines not on this page · raw message

Signature · 1 line
2.51.1.930.gacf6e81ea2-goog
#21 lore raw

Re: [PATCH v9 2/9] kho: drop notifiers

kernel test robot noticed "WARNING:at_kernel/kexec_handover.c:#kho_add_subtree" on:

Hello,

kernel test robot noticed "WARNING:at_kernel/kexec_handover.c:#kho_add_subtree" on:

commit: e44a700c561d1e892a8d0829d557e221604a7b93 ("[PATCH v9 2/9] kho: drop notifiers")
url: https://github.com/intel-lab-lkp/linux/commits/Pasha-Tatashin/kho-make-debugfs-interface-optional/20251101-222610
patch link: https://lore.kernel.org/all/[email protected]/
patch subject: [PATCH v9 2/9] kho: drop notifiers

in testcase: boot

config: x86_64-randconfig-001-20251015
compiler: gcc-14
test machine: qemu-system-x86_64 -enable-kvm -cpu SandyBridge -smp 2 -m 16G

(please refer to attached dmesg/kmsg for entire log/backtrace)

+--------------------------------------------------------+------------+------------+
|                                                        | 93e4b3b2e9 | e44a700c56 |
+--------------------------------------------------------+------------+------------+
| WARNING:at_kernel/kexec_handover.c:#kho_add_subtree    | 0          | 8          |
| RIP:kho_add_subtree                                    | 0          | 8          |
+--------------------------------------------------------+------------+------------+

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 <[email protected]>
| Closes: https://lore.kernel.org/oe-lkp/[email protected]

[   13.620111][    T1] ------------[ cut here ]------------
[   13.620739][    T1] WARNING: CPU: 1 PID: 1 at kernel/kexec_handover.c:704 kho_add_subtree (kernel/kexec_handover.c:704)
[   13.621665][    T1] Modules linked in:
[   13.622090][    T1] CPU: 1 UID: 0 PID: 1 Comm: swapper/0 Not tainted 6.18.0-rc3-00211-ge44a700c561d #1 VOLUNTARY
[   13.623073][    T1] Hardware name: QEMU Standard PC (i440FX + PIIX, 1996), BIOS 1.16.3-debian-1.16.3-2 04/01/2014
[   13.624054][    T1] RIP: 0010:kho_add_subtree (kernel/kexec_handover.c:704)
[   13.624596][    T1] Code: c7 38 b4 ac 85 31 ed e8 01 1c 00 00 48 c7 c7 70 5a ca 86 85 c0 89 c3 40 0f 95 c5 31 c9 31 d2 89 ee e8 37 b5 0a 00 85 db 74 02 <0f> 0b b9 01 00 00 00 31 d2 89 ee 48 c7 c7 40 5a ca 86 e8 1c b5 0a
All code
========
   0:	c7 38 b4 ac 85       	xbegin 0xffffffff85acb43d,(bad)
   5:	31 ed                	xor    %ebp,%ebp
   7:	e8 01 1c 00 00       	call   0x1c0d
   c:	48 c7 c7 70 5a ca 86 	mov    $0xffffffff86ca5a70,%rdi
  13:	85 c0                	test   %eax,%eax
  15:	89 c3                	mov    %eax,%ebx
  17:	40 0f 95 c5          	setne  %bpl
  1b:	31 c9                	xor    %ecx,%ecx
  1d:	31 d2                	xor    %edx,%edx
  1f:	89 ee                	mov    %ebp,%esi
  21:	e8 37 b5 0a 00       	call   0xab55d
  26:	85 db                	test   %ebx,%ebx
  28:	74 02                	je     0x2c
  2a:*	0f 0b                	ud2		<-- trapping instruction
  2c:	b9 01 00 00 00       	mov    $0x1,%ecx
  31:	31 d2                	xor    %edx,%edx
  33:	89 ee                	mov    %ebp,%esi
  35:	48 c7 c7 40 5a ca 86 	mov    $0xffffffff86ca5a40,%rdi
  3c:	e8                   	.byte 0xe8
  3d:	1c b5                	sbb    $0xb5,%al
  3f:	0a                   	.byte 0xa

Code starting with the faulting instruction
===========================================

   0:	0f 0b                	ud2
   2:	b9 01 00 00 00       	mov    $0x1,%ecx
   7:	31 d2                	xor    %edx,%edx
   9:	89 ee                	mov    %ebp,%esi
   b:	48 c7 c7 40 5a ca 86 	mov    $0xffffffff86ca5a40,%rdi
  12:	e8                   	.byte 0xe8
  13:	1c b5                	sbb    $0xb5,%al
  15:	0a                   	.byte 0xa
[   13.626370][    T1] RSP: 0018:ffffc9000001fca0 EFLAGS: 00010286
[   13.626951][    T1] RAX: dffffc0000000000 RBX: 00000000ffffffff RCX: 0000000000000000
[   13.627737][    T1] RDX: 1ffffffff0d94b52 RSI: 0000000000000001 RDI: ffffffff86ca5a90
[   13.628523][    T1] RBP: 0000000000000001 R08: 0000000000000008 R09: fffffbfff0dfac4c
[   13.629330][    T1] R10: 0000000000000000 R11: ffffffff86fd6267 R12: ffff888133ee2000
[   13.630101][    T1] R13: ffffffff85acb340 R14: ffff888117a5f988 R15: dffffc0000000000
[   13.630869][    T1] FS:  0000000000000000(0000) GS:ffff888426ea0000(0000) knlGS:0000000000000000
[   13.631727][    T1] CS:  0010 DS: 0000 ES: 0000 CR0: 0000000080050033
[   13.632370][    T1] CR2: 00007f586df260ac CR3: 00000000054ea000 CR4: 00000000000406f0
[   13.633154][    T1] Call Trace:
[   13.633506][    T1]  <TASK>
[   13.633833][    T1]  kho_test_prepare_fdt+0x145/0x180
[   13.634446][    T1]  ? kho_test_save_data+0x210/0x210
[   13.635097][    T1]  ? csum_partial (lib/checksum.c:123)
[   13.635546][    T1]  kho_test_init (lib/test_kho.c:177 lib/test_kho.c:284)
[   13.636018][    T1]  ? vmalloc_test_init (lib/test_kho.c:271)
[   13.636508][    T1]  ? add_device_randomness (drivers/char/random.c:944)
[   13.637485][    T1]  ? mix_pool_bytes (drivers/char/random.c:944)
[   13.637955][    T1]  ? trace_initcall_start (include/trace/events/initcall.h:27 (discriminator 3))
[   13.638498][    T1]  ? vmalloc_test_init (lib/test_kho.c:271)
[   13.638989][    T1]  do_one_initcall (init/main.c:1284)
[   13.639477][    T1]  ? trace_initcall_start (init/main.c:1274)
[   13.639998][    T1]  ? parse_one (kernel/params.c:143)
[   13.640455][    T1]  ? kasan_save_track (mm/kasan/common.c:69 (discriminator 1) mm/kasan/common.c:78 (discriminator 1))
[   13.640948][    T1]  ? __kmalloc_noprof (mm/slub.c:5659)
[   13.641465][    T1]  do_initcalls (init/main.c:1344 (discriminator 3) init/main.c:1361 (discriminator 3))
[   13.641924][    T1]  kernel_init_freeable (init/main.c:1595)
[   13.642441][    T1]  ? rest_init (init/main.c:1475)
[   13.642891][    T1]  kernel_init (init/main.c:1485)
[   13.643345][    T1]  ? rest_init (init/main.c:1475)
[   13.643788][    T1]  ret_from_fork (arch/x86/kernel/process.c:164)
[   13.644256][    T1]  ? rest_init (init/main.c:1475)
[   13.644703][    T1]  ret_from_fork_asm (arch/x86/entry/entry_64.S:255)
[   13.645213][    T1]  </TASK>
[   13.645540][    T1] irq event stamp: 132025
[   13.645971][    T1] hardirqs last  enabled at (132035): __up_console_sem (arch/x86/include/asm/irqflags.h:26 arch/x86/include/asm/irqflags.h:109 arch/x86/include/asm/irqflags.h:151 kernel/printk/printk.c:345)
[   13.646887][    T1] hardirqs last disabled at (132046): __up_console_sem (kernel/printk/printk.c:343 (discriminator 3))
[   13.648253][    T1] softirqs last  enabled at (131286): handle_softirqs (kernel/softirq.c:469 (discriminator 1) kernel/softirq.c:650 (discriminator 1))
[   13.649690][    T1] softirqs last disabled at (131281): __irq_exit_rcu (kernel/softirq.c:496 kernel/softirq.c:723)
[   13.651128][    T1] ---[ end trace 0000000000000000 ]---

The kernel config and materials to reproduce are available at:
https://download.01.org/0day-ci/archive/20251106/[email protected]

Signature · 2 lines
0-DAY CI Kernel Test Service
https://github.com/intel/lkp-tests/wiki
author maintainer
#22 lore raw

Re: [PATCH v9 2/9] kho: drop notifiers

The bug is in lib/test_kho.c, when KHO is not enabled, it should not run KHO commands, there is a function to test that: kho_is_enabled(). So, KHO is disabled and kho_add_subtree() which calles add debugfs entry, and the list is not initialized, because KHO is disabled. The fix is:

lib/test_kho.c +3 -0
index 025ea251a186..85b60d87a50a 100644
@@ -315,6 +315,9 @@ static int __init kho_test_init(void)
        phys_addr_t fdt_phys;
        int err;
 
+       if (!kho_is_enabled())
+               return 0;
+
        err = kho_retrieve_subtree(KHO_TEST_FDT, &fdt_phys);
        if (!err)
                return kho_test_restore(fdt_phys);
Quoted 127 lines · kernel test robot

Hello,

kernel test robot noticed "WARNING:at_kernel/kexec_handover.c:#kho_add_subtree" on:

commit: e44a700c561d1e892a8d0829d557e221604a7b93 ("[PATCH v9 2/9] kho: drop notifiers")
url: https://github.com/intel-lab-lkp/linux/commits/Pasha-Tatashin/kho-make-debugfs-interface-optional/20251101-222610
patch link: https://lore.kernel.org/all/[email protected]/
patch subject: [PATCH v9 2/9] kho: drop notifiers

in testcase: boot

config: x86_64-randconfig-001-20251015
compiler: gcc-14
test machine: qemu-system-x86_64 -enable-kvm -cpu SandyBridge -smp 2 -m 16G

(please refer to attached dmesg/kmsg for entire log/backtrace)

+--------------------------------------------------------+------------+------------+
|                                                        | 93e4b3b2e9 | e44a700c56 |
+--------------------------------------------------------+------------+------------+
| WARNING:at_kernel/kexec_handover.c:#kho_add_subtree    | 0          | 8          |
| RIP:kho_add_subtree                                    | 0          | 8          |
+--------------------------------------------------------+------------+------------+

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 <[email protected]>
| Closes: https://lore.kernel.org/oe-lkp/[email protected]

[   13.620111][    T1] ------------[ cut here ]------------
[   13.620739][    T1] WARNING: CPU: 1 PID: 1 at kernel/kexec_handover.c:704 kho_add_subtree (kernel/kexec_handover.c:704)
[   13.621665][    T1] Modules linked in:
[   13.622090][    T1] CPU: 1 UID: 0 PID: 1 Comm: swapper/0 Not tainted 6.18.0-rc3-00211-ge44a700c561d #1 VOLUNTARY
[   13.623073][    T1] Hardware name: QEMU Standard PC (i440FX + PIIX, 1996), BIOS 1.16.3-debian-1.16.3-2 04/01/2014
[   13.624054][    T1] RIP: 0010:kho_add_subtree (kernel/kexec_handover.c:704)
[   13.624596][    T1] Code: c7 38 b4 ac 85 31 ed e8 01 1c 00 00 48 c7 c7 70 5a ca 86 85 c0 89 c3 40 0f 95 c5 31 c9 31 d2 89 ee e8 37 b5 0a 00 85 db 74 02 <0f> 0b b9 01 00 00 00 31 d2 89 ee 48 c7 c7 40 5a ca 86 e8 1c b5 0a
All code
========
   0:   c7 38 b4 ac 85          xbegin 0xffffffff85acb43d,(bad)
   5:   31 ed                   xor    %ebp,%ebp
   7:   e8 01 1c 00 00          call   0x1c0d
   c:   48 c7 c7 70 5a ca 86    mov    $0xffffffff86ca5a70,%rdi
  13:   85 c0                   test   %eax,%eax
  15:   89 c3                   mov    %eax,%ebx
  17:   40 0f 95 c5             setne  %bpl
  1b:   31 c9                   xor    %ecx,%ecx
  1d:   31 d2                   xor    %edx,%edx
  1f:   89 ee                   mov    %ebp,%esi
  21:   e8 37 b5 0a 00          call   0xab55d
  26:   85 db                   test   %ebx,%ebx
  28:   74 02                   je     0x2c
  2a:*  0f 0b                   ud2             <-- trapping instruction
  2c:   b9 01 00 00 00          mov    $0x1,%ecx
  31:   31 d2                   xor    %edx,%edx
  33:   89 ee                   mov    %ebp,%esi
  35:   48 c7 c7 40 5a ca 86    mov    $0xffffffff86ca5a40,%rdi
  3c:   e8                      .byte 0xe8
  3d:   1c b5                   sbb    $0xb5,%al
  3f:   0a                      .byte 0xa

Code starting with the faulting instruction
===========================================

   0:   0f 0b                   ud2
   2:   b9 01 00 00 00          mov    $0x1,%ecx
   7:   31 d2                   xor    %edx,%edx
   9:   89 ee                   mov    %ebp,%esi
   b:   48 c7 c7 40 5a ca 86    mov    $0xffffffff86ca5a40,%rdi
  12:   e8                      .byte 0xe8
  13:   1c b5                   sbb    $0xb5,%al
  15:   0a                      .byte 0xa
[   13.626370][    T1] RSP: 0018:ffffc9000001fca0 EFLAGS: 00010286
[   13.626951][    T1] RAX: dffffc0000000000 RBX: 00000000ffffffff RCX: 0000000000000000
[   13.627737][    T1] RDX: 1ffffffff0d94b52 RSI: 0000000000000001 RDI: ffffffff86ca5a90
[   13.628523][    T1] RBP: 0000000000000001 R08: 0000000000000008 R09: fffffbfff0dfac4c
[   13.629330][    T1] R10: 0000000000000000 R11: ffffffff86fd6267 R12: ffff888133ee2000
[   13.630101][    T1] R13: ffffffff85acb340 R14: ffff888117a5f988 R15: dffffc0000000000
[   13.630869][    T1] FS:  0000000000000000(0000) GS:ffff888426ea0000(0000) knlGS:0000000000000000
[   13.631727][    T1] CS:  0010 DS: 0000 ES: 0000 CR0: 0000000080050033
[   13.632370][    T1] CR2: 00007f586df260ac CR3: 00000000054ea000 CR4: 00000000000406f0
[   13.633154][    T1] Call Trace:
[   13.633506][    T1]  <TASK>
[   13.633833][    T1]  kho_test_prepare_fdt+0x145/0x180
[   13.634446][    T1]  ? kho_test_save_data+0x210/0x210
[   13.635097][    T1]  ? csum_partial (lib/checksum.c:123)
[   13.635546][    T1]  kho_test_init (lib/test_kho.c:177 lib/test_kho.c:284)
[   13.636018][    T1]  ? vmalloc_test_init (lib/test_kho.c:271)
[   13.636508][    T1]  ? add_device_randomness (drivers/char/random.c:944)
[   13.637485][    T1]  ? mix_pool_bytes (drivers/char/random.c:944)
[   13.637955][    T1]  ? trace_initcall_start (include/trace/events/initcall.h:27 (discriminator 3))
[   13.638498][    T1]  ? vmalloc_test_init (lib/test_kho.c:271)
[   13.638989][    T1]  do_one_initcall (init/main.c:1284)
[   13.639477][    T1]  ? trace_initcall_start (init/main.c:1274)
[   13.639998][    T1]  ? parse_one (kernel/params.c:143)
[   13.640455][    T1]  ? kasan_save_track (mm/kasan/common.c:69 (discriminator 1) mm/kasan/common.c:78 (discriminator 1))
[   13.640948][    T1]  ? __kmalloc_noprof (mm/slub.c:5659)
[   13.641465][    T1]  do_initcalls (init/main.c:1344 (discriminator 3) init/main.c:1361 (discriminator 3))
[   13.641924][    T1]  kernel_init_freeable (init/main.c:1595)
[   13.642441][    T1]  ? rest_init (init/main.c:1475)
[   13.642891][    T1]  kernel_init (init/main.c:1485)
[   13.643345][    T1]  ? rest_init (init/main.c:1475)
[   13.643788][    T1]  ret_from_fork (arch/x86/kernel/process.c:164)
[   13.644256][    T1]  ? rest_init (init/main.c:1475)
[   13.644703][    T1]  ret_from_fork_asm (arch/x86/entry/entry_64.S:255)
[   13.645213][    T1]  </TASK>
[   13.645540][    T1] irq event stamp: 132025
[   13.645971][    T1] hardirqs last  enabled at (132035): __up_console_sem (arch/x86/include/asm/irqflags.h:26 arch/x86/include/asm/irqflags.h:109 arch/x86/include/asm/irqflags.h:151 kernel/printk/printk.c:345)
[   13.646887][    T1] hardirqs last disabled at (132046): __up_console_sem (kernel/printk/printk.c:343 (discriminator 3))
[   13.648253][    T1] softirqs last  enabled at (131286): handle_softirqs (kernel/softirq.c:469 (discriminator 1) kernel/softirq.c:650 (discriminator 1))
[   13.649690][    T1] softirqs last disabled at (131281): __irq_exit_rcu (kernel/softirq.c:496 kernel/softirq.c:723)
[   13.651128][    T1] ---[ end trace 0000000000000000 ]---

The kernel config and materials to reproduce are available at:
https://download.01.org/0day-ci/archive/20251106/[email protected]

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

author maintainer
#23 lore raw

Re: [PATCH v9 2/9] kho: drop notifiers

Quoted 6 lines · Pasha Tatashin

The bug is in lib/test_kho.c, when KHO is not enabled, it should not run KHO commands, there is a function to test that: kho_is_enabled(). So, KHO is disabled and kho_add_subtree() which calles add debugfs entry, and the list is not initialized, because KHO is disabled. The fix is:

Sent it as a patch:
https://lore.kernel.org/all/[email protected]

Quoted 144 lines
lib/test_kho.c +3 -0
index 025ea251a186..85b60d87a50a 100644
@@ -315,6 +315,9 @@ static int __init kho_test_init(void)
        phys_addr_t fdt_phys;
        int err;
 
+       if (!kho_is_enabled())
+               return 0;
+
        err = kho_retrieve_subtree(KHO_TEST_FDT, &fdt_phys);
        if (!err)
                return kho_test_restore(fdt_phys);
Quoted 127 lines · kernel test robot

Hello,

kernel test robot noticed "WARNING:at_kernel/kexec_handover.c:#kho_add_subtree" on:

commit: e44a700c561d1e892a8d0829d557e221604a7b93 ("[PATCH v9 2/9] kho: drop notifiers")
url: https://github.com/intel-lab-lkp/linux/commits/Pasha-Tatashin/kho-make-debugfs-interface-optional/20251101-222610
patch link: https://lore.kernel.org/all/[email protected]/
patch subject: [PATCH v9 2/9] kho: drop notifiers

in testcase: boot

config: x86_64-randconfig-001-20251015
compiler: gcc-14
test machine: qemu-system-x86_64 -enable-kvm -cpu SandyBridge -smp 2 -m 16G

(please refer to attached dmesg/kmsg for entire log/backtrace)

+--------------------------------------------------------+------------+------------+
|                                                        | 93e4b3b2e9 | e44a700c56 |
+--------------------------------------------------------+------------+------------+
| WARNING:at_kernel/kexec_handover.c:#kho_add_subtree    | 0          | 8          |
| RIP:kho_add_subtree                                    | 0          | 8          |
+--------------------------------------------------------+------------+------------+

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 <[email protected]>
| Closes: https://lore.kernel.org/oe-lkp/[email protected]

[   13.620111][    T1] ------------[ cut here ]------------
[   13.620739][    T1] WARNING: CPU: 1 PID: 1 at kernel/kexec_handover.c:704 kho_add_subtree (kernel/kexec_handover.c:704)
[   13.621665][    T1] Modules linked in:
[   13.622090][    T1] CPU: 1 UID: 0 PID: 1 Comm: swapper/0 Not tainted 6.18.0-rc3-00211-ge44a700c561d #1 VOLUNTARY
[   13.623073][    T1] Hardware name: QEMU Standard PC (i440FX + PIIX, 1996), BIOS 1.16.3-debian-1.16.3-2 04/01/2014
[   13.624054][    T1] RIP: 0010:kho_add_subtree (kernel/kexec_handover.c:704)
[   13.624596][    T1] Code: c7 38 b4 ac 85 31 ed e8 01 1c 00 00 48 c7 c7 70 5a ca 86 85 c0 89 c3 40 0f 95 c5 31 c9 31 d2 89 ee e8 37 b5 0a 00 85 db 74 02 <0f> 0b b9 01 00 00 00 31 d2 89 ee 48 c7 c7 40 5a ca 86 e8 1c b5 0a
All code
========
   0:   c7 38 b4 ac 85          xbegin 0xffffffff85acb43d,(bad)
   5:   31 ed                   xor    %ebp,%ebp
   7:   e8 01 1c 00 00          call   0x1c0d
   c:   48 c7 c7 70 5a ca 86    mov    $0xffffffff86ca5a70,%rdi
  13:   85 c0                   test   %eax,%eax
  15:   89 c3                   mov    %eax,%ebx
  17:   40 0f 95 c5             setne  %bpl
  1b:   31 c9                   xor    %ecx,%ecx
  1d:   31 d2                   xor    %edx,%edx
  1f:   89 ee                   mov    %ebp,%esi
  21:   e8 37 b5 0a 00          call   0xab55d
  26:   85 db                   test   %ebx,%ebx
  28:   74 02                   je     0x2c
  2a:*  0f 0b                   ud2             <-- trapping instruction
  2c:   b9 01 00 00 00          mov    $0x1,%ecx
  31:   31 d2                   xor    %edx,%edx
  33:   89 ee                   mov    %ebp,%esi
  35:   48 c7 c7 40 5a ca 86    mov    $0xffffffff86ca5a40,%rdi
  3c:   e8                      .byte 0xe8
  3d:   1c b5                   sbb    $0xb5,%al
  3f:   0a                      .byte 0xa

Code starting with the faulting instruction
===========================================

   0:   0f 0b                   ud2
   2:   b9 01 00 00 00          mov    $0x1,%ecx
   7:   31 d2                   xor    %edx,%edx
   9:   89 ee                   mov    %ebp,%esi
   b:   48 c7 c7 40 5a ca 86    mov    $0xffffffff86ca5a40,%rdi
  12:   e8                      .byte 0xe8
  13:   1c b5                   sbb    $0xb5,%al
  15:   0a                      .byte 0xa
[   13.626370][    T1] RSP: 0018:ffffc9000001fca0 EFLAGS: 00010286
[   13.626951][    T1] RAX: dffffc0000000000 RBX: 00000000ffffffff RCX: 0000000000000000
[   13.627737][    T1] RDX: 1ffffffff0d94b52 RSI: 0000000000000001 RDI: ffffffff86ca5a90
[   13.628523][    T1] RBP: 0000000000000001 R08: 0000000000000008 R09: fffffbfff0dfac4c
[   13.629330][    T1] R10: 0000000000000000 R11: ffffffff86fd6267 R12: ffff888133ee2000
[   13.630101][    T1] R13: ffffffff85acb340 R14: ffff888117a5f988 R15: dffffc0000000000
[   13.630869][    T1] FS:  0000000000000000(0000) GS:ffff888426ea0000(0000) knlGS:0000000000000000
[   13.631727][    T1] CS:  0010 DS: 0000 ES: 0000 CR0: 0000000080050033
[   13.632370][    T1] CR2: 00007f586df260ac CR3: 00000000054ea000 CR4: 00000000000406f0
[   13.633154][    T1] Call Trace:
[   13.633506][    T1]  <TASK>
[   13.633833][    T1]  kho_test_prepare_fdt+0x145/0x180
[   13.634446][    T1]  ? kho_test_save_data+0x210/0x210
[   13.635097][    T1]  ? csum_partial (lib/checksum.c:123)
[   13.635546][    T1]  kho_test_init (lib/test_kho.c:177 lib/test_kho.c:284)
[   13.636018][    T1]  ? vmalloc_test_init (lib/test_kho.c:271)
[   13.636508][    T1]  ? add_device_randomness (drivers/char/random.c:944)
[   13.637485][    T1]  ? mix_pool_bytes (drivers/char/random.c:944)
[   13.637955][    T1]  ? trace_initcall_start (include/trace/events/initcall.h:27 (discriminator 3))
[   13.638498][    T1]  ? vmalloc_test_init (lib/test_kho.c:271)
[   13.638989][    T1]  do_one_initcall (init/main.c:1284)
[   13.639477][    T1]  ? trace_initcall_start (init/main.c:1274)
[   13.639998][    T1]  ? parse_one (kernel/params.c:143)
[   13.640455][    T1]  ? kasan_save_track (mm/kasan/common.c:69 (discriminator 1) mm/kasan/common.c:78 (discriminator 1))
[   13.640948][    T1]  ? __kmalloc_noprof (mm/slub.c:5659)
[   13.641465][    T1]  do_initcalls (init/main.c:1344 (discriminator 3) init/main.c:1361 (discriminator 3))
[   13.641924][    T1]  kernel_init_freeable (init/main.c:1595)
[   13.642441][    T1]  ? rest_init (init/main.c:1475)
[   13.642891][    T1]  kernel_init (init/main.c:1485)
[   13.643345][    T1]  ? rest_init (init/main.c:1475)
[   13.643788][    T1]  ret_from_fork (arch/x86/kernel/process.c:164)
[   13.644256][    T1]  ? rest_init (init/main.c:1475)
[   13.644703][    T1]  ret_from_fork_asm (arch/x86/entry/entry_64.S:255)
[   13.645213][    T1]  </TASK>
[   13.645540][    T1] irq event stamp: 132025
[   13.645971][    T1] hardirqs last  enabled at (132035): __up_console_sem (arch/x86/include/asm/irqflags.h:26 arch/x86/include/asm/irqflags.h:109 arch/x86/include/asm/irqflags.h:151 kernel/printk/printk.c:345)
[   13.646887][    T1] hardirqs last disabled at (132046): __up_console_sem (kernel/printk/printk.c:343 (discriminator 3))
[   13.648253][    T1] softirqs last  enabled at (131286): handle_softirqs (kernel/softirq.c:469 (discriminator 1) kernel/softirq.c:650 (discriminator 1))
[   13.649690][    T1] softirqs last disabled at (131281): __irq_exit_rcu (kernel/softirq.c:496 kernel/softirq.c:723)
[   13.651128][    T1] ---[ end trace 0000000000000000 ]---

The kernel config and materials to reproduce are available at:
https://download.01.org/0day-ci/archive/20251106/[email protected]

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

author maintainer
#24 lore raw

PATCH v9 3/9 kho: add interfaces to unpreserve folios, page ranges, and vmalloc

In reply to Pasha Tatashin

Allow users of KHO to cancel the previous preservation by adding the necessary interfaces to unpreserve folio, pages, and vmallocs.

---
 include/linux/kexec_handover.h |  18 ++++++
 kernel/kexec_handover.c        | 104 ++++++++++++++++++++++++++++-----
 2 files changed, 109 insertions(+), 13 deletions(-)
include/linux/kexec_handover.h +18 -0
index 0d860d793b66..80ece4232617 100644
@@ -43,8 +43,11 @@ bool kho_is_enabled(void);
 bool is_kho_boot(void);
 
 int kho_preserve_folio(struct folio *folio);
+int kho_unpreserve_folio(struct folio *folio);
 int kho_preserve_pages(struct page *page, unsigned int nr_pages);
+int kho_unpreserve_pages(struct page *page, unsigned int nr_pages);
 int kho_preserve_vmalloc(void *ptr, struct kho_vmalloc *preservation);
+int kho_unpreserve_vmalloc(struct kho_vmalloc *preservation);
 struct folio *kho_restore_folio(phys_addr_t phys);
 struct page *kho_restore_pages(phys_addr_t phys, unsigned int nr_pages);
 void *kho_restore_vmalloc(const struct kho_vmalloc *preservation);
@@ -72,17 +75,32 @@ static inline int kho_preserve_folio(struct folio *folio)
 	return -EOPNOTSUPP;
 }
 
+static inline int kho_unpreserve_folio(struct folio *folio)
+{
+	return -EOPNOTSUPP;
+}
+
 static inline int kho_preserve_pages(struct page *page, unsigned int nr_pages)
 {
 	return -EOPNOTSUPP;
 }
 
+static inline int kho_unpreserve_pages(struct page *page, unsigned int nr_pages)
+{
+	return -EOPNOTSUPP;
+}
+
 static inline int kho_preserve_vmalloc(void *ptr,
 				       struct kho_vmalloc *preservation)
 {
 	return -EOPNOTSUPP;
 }
 
+static inline int kho_unpreserve_vmalloc(struct kho_vmalloc *preservation)
+{
+	return -EOPNOTSUPP;
+}
+
 static inline struct folio *kho_restore_folio(phys_addr_t phys)
 {
 	return NULL;
kernel/kexec_handover.c +91 -13

135 lines not on this page · raw message

Signature · 1 line
2.51.1.930.gacf6e81ea2-goog
maintainer
#25 lore raw

Re: [PATCH v9 3/9] kho: add interfaces to unpreserve folios, page ranges, and vmalloc

Hi Pasha,

Quoted 6 lines · Pasha Tatashin

Allow users of KHO to cancel the previous preservation by adding the necessary interfaces to unpreserve folio, pages, and vmallocs.

[...]

Quoted 5 lines
kernel/kexec_handover.c +5 -0
+/**
+ * kho_unpreserve_vmalloc - unpreserve memory allocated with vmalloc()
+ * @preservation: preservation metadata returned by kho_preserve_vmalloc()
+ *
+ * Instructs KHO to unpreserve the area in vmalloc address space that was

kernel/kexec_handover.c int kho_preserve_vmalloc(void *ptr, struct kho_vmalloc *preservation) · line 1024

Quoted 10 lines
kernel/kexec_handover.c +10 -0
+ * previously preserved with kho_preserve_vmalloc().
+ *
+ * Return: 0 on success, error code on failure
+ */
+int kho_unpreserve_vmalloc(struct kho_vmalloc *preservation)
+{
+	if (kho_out.finalized)
+		return -EBUSY;
+
+	kho_vmalloc_free_chunks(preservation);

When reviewing this patch, I spotted that kho_vmalloc_free_chunks() is broken. Well it happens to work if all pages are 0-order, but breaks on higher-order allocations.

I have sent a separate patch [0] to fix this on top of mm-stable. It doesn't have a conflict with this patch so it shouldn't cause trouble. And I **don't** think it should block this patch either. This is mostly a heads up.

[0] https://lore.kernel.org/linux-mm/[email protected]/T/#u

Signature · 2 lines
Regards,
Pratyush Yadav
author maintainer
#26 lore raw

PATCH v9 4/9 memblock: Unpreserve memory in case of error

In reply to Pasha Tatashin

If there is an error half way through KHO memory preservation, we should rollback and unpreserve everything that is partially preserved.

---
 mm/memblock.c | 73 ++++++++++++++++++++++++++++++++++++++++-----------
 1 file changed, 58 insertions(+), 15 deletions(-)
mm/memblock.c +58 -15
index e3bef9b35d63..f527ad1ca682 100644
@@ -2445,29 +2445,60 @@ int reserve_mem_release_by_name(const char *name)
 #define MEMBLOCK_KHO_NODE_COMPATIBLE "memblock-v1"
 #define RESERVE_MEM_KHO_NODE_COMPATIBLE "reserve-mem-v1"
 
+static int __init reserved_mem_preserve(void)
+{
+	unsigned int nr_preserved = 0;
+	int err;
+
+	for (unsigned int i = 0; i < reserved_mem_count; i++, nr_preserved++) {
+		struct reserve_mem_table *map = &reserved_mem_table[i];
+		struct page *page = phys_to_page(map->start);
+		unsigned int nr_pages = map->size >> PAGE_SHIFT;
+
+		err = kho_preserve_pages(page, nr_pages);
+		if (err)
+			goto err_unpreserve;
+	}
+
+	return 0;
+
+err_unpreserve:
+	for (unsigned int i = 0; i < nr_preserved; i++) {
+		struct reserve_mem_table *map = &reserved_mem_table[i];
+		struct page *page = phys_to_page(map->start);
+		unsigned int nr_pages = map->size >> PAGE_SHIFT;
+
+		kho_unpreserve_pages(page, nr_pages);
+	}
+
+	return err;
+}
+
 static int __init prepare_kho_fdt(void)
 {
-	int err = 0, i;
 	struct page *fdt_page;
 	void *fdt;
+	int err;
 
 	fdt_page = alloc_page(GFP_KERNEL);
-	if (!fdt_page)
-		return -ENOMEM;
+	if (!fdt_page) {
+		err = -ENOMEM;
+		goto err_no_fdt_page;
+	}
 
 	fdt = page_to_virt(fdt_page);
+	err = kho_preserve_pages(fdt_page, 1);
+	if (err)
+		goto err_free_fdt;
 
 	err |= fdt_create(fdt, PAGE_SIZE);
 	err |= fdt_finish_reservemap(fdt);
-
 	err |= fdt_begin_node(fdt, "");
 	err |= fdt_property_string(fdt, "compatible", MEMBLOCK_KHO_NODE_COMPATIBLE);
-	for (i = 0; i < reserved_mem_count; i++) {
+
+	for (unsigned int i = 0; !err && i < reserved_mem_count; i++) {
 		struct reserve_mem_table *map = &reserved_mem_table[i];
-		struct page *page = phys_to_page(map->start);
-		unsigned int nr_pages = map->size >> PAGE_SHIFT;
 
-		err |= kho_preserve_pages(page, nr_pages);
 		err |= fdt_begin_node(fdt, map->name);
 		err |= fdt_property_string(fdt, "compatible", RESERVE_MEM_KHO_NODE_COMPATIBLE);
 		err |= fdt_property(fdt, "start", &map->start, sizeof(map->start));
@@ -2477,15 +2508,27 @@ static int __init prepare_kho_fdt(void)
 	err |= fdt_end_node(fdt);
 	err |= fdt_finish(fdt);
 
-	err |= kho_preserve_folio(page_folio(fdt_page));
+	if (err)
+		goto err_unpreserve_fdt;
 
-	if (!err)
-		err = kho_add_subtree(MEMBLOCK_KHO_FDT, fdt);
+	err = kho_add_subtree(MEMBLOCK_KHO_FDT, fdt);
+	if (err)
+		goto err_unpreserve_fdt;
 
-	if (err) {
-		pr_err("failed to prepare memblock FDT for KHO: %d\n", err);
-		put_page(fdt_page);
-	}
+	err = reserved_mem_preserve();
+	if (err)
+		goto err_remove_subtree;
+
+	return 0;
+
+err_remove_subtree:
+	kho_remove_subtree(fdt);
+err_unpreserve_fdt:
+	kho_unpreserve_pages(fdt_page, 1);
+err_free_fdt:
+	put_page(fdt_page);
+err_no_fdt_page:
+	pr_err("failed to prepare memblock FDT for KHO: %d\n", err);
 
 	return err;
 }
Signature · 1 line
2.51.1.930.gacf6e81ea2-goog
maintainer Reviewed-by on v9 4/9
#27 lore raw

Re: [PATCH v9 4/9] memblock: Unpreserve memory in case of error

Quoted 5 lines · Pasha Tatashin

If there is an error half way through KHO memory preservation, we should rollback and unpreserve everything that is partially preserved.

with a small nit below.

Quoted 9 lines
---
 mm/memblock.c | 73 ++++++++++++++++++++++++++++++++++++++++-----------
 1 file changed, 58 insertions(+), 15 deletions(-)
mm/memblock.c +0 -0
index e3bef9b35d63..f527ad1ca682 100644
@@ -2445,29 +2445,60 @@ int reserve_mem_release_by_name(const char *name)

...

mm/memblock.c int reserve_mem_release_by_name(const char *name) · line 2486

Quoted 13 lines

static int __init prepare_kho_fdt(void)
{

mm/memblock.c +4 -3
-	int err = 0, i;
 	struct page *fdt_page;
 	void *fdt;
+	int err;
 
 	fdt_page = alloc_page(GFP_KERNEL);
-	if (!fdt_page)
-		return -ENOMEM;
+	if (!fdt_page) {
+		err = -ENOMEM;
+		goto err_no_fdt_page;

Please rename the label to describe what the goto does, say, err_report. I believe it can be a fixup on top after Andrew merges these.

...

Quoted 14 lines
mm/memblock.c +8 -0
+err_remove_subtree:
+	kho_remove_subtree(fdt);
+err_unpreserve_fdt:
+	kho_unpreserve_pages(fdt_page, 1);
+err_free_fdt:
+	put_page(fdt_page);
+err_no_fdt_page:
+	pr_err("failed to prepare memblock FDT for KHO: %d\n", err);
 
 	return err;
 }
Signature · 1 line
2.51.1.930.gacf6e81ea2-goog
Signature · 2 lines
Sincerely yours,
Mike.
maintainer Reviewed-by on v9 4/9
#28 lore raw

Re: [PATCH v9 4/9] memblock: Unpreserve memory in case of error

In reply to Pasha Tatashin
Quoted 5 lines · Pasha Tatashin

If there is an error half way through KHO memory preservation, we should rollback and unpreserve everything that is partially preserved.

Nice! This is quite an improvement in readability compared to the previous version.

[...]

Signature · 2 lines
Regards,
Pratyush Yadav
author maintainer
#29 lore raw

PATCH v9 5/9 test_kho: Unpreserve memory in case of error

In reply to Pasha Tatashin

If there is an error half way through KHO memory preservation, we should rollback and unpreserve everything that is partially preserved.

---
 lib/test_kho.c | 103 +++++++++++++++++++++++++++++++++++--------------
 1 file changed, 73 insertions(+), 30 deletions(-)
lib/test_kho.c +73 -30
index 9f7cfa6ac855..025ea251a186 100644
@@ -33,17 +33,28 @@ struct kho_test_state {
 	unsigned int nr_folios;
 	struct folio **folios;
 	phys_addr_t *folios_info;
+	struct kho_vmalloc folios_info_phys;
+	int nr_folios_preserved;
 	struct folio *fdt;
 	__wsum csum;
 };
 
 static struct kho_test_state kho_test_state;
 
-static int kho_test_save_data(struct kho_test_state *state, void *fdt)
+static void kho_test_unpreserve_data(struct kho_test_state *state)
+{
+	for (int i = 0; i < state->nr_folios_preserved; i++)
+		kho_unpreserve_folio(state->folios[i]);
+
+	kho_unpreserve_vmalloc(&state->folios_info_phys);
+	vfree(state->folios_info);
+}
+
+static int kho_test_preserve_data(struct kho_test_state *state)
 {
-	phys_addr_t *folios_info __free(kvfree) = NULL;
 	struct kho_vmalloc folios_info_phys;
-	int err = 0;
+	phys_addr_t *folios_info;
+	int err;
 
 	folios_info = vmalloc_array(state->nr_folios, sizeof(*folios_info));
 	if (!folios_info)
@@ -51,64 +62,98 @@ static int kho_test_save_data(struct kho_test_state *state, void *fdt)
 
 	err = kho_preserve_vmalloc(folios_info, &folios_info_phys);
 	if (err)
-		return err;
+		goto err_free_info;
+
+	state->folios_info_phys = folios_info_phys;
+	state->folios_info = folios_info;
 
 	for (int i = 0; i < state->nr_folios; i++) {
 		struct folio *folio = state->folios[i];
 		unsigned int order = folio_order(folio);
 
 		folios_info[i] = virt_to_phys(folio_address(folio)) | order;
-
 		err = kho_preserve_folio(folio);
 		if (err)
-			break;
+			goto err_unpreserve;
+		state->nr_folios_preserved++;
 	}
 
+	return 0;
+
+err_unpreserve:
+	/*
+	 * kho_test_unpreserve_data frees folio_info, bail out immediately to
+	 * avoid double free
+	 */
+	kho_test_unpreserve_data(state);
+	return err;
+
+err_free_info:
+	vfree(folios_info);
+	return err;
+}
+
+static int kho_test_prepare_fdt(struct kho_test_state *state, ssize_t fdt_size)
+{
+	const char compatible[] = KHO_TEST_COMPAT;
+	unsigned int magic = KHO_TEST_MAGIC;
+	void *fdt = folio_address(state->fdt);
+	int err;
+
+	err = fdt_create(fdt, fdt_size);
+	err |= fdt_finish_reservemap(fdt);
+	err |= fdt_begin_node(fdt, "");
+	err |= fdt_property(fdt, "compatible", compatible, sizeof(compatible));
+	err |= fdt_property(fdt, "magic", &magic, sizeof(magic));
+
 	err |= fdt_begin_node(fdt, "data");
 	err |= fdt_property(fdt, "nr_folios", &state->nr_folios,
 			    sizeof(state->nr_folios));
-	err |= fdt_property(fdt, "folios_info", &folios_info_phys,
-			    sizeof(folios_info_phys));
+	err |= fdt_property(fdt, "folios_info", &state->folios_info_phys,
+			    sizeof(state->folios_info_phys));
 	err |= fdt_property(fdt, "csum", &state->csum, sizeof(state->csum));
 	err |= fdt_end_node(fdt);
 
-	if (!err)
-		state->folios_info = no_free_ptr(folios_info);
+	err |= fdt_end_node(fdt);
+	err |= fdt_finish(fdt);
 
 	return err;
 }
 
-static int kho_test_prepare_fdt(struct kho_test_state *state)
+static int kho_test_preserve(struct kho_test_state *state)
 {
-	const char compatible[] = KHO_TEST_COMPAT;
-	unsigned int magic = KHO_TEST_MAGIC;
 	ssize_t fdt_size;
-	int err = 0;
-	void *fdt;
+	int err;
 
 	fdt_size = state->nr_folios * sizeof(phys_addr_t) + PAGE_SIZE;
 	state->fdt = folio_alloc(GFP_KERNEL, get_order(fdt_size));
 	if (!state->fdt)
 		return -ENOMEM;
 
-	fdt = folio_address(state->fdt);
-
-	err |= kho_preserve_folio(state->fdt);
-	err |= fdt_create(fdt, fdt_size);
-	err |= fdt_finish_reservemap(fdt);
+	err = kho_preserve_folio(state->fdt);
+	if (err)
+		goto err_free_fdt;
 
-	err |= fdt_begin_node(fdt, "");
-	err |= fdt_property(fdt, "compatible", compatible, sizeof(compatible));
-	err |= fdt_property(fdt, "magic", &magic, sizeof(magic));
-	err |= kho_test_save_data(state, fdt);
-	err |= fdt_end_node(fdt);
+	err = kho_test_preserve_data(state);
+	if (err)
+		goto err_unpreserve_fdt;
 
-	err |= fdt_finish(fdt);
+	err = kho_test_prepare_fdt(state, fdt_size);
+	if (err)
+		goto err_unpreserve_data;
 
 	err = kho_add_subtree(KHO_TEST_FDT, folio_address(state->fdt));
 	if (err)
-		folio_put(state->fdt);
+		goto err_unpreserve_data;
 
+	return 0;
+
+err_unpreserve_data:
+	kho_test_unpreserve_data(state);
+err_unpreserve_fdt:
+	kho_unpreserve_folio(state->fdt);
+err_free_fdt:
+	folio_put(state->fdt);
 	return err;
 }
 
@@ -174,14 +219,12 @@ static int kho_test_save(void)
 	if (err)
 		goto err_free_folios;
 
-	err = kho_test_prepare_fdt(state);
+	err = kho_test_preserve(state);
 	if (err)
 		goto err_free_folios;
 
 	return 0;
 
-err_free_fdt:
-	folio_put(state->fdt);
 err_free_folios:
 	kvfree(folios);
 	return err;
Signature · 1 line
2.51.1.930.gacf6e81ea2-goog
author maintainer
#30 lore raw

PATCH v9 6/9 kho: don't unpreserve memory during abort

In reply to Pasha Tatashin

KHO allows clients to preserve memory regions at any point before the KHO state is finalized. The finalization process itself involves KHO performing its own actions, such as serializing the overall preserved memory map.

If this finalization process is aborted, the current implementation destroys KHO's internal memory tracking structures (kho_out.ser.track.orders). This behavior effectively unpreserves all memory from KHO's perspective, regardless of whether those preservations were made by clients before the finalization attempt or by KHO itself during finalization.

This premature unpreservation is incorrect. An abort of the finalization process should only undo actions taken by KHO as part of that specific finalization attempt. Individual memory regions preserved by clients prior to finalization should remain preserved, as their lifecycle is managed by the clients themselves. These clients might still need to call kho_unpreserve_folio() or kho_unpreserve_phys() based on their own logic, even after a KHO finalization attempt is aborted.

---
 kernel/kexec_handover.c | 21 +--------------------
 1 file changed, 1 insertion(+), 20 deletions(-)
kernel/kexec_handover.c +1 -20
index c514b300ebe6..3adf86c7c2db 100644
@@ -1118,31 +1118,12 @@ EXPORT_SYMBOL_GPL(kho_restore_vmalloc);
 
 static int __kho_abort(void)
 {
-	int err = 0;
-	unsigned long order;
-	struct kho_mem_phys *physxa;
-
-	xa_for_each(&kho_out.track.orders, order, physxa) {
-		struct kho_mem_phys_bits *bits;
-		unsigned long phys;
-
-		xa_for_each(&physxa->phys_bits, phys, bits)
-			kfree(bits);
-
-		xa_destroy(&physxa->phys_bits);
-		kfree(physxa);
-	}
-	xa_destroy(&kho_out.track.orders);
-
 	if (kho_out.preserved_mem_map) {
 		kho_mem_ser_free(kho_out.preserved_mem_map);
 		kho_out.preserved_mem_map = NULL;
 	}
 
-	if (err)
-		pr_err("Failed to abort KHO finalization: %d\n", err);
-
-	return err;
+	return 0;
 }
 
 int kho_abort(void)
Signature · 1 line
2.51.1.930.gacf6e81ea2-goog
maintainer Reviewed-by on v9 6/9
#31 lore raw

Re: [PATCH v9 6/9] kho: don't unpreserve memory during abort

Quoted 21 lines · Pasha Tatashin

KHO allows clients to preserve memory regions at any point before the KHO state is finalized. The finalization process itself involves KHO performing its own actions, such as serializing the overall preserved memory map.

If this finalization process is aborted, the current implementation destroys KHO's internal memory tracking structures (kho_out.ser.track.orders). This behavior effectively unpreserves all memory from KHO's perspective, regardless of whether those preservations were made by clients before the finalization attempt or by KHO itself during finalization.

This premature unpreservation is incorrect. An abort of the finalization process should only undo actions taken by KHO as part of that specific finalization attempt. Individual memory regions preserved by clients prior to finalization should remain preserved, as their lifecycle is managed by the clients themselves. These clients might still need to call kho_unpreserve_folio() or kho_unpreserve_phys() based on their own logic, even after a KHO finalization attempt is aborted.

Quoted 1 line

[...]

Signature · 2 lines
Regards,
Pratyush Yadav
author maintainer
#32 lore raw

PATCH v9 7/9 liveupdate: kho: move to kernel/liveupdate

In reply to Pasha Tatashin

Move KHO to kernel/liveupdate/ in preparation of placing all Live Update core kernel related files to the same place.

---
 Documentation/core-api/kho/concepts.rst       |  2 +-
 MAINTAINERS                                   |  2 +-
 init/Kconfig                                  |  2 +
 kernel/Kconfig.kexec                          | 34 ----------------
 kernel/Makefile                               |  4 +-
 kernel/liveupdate/Kconfig                     | 39 +++++++++++++++++++
 kernel/liveupdate/Makefile                    |  5 +++
 kernel/{ => liveupdate}/kexec_handover.c      |  4 +-
 .../{ => liveupdate}/kexec_handover_debug.c   |  0
 .../{ => liveupdate}/kexec_handover_debugfs.c |  0
 .../kexec_handover_internal.h                 |  0
 11 files changed, 51 insertions(+), 41 deletions(-)
 create mode 100644 kernel/liveupdate/Kconfig
 create mode 100644 kernel/liveupdate/Makefile
 rename kernel/{ => liveupdate}/kexec_handover.c (99%)
 rename kernel/{ => liveupdate}/kexec_handover_debug.c (100%)
 rename kernel/{ => liveupdate}/kexec_handover_debugfs.c (100%)
 rename kernel/{ => liveupdate}/kexec_handover_internal.h (100%)
Documentation/core-api/kho/concepts.rst +1 -1
index 36d5c05cfb30..d626d1dbd678 100644
@@ -70,5 +70,5 @@ in the FDT. That state is called the KHO finalization phase.
 
 Public API
 ==========
-.. kernel-doc:: kernel/kexec_handover.c
+.. kernel-doc:: kernel/liveupdate/kexec_handover.c
    :export:
MAINTAINERS +1 -1
index bdd0a1260421..764df916fae7 100644
@@ -13795,7 +13795,7 @@ S:	Maintained
 F:	Documentation/admin-guide/mm/kho.rst
 F:	Documentation/core-api/kho/*
 F:	include/linux/kexec_handover.h
-F:	kernel/kexec_handover*
+F:	kernel/liveupdate/kexec_handover*
 F:	tools/testing/selftests/kho/
 
 KEYS-ENCRYPTED
init/Kconfig +2 -0
index cab3ad28ca49..0605de5d96c0 100644
@@ -2138,6 +2138,8 @@ config TRACEPOINTS
 
 source "kernel/Kconfig.kexec"
 
+source "kernel/liveupdate/Kconfig"
+
 endmenu		# General setup
 
 source "arch/Kconfig"
kernel/Kconfig.kexec +0 -34
index cc6743137946..15632358bcf7 100644
@@ -94,40 +94,6 @@ config KEXEC_JUMP
 	  Jump between original kernel and kexeced kernel and invoke
 	  code in physical address mode via KEXEC
 
-config KEXEC_HANDOVER
-	bool "kexec handover"
-	depends on ARCH_SUPPORTS_KEXEC_HANDOVER && ARCH_SUPPORTS_KEXEC_FILE
-	depends on !DEFERRED_STRUCT_PAGE_INIT
-	select MEMBLOCK_KHO_SCRATCH
-	select KEXEC_FILE
-	select LIBFDT
-	select CMA
-	help
-	  Allow kexec to hand over state across kernels by generating and
-	  passing additional metadata to the target kernel. This is useful
-	  to keep data or state alive across the kexec. For this to work,
-	  both source and target kernels need to have this option enabled.
-
-config KEXEC_HANDOVER_DEBUG
-	bool "Enable Kexec Handover debug checks"
-	depends on KEXEC_HANDOVER
-	help
-	  This option enables extra sanity checks for the Kexec Handover
-	  subsystem. Since, KHO performance is crucial in live update
-	  scenarios and the extra code might be adding overhead it is
-	  only optionally enabled.
-
-config KEXEC_HANDOVER_DEBUGFS
-	bool "kexec handover debugfs interface"
-	default KEXEC_HANDOVER
-	depends on KEXEC_HANDOVER
-	select DEBUG_FS
-	help
-	  Allow to control kexec handover device tree via debugfs
-	  interface, i.e. finalize the state or aborting the finalization.
-	  Also, enables inspecting the KHO fdt trees with the debugfs binary
-	  blobs.
-
 config CRASH_DUMP
 	bool "kernel crash dumps"
 	default ARCH_DEFAULT_CRASH_DUMP
kernel/Makefile +1 -3
index 2cf7909a74e5..e83669841b8c 100644
@@ -52,6 +52,7 @@ obj-y += printk/
 obj-y += irq/
 obj-y += rcu/
 obj-y += livepatch/
+obj-y += liveupdate/
 obj-y += dma/
 obj-y += entry/
 obj-y += unwind/
@@ -82,9 +83,6 @@ obj-$(CONFIG_CRASH_DUMP_KUNIT_TEST) += crash_core_test.o
 obj-$(CONFIG_KEXEC) += kexec.o
 obj-$(CONFIG_KEXEC_FILE) += kexec_file.o
 obj-$(CONFIG_KEXEC_ELF) += kexec_elf.o
-obj-$(CONFIG_KEXEC_HANDOVER) += kexec_handover.o
-obj-$(CONFIG_KEXEC_HANDOVER_DEBUG) += kexec_handover_debug.o
-obj-$(CONFIG_KEXEC_HANDOVER_DEBUGFS) += kexec_handover_debugfs.o
 obj-$(CONFIG_BACKTRACE_SELF_TEST) += backtracetest.o
 obj-$(CONFIG_COMPAT) += compat.o
 obj-$(CONFIG_CGROUPS) += cgroup/
kernel/liveupdate/Kconfig new file +39 -0
new file mode 100644
index 000000000000..1379a4c40b09
@@ -0,0 +1,39 @@
+# SPDX-License-Identifier: GPL-2.0-only
+
+menu "Live Update and Kexec HandOver"
+
+config KEXEC_HANDOVER
+	bool "kexec handover"
+	depends on ARCH_SUPPORTS_KEXEC_HANDOVER && ARCH_SUPPORTS_KEXEC_FILE
+	depends on !DEFERRED_STRUCT_PAGE_INIT
+	select MEMBLOCK_KHO_SCRATCH
+	select KEXEC_FILE
+	select LIBFDT
+	select CMA
+	help
+	  Allow kexec to hand over state across kernels by generating and
+	  passing additional metadata to the target kernel. This is useful
+	  to keep data or state alive across the kexec. For this to work,
+	  both source and target kernels need to have this option enabled.
+
+config KEXEC_HANDOVER_DEBUG
+	bool "Enable Kexec Handover debug checks"
+	depends on KEXEC_HANDOVER
+	help
+	  This option enables extra sanity checks for the Kexec Handover
+	  subsystem. Since, KHO performance is crucial in live update
+	  scenarios and the extra code might be adding overhead it is
+	  only optionally enabled.
+
+config KEXEC_HANDOVER_DEBUGFS
+	bool "kexec handover debugfs interface"
+	default KEXEC_HANDOVER
+	depends on KEXEC_HANDOVER
+	select DEBUG_FS
+	help
+	  Allow to control kexec handover device tree via debugfs
+	  interface, i.e. finalize the state or aborting the finalization.
+	  Also, enables inspecting the KHO fdt trees with the debugfs binary
+	  blobs.
+
+endmenu
kernel/liveupdate/Makefile new file +5 -0
new file mode 100644
index 000000000000..f52ce1ebcf86
@@ -0,0 +1,5 @@
+# SPDX-License-Identifier: GPL-2.0
+
+obj-$(CONFIG_KEXEC_HANDOVER)		+= kexec_handover.o
+obj-$(CONFIG_KEXEC_HANDOVER_DEBUG)	+= kexec_handover_debug.o
+obj-$(CONFIG_KEXEC_HANDOVER_DEBUGFS)	+= kexec_handover_debugfs.o
kernel/liveupdate/kexec_handover.c renamed from kernel/kexec_handover.c +2 -2
similarity index 99%
rename from kernel/kexec_handover.c
rename to kernel/liveupdate/kexec_handover.c
index 3adf86c7c2db..be945c133a2f 100644
@@ -26,8 +26,8 @@
  * KHO is tightly coupled with mm init and needs access to some of mm
  * internal APIs.
  */
-#include "../mm/internal.h"
-#include "kexec_internal.h"
+#include "../../mm/internal.h"
+#include "../kexec_internal.h"
 #include "kexec_handover_internal.h"
 
 #define KHO_FDT_COMPATIBLE "kho-v1"
kernel/liveupdate/kexec_handover_debug.c renamed from kernel/kexec_handover_debug.c +0 -0
similarity index 100%
rename from kernel/kexec_handover_debug.c
rename to kernel/liveupdate/kexec_handover_debug.c
kernel/liveupdate/kexec_handover_debugfs.c renamed from kernel/kexec_handover_debugfs.c +0 -0
similarity index 100%
rename from kernel/kexec_handover_debugfs.c
rename to kernel/liveupdate/kexec_handover_debugfs.c
kernel/liveupdate/kexec_handover_internal.h renamed from kernel/kexec_handover_internal.h +0 -0
similarity index 100%
rename from kernel/kexec_handover_internal.h
rename to kernel/liveupdate/kexec_handover_internal.h
Signature · 1 line
2.51.1.930.gacf6e81ea2-goog
#33 lore raw

Re: [PATCH v9 7/9] liveupdate: kho: move to kernel/liveupdate

as we understand, this commit is not the root cause of the WARNING. but just changes the stats as below table [1]

Hello,

as we understand, this commit is not the root cause of the WARNING. but just changes the stats as below table [1]

we just report FYI there is a WARNING caused by related code in our tests, in case anybody think it's worth to look further. thanks

kernel test robot noticed "WARNING:at_kernel/liveupdate/kexec_handover.c:#kho_add_subtree" on:

commit: 91cb1aaea4b8276323b3814d35f6e62133f64c1b ("[PATCH v9 7/9] liveupdate: kho: move to kernel/liveupdate")
url: https://github.com/intel-lab-lkp/linux/commits/Pasha-Tatashin/kho-make-debugfs-interface-optional/20251101-222610
patch link: https://lore.kernel.org/all/[email protected]/
patch subject: [PATCH v9 7/9] liveupdate: kho: move to kernel/liveupdate

in testcase: boot

config: x86_64-randconfig-001-20251015
compiler: gcc-14
test machine: qemu-system-x86_64 -enable-kvm -cpu SandyBridge -smp 2 -m 16G

(please refer to attached dmesg/kmsg for entire log/backtrace)

[1]

+--------------------------------------------------------------------------------------+------------+------------+
|                                                                                      | dc74e80622 | 91cb1aaea4 |
+--------------------------------------------------------------------------------------+------------+------------+
| WARNING:at_kernel/kexec_handover.c:#kho_add_subtree                                  | 8          |            |
| WARNING:at_kernel/liveupdate/kexec_handover.c:#kho_add_subtree                       | 0          | 11         |
+--------------------------------------------------------------------------------------+------------+------------+

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 <[email protected]>
| Closes: https://lore.kernel.org/oe-lkp/[email protected]

[   12.679864][    T1] ------------[ cut here ]------------
[   12.680514][    T1] WARNING: CPU: 0 PID: 1 at kernel/liveupdate/kexec_handover.c:711 kho_add_subtree (kernel/liveupdate/kexec_handover.c:711)
[   12.681526][    T1] Modules linked in:
[   12.681957][    T1] CPU: 0 UID: 0 PID: 1 Comm: swapper/0 Not tainted 6.18.0-rc3-00216-g91cb1aaea4b8 #1 VOLUNTARY
[   12.682956][    T1] Hardware name: QEMU Standard PC (i440FX + PIIX, 1996), BIOS 1.16.3-debian-1.16.3-2 04/01/2014
[   12.683951][    T1] RIP: 0010:kho_add_subtree (kernel/liveupdate/kexec_handover.c:711)
[   12.684514][    T1] Code: c7 58 2e a7 85 31 ed e8 31 1a 00 00 48 c7 c7 c0 12 c9 86 85 c0 89 c3 40 0f 95 c5 31 c9 31 d2 89 ee e8 57 a0 13 00 85 db 74 02 <0f> 0b b9 01 00 00 00 31 d2 89 ee 48 c7 c7 90 12 c9 86 e8 3c a0 13
All code
========
   0:	c7                   	(bad)
   1:	58                   	pop    %rax
   2:	2e a7                	cmpsl  %es:(%rdi),%ds:(%rsi)
   4:	85 31                	test   %esi,(%rcx)
   6:	ed                   	in     (%dx),%eax
   7:	e8 31 1a 00 00       	call   0x1a3d
   c:	48 c7 c7 c0 12 c9 86 	mov    $0xffffffff86c912c0,%rdi
  13:	85 c0                	test   %eax,%eax
  15:	89 c3                	mov    %eax,%ebx
  17:	40 0f 95 c5          	setne  %bpl
  1b:	31 c9                	xor    %ecx,%ecx
  1d:	31 d2                	xor    %edx,%edx
  1f:	89 ee                	mov    %ebp,%esi
  21:	e8 57 a0 13 00       	call   0x13a07d
  26:	85 db                	test   %ebx,%ebx
  28:	74 02                	je     0x2c
  2a:*	0f 0b                	ud2		<-- trapping instruction
  2c:	b9 01 00 00 00       	mov    $0x1,%ecx
  31:	31 d2                	xor    %edx,%edx
  33:	89 ee                	mov    %ebp,%esi
  35:	48 c7 c7 90 12 c9 86 	mov    $0xffffffff86c91290,%rdi
  3c:	e8                   	.byte 0xe8
  3d:	3c a0                	cmp    $0xa0,%al
  3f:	13                   	.byte 0x13

Code starting with the faulting instruction
===========================================

   0:	0f 0b                	ud2
   2:	b9 01 00 00 00       	mov    $0x1,%ecx
   7:	31 d2                	xor    %edx,%edx
   9:	89 ee                	mov    %ebp,%esi
   b:	48 c7 c7 90 12 c9 86 	mov    $0xffffffff86c91290,%rdi
  12:	e8                   	.byte 0xe8
  13:	3c a0                	cmp    $0xa0,%al
  15:	13                   	.byte 0x13
[   12.686315][    T1] RSP: 0018:ffffc9000001fc58 EFLAGS: 00010286
[   12.687184][    T1] RAX: dffffc0000000000 RBX: 00000000ffffffff RCX: 0000000000000000
[   12.688370][    T1] RDX: 1ffffffff0d9225c RSI: 0000000000000001 RDI: ffffffff86c912e0
[   12.689572][    T1] RBP: 0000000000000001 R08: 0000000000000008 R09: fffffbfff0dfac6c
[   12.690762][    T1] R10: 0000000000000000 R11: ffffffff86fd6367 R12: ffff888133ce6000
[   12.691996][    T1] R13: ffffffff85a72d60 R14: ffff88810ce59888 R15: dffffc0000000000
[   12.693231][    T1] FS:  0000000000000000(0000) GS:ffff888426da0000(0000) knlGS:0000000000000000
[   12.694585][    T1] CS:  0010 DS: 0000 ES: 0000 CR0: 0000000080050033
[   12.695569][    T1] CR2: 00007f6d5dc8f0ac CR3: 00000000054ea000 CR4: 00000000000406f0
[   12.696832][    T1] Call Trace:
[   12.697400][    T1]  <TASK>
[   12.697922][    T1]  kho_test_preserve+0x2fa/0x360
[   12.698835][    T1]  ? folio_order (arch/x86/kvm/../../../virt/kvm/guest_memfd.c:181 (discriminator 3))
[   12.699556][    T1]  ? kho_test_generate_data+0x107/0x180
[   12.700561][    T1]  kho_test_init (lib/test_kho.c:222 lib/test_kho.c:327)
[   12.701312][    T1]  ? vmalloc_test_init (lib/test_kho.c:314)
[   12.702100][    T1]  ? add_device_randomness (drivers/char/random.c:944)
[   12.702924][    T1]  ? mix_pool_bytes (drivers/char/random.c:944)
[   12.703646][    T1]  ? trace_initcall_start (include/trace/events/initcall.h:27 (discriminator 3))
[   12.704499][    T1]  ? vmalloc_test_init (lib/test_kho.c:314)
[   12.705291][    T1]  do_one_initcall (init/main.c:1284)
[   12.706047][    T1]  ? trace_initcall_start (init/main.c:1274)
[   12.706897][    T1]  ? parse_one (kernel/params.c:143)
[   12.707623][    T1]  ? kasan_save_track (mm/kasan/common.c:69 (discriminator 1) mm/kasan/common.c:78 (discriminator 1))
[   12.708394][    T1]  ? __kmalloc_noprof (mm/slub.c:5659)
[   12.709218][    T1]  do_initcalls (init/main.c:1344 (discriminator 3) init/main.c:1361 (discriminator 3))
[   12.709976][    T1]  kernel_init_freeable (init/main.c:1595)
[   12.710752][    T1]  ? rest_init (init/main.c:1475)
[   12.711473][    T1]  kernel_init (init/main.c:1485)
[   12.712165][    T1]  ? rest_init (init/main.c:1475)
[   12.712871][    T1]  ret_from_fork (arch/x86/kernel/process.c:164)
[   12.713609][    T1]  ? rest_init (init/main.c:1475)
[   12.714326][    T1]  ret_from_fork_asm (arch/x86/entry/entry_64.S:255)
[   12.715029][    T1]  </TASK>
[   12.715548][    T1] irq event stamp: 131753
[   12.716243][    T1] hardirqs last  enabled at (131763): __up_console_sem (arch/x86/include/asm/irqflags.h:26 arch/x86/include/asm/irqflags.h:109 arch/x86/include/asm/irqflags.h:151 kernel/printk/printk.c:345)
[   12.717702][    T1] hardirqs last disabled at (131776): __up_console_sem (kernel/printk/printk.c:343 (discriminator 3))
[   12.719185][    T1] softirqs last  enabled at (131460): handle_softirqs (kernel/softirq.c:469 (discriminator 1) kernel/softirq.c:650 (discriminator 1))
[   12.720632][    T1] softirqs last disabled at (131455): __irq_exit_rcu (kernel/softirq.c:496 kernel/softirq.c:723)
[   12.721755][    T1] ---[ end trace 0000000000000000 ]---

The kernel config and materials to reproduce are available at:
https://download.01.org/0day-ci/archive/20251106/[email protected]

Signature · 2 lines
0-DAY CI Kernel Test Service
https://github.com/intel/lkp-tests/wiki
maintainer
#34 lore raw

Re: [PATCH v9 7/9] liveupdate: kho: move to kernel/liveupdate

In reply to Pasha Tatashin
Quoted 2 lines · On Sat, 1 Nov 2025 10:23:23 -0400 Pasha Tatashin <[email protected]>…

Move KHO to kernel/liveupdate/ in preparation of placing all Live Update core kernel related files to the same place.

I notice that menuconfig is a bit weird after this.

The "General setup" menu offers the "Live Update and Kexec HandOver" menu but there's nothing in there. If one sets DEFERRED_STRUCT_PAGE_INIT then things look normal.

Perhaps we shouldn't be offering "Live Update and Kexec HandOver" at all if !DEFERRED_STRUCT_PAGE_INIT.

author maintainer
#35 lore raw

Re: [PATCH v9 7/9] liveupdate: kho: move to kernel/liveupdate

Quoted 6 lines · Andrew Morton
Quoted 2 lines · On Sat, 1 Nov 2025 10:23:23 -0400 Pasha Tatashin <[email protected]>…

Move KHO to kernel/liveupdate/ in preparation of placing all Live Update core kernel related files to the same place.

Quoted 8 lines

I notice that menuconfig is a bit weird after this.

The "General setup" menu offers the "Live Update and Kexec HandOver" menu but there's nothing in there. If one sets DEFERRED_STRUCT_PAGE_INIT then things look normal.

Perhaps we shouldn't be offering "Live Update and Kexec HandOver" at all if !DEFERRED_STRUCT_PAGE_INIT.

Hi Andrew, thank you for noticing this, yes, indeed it looks strange when empty. Let's disable the menu when DEFERRED_STRUCT_PAGE_INIT until we relax this KHO/deferred init dependency.

kernel/liveupdate/Kconfig +1 -0
index 054f6375a7af..d7344d347f69 100644
@@ -7,6 +7,7 @@
 #
 
 menu "Live Update and Kexec HandOver"
+       depends on !DEFERRED_STRUCT_PAGE_INIT
 
 config LIVEUPDATE
        bool "Live Update Orchestrator"
author maintainer
#36 lore raw

PATCH v9 8/9 MAINTAINERS: update KHO maintainers

In reply to Pasha Tatashin

Changyuan does not have cycles to commit to the upstream work of KHO. Remove from KHO maintainers.

---
 MAINTAINERS | 2 +-
 1 file changed, 1 insertion(+), 1 deletion(-)
MAINTAINERS +1 -1
index 764df916fae7..6200de2027fe 100644
@@ -13788,7 +13788,7 @@ F:	kernel/kexec*
 KEXEC HANDOVER (KHO)
 M:	Alexander Graf <[email protected]>
 M:	Mike Rapoport <[email protected]>
-M:	Changyuan Lyu <[email protected]>
+M:	Pasha Tatashin <[email protected]>
 L:	[email protected]
 L:	[email protected]
 S:	Maintained
Signature · 1 line
2.51.1.930.gacf6e81ea2-goog
maintainer Reviewed-by on v9 8/9
#37 lore raw

Re: [PATCH v9 8/9] MAINTAINERS: update KHO maintainers

Quoted 5 lines · Pasha Tatashin

Changyuan does not have cycles to commit to the upstream work of KHO. Remove from KHO maintainers.

Quoted 20 lines
---
 MAINTAINERS | 2 +-
 1 file changed, 1 insertion(+), 1 deletion(-)
MAINTAINERS +1 -1
index 764df916fae7..6200de2027fe 100644
@@ -13788,7 +13788,7 @@ F:	kernel/kexec*
 KEXEC HANDOVER (KHO)
 M:	Alexander Graf <[email protected]>
 M:	Mike Rapoport <[email protected]>
-M:	Changyuan Lyu <[email protected]>
+M:	Pasha Tatashin <[email protected]>
 L:	[email protected]
 L:	[email protected]
 S:	Maintained
Signature · 1 line
2.51.1.930.gacf6e81ea2-goog
Signature · 2 lines
Sincerely yours,
Mike.
author maintainer
#38 lore raw

PATCH v9 9/9 liveupdate: kho: Use %pe format specifier for error pointer printing

In reply to Pasha Tatashin

From: Zhu Yanjun <[email protected]>

Make pr_xxx() call to use the %pe format specifier instead of %d. The %pe specifier prints a symbolic error string (e.g., -ENOMEM, -EINVAL) when given an error pointer created with ERR_PTR(err).

This change enhances the clarity and diagnostic value of the error message by showing a descriptive error name rather than a numeric error code.

Note, that some err are still printed by value, as those errors might come from libfdt and not regular errnos.

---
 kernel/liveupdate/kexec_handover.c         |  4 ++--
 kernel/liveupdate/kexec_handover_debugfs.c | 10 ++++++----
 2 files changed, 8 insertions(+), 6 deletions(-)
kernel/liveupdate/kexec_handover.c +2 -2
index be945c133a2f..167c761988d3 100644
@@ -1448,8 +1448,8 @@ void __init kho_populate(phys_addr_t fdt_phys, u64 fdt_len,
 		memblock_add(area->addr, size);
 		err = memblock_mark_kho_scratch(area->addr, size);
 		if (WARN_ON(err)) {
-			pr_warn("failed to mark the scratch region 0x%pa+0x%pa: %d",
-				&area->addr, &size, err);
+			pr_warn("failed to mark the scratch region 0x%pa+0x%pa: %pe",
+				&area->addr, &size, ERR_PTR(err));
 			goto out;
 		}
 		pr_debug("Marked 0x%pa+0x%pa as scratch", &area->addr, &size);
kernel/liveupdate/kexec_handover_debugfs.c +6 -4
index 46e9e6c0791f..ac739d25094d 100644
@@ -150,8 +150,8 @@ __init void kho_in_debugfs_init(struct kho_debugfs *dbg, const void *fdt)
 		err = __kho_debugfs_fdt_add(&dbg->fdt_list, sub_fdt_dir, name,
 					    phys_to_virt(*fdt_phys));
 		if (err) {
-			pr_warn("failed to add fdt %s to debugfs: %d\n", name,
-				err);
+			pr_warn("failed to add fdt %s to debugfs: %pe\n", name,
+				ERR_PTR(err));
 			continue;
 		}
 	}
@@ -168,8 +168,10 @@ __init void kho_in_debugfs_init(struct kho_debugfs *dbg, const void *fdt)
 	 * reviving state from KHO and setting up KHO for the next
 	 * kexec.
 	 */
-	if (err)
-		pr_err("failed exposing handover FDT in debugfs: %d\n", err);
+	if (err) {
+		pr_err("failed exposing handover FDT in debugfs: %pe\n",
+		       ERR_PTR(err));
+	}
 }
 
 __init int kho_out_debugfs_init(struct kho_debugfs *dbg)
Signature · 1 line
2.51.1.930.gacf6e81ea2-goog
#39 lore raw

Re: [PATCH v9 9/9] liveupdate: kho: Use %pe format specifier for error pointer printing

Quoted 10 lines · Pasha Tatashin

From: Zhu Yanjun <[email protected]>

Make pr_xxx() call to use the %pe format specifier instead of %d. The %pe specifier prints a symbolic error string (e.g., -ENOMEM, -EINVAL) when given an error pointer created with ERR_PTR(err).

This change enhances the clarity and diagnostic value of the error message by showing a descriptive error name rather than a numeric error code.

Quoted 6 lines

Note, that some err are still printed by value, as those errors might come from libfdt and not regular errnos.

Appreciate your help, Pasha

Yanjun.Zhu

Quoted 49 lines
---
  kernel/liveupdate/kexec_handover.c         |  4 ++--
  kernel/liveupdate/kexec_handover_debugfs.c | 10 ++++++----
  2 files changed, 8 insertions(+), 6 deletions(-)
kernel/liveupdate/kexec_handover.c +2 -2
index be945c133a2f..167c761988d3 100644
@@ -1448,8 +1448,8 @@ void __init kho_populate(phys_addr_t fdt_phys, u64 fdt_len,
  		memblock_add(area->addr, size);
  		err = memblock_mark_kho_scratch(area->addr, size);
  		if (WARN_ON(err)) {
-			pr_warn("failed to mark the scratch region 0x%pa+0x%pa: %d",
-				&area->addr, &size, err);
+			pr_warn("failed to mark the scratch region 0x%pa+0x%pa: %pe",
+				&area->addr, &size, ERR_PTR(err));
  			goto out;
  		}
  		pr_debug("Marked 0x%pa+0x%pa as scratch", &area->addr, &size);
kernel/liveupdate/kexec_handover_debugfs.c +6 -4
index 46e9e6c0791f..ac739d25094d 100644
@@ -150,8 +150,8 @@ __init void kho_in_debugfs_init(struct kho_debugfs *dbg, const void *fdt)
  		err = __kho_debugfs_fdt_add(&dbg->fdt_list, sub_fdt_dir, name,
  					    phys_to_virt(*fdt_phys));
  		if (err) {
-			pr_warn("failed to add fdt %s to debugfs: %d\n", name,
-				err);
+			pr_warn("failed to add fdt %s to debugfs: %pe\n", name,
+				ERR_PTR(err));
  			continue;
  		}
  	}
@@ -168,8 +168,10 @@ __init void kho_in_debugfs_init(struct kho_debugfs *dbg, const void *fdt)
  	 * reviving state from KHO and setting up KHO for the next
  	 * kexec.
  	 */
-	if (err)
-		pr_err("failed exposing handover FDT in debugfs: %d\n", err);
+	if (err) {
+		pr_err("failed exposing handover FDT in debugfs: %pe\n",
+		       ERR_PTR(err));
+	}
  }
 
  __init int kho_out_debugfs_init(struct kho_debugfs *dbg)
Signature · 2 lines
Best Regards,
Yanjun.Zhu
maintainer Reviewed-by on v9 9/9
#40 lore raw

Re: [PATCH v9 9/9] liveupdate: kho: Use %pe format specifier for error pointer printing

In reply to Pasha Tatashin
Quoted 10 lines · Pasha Tatashin

From: Zhu Yanjun <[email protected]>

Make pr_xxx() call to use the %pe format specifier instead of %d. The %pe specifier prints a symbolic error string (e.g., -ENOMEM, -EINVAL) when given an error pointer created with ERR_PTR(err).

This change enhances the clarity and diagnostic value of the error message by showing a descriptive error name rather than a numeric error code.

Quoted 7 lines

Note, that some err are still printed by value, as those errors might come from libfdt and not regular errnos.

Quoted 4 lines
---
 kernel/liveupdate/kexec_handover.c         |  4 ++--
 kernel/liveupdate/kexec_handover_debugfs.c | 10 ++++++----
 2 files changed, 8 insertions(+), 6 deletions(-)
Signature · 2 lines
Sincerely yours,
Mike.
maintainer Reviewed-by on v9 9/9
#41 lore raw

Re: [PATCH v9 9/9] liveupdate: kho: Use %pe format specifier for error pointer printing

In reply to Pasha Tatashin
Quoted 6 lines · Pasha Tatashin

From: Zhu Yanjun <[email protected]>

Make pr_xxx() call to use the %pe format specifier instead of %d. The %pe specifier prints a symbolic error string (e.g., -ENOMEM, -EINVAL) when given an error pointer created with ERR_PTR(err).

Quoted 6 lines

This change enhances the clarity and diagnostic value of the error message by showing a descriptive error name rather than a numeric error code.

Note, that some err are still printed by value, as those errors might come from libfdt and not regular errnos.

There is fdt_strerror() that does this for libfdt errnos. Something to do in a follow up patch I suppose.

Quoted 5 lines

[...]

Signature · 2 lines
Regards,
Pratyush Yadav