linux-mm.kvack.org archive mirror
 help / color / mirror / Atom feed
* [PATCH v9 0/9] liveupdate: Rework KHO for in-kernel users
@ 2025-11-01 14:23 Pasha Tatashin
  2025-11-01 14:23 ` [PATCH v9 1/9] kho: make debugfs interface optional Pasha Tatashin
                   ` (8 more replies)
  0 siblings, 9 replies; 42+ messages in thread
From: Pasha Tatashin @ 2025-11-01 14:23 UTC (permalink / raw)
  To: akpm, brauner, corbet, graf, jgg, linux-kernel, linux-kselftest,
	linux-mm, masahiroy, ojeda, pasha.tatashin, pratyush, rdunlap,
	rppt, tj, yanjun.zhu

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/20251020100306.2709352-1-jasonmiu@google.com

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
-- 
2.51.1.930.gacf6e81ea2-goog



^ permalink raw reply	[flat|nested] 42+ messages in thread

* [PATCH v9 1/9] kho: make debugfs interface optional
  2025-11-01 14:23 [PATCH v9 0/9] liveupdate: Rework KHO for in-kernel users Pasha Tatashin
@ 2025-11-01 14:23 ` Pasha Tatashin
  2025-11-07  6:03   ` Zhu Yanjun
  2025-11-01 14:23 ` [PATCH v9 2/9] kho: drop notifiers Pasha Tatashin
                   ` (7 subsequent siblings)
  8 siblings, 1 reply; 42+ messages in thread
From: Pasha Tatashin @ 2025-11-01 14:23 UTC (permalink / raw)
  To: akpm, brauner, corbet, graf, jgg, linux-kernel, linux-kselftest,
	linux-mm, masahiroy, ojeda, pasha.tatashin, pratyush, rdunlap,
	rppt, tj, yanjun.zhu

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.

Co-developed-by: Mike Rapoport (Microsoft) <rppt@kernel.org>
Signed-off-by: Mike Rapoport (Microsoft) <rppt@kernel.org>
Signed-off-by: Pasha Tatashin <pasha.tatashin@soleen.com>
Reviewed-by: Pratyush Yadav <pratyush@kernel.org>
---
 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

diff --git a/MAINTAINERS b/MAINTAINERS
index 2628431dcdfe..bdd0a1260421 100644
--- a/MAINTAINERS
+++ b/MAINTAINERS
@@ -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
diff --git a/kernel/Kconfig.kexec b/kernel/Kconfig.kexec
index 54e581072617..cc6743137946 100644
--- a/kernel/Kconfig.kexec
+++ b/kernel/Kconfig.kexec
@@ -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
diff --git a/kernel/Makefile b/kernel/Makefile
index 9fe722305c9b..2cf7909a74e5 100644
--- a/kernel/Makefile
+++ b/kernel/Makefile
@@ -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/
diff --git a/kernel/kexec_handover.c b/kernel/kexec_handover.c
index de4466b47455..da071277d85e 100644
--- a/kernel/kexec_handover.c
+++ b/kernel/kexec_handover.c
@@ -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;
 	}
 
diff --git a/kernel/kexec_handover_debugfs.c b/kernel/kexec_handover_debugfs.c
new file mode 100644
index 000000000000..a91b279f1b23
--- /dev/null
+++ b/kernel/kexec_handover_debugfs.c
@@ -0,0 +1,216 @@
+// SPDX-License-Identifier: GPL-2.0-only
+/*
+ * kexec_handover_debugfs.c - kexec handover debugfs interfaces
+ * Copyright (C) 2023 Alexander Graf <graf@amazon.com>
+ * Copyright (C) 2025 Microsoft Corporation, Mike Rapoport <rppt@kernel.org>
+ * Copyright (C) 2025 Google LLC, Changyuan Lyu <changyuanl@google.com>
+ * Copyright (C) 2025 Google LLC, Pasha Tatashin <pasha.tatashin@soleen.com>
+ */
+
+#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;
+}
diff --git a/kernel/kexec_handover_internal.h b/kernel/kexec_handover_internal.h
index 05e9720ba7b9..217b8b25a542 100644
--- a/kernel/kexec_handover_internal.h
+++ b/kernel/kexec_handover_internal.h
@@ -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
diff --git a/tools/testing/selftests/kho/vmtest.sh b/tools/testing/selftests/kho/vmtest.sh
index 3f6c17166846..49fdac8e8b15 100755
--- a/tools/testing/selftests/kho/vmtest.sh
+++ b/tools/testing/selftests/kho/vmtest.sh
@@ -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
-- 
2.51.1.930.gacf6e81ea2-goog



^ permalink raw reply related	[flat|nested] 42+ messages in thread

* [PATCH v9 2/9] kho: drop notifiers
  2025-11-01 14:23 [PATCH v9 0/9] liveupdate: Rework KHO for in-kernel users Pasha Tatashin
  2025-11-01 14:23 ` [PATCH v9 1/9] kho: make debugfs interface optional Pasha Tatashin
@ 2025-11-01 14:23 ` Pasha Tatashin
  2025-11-06  8:41   ` kernel test robot
  2025-11-01 14:23 ` [PATCH v9 3/9] kho: add interfaces to unpreserve folios, page ranges, and vmalloc Pasha Tatashin
                   ` (6 subsequent siblings)
  8 siblings, 1 reply; 42+ messages in thread
From: Pasha Tatashin @ 2025-11-01 14:23 UTC (permalink / raw)
  To: akpm, brauner, corbet, graf, jgg, linux-kernel, linux-kselftest,
	linux-mm, masahiroy, ojeda, pasha.tatashin, pratyush, rdunlap,
	rppt, tj, yanjun.zhu

From: "Mike Rapoport (Microsoft)" <rppt@kernel.org>

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.

Signed-off-by: Mike Rapoport (Microsoft) <rppt@kernel.org>
Co-developed-by: Pasha Tatashin <pasha.tatashin@soleen.com>
Signed-off-by: Pasha Tatashin <pasha.tatashin@soleen.com>
---
 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(-)

diff --git a/include/linux/kexec_handover.h b/include/linux/kexec_handover.h
index 25042c1d8d54..0d860d793b66 100644
--- a/include/linux/kexec_handover.h
+++ b/include/linux/kexec_handover.h
@@ -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;
 }
diff --git a/kernel/kexec_handover.c b/kernel/kexec_handover.c
index da071277d85e..82137eba1474 100644
--- a/kernel/kexec_handover.c
+++ b/kernel/kexec_handover.c
@@ -16,7 +16,6 @@
 #include <linux/libfdt.h>
 #include <linux/list.h>
 #include <linux/memblock.h>
-#include <linux/notifier.h>
 #include <linux/page-isolation.h>
 #include <linux/vmalloc.h>
 
@@ -103,29 +102,34 @@ struct kho_mem_track {
 
 struct khoser_mem_chunk;
 
-struct kho_serialization {
-	struct page *fdt;
-	struct kho_mem_track track;
-	/* First chunk of serialized preserved memory map */
-	struct khoser_mem_chunk *preserved_mem_map;
+struct kho_sub_fdt {
+	struct list_head l;
+	const char *name;
+	void *fdt;
 };
 
 struct kho_out {
-	struct blocking_notifier_head chain_head;
-	struct mutex lock; /* protects KHO FDT finalization */
-	struct kho_serialization ser;
+	void *fdt;
 	bool finalized;
+	struct mutex lock; /* protects KHO FDT finalization */
+
+	struct list_head sub_fdts;
+	struct mutex fdts_lock;
+
+	struct kho_mem_track track;
+	/* First chunk of serialized preserved memory map */
+	struct khoser_mem_chunk *preserved_mem_map;
+
 	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 = {
-		.track = {
-			.orders = XARRAY_INIT(kho_out.ser.track.orders, 0),
-		},
+	.track = {
+		.orders = XARRAY_INIT(kho_out.track.orders, 0),
 	},
+	.sub_fdts = LIST_HEAD_INIT(kho_out.sub_fdts),
+	.fdts_lock = __MUTEX_INITIALIZER(kho_out.fdts_lock),
 	.finalized = false,
 };
 
@@ -369,7 +373,7 @@ static void kho_mem_ser_free(struct khoser_mem_chunk *first_chunk)
 	}
 }
 
-static int kho_mem_serialize(struct kho_serialization *ser)
+static int kho_mem_serialize(struct kho_out *kho_out)
 {
 	struct khoser_mem_chunk *first_chunk = NULL;
 	struct khoser_mem_chunk *chunk = NULL;
@@ -377,7 +381,7 @@ static int kho_mem_serialize(struct kho_serialization *ser)
 	unsigned long order;
 	int err = -ENOMEM;
 
-	xa_for_each(&ser->track.orders, order, physxa) {
+	xa_for_each(&kho_out->track.orders, order, physxa) {
 		struct kho_mem_phys_bits *bits;
 		unsigned long phys;
 
@@ -409,7 +413,7 @@ static int kho_mem_serialize(struct kho_serialization *ser)
 		}
 	}
 
-	ser->preserved_mem_map = first_chunk;
+	kho_out->preserved_mem_map = first_chunk;
 
 	return 0;
 
@@ -670,7 +674,6 @@ static void __init kho_reserve_scratch(void)
 
 /**
  * kho_add_subtree - record the physical address of a sub FDT in KHO root tree.
- * @ser: serialization control object passed by KHO notifiers.
  * @name: name of the sub tree.
  * @fdt: the sub tree blob.
  *
@@ -684,34 +687,41 @@ static void __init kho_reserve_scratch(void)
  *
  * Return: 0 on success, error code on failure
  */
-int kho_add_subtree(struct kho_serialization *ser, const char *name, void *fdt)
+int kho_add_subtree(const char *name, void *fdt)
 {
-	int err = 0;
-	u64 phys = (u64)virt_to_phys(fdt);
-	void *root = page_to_virt(ser->fdt);
+	struct kho_sub_fdt *sub_fdt;
 
-	err |= fdt_begin_node(root, name);
-	err |= fdt_property(root, PROP_SUB_FDT, &phys, sizeof(phys));
-	err |= fdt_end_node(root);
+	sub_fdt = kmalloc(sizeof(*sub_fdt), GFP_KERNEL);
+	if (!sub_fdt)
+		return -ENOMEM;
 
-	if (err)
-		return err;
+	INIT_LIST_HEAD(&sub_fdt->l);
+	sub_fdt->name = name;
+	sub_fdt->fdt = fdt;
 
-	return kho_debugfs_fdt_add(&kho_out.dbg, name, fdt, false);
-}
-EXPORT_SYMBOL_GPL(kho_add_subtree);
+	guard(mutex)(&kho_out.fdts_lock);
+	list_add_tail(&sub_fdt->l, &kho_out.sub_fdts);
+	WARN_ON_ONCE(kho_debugfs_fdt_add(&kho_out.dbg, name, fdt, false));
 
-int register_kho_notifier(struct notifier_block *nb)
-{
-	return blocking_notifier_chain_register(&kho_out.chain_head, nb);
+	return 0;
 }
-EXPORT_SYMBOL_GPL(register_kho_notifier);
+EXPORT_SYMBOL_GPL(kho_add_subtree);
 
-int unregister_kho_notifier(struct notifier_block *nb)
+void kho_remove_subtree(void *fdt)
 {
-	return blocking_notifier_chain_unregister(&kho_out.chain_head, nb);
+	struct kho_sub_fdt *sub_fdt;
+
+	guard(mutex)(&kho_out.fdts_lock);
+	list_for_each_entry(sub_fdt, &kho_out.sub_fdts, l) {
+		if (sub_fdt->fdt == fdt) {
+			list_del(&sub_fdt->l);
+			kfree(sub_fdt);
+			kho_debugfs_fdt_remove(&kho_out.dbg, fdt);
+			break;
+		}
+	}
 }
-EXPORT_SYMBOL_GPL(unregister_kho_notifier);
+EXPORT_SYMBOL_GPL(kho_remove_subtree);
 
 /**
  * kho_preserve_folio - preserve a folio across kexec.
@@ -726,7 +736,7 @@ int kho_preserve_folio(struct folio *folio)
 {
 	const unsigned long pfn = folio_pfn(folio);
 	const unsigned int order = folio_order(folio);
-	struct kho_mem_track *track = &kho_out.ser.track;
+	struct kho_mem_track *track = &kho_out.track;
 
 	if (WARN_ON(kho_scratch_overlap(pfn << PAGE_SHIFT, PAGE_SIZE << order)))
 		return -EINVAL;
@@ -747,7 +757,7 @@ EXPORT_SYMBOL_GPL(kho_preserve_folio);
  */
 int kho_preserve_pages(struct page *page, unsigned int nr_pages)
 {
-	struct kho_mem_track *track = &kho_out.ser.track;
+	struct kho_mem_track *track = &kho_out.track;
 	const unsigned long start_pfn = page_to_pfn(page);
 	const unsigned long end_pfn = start_pfn + nr_pages;
 	unsigned long pfn = start_pfn;
@@ -848,7 +858,7 @@ static struct kho_vmalloc_chunk *new_vmalloc_chunk(struct kho_vmalloc_chunk *cur
 
 static void kho_vmalloc_unpreserve_chunk(struct kho_vmalloc_chunk *chunk)
 {
-	struct kho_mem_track *track = &kho_out.ser.track;
+	struct kho_mem_track *track = &kho_out.track;
 	unsigned long pfn = PHYS_PFN(virt_to_phys(chunk));
 
 	__kho_unpreserve(track, pfn, pfn + 1);
@@ -1030,11 +1040,11 @@ EXPORT_SYMBOL_GPL(kho_restore_vmalloc);
 
 static int __kho_abort(void)
 {
-	int err;
+	int err = 0;
 	unsigned long order;
 	struct kho_mem_phys *physxa;
 
-	xa_for_each(&kho_out.ser.track.orders, order, physxa) {
+	xa_for_each(&kho_out.track.orders, order, physxa) {
 		struct kho_mem_phys_bits *bits;
 		unsigned long phys;
 
@@ -1044,17 +1054,13 @@ static int __kho_abort(void)
 		xa_destroy(&physxa->phys_bits);
 		kfree(physxa);
 	}
-	xa_destroy(&kho_out.ser.track.orders);
+	xa_destroy(&kho_out.track.orders);
 
-	if (kho_out.ser.preserved_mem_map) {
-		kho_mem_ser_free(kho_out.ser.preserved_mem_map);
-		kho_out.ser.preserved_mem_map = NULL;
+	if (kho_out.preserved_mem_map) {
+		kho_mem_ser_free(kho_out.preserved_mem_map);
+		kho_out.preserved_mem_map = NULL;
 	}
 
-	err = blocking_notifier_call_chain(&kho_out.chain_head, KEXEC_KHO_ABORT,
-					   NULL);
-	err = notifier_to_errno(err);
-
 	if (err)
 		pr_err("Failed to abort KHO finalization: %d\n", err);
 
@@ -1077,7 +1083,8 @@ int kho_abort(void)
 		return ret;
 
 	kho_out.finalized = false;
-	kho_debugfs_cleanup(&kho_out.dbg);
+
+	kho_debugfs_fdt_remove(&kho_out.dbg, kho_out.fdt);
 
 	return 0;
 }
@@ -1086,41 +1093,46 @@ static int __kho_finalize(void)
 {
 	int err = 0;
 	u64 *preserved_mem_map;
-	void *fdt = page_to_virt(kho_out.ser.fdt);
+	void *root = kho_out.fdt;
+	struct kho_sub_fdt *fdt;
 
-	err |= fdt_create(fdt, PAGE_SIZE);
-	err |= fdt_finish_reservemap(fdt);
-	err |= fdt_begin_node(fdt, "");
-	err |= fdt_property_string(fdt, "compatible", KHO_FDT_COMPATIBLE);
+	err |= fdt_create(root, PAGE_SIZE);
+	err |= fdt_finish_reservemap(root);
+	err |= fdt_begin_node(root, "");
+	err |= fdt_property_string(root, "compatible", KHO_FDT_COMPATIBLE);
 	/**
 	 * Reserve the preserved-memory-map property in the root FDT, so
 	 * that all property definitions will precede subnodes created by
 	 * KHO callers.
 	 */
-	err |= fdt_property_placeholder(fdt, PROP_PRESERVED_MEMORY_MAP,
+	err |= fdt_property_placeholder(root, PROP_PRESERVED_MEMORY_MAP,
 					sizeof(*preserved_mem_map),
 					(void **)&preserved_mem_map);
 	if (err)
 		goto abort;
 
-	err = kho_preserve_folio(page_folio(kho_out.ser.fdt));
+	err = kho_preserve_folio(virt_to_folio(kho_out.fdt));
 	if (err)
 		goto abort;
 
-	err = blocking_notifier_call_chain(&kho_out.chain_head,
-					   KEXEC_KHO_FINALIZE, &kho_out.ser);
-	err = notifier_to_errno(err);
+	err = kho_mem_serialize(&kho_out);
 	if (err)
 		goto abort;
 
-	err = kho_mem_serialize(&kho_out.ser);
-	if (err)
-		goto abort;
+	*preserved_mem_map = (u64)virt_to_phys(kho_out.preserved_mem_map);
+
+	mutex_lock(&kho_out.fdts_lock);
+	list_for_each_entry(fdt, &kho_out.sub_fdts, l) {
+		phys_addr_t phys = virt_to_phys(fdt->fdt);
 
-	*preserved_mem_map = (u64)virt_to_phys(kho_out.ser.preserved_mem_map);
+		err |= fdt_begin_node(root, fdt->name);
+		err |= fdt_property(root, PROP_SUB_FDT, &phys, sizeof(phys));
+		err |= fdt_end_node(root);
+	}
+	mutex_unlock(&kho_out.fdts_lock);
 
-	err |= fdt_end_node(fdt);
-	err |= fdt_finish(fdt);
+	err |= fdt_end_node(root);
+	err |= fdt_finish(root);
 
 abort:
 	if (err) {
@@ -1148,8 +1160,10 @@ int kho_finalize(void)
 
 	kho_out.finalized = true;
 
-	return kho_debugfs_fdt_add(&kho_out.dbg, "fdt",
-				   page_to_virt(kho_out.ser.fdt), true);
+	WARN_ON_ONCE(kho_debugfs_fdt_add(&kho_out.dbg, "fdt",
+					 kho_out.fdt, true));
+
+	return 0;
 }
 
 bool kho_finalized(void)
@@ -1232,15 +1246,17 @@ static __init int kho_init(void)
 {
 	int err = 0;
 	const void *fdt = kho_get_fdt();
+	struct page *fdt_page;
 
 	if (!kho_enable)
 		return 0;
 
-	kho_out.ser.fdt = alloc_page(GFP_KERNEL);
-	if (!kho_out.ser.fdt) {
+	fdt_page = alloc_page(GFP_KERNEL);
+	if (!fdt_page) {
 		err = -ENOMEM;
 		goto err_free_scratch;
 	}
+	kho_out.fdt = page_to_virt(fdt_page);
 
 	err = kho_debugfs_init();
 	if (err)
@@ -1268,8 +1284,8 @@ static __init int kho_init(void)
 	return 0;
 
 err_free_fdt:
-	put_page(kho_out.ser.fdt);
-	kho_out.ser.fdt = NULL;
+	put_page(fdt_page);
+	kho_out.fdt = NULL;
 err_free_scratch:
 	for (int i = 0; i < kho_scratch_cnt; i++) {
 		void *start = __va(kho_scratch[i].addr);
@@ -1280,7 +1296,7 @@ static __init int kho_init(void)
 	kho_enable = false;
 	return err;
 }
-late_initcall(kho_init);
+fs_initcall(kho_init);
 
 static void __init kho_release_scratch(void)
 {
@@ -1416,7 +1432,7 @@ int kho_fill_kimage(struct kimage *image)
 	if (!kho_out.finalized)
 		return 0;
 
-	image->kho.fdt = page_to_phys(kho_out.ser.fdt);
+	image->kho.fdt = virt_to_phys(kho_out.fdt);
 
 	scratch_size = sizeof(*kho_scratch) * kho_scratch_cnt;
 	scratch = (struct kexec_buf){
diff --git a/kernel/kexec_handover_debugfs.c b/kernel/kexec_handover_debugfs.c
index a91b279f1b23..46e9e6c0791f 100644
--- a/kernel/kexec_handover_debugfs.c
+++ b/kernel/kexec_handover_debugfs.c
@@ -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;
+		}
 	}
 }
 
diff --git a/kernel/kexec_handover_internal.h b/kernel/kexec_handover_internal.h
index 217b8b25a542..52ed73659fe6 100644
--- a/kernel/kexec_handover_internal.h
+++ b/kernel/kexec_handover_internal.h
@@ -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
diff --git a/lib/test_kho.c b/lib/test_kho.c
index 60cd899ea745..9f7cfa6ac855 100644
--- a/lib/test_kho.c
+++ b/lib/test_kho.c
@@ -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);
diff --git a/mm/memblock.c b/mm/memblock.c
index e23e16618e9b..e3bef9b35d63 100644
--- a/mm/memblock.c
+++ b/mm/memblock.c
@@ -2444,53 +2444,18 @@ int reserve_mem_release_by_name(const char *name)
 #define MEMBLOCK_KHO_FDT "memblock"
 #define MEMBLOCK_KHO_NODE_COMPATIBLE "memblock-v1"
 #define RESERVE_MEM_KHO_NODE_COMPATIBLE "reserve-mem-v1"
-static struct page *kho_fdt;
-
-static int reserve_mem_kho_finalize(struct kho_serialization *ser)
-{
-	int err = 0, i;
-
-	for (i = 0; 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 |= kho_preserve_folio(page_folio(kho_fdt));
-	err |= kho_add_subtree(ser, MEMBLOCK_KHO_FDT, page_to_virt(kho_fdt));
-
-	return notifier_from_errno(err);
-}
-
-static int reserve_mem_kho_notifier(struct notifier_block *self,
-				    unsigned long cmd, void *v)
-{
-	switch (cmd) {
-	case KEXEC_KHO_FINALIZE:
-		return reserve_mem_kho_finalize((struct kho_serialization *)v);
-	case KEXEC_KHO_ABORT:
-		return NOTIFY_DONE;
-	default:
-		return NOTIFY_BAD;
-	}
-}
-
-static struct notifier_block reserve_mem_kho_nb = {
-	.notifier_call = reserve_mem_kho_notifier,
-};
 
 static int __init prepare_kho_fdt(void)
 {
 	int err = 0, i;
+	struct page *fdt_page;
 	void *fdt;
 
-	kho_fdt = alloc_page(GFP_KERNEL);
-	if (!kho_fdt)
+	fdt_page = alloc_page(GFP_KERNEL);
+	if (!fdt_page)
 		return -ENOMEM;
 
-	fdt = page_to_virt(kho_fdt);
+	fdt = page_to_virt(fdt_page);
 
 	err |= fdt_create(fdt, PAGE_SIZE);
 	err |= fdt_finish_reservemap(fdt);
@@ -2499,7 +2464,10 @@ static int __init prepare_kho_fdt(void)
 	err |= fdt_property_string(fdt, "compatible", MEMBLOCK_KHO_NODE_COMPATIBLE);
 	for (i = 0; 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));
@@ -2507,13 +2475,16 @@ static int __init prepare_kho_fdt(void)
 		err |= fdt_end_node(fdt);
 	}
 	err |= fdt_end_node(fdt);
-
 	err |= fdt_finish(fdt);
 
+	err |= kho_preserve_folio(page_folio(fdt_page));
+
+	if (!err)
+		err = kho_add_subtree(MEMBLOCK_KHO_FDT, fdt);
+
 	if (err) {
 		pr_err("failed to prepare memblock FDT for KHO: %d\n", err);
-		put_page(kho_fdt);
-		kho_fdt = NULL;
+		put_page(fdt_page);
 	}
 
 	return err;
@@ -2529,13 +2500,6 @@ static int __init reserve_mem_init(void)
 	err = prepare_kho_fdt();
 	if (err)
 		return err;
-
-	err = register_kho_notifier(&reserve_mem_kho_nb);
-	if (err) {
-		put_page(kho_fdt);
-		kho_fdt = NULL;
-	}
-
 	return err;
 }
 late_initcall(reserve_mem_init);
-- 
2.51.1.930.gacf6e81ea2-goog



^ permalink raw reply related	[flat|nested] 42+ messages in thread

* [PATCH v9 3/9] kho: add interfaces to unpreserve folios, page ranges, and vmalloc
  2025-11-01 14:23 [PATCH v9 0/9] liveupdate: Rework KHO for in-kernel users Pasha Tatashin
  2025-11-01 14:23 ` [PATCH v9 1/9] kho: make debugfs interface optional Pasha Tatashin
  2025-11-01 14:23 ` [PATCH v9 2/9] kho: drop notifiers Pasha Tatashin
@ 2025-11-01 14:23 ` Pasha Tatashin
  2025-11-03 18:05   ` Pratyush Yadav
  2025-11-01 14:23 ` [PATCH v9 4/9] memblock: Unpreserve memory in case of error Pasha Tatashin
                   ` (5 subsequent siblings)
  8 siblings, 1 reply; 42+ messages in thread
From: Pasha Tatashin @ 2025-11-01 14:23 UTC (permalink / raw)
  To: akpm, brauner, corbet, graf, jgg, linux-kernel, linux-kselftest,
	linux-mm, masahiroy, ojeda, pasha.tatashin, pratyush, rdunlap,
	rppt, tj, yanjun.zhu

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

Signed-off-by: Pasha Tatashin <pasha.tatashin@soleen.com>
Reviewed-by: Pratyush Yadav <pratyush@kernel.org>
Reviewed-by: Mike Rapoport (Microsoft) <rppt@kernel.org>
---
 include/linux/kexec_handover.h |  18 ++++++
 kernel/kexec_handover.c        | 104 ++++++++++++++++++++++++++++-----
 2 files changed, 109 insertions(+), 13 deletions(-)

diff --git a/include/linux/kexec_handover.h b/include/linux/kexec_handover.h
index 0d860d793b66..80ece4232617 100644
--- a/include/linux/kexec_handover.h
+++ b/include/linux/kexec_handover.h
@@ -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;
diff --git a/kernel/kexec_handover.c b/kernel/kexec_handover.c
index 82137eba1474..c514b300ebe6 100644
--- a/kernel/kexec_handover.c
+++ b/kernel/kexec_handover.c
@@ -157,26 +157,33 @@ static void *xa_load_or_alloc(struct xarray *xa, unsigned long index)
 	return no_free_ptr(elm);
 }
 
-static void __kho_unpreserve(struct kho_mem_track *track, unsigned long pfn,
-			     unsigned long end_pfn)
+static void __kho_unpreserve_order(struct kho_mem_track *track, unsigned long pfn,
+				   unsigned int order)
 {
 	struct kho_mem_phys_bits *bits;
 	struct kho_mem_phys *physxa;
+	const unsigned long pfn_high = pfn >> order;
 
-	while (pfn < end_pfn) {
-		const unsigned int order =
-			min(count_trailing_zeros(pfn), ilog2(end_pfn - pfn));
-		const unsigned long pfn_high = pfn >> order;
+	physxa = xa_load(&track->orders, order);
+	if (!physxa)
+		return;
 
-		physxa = xa_load(&track->orders, order);
-		if (!physxa)
-			continue;
+	bits = xa_load(&physxa->phys_bits, pfn_high / PRESERVE_BITS);
+	if (!bits)
+		return;
 
-		bits = xa_load(&physxa->phys_bits, pfn_high / PRESERVE_BITS);
-		if (!bits)
-			continue;
+	clear_bit(pfn_high % PRESERVE_BITS, bits->preserve);
+}
+
+static void __kho_unpreserve(struct kho_mem_track *track, unsigned long pfn,
+			     unsigned long end_pfn)
+{
+	unsigned int order;
+
+	while (pfn < end_pfn) {
+		order = min(count_trailing_zeros(pfn), ilog2(end_pfn - pfn));
 
-		clear_bit(pfn_high % PRESERVE_BITS, bits->preserve);
+		__kho_unpreserve_order(track, pfn, order);
 
 		pfn += 1 << order;
 	}
@@ -745,6 +752,30 @@ int kho_preserve_folio(struct folio *folio)
 }
 EXPORT_SYMBOL_GPL(kho_preserve_folio);
 
+/**
+ * kho_unpreserve_folio - unpreserve a folio.
+ * @folio: folio to unpreserve.
+ *
+ * Instructs KHO to unpreserve a folio that was preserved by
+ * kho_preserve_folio() before. The provided @folio (pfn and order)
+ * must exactly match a previously preserved folio.
+ *
+ * Return: 0 on success, error code on failure
+ */
+int kho_unpreserve_folio(struct folio *folio)
+{
+	const unsigned long pfn = folio_pfn(folio);
+	const unsigned int order = folio_order(folio);
+	struct kho_mem_track *track = &kho_out.track;
+
+	if (kho_out.finalized)
+		return -EBUSY;
+
+	__kho_unpreserve_order(track, pfn, order);
+	return 0;
+}
+EXPORT_SYMBOL_GPL(kho_unpreserve_folio);
+
 /**
  * kho_preserve_pages - preserve contiguous pages across kexec
  * @page: first page in the list.
@@ -789,6 +820,33 @@ int kho_preserve_pages(struct page *page, unsigned int nr_pages)
 }
 EXPORT_SYMBOL_GPL(kho_preserve_pages);
 
+/**
+ * kho_unpreserve_pages - unpreserve contiguous pages.
+ * @page: first page in the list.
+ * @nr_pages: number of pages.
+ *
+ * Instructs KHO to unpreserve @nr_pages contiguous pages starting from @page.
+ * This must be called with the same @page and @nr_pages as the corresponding
+ * kho_preserve_pages() call. Unpreserving arbitrary sub-ranges of larger
+ * preserved blocks is not supported.
+ *
+ * Return: 0 on success, error code on failure
+ */
+int kho_unpreserve_pages(struct page *page, unsigned int nr_pages)
+{
+	struct kho_mem_track *track = &kho_out.track;
+	const unsigned long start_pfn = page_to_pfn(page);
+	const unsigned long end_pfn = start_pfn + nr_pages;
+
+	if (kho_out.finalized)
+		return -EBUSY;
+
+	__kho_unpreserve(track, start_pfn, end_pfn);
+
+	return 0;
+}
+EXPORT_SYMBOL_GPL(kho_unpreserve_pages);
+
 struct kho_vmalloc_hdr {
 	DECLARE_KHOSER_PTR(next, struct kho_vmalloc_chunk *);
 };
@@ -949,6 +1007,26 @@ int kho_preserve_vmalloc(void *ptr, struct kho_vmalloc *preservation)
 }
 EXPORT_SYMBOL_GPL(kho_preserve_vmalloc);
 
+/**
+ * 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
+ * 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);
+
+	return 0;
+}
+EXPORT_SYMBOL_GPL(kho_unpreserve_vmalloc);
+
 /**
  * kho_restore_vmalloc - recreates and populates an area in vmalloc address
  * space from the preserved memory.
-- 
2.51.1.930.gacf6e81ea2-goog



^ permalink raw reply related	[flat|nested] 42+ messages in thread

* [PATCH v9 4/9] memblock: Unpreserve memory in case of error
  2025-11-01 14:23 [PATCH v9 0/9] liveupdate: Rework KHO for in-kernel users Pasha Tatashin
                   ` (2 preceding siblings ...)
  2025-11-01 14:23 ` [PATCH v9 3/9] kho: add interfaces to unpreserve folios, page ranges, and vmalloc Pasha Tatashin
@ 2025-11-01 14:23 ` Pasha Tatashin
  2025-11-02  6:51   ` Mike Rapoport
  2025-11-05 10:26   ` Pratyush Yadav
  2025-11-01 14:23 ` [PATCH v9 5/9] test_kho: " Pasha Tatashin
                   ` (4 subsequent siblings)
  8 siblings, 2 replies; 42+ messages in thread
From: Pasha Tatashin @ 2025-11-01 14:23 UTC (permalink / raw)
  To: akpm, brauner, corbet, graf, jgg, linux-kernel, linux-kselftest,
	linux-mm, masahiroy, ojeda, pasha.tatashin, pratyush, rdunlap,
	rppt, tj, yanjun.zhu

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

Signed-off-by: Pasha Tatashin <pasha.tatashin@soleen.com>
Suggested-by: Pratyush Yadav <pratyush@kernel.org>
---
 mm/memblock.c | 73 ++++++++++++++++++++++++++++++++++++++++-----------
 1 file changed, 58 insertions(+), 15 deletions(-)

diff --git a/mm/memblock.c b/mm/memblock.c
index e3bef9b35d63..f527ad1ca682 100644
--- a/mm/memblock.c
+++ b/mm/memblock.c
@@ -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;
 }
-- 
2.51.1.930.gacf6e81ea2-goog



^ permalink raw reply related	[flat|nested] 42+ messages in thread

* [PATCH v9 5/9] test_kho: Unpreserve memory in case of error
  2025-11-01 14:23 [PATCH v9 0/9] liveupdate: Rework KHO for in-kernel users Pasha Tatashin
                   ` (3 preceding siblings ...)
  2025-11-01 14:23 ` [PATCH v9 4/9] memblock: Unpreserve memory in case of error Pasha Tatashin
@ 2025-11-01 14:23 ` Pasha Tatashin
  2025-11-01 14:23 ` [PATCH v9 6/9] kho: don't unpreserve memory during abort Pasha Tatashin
                   ` (3 subsequent siblings)
  8 siblings, 0 replies; 42+ messages in thread
From: Pasha Tatashin @ 2025-11-01 14:23 UTC (permalink / raw)
  To: akpm, brauner, corbet, graf, jgg, linux-kernel, linux-kselftest,
	linux-mm, masahiroy, ojeda, pasha.tatashin, pratyush, rdunlap,
	rppt, tj, yanjun.zhu

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

Co-developed-by: Mike Rapoport (Microsoft) <rppt@kernel.org>
Signed-off-by: Mike Rapoport (Microsoft) <rppt@kernel.org>
Signed-off-by: Pasha Tatashin <pasha.tatashin@soleen.com>
---
 lib/test_kho.c | 103 +++++++++++++++++++++++++++++++++++--------------
 1 file changed, 73 insertions(+), 30 deletions(-)

diff --git a/lib/test_kho.c b/lib/test_kho.c
index 9f7cfa6ac855..025ea251a186 100644
--- a/lib/test_kho.c
+++ b/lib/test_kho.c
@@ -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;
-- 
2.51.1.930.gacf6e81ea2-goog



^ permalink raw reply related	[flat|nested] 42+ messages in thread

* [PATCH v9 6/9] kho: don't unpreserve memory during abort
  2025-11-01 14:23 [PATCH v9 0/9] liveupdate: Rework KHO for in-kernel users Pasha Tatashin
                   ` (4 preceding siblings ...)
  2025-11-01 14:23 ` [PATCH v9 5/9] test_kho: " Pasha Tatashin
@ 2025-11-01 14:23 ` Pasha Tatashin
  2025-11-05 10:28   ` Pratyush Yadav
  2025-11-01 14:23 ` [PATCH v9 7/9] liveupdate: kho: move to kernel/liveupdate Pasha Tatashin
                   ` (2 subsequent siblings)
  8 siblings, 1 reply; 42+ messages in thread
From: Pasha Tatashin @ 2025-11-01 14:23 UTC (permalink / raw)
  To: akpm, brauner, corbet, graf, jgg, linux-kernel, linux-kselftest,
	linux-mm, masahiroy, ojeda, pasha.tatashin, pratyush, rdunlap,
	rppt, tj, yanjun.zhu

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.

Signed-off-by: Pasha Tatashin <pasha.tatashin@soleen.com>
---
 kernel/kexec_handover.c | 21 +--------------------
 1 file changed, 1 insertion(+), 20 deletions(-)

diff --git a/kernel/kexec_handover.c b/kernel/kexec_handover.c
index c514b300ebe6..3adf86c7c2db 100644
--- a/kernel/kexec_handover.c
+++ b/kernel/kexec_handover.c
@@ -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)
-- 
2.51.1.930.gacf6e81ea2-goog



^ permalink raw reply related	[flat|nested] 42+ messages in thread

* [PATCH v9 7/9] liveupdate: kho: move to kernel/liveupdate
  2025-11-01 14:23 [PATCH v9 0/9] liveupdate: Rework KHO for in-kernel users Pasha Tatashin
                   ` (5 preceding siblings ...)
  2025-11-01 14:23 ` [PATCH v9 6/9] kho: don't unpreserve memory during abort Pasha Tatashin
@ 2025-11-01 14:23 ` Pasha Tatashin
  2025-11-06  7:21   ` kernel test robot
  2025-11-07 22:23   ` Andrew Morton
  2025-11-01 14:23 ` [PATCH v9 8/9] MAINTAINERS: update KHO maintainers Pasha Tatashin
  2025-11-01 14:23 ` [PATCH v9 9/9] liveupdate: kho: Use %pe format specifier for error pointer printing Pasha Tatashin
  8 siblings, 2 replies; 42+ messages in thread
From: Pasha Tatashin @ 2025-11-01 14:23 UTC (permalink / raw)
  To: akpm, brauner, corbet, graf, jgg, linux-kernel, linux-kselftest,
	linux-mm, masahiroy, ojeda, pasha.tatashin, pratyush, rdunlap,
	rppt, tj, yanjun.zhu

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

Signed-off-by: Pasha Tatashin <pasha.tatashin@soleen.com>
Reviewed-by: Jason Gunthorpe <jgg@nvidia.com>
Reviewed-by: Mike Rapoport (Microsoft) <rppt@kernel.org>
---
 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%)

diff --git a/Documentation/core-api/kho/concepts.rst b/Documentation/core-api/kho/concepts.rst
index 36d5c05cfb30..d626d1dbd678 100644
--- a/Documentation/core-api/kho/concepts.rst
+++ b/Documentation/core-api/kho/concepts.rst
@@ -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:
diff --git a/MAINTAINERS b/MAINTAINERS
index bdd0a1260421..764df916fae7 100644
--- a/MAINTAINERS
+++ b/MAINTAINERS
@@ -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
diff --git a/init/Kconfig b/init/Kconfig
index cab3ad28ca49..0605de5d96c0 100644
--- a/init/Kconfig
+++ b/init/Kconfig
@@ -2138,6 +2138,8 @@ config TRACEPOINTS
 
 source "kernel/Kconfig.kexec"
 
+source "kernel/liveupdate/Kconfig"
+
 endmenu		# General setup
 
 source "arch/Kconfig"
diff --git a/kernel/Kconfig.kexec b/kernel/Kconfig.kexec
index cc6743137946..15632358bcf7 100644
--- a/kernel/Kconfig.kexec
+++ b/kernel/Kconfig.kexec
@@ -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
diff --git a/kernel/Makefile b/kernel/Makefile
index 2cf7909a74e5..e83669841b8c 100644
--- a/kernel/Makefile
+++ b/kernel/Makefile
@@ -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/
diff --git a/kernel/liveupdate/Kconfig b/kernel/liveupdate/Kconfig
new file mode 100644
index 000000000000..1379a4c40b09
--- /dev/null
+++ b/kernel/liveupdate/Kconfig
@@ -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
diff --git a/kernel/liveupdate/Makefile b/kernel/liveupdate/Makefile
new file mode 100644
index 000000000000..f52ce1ebcf86
--- /dev/null
+++ b/kernel/liveupdate/Makefile
@@ -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
diff --git a/kernel/kexec_handover.c b/kernel/liveupdate/kexec_handover.c
similarity index 99%
rename from kernel/kexec_handover.c
rename to kernel/liveupdate/kexec_handover.c
index 3adf86c7c2db..be945c133a2f 100644
--- a/kernel/kexec_handover.c
+++ b/kernel/liveupdate/kexec_handover.c
@@ -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"
diff --git a/kernel/kexec_handover_debug.c b/kernel/liveupdate/kexec_handover_debug.c
similarity index 100%
rename from kernel/kexec_handover_debug.c
rename to kernel/liveupdate/kexec_handover_debug.c
diff --git a/kernel/kexec_handover_debugfs.c b/kernel/liveupdate/kexec_handover_debugfs.c
similarity index 100%
rename from kernel/kexec_handover_debugfs.c
rename to kernel/liveupdate/kexec_handover_debugfs.c
diff --git a/kernel/kexec_handover_internal.h b/kernel/liveupdate/kexec_handover_internal.h
similarity index 100%
rename from kernel/kexec_handover_internal.h
rename to kernel/liveupdate/kexec_handover_internal.h
-- 
2.51.1.930.gacf6e81ea2-goog



^ permalink raw reply related	[flat|nested] 42+ messages in thread

* [PATCH v9 8/9] MAINTAINERS: update KHO maintainers
  2025-11-01 14:23 [PATCH v9 0/9] liveupdate: Rework KHO for in-kernel users Pasha Tatashin
                   ` (6 preceding siblings ...)
  2025-11-01 14:23 ` [PATCH v9 7/9] liveupdate: kho: move to kernel/liveupdate Pasha Tatashin
@ 2025-11-01 14:23 ` Pasha Tatashin
  2025-11-01 16:36   ` Mike Rapoport
  2025-11-01 14:23 ` [PATCH v9 9/9] liveupdate: kho: Use %pe format specifier for error pointer printing Pasha Tatashin
  8 siblings, 1 reply; 42+ messages in thread
From: Pasha Tatashin @ 2025-11-01 14:23 UTC (permalink / raw)
  To: akpm, brauner, corbet, graf, jgg, linux-kernel, linux-kselftest,
	linux-mm, masahiroy, ojeda, pasha.tatashin, pratyush, rdunlap,
	rppt, tj, yanjun.zhu

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

Signed-off-by: Changyuan Lyu <changyuanl@google.com>
Signed-off-by: Pasha Tatashin <pasha.tatashin@soleen.com>
---
 MAINTAINERS | 2 +-
 1 file changed, 1 insertion(+), 1 deletion(-)

diff --git a/MAINTAINERS b/MAINTAINERS
index 764df916fae7..6200de2027fe 100644
--- a/MAINTAINERS
+++ b/MAINTAINERS
@@ -13788,7 +13788,7 @@ F:	kernel/kexec*
 KEXEC HANDOVER (KHO)
 M:	Alexander Graf <graf@amazon.com>
 M:	Mike Rapoport <rppt@kernel.org>
-M:	Changyuan Lyu <changyuanl@google.com>
+M:	Pasha Tatashin <pasha.tatashin@soleen.com>
 L:	kexec@lists.infradead.org
 L:	linux-mm@kvack.org
 S:	Maintained
-- 
2.51.1.930.gacf6e81ea2-goog



^ permalink raw reply related	[flat|nested] 42+ messages in thread

* [PATCH v9 9/9] liveupdate: kho: Use %pe format specifier for error pointer printing
  2025-11-01 14:23 [PATCH v9 0/9] liveupdate: Rework KHO for in-kernel users Pasha Tatashin
                   ` (7 preceding siblings ...)
  2025-11-01 14:23 ` [PATCH v9 8/9] MAINTAINERS: update KHO maintainers Pasha Tatashin
@ 2025-11-01 14:23 ` Pasha Tatashin
  2025-11-01 19:45   ` Zhu Yanjun
                     ` (2 more replies)
  8 siblings, 3 replies; 42+ messages in thread
From: Pasha Tatashin @ 2025-11-01 14:23 UTC (permalink / raw)
  To: akpm, brauner, corbet, graf, jgg, linux-kernel, linux-kselftest,
	linux-mm, masahiroy, ojeda, pasha.tatashin, pratyush, rdunlap,
	rppt, tj, yanjun.zhu

From: Zhu Yanjun <yanjun.zhu@linux.dev>

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.

Signed-off-by: Zhu Yanjun <yanjun.zhu@linux.dev>
Co-developed-by: Pasha Tatashin <pasha.tatashin@soleen.com>
Signed-off-by: Pasha Tatashin <pasha.tatashin@soleen.com>
Reviewed-by: Simon Horman <horms@kernel.org>
---
 kernel/liveupdate/kexec_handover.c         |  4 ++--
 kernel/liveupdate/kexec_handover_debugfs.c | 10 ++++++----
 2 files changed, 8 insertions(+), 6 deletions(-)

diff --git a/kernel/liveupdate/kexec_handover.c b/kernel/liveupdate/kexec_handover.c
index be945c133a2f..167c761988d3 100644
--- a/kernel/liveupdate/kexec_handover.c
+++ b/kernel/liveupdate/kexec_handover.c
@@ -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);
diff --git a/kernel/liveupdate/kexec_handover_debugfs.c b/kernel/liveupdate/kexec_handover_debugfs.c
index 46e9e6c0791f..ac739d25094d 100644
--- a/kernel/liveupdate/kexec_handover_debugfs.c
+++ b/kernel/liveupdate/kexec_handover_debugfs.c
@@ -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)
-- 
2.51.1.930.gacf6e81ea2-goog



^ permalink raw reply related	[flat|nested] 42+ messages in thread

* Re: [PATCH v9 8/9] MAINTAINERS: update KHO maintainers
  2025-11-01 14:23 ` [PATCH v9 8/9] MAINTAINERS: update KHO maintainers Pasha Tatashin
@ 2025-11-01 16:36   ` Mike Rapoport
  0 siblings, 0 replies; 42+ messages in thread
From: Mike Rapoport @ 2025-11-01 16:36 UTC (permalink / raw)
  To: Pasha Tatashin
  Cc: akpm, brauner, corbet, graf, jgg, linux-kernel, linux-kselftest,
	linux-mm, masahiroy, ojeda, pratyush, rdunlap, tj, yanjun.zhu

On Sat, Nov 01, 2025 at 10:23:24AM -0400, Pasha Tatashin wrote:
> Changyuan does not have cycles to commit to the upstream work of KHO.
> Remove from KHO maintainers.
> 
> Signed-off-by: Changyuan Lyu <changyuanl@google.com>
> Signed-off-by: Pasha Tatashin <pasha.tatashin@soleen.com>

Reviewed-by: Mike Rapoport (Microsoft) <rppt@kernel.org>

> ---
>  MAINTAINERS | 2 +-
>  1 file changed, 1 insertion(+), 1 deletion(-)
> 
> diff --git a/MAINTAINERS b/MAINTAINERS
> index 764df916fae7..6200de2027fe 100644
> --- a/MAINTAINERS
> +++ b/MAINTAINERS
> @@ -13788,7 +13788,7 @@ F:	kernel/kexec*
>  KEXEC HANDOVER (KHO)
>  M:	Alexander Graf <graf@amazon.com>
>  M:	Mike Rapoport <rppt@kernel.org>
> -M:	Changyuan Lyu <changyuanl@google.com>
> +M:	Pasha Tatashin <pasha.tatashin@soleen.com>
>  L:	kexec@lists.infradead.org
>  L:	linux-mm@kvack.org
>  S:	Maintained
> -- 
> 2.51.1.930.gacf6e81ea2-goog
> 

-- 
Sincerely yours,
Mike.


^ permalink raw reply	[flat|nested] 42+ messages in thread

* Re: [PATCH v9 9/9] liveupdate: kho: Use %pe format specifier for error pointer printing
  2025-11-01 14:23 ` [PATCH v9 9/9] liveupdate: kho: Use %pe format specifier for error pointer printing Pasha Tatashin
@ 2025-11-01 19:45   ` Zhu Yanjun
  2025-11-02  6:59   ` Mike Rapoport
  2025-11-03 12:59   ` Pratyush Yadav
  2 siblings, 0 replies; 42+ messages in thread
From: Zhu Yanjun @ 2025-11-01 19:45 UTC (permalink / raw)
  To: Pasha Tatashin, akpm, brauner, corbet, graf, jgg, linux-kernel,
	linux-kselftest, linux-mm, masahiroy, ojeda, pratyush, rdunlap,
	rppt, tj


在 2025/11/1 7:23, Pasha Tatashin 写道:
> From: Zhu Yanjun <yanjun.zhu@linux.dev>
>
> 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.
>
> Signed-off-by: Zhu Yanjun <yanjun.zhu@linux.dev>
> Co-developed-by: Pasha Tatashin <pasha.tatashin@soleen.com>
> Signed-off-by: Pasha Tatashin <pasha.tatashin@soleen.com>

Appreciate your help, Pasha

Yanjun.Zhu

> Reviewed-by: Simon Horman <horms@kernel.org>
> ---
>   kernel/liveupdate/kexec_handover.c         |  4 ++--
>   kernel/liveupdate/kexec_handover_debugfs.c | 10 ++++++----
>   2 files changed, 8 insertions(+), 6 deletions(-)
>
> diff --git a/kernel/liveupdate/kexec_handover.c b/kernel/liveupdate/kexec_handover.c
> index be945c133a2f..167c761988d3 100644
> --- a/kernel/liveupdate/kexec_handover.c
> +++ b/kernel/liveupdate/kexec_handover.c
> @@ -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);
> diff --git a/kernel/liveupdate/kexec_handover_debugfs.c b/kernel/liveupdate/kexec_handover_debugfs.c
> index 46e9e6c0791f..ac739d25094d 100644
> --- a/kernel/liveupdate/kexec_handover_debugfs.c
> +++ b/kernel/liveupdate/kexec_handover_debugfs.c
> @@ -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)

-- 
Best Regards,
Yanjun.Zhu



^ permalink raw reply	[flat|nested] 42+ messages in thread

* Re: [PATCH v9 4/9] memblock: Unpreserve memory in case of error
  2025-11-01 14:23 ` [PATCH v9 4/9] memblock: Unpreserve memory in case of error Pasha Tatashin
@ 2025-11-02  6:51   ` Mike Rapoport
  2025-11-05 10:26   ` Pratyush Yadav
  1 sibling, 0 replies; 42+ messages in thread
From: Mike Rapoport @ 2025-11-02  6:51 UTC (permalink / raw)
  To: Pasha Tatashin
  Cc: akpm, brauner, corbet, graf, jgg, linux-kernel, linux-kselftest,
	linux-mm, masahiroy, ojeda, pratyush, rdunlap, tj, yanjun.zhu

On Sat, Nov 01, 2025 at 10:23:20AM -0400, Pasha Tatashin wrote:
> If there is an error half way through KHO memory preservation, we should
> rollback and unpreserve everything that is partially preserved.
> 
> Signed-off-by: Pasha Tatashin <pasha.tatashin@soleen.com>
> Suggested-by: Pratyush Yadav <pratyush@kernel.org>

Reviewed-by: Mike Rapoport (Microsoft) <rppt@kernel.org>

with a small nit below.

> ---
>  mm/memblock.c | 73 ++++++++++++++++++++++++++++++++++++++++-----------
>  1 file changed, 58 insertions(+), 15 deletions(-)
> 
> diff --git a/mm/memblock.c b/mm/memblock.c
> index e3bef9b35d63..f527ad1ca682 100644
> --- a/mm/memblock.c
> +++ b/mm/memblock.c
> @@ -2445,29 +2445,60 @@ int reserve_mem_release_by_name(const char *name)

...

>  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;

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.

...

> +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;
>  }
> -- 
> 2.51.1.930.gacf6e81ea2-goog
> 

-- 
Sincerely yours,
Mike.


^ permalink raw reply	[flat|nested] 42+ messages in thread

* Re: [PATCH v9 9/9] liveupdate: kho: Use %pe format specifier for error pointer printing
  2025-11-01 14:23 ` [PATCH v9 9/9] liveupdate: kho: Use %pe format specifier for error pointer printing Pasha Tatashin
  2025-11-01 19:45   ` Zhu Yanjun
@ 2025-11-02  6:59   ` Mike Rapoport
  2025-11-03 12:59   ` Pratyush Yadav
  2 siblings, 0 replies; 42+ messages in thread
From: Mike Rapoport @ 2025-11-02  6:59 UTC (permalink / raw)
  To: Pasha Tatashin
  Cc: akpm, brauner, corbet, graf, jgg, linux-kernel, linux-kselftest,
	linux-mm, masahiroy, ojeda, pratyush, rdunlap, tj, yanjun.zhu

On Sat, Nov 01, 2025 at 10:23:25AM -0400, Pasha Tatashin wrote:
> From: Zhu Yanjun <yanjun.zhu@linux.dev>
> 
> 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.
> 
> Signed-off-by: Zhu Yanjun <yanjun.zhu@linux.dev>
> Co-developed-by: Pasha Tatashin <pasha.tatashin@soleen.com>
> Signed-off-by: Pasha Tatashin <pasha.tatashin@soleen.com>
> Reviewed-by: Simon Horman <horms@kernel.org>

Reviewed-by: Mike Rapoport (Microsoft) <rppt@kernel.org>

> ---
>  kernel/liveupdate/kexec_handover.c         |  4 ++--
>  kernel/liveupdate/kexec_handover_debugfs.c | 10 ++++++----
>  2 files changed, 8 insertions(+), 6 deletions(-)

-- 
Sincerely yours,
Mike.


^ permalink raw reply	[flat|nested] 42+ messages in thread

* Re: [PATCH v9 9/9] liveupdate: kho: Use %pe format specifier for error pointer printing
  2025-11-01 14:23 ` [PATCH v9 9/9] liveupdate: kho: Use %pe format specifier for error pointer printing Pasha Tatashin
  2025-11-01 19:45   ` Zhu Yanjun
  2025-11-02  6:59   ` Mike Rapoport
@ 2025-11-03 12:59   ` Pratyush Yadav
  2 siblings, 0 replies; 42+ messages in thread
From: Pratyush Yadav @ 2025-11-03 12:59 UTC (permalink / raw)
  To: Pasha Tatashin
  Cc: akpm, brauner, corbet, graf, jgg, linux-kernel, linux-kselftest,
	linux-mm, masahiroy, ojeda, pratyush, rdunlap, rppt, tj,
	yanjun.zhu

On Sat, Nov 01 2025, Pasha Tatashin wrote:

> From: Zhu Yanjun <yanjun.zhu@linux.dev>
>
> 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.

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

>
> Signed-off-by: Zhu Yanjun <yanjun.zhu@linux.dev>
> Co-developed-by: Pasha Tatashin <pasha.tatashin@soleen.com>
> Signed-off-by: Pasha Tatashin <pasha.tatashin@soleen.com>
> Reviewed-by: Simon Horman <horms@kernel.org>

Reviewed-by: Pratyush Yadav <pratyush@kernel.org>

[...]

-- 
Regards,
Pratyush Yadav


^ permalink raw reply	[flat|nested] 42+ messages in thread

* Re: [PATCH v9 3/9] kho: add interfaces to unpreserve folios, page ranges, and vmalloc
  2025-11-01 14:23 ` [PATCH v9 3/9] kho: add interfaces to unpreserve folios, page ranges, and vmalloc Pasha Tatashin
@ 2025-11-03 18:05   ` Pratyush Yadav
  0 siblings, 0 replies; 42+ messages in thread
From: Pratyush Yadav @ 2025-11-03 18:05 UTC (permalink / raw)
  To: Pasha Tatashin
  Cc: akpm, brauner, corbet, graf, jgg, linux-kernel, linux-kselftest,
	linux-mm, masahiroy, ojeda, pratyush, rdunlap, rppt, tj,
	yanjun.zhu

Hi Pasha,

On Sat, Nov 01 2025, Pasha Tatashin wrote:

> Allow users of KHO to cancel the previous preservation by adding the
> necessary interfaces to unpreserve folio, pages, and vmallocs.
>
> Signed-off-by: Pasha Tatashin <pasha.tatashin@soleen.com>
> Reviewed-by: Pratyush Yadav <pratyush@kernel.org>
> Reviewed-by: Mike Rapoport (Microsoft) <rppt@kernel.org>
[...]
> +/**
> + * 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
> + * 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/20251103180235.71409-2-pratyush@kernel.org/T/#u

-- 
Regards,
Pratyush Yadav


^ permalink raw reply	[flat|nested] 42+ messages in thread

* Re: [PATCH v9 4/9] memblock: Unpreserve memory in case of error
  2025-11-01 14:23 ` [PATCH v9 4/9] memblock: Unpreserve memory in case of error Pasha Tatashin
  2025-11-02  6:51   ` Mike Rapoport
@ 2025-11-05 10:26   ` Pratyush Yadav
  1 sibling, 0 replies; 42+ messages in thread
From: Pratyush Yadav @ 2025-11-05 10:26 UTC (permalink / raw)
  To: Pasha Tatashin
  Cc: akpm, brauner, corbet, graf, jgg, linux-kernel, linux-kselftest,
	linux-mm, masahiroy, ojeda, pratyush, rdunlap, rppt, tj,
	yanjun.zhu

On Sat, Nov 01 2025, Pasha Tatashin wrote:

> If there is an error half way through KHO memory preservation, we should
> rollback and unpreserve everything that is partially preserved.
>
> Signed-off-by: Pasha Tatashin <pasha.tatashin@soleen.com>
> Suggested-by: Pratyush Yadav <pratyush@kernel.org>

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

Reviewed-by: Pratyush Yadav <pratyush@kernel.org>

[...]

-- 
Regards,
Pratyush Yadav


^ permalink raw reply	[flat|nested] 42+ messages in thread

* Re: [PATCH v9 6/9] kho: don't unpreserve memory during abort
  2025-11-01 14:23 ` [PATCH v9 6/9] kho: don't unpreserve memory during abort Pasha Tatashin
@ 2025-11-05 10:28   ` Pratyush Yadav
  0 siblings, 0 replies; 42+ messages in thread
From: Pratyush Yadav @ 2025-11-05 10:28 UTC (permalink / raw)
  To: Pasha Tatashin
  Cc: akpm, brauner, corbet, graf, jgg, linux-kernel, linux-kselftest,
	linux-mm, masahiroy, ojeda, pratyush, rdunlap, rppt, tj,
	yanjun.zhu

On Sat, Nov 01 2025, Pasha Tatashin wrote:

> 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.
>
> Signed-off-by: Pasha Tatashin <pasha.tatashin@soleen.com>

Reviewed-by: Pratyush Yadav <pratyush@kernel.org>

[...]

-- 
Regards,
Pratyush Yadav


^ permalink raw reply	[flat|nested] 42+ messages in thread

* Re: [PATCH v9 7/9] liveupdate: kho: move to kernel/liveupdate
  2025-11-01 14:23 ` [PATCH v9 7/9] liveupdate: kho: move to kernel/liveupdate Pasha Tatashin
@ 2025-11-06  7:21   ` kernel test robot
  2025-11-07 22:23   ` Andrew Morton
  1 sibling, 0 replies; 42+ messages in thread
From: kernel test robot @ 2025-11-06  7:21 UTC (permalink / raw)
  To: Pasha Tatashin
  Cc: oe-lkp, lkp, Jason Gunthorpe, Mike Rapoport, kexec, linux-mm,
	linux-kernel, akpm, brauner, corbet, graf, jgg, linux-kselftest,
	masahiroy, ojeda, pasha.tatashin, pratyush, rdunlap, tj,
	yanjun.zhu, oliver.sang



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/20251101142325.1326536-8-pasha.tatashin@soleen.com/
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 <oliver.sang@intel.com>
| Closes: https://lore.kernel.org/oe-lkp/202511061443.64dd159-lkp@intel.com


[   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/202511061443.64dd159-lkp@intel.com



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



^ permalink raw reply	[flat|nested] 42+ messages in thread

* Re: [PATCH v9 2/9] kho: drop notifiers
  2025-11-01 14:23 ` [PATCH v9 2/9] kho: drop notifiers Pasha Tatashin
@ 2025-11-06  8:41   ` kernel test robot
  2025-11-06 21:46     ` Pasha Tatashin
  0 siblings, 1 reply; 42+ messages in thread
From: kernel test robot @ 2025-11-06  8:41 UTC (permalink / raw)
  To: Pasha Tatashin
  Cc: oe-lkp, lkp, Pasha Tatashin, kexec, linux-mm, linux-kernel, akpm,
	brauner, corbet, graf, jgg, linux-kselftest, masahiroy, ojeda,
	pratyush, rdunlap, rppt, tj, yanjun.zhu, oliver.sang



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/20251101142325.1326536-3-pasha.tatashin@soleen.com/
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 <oliver.sang@intel.com>
| Closes: https://lore.kernel.org/oe-lkp/202511061629.e242724-lkp@intel.com


[   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/202511061629.e242724-lkp@intel.com



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



^ permalink raw reply	[flat|nested] 42+ messages in thread

* Re: [PATCH v9 2/9] kho: drop notifiers
  2025-11-06  8:41   ` kernel test robot
@ 2025-11-06 21:46     ` Pasha Tatashin
  2025-11-06 22:14       ` Pasha Tatashin
  0 siblings, 1 reply; 42+ messages in thread
From: Pasha Tatashin @ 2025-11-06 21:46 UTC (permalink / raw)
  To: kernel test robot
  Cc: oe-lkp, lkp, kexec, linux-mm, linux-kernel, akpm, brauner, corbet,
	graf, jgg, linux-kselftest, masahiroy, ojeda, pratyush, rdunlap,
	rppt, tj, yanjun.zhu

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:

diff --git a/lib/test_kho.c b/lib/test_kho.c
index 025ea251a186..85b60d87a50a 100644
--- a/lib/test_kho.c
+++ b/lib/test_kho.c
@@ -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);

On Thu, Nov 6, 2025 at 3:41 AM kernel test robot <oliver.sang@intel.com> wrote:
>
>
>
> 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/20251101142325.1326536-3-pasha.tatashin@soleen.com/
> 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 <oliver.sang@intel.com>
> | Closes: https://lore.kernel.org/oe-lkp/202511061629.e242724-lkp@intel.com
>
>
> [   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/202511061629.e242724-lkp@intel.com
>
>
>
> --
> 0-DAY CI Kernel Test Service
> https://github.com/intel/lkp-tests/wiki
>


^ permalink raw reply related	[flat|nested] 42+ messages in thread

* Re: [PATCH v9 2/9] kho: drop notifiers
  2025-11-06 21:46     ` Pasha Tatashin
@ 2025-11-06 22:14       ` Pasha Tatashin
  0 siblings, 0 replies; 42+ messages in thread
From: Pasha Tatashin @ 2025-11-06 22:14 UTC (permalink / raw)
  To: kernel test robot
  Cc: oe-lkp, lkp, kexec, linux-mm, linux-kernel, akpm, brauner, corbet,
	graf, jgg, linux-kselftest, masahiroy, ojeda, pratyush, rdunlap,
	rppt, tj, yanjun.zhu

On Thu, Nov 6, 2025 at 4:46 PM Pasha Tatashin <pasha.tatashin@soleen.com> wrote:
>
> 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/20251106220635.2608494-1-pasha.tatashin@soleen.com

>
> diff --git a/lib/test_kho.c b/lib/test_kho.c
> index 025ea251a186..85b60d87a50a 100644
> --- a/lib/test_kho.c
> +++ b/lib/test_kho.c
> @@ -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);
>
> On Thu, Nov 6, 2025 at 3:41 AM kernel test robot <oliver.sang@intel.com> wrote:
> >
> >
> >
> > 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/20251101142325.1326536-3-pasha.tatashin@soleen.com/
> > 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 <oliver.sang@intel.com>
> > | Closes: https://lore.kernel.org/oe-lkp/202511061629.e242724-lkp@intel.com
> >
> >
> > [   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/202511061629.e242724-lkp@intel.com
> >
> >
> >
> > --
> > 0-DAY CI Kernel Test Service
> > https://github.com/intel/lkp-tests/wiki
> >


^ permalink raw reply	[flat|nested] 42+ messages in thread

* Re: [PATCH v9 1/9] kho: make debugfs interface optional
  2025-11-01 14:23 ` [PATCH v9 1/9] kho: make debugfs interface optional Pasha Tatashin
@ 2025-11-07  6:03   ` Zhu Yanjun
  2025-11-07 12:00     ` Pasha Tatashin
  0 siblings, 1 reply; 42+ messages in thread
From: Zhu Yanjun @ 2025-11-07  6:03 UTC (permalink / raw)
  To: Pasha Tatashin, akpm, brauner, corbet, graf, jgg, linux-kernel,
	linux-kselftest, linux-mm, masahiroy, ojeda, pratyush, rdunlap,
	rppt, tj

在 2025/11/1 7:23, 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.
> 
> Co-developed-by: Mike Rapoport (Microsoft) <rppt@kernel.org>
> Signed-off-by: Mike Rapoport (Microsoft) <rppt@kernel.org>
> Signed-off-by: Pasha Tatashin <pasha.tatashin@soleen.com>
> Reviewed-by: Pratyush Yadav <pratyush@kernel.org>
> ---
>   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
> 
> diff --git a/MAINTAINERS b/MAINTAINERS
> index 2628431dcdfe..bdd0a1260421 100644
> --- a/MAINTAINERS
> +++ b/MAINTAINERS
> @@ -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
> diff --git a/kernel/Kconfig.kexec b/kernel/Kconfig.kexec
> index 54e581072617..cc6743137946 100644
> --- a/kernel/Kconfig.kexec
> +++ b/kernel/Kconfig.kexec
> @@ -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.

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

> +
>   config CRASH_DUMP
>   	bool "kernel crash dumps"
>   	default ARCH_DEFAULT_CRASH_DUMP
> diff --git a/kernel/Makefile b/kernel/Makefile
> index 9fe722305c9b..2cf7909a74e5 100644
> --- a/kernel/Makefile
> +++ b/kernel/Makefile
> @@ -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/
> diff --git a/kernel/kexec_handover.c b/kernel/kexec_handover.c
> index de4466b47455..da071277d85e 100644
> --- a/kernel/kexec_handover.c
> +++ b/kernel/kexec_handover.c
> @@ -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;
>   	}
>   
> diff --git a/kernel/kexec_handover_debugfs.c b/kernel/kexec_handover_debugfs.c
> new file mode 100644
> index 000000000000..a91b279f1b23
> --- /dev/null
> +++ b/kernel/kexec_handover_debugfs.c
> @@ -0,0 +1,216 @@
> +// SPDX-License-Identifier: GPL-2.0-only
> +/*
> + * kexec_handover_debugfs.c - kexec handover debugfs interfaces
> + * Copyright (C) 2023 Alexander Graf <graf@amazon.com>
> + * Copyright (C) 2025 Microsoft Corporation, Mike Rapoport <rppt@kernel.org>
> + * Copyright (C) 2025 Google LLC, Changyuan Lyu <changyuanl@google.com>
> + * Copyright (C) 2025 Google LLC, Pasha Tatashin <pasha.tatashin@soleen.com>
> + */
> +
> +#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;
> +}
> diff --git a/kernel/kexec_handover_internal.h b/kernel/kexec_handover_internal.h
> index 05e9720ba7b9..217b8b25a542 100644
> --- a/kernel/kexec_handover_internal.h
> +++ b/kernel/kexec_handover_internal.h
> @@ -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
> diff --git a/tools/testing/selftests/kho/vmtest.sh b/tools/testing/selftests/kho/vmtest.sh
> index 3f6c17166846..49fdac8e8b15 100755
> --- a/tools/testing/selftests/kho/vmtest.sh
> +++ b/tools/testing/selftests/kho/vmtest.sh
> @@ -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



^ permalink raw reply	[flat|nested] 42+ messages in thread

* Re: [PATCH v9 1/9] kho: make debugfs interface optional
  2025-11-07  6:03   ` Zhu Yanjun
@ 2025-11-07 12:00     ` Pasha Tatashin
  2025-11-07 12:02       ` Pasha Tatashin
  0 siblings, 1 reply; 42+ messages in thread
From: Pasha Tatashin @ 2025-11-07 12:00 UTC (permalink / raw)
  To: Zhu Yanjun
  Cc: akpm, brauner, corbet, graf, jgg, linux-kernel, linux-kselftest,
	linux-mm, masahiroy, ojeda, pratyush, rdunlap, rppt, tj

> 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


^ permalink raw reply	[flat|nested] 42+ messages in thread

* Re: [PATCH v9 1/9] kho: make debugfs interface optional
  2025-11-07 12:00     ` Pasha Tatashin
@ 2025-11-07 12:02       ` Pasha Tatashin
  2025-11-07 23:35         ` Yanjun.Zhu
  0 siblings, 1 reply; 42+ messages in thread
From: Pasha Tatashin @ 2025-11-07 12:02 UTC (permalink / raw)
  To: Zhu Yanjun
  Cc: akpm, brauner, corbet, graf, jgg, linux-kernel, linux-kselftest,
	linux-mm, masahiroy, ojeda, pratyush, rdunlap, rppt, tj

On Fri, Nov 7, 2025 at 7:00 AM Pasha Tatashin <pasha.tatashin@soleen.com> wrote:
>
> > 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

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


^ permalink raw reply	[flat|nested] 42+ messages in thread

* Re: [PATCH v9 7/9] liveupdate: kho: move to kernel/liveupdate
  2025-11-01 14:23 ` [PATCH v9 7/9] liveupdate: kho: move to kernel/liveupdate Pasha Tatashin
  2025-11-06  7:21   ` kernel test robot
@ 2025-11-07 22:23   ` Andrew Morton
  2025-11-08 18:01     ` Pasha Tatashin
  1 sibling, 1 reply; 42+ messages in thread
From: Andrew Morton @ 2025-11-07 22:23 UTC (permalink / raw)
  To: Pasha Tatashin
  Cc: brauner, corbet, graf, jgg, linux-kernel, linux-kselftest,
	linux-mm, masahiroy, ojeda, pratyush, rdunlap, rppt, tj,
	yanjun.zhu

On Sat,  1 Nov 2025 10:23:23 -0400 Pasha Tatashin <pasha.tatashin@soleen.com> wrote:

> 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.


^ permalink raw reply	[flat|nested] 42+ messages in thread

* Re: [PATCH v9 1/9] kho: make debugfs interface optional
  2025-11-07 12:02       ` Pasha Tatashin
@ 2025-11-07 23:35         ` Yanjun.Zhu
  2025-11-08 18:13           ` Pasha Tatashin
  0 siblings, 1 reply; 42+ messages in thread
From: Yanjun.Zhu @ 2025-11-07 23:35 UTC (permalink / raw)
  To: Pasha Tatashin
  Cc: akpm, brauner, corbet, graf, jgg, linux-kernel, linux-kselftest,
	linux-mm, masahiroy, ojeda, pratyush, rdunlap, rppt, tj


On 11/7/25 4:02 AM, Pasha Tatashin wrote:
> On Fri, Nov 7, 2025 at 7:00 AM Pasha Tatashin <pasha.tatashin@soleen.com> wrote:
>>> 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
> 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



^ permalink raw reply	[flat|nested] 42+ messages in thread

* Re: [PATCH v9 7/9] liveupdate: kho: move to kernel/liveupdate
  2025-11-07 22:23   ` Andrew Morton
@ 2025-11-08 18:01     ` Pasha Tatashin
  0 siblings, 0 replies; 42+ messages in thread
From: Pasha Tatashin @ 2025-11-08 18:01 UTC (permalink / raw)
  To: Andrew Morton
  Cc: brauner, corbet, graf, jgg, linux-kernel, linux-kselftest,
	linux-mm, masahiroy, ojeda, pratyush, rdunlap, rppt, tj,
	yanjun.zhu

On Fri, Nov 7, 2025 at 5:23 PM Andrew Morton <akpm@linux-foundation.org> wrote:
>
> On Sat,  1 Nov 2025 10:23:23 -0400 Pasha Tatashin <pasha.tatashin@soleen.com> wrote:
>
> > 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.

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.

diff --git a/kernel/liveupdate/Kconfig b/kernel/liveupdate/Kconfig
index 054f6375a7af..d7344d347f69 100644
--- a/kernel/liveupdate/Kconfig
+++ b/kernel/liveupdate/Kconfig
@@ -7,6 +7,7 @@
 #

 menu "Live Update and Kexec HandOver"
+       depends on !DEFERRED_STRUCT_PAGE_INIT

 config LIVEUPDATE
        bool "Live Update Orchestrator"


^ permalink raw reply related	[flat|nested] 42+ messages in thread

* Re: [PATCH v9 1/9] kho: make debugfs interface optional
  2025-11-07 23:35         ` Yanjun.Zhu
@ 2025-11-08 18:13           ` Pasha Tatashin
  2025-11-10  0:20             ` Zhu Yanjun
  0 siblings, 1 reply; 42+ messages in thread
From: Pasha Tatashin @ 2025-11-08 18:13 UTC (permalink / raw)
  To: Yanjun.Zhu
  Cc: akpm, brauner, corbet, graf, jgg, linux-kernel, linux-kselftest,
	linux-mm, masahiroy, ojeda, pratyush, rdunlap, rppt, tj

On Fri, Nov 7, 2025 at 6:36 PM Yanjun.Zhu <yanjun.zhu@linux.dev> wrote:
>
>
> On 11/7/25 4:02 AM, Pasha Tatashin wrote:
> > On Fri, Nov 7, 2025 at 7:00 AM Pasha Tatashin <pasha.tatashin@soleen.com> wrote:
> >>> 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
> > 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?

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

> Best Regards,
>
> Yanjun.Zhu
>


^ permalink raw reply	[flat|nested] 42+ messages in thread

* Re: [PATCH v9 1/9] kho: make debugfs interface optional
  2025-11-08 18:13           ` Pasha Tatashin
@ 2025-11-10  0:20             ` Zhu Yanjun
  2025-11-10 13:16               ` Pratyush Yadav
  0 siblings, 1 reply; 42+ messages in thread
From: Zhu Yanjun @ 2025-11-10  0:20 UTC (permalink / raw)
  To: Pasha Tatashin
  Cc: akpm, brauner, corbet, graf, jgg, linux-kernel, linux-kselftest,
	linux-mm, masahiroy, ojeda, pratyush, rdunlap, rppt, tj


在 2025/11/8 10:13, Pasha Tatashin 写道:
> On Fri, Nov 7, 2025 at 6:36 PM Yanjun.Zhu <yanjun.zhu@linux.dev> wrote:
>>
>> On 11/7/25 4:02 AM, Pasha Tatashin wrote:
>>> On Fri, Nov 7, 2025 at 7:00 AM Pasha Tatashin <pasha.tatashin@soleen.com> wrote:
>>>>> 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
>>> 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?
> 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:

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

> # ./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
>
>> Best Regards,
>>
>> Yanjun.Zhu
>>
-- 
Best Regards,
Yanjun.Zhu



^ permalink raw reply	[flat|nested] 42+ messages in thread

* Re: [PATCH v9 1/9] kho: make debugfs interface optional
  2025-11-10  0:20             ` Zhu Yanjun
@ 2025-11-10 13:16               ` Pratyush Yadav
  2025-11-10 15:26                 ` Pasha Tatashin
  0 siblings, 1 reply; 42+ messages in thread
From: Pratyush Yadav @ 2025-11-10 13:16 UTC (permalink / raw)
  To: Zhu Yanjun
  Cc: Pasha Tatashin, akpm, brauner, corbet, graf, jgg, linux-kernel,
	linux-kselftest, linux-mm, masahiroy, ojeda, pratyush, rdunlap,
	rppt, tj

On Sun, Nov 09 2025, Zhu Yanjun wrote:

> 在 2025/11/8 10:13, Pasha Tatashin 写道:
>> On Fri, Nov 7, 2025 at 6:36 PM Yanjun.Zhu <yanjun.zhu@linux.dev> wrote:
>>>
>>> On 11/7/25 4:02 AM, Pasha Tatashin wrote:
>>>> On Fri, Nov 7, 2025 at 7:00 AM Pasha Tatashin <pasha.tatashin@soleen.com> wrote:
>>>>>> 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
>>>> 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?
>> 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:
>
> 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.

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.

-- 
Regards,
Pratyush Yadav


^ permalink raw reply	[flat|nested] 42+ messages in thread

* Re: [PATCH v9 1/9] kho: make debugfs interface optional
  2025-11-10 13:16               ` Pratyush Yadav
@ 2025-11-10 15:26                 ` Pasha Tatashin
  2025-11-11  4:11                   ` Zhu Yanjun
  0 siblings, 1 reply; 42+ messages in thread
From: Pasha Tatashin @ 2025-11-10 15:26 UTC (permalink / raw)
  To: Pratyush Yadav
  Cc: Zhu Yanjun, akpm, brauner, corbet, graf, jgg, linux-kernel,
	linux-kselftest, linux-mm, masahiroy, ojeda, rdunlap, rppt, tj

On Mon, Nov 10, 2025 at 8:16 AM Pratyush Yadav <pratyush@kernel.org> wrote:
>
> On Sun, Nov 09 2025, Zhu Yanjun wrote:
>
> > 在 2025/11/8 10:13, Pasha Tatashin 写道:
> >> On Fri, Nov 7, 2025 at 6:36 PM Yanjun.Zhu <yanjun.zhu@linux.dev> wrote:
> >>>
> >>> On 11/7/25 4:02 AM, Pasha Tatashin wrote:
> >>>> On Fri, Nov 7, 2025 at 7:00 AM Pasha Tatashin <pasha.tatashin@soleen.com> wrote:
> >>>>>> 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
> >>>> 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?
> >> 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:
> >
> > 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.
>
> 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

>
> 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


^ permalink raw reply	[flat|nested] 42+ messages in thread

* Re: [PATCH v9 1/9] kho: make debugfs interface optional
  2025-11-10 15:26                 ` Pasha Tatashin
@ 2025-11-11  4:11                   ` Zhu Yanjun
  2025-11-11 15:26                     ` Pasha Tatashin
  0 siblings, 1 reply; 42+ messages in thread
From: Zhu Yanjun @ 2025-11-11  4:11 UTC (permalink / raw)
  To: Pasha Tatashin, Pratyush Yadav
  Cc: akpm, brauner, corbet, graf, jgg, linux-kernel, linux-kselftest,
	linux-mm, masahiroy, ojeda, rdunlap, rppt, tj

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

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

在 2025/11/10 7:26, Pasha Tatashin 写道:
> On Mon, Nov 10, 2025 at 8:16 AM Pratyush Yadav <pratyush@kernel.org> wrote:
>> On Sun, Nov 09 2025, Zhu Yanjun wrote:
>>
>>> 在 2025/11/8 10:13, Pasha Tatashin 写道:
>>>> On Fri, Nov 7, 2025 at 6:36 PM Yanjun.Zhu <yanjun.zhu@linux.dev> wrote:
>>>>> On 11/7/25 4:02 AM, Pasha Tatashin wrote:
>>>>>> On Fri, Nov 7, 2025 at 7:00 AM Pasha Tatashin <pasha.tatashin@soleen.com> wrote:
>>>>>>>> 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
>>>>>> 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?
>>>> 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:
>>> 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.
>> 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
>
>> 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

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

^ permalink raw reply	[flat|nested] 42+ messages in thread

* Re: [PATCH v9 1/9] kho: make debugfs interface optional
  2025-11-11  4:11                   ` Zhu Yanjun
@ 2025-11-11 15:26                     ` Pasha Tatashin
  2025-11-13  1:41                       ` Yanjun.Zhu
  2025-11-13 19:55                       ` Yanjun.Zhu
  0 siblings, 2 replies; 42+ messages in thread
From: Pasha Tatashin @ 2025-11-11 15:26 UTC (permalink / raw)
  To: Zhu Yanjun
  Cc: Pratyush Yadav, akpm, brauner, corbet, graf, jgg, linux-kernel,
	linux-kselftest, linux-mm, masahiroy, ojeda, rdunlap, rppt, tj

On Mon, Nov 10, 2025 at 11:11 PM Zhu Yanjun <yanjun.zhu@linux.dev> wrote:
>
> 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.

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

>
> The call trace is in the attachment.
>
> Yanjun.Zhu
>
> 在 2025/11/10 7:26, Pasha Tatashin 写道:
> > On Mon, Nov 10, 2025 at 8:16 AM Pratyush Yadav <pratyush@kernel.org> wrote:
> >> On Sun, Nov 09 2025, Zhu Yanjun wrote:
> >>
> >>> 在 2025/11/8 10:13, Pasha Tatashin 写道:
> >>>> On Fri, Nov 7, 2025 at 6:36 PM Yanjun.Zhu <yanjun.zhu@linux.dev> wrote:
> >>>>> On 11/7/25 4:02 AM, Pasha Tatashin wrote:
> >>>>>> On Fri, Nov 7, 2025 at 7:00 AM Pasha Tatashin <pasha.tatashin@soleen.com> wrote:
> >>>>>>>> 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
> >>>>>> 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?
> >>>> 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:
> >>> 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.
> >> 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
> >
> >> 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


^ permalink raw reply	[flat|nested] 42+ messages in thread

* Re: [PATCH v9 1/9] kho: make debugfs interface optional
  2025-11-11 15:26                     ` Pasha Tatashin
@ 2025-11-13  1:41                       ` Yanjun.Zhu
  2025-11-13  2:11                         ` Yanjun.Zhu
  2025-11-13 19:55                       ` Yanjun.Zhu
  1 sibling, 1 reply; 42+ messages in thread
From: Yanjun.Zhu @ 2025-11-13  1:41 UTC (permalink / raw)
  To: Pasha Tatashin
  Cc: Pratyush Yadav, akpm, brauner, corbet, graf, jgg, linux-kernel,
	linux-kselftest, linux-mm, masahiroy, ojeda, rdunlap, rppt, tj


On 11/11/25 7:26 AM, Pasha Tatashin wrote:
> On Mon, Nov 10, 2025 at 11:11 PM Zhu Yanjun <yanjun.zhu@linux.dev> wrote:
>> 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.
> 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

>
> Pasha
>
>> The call trace is in the attachment.
>>
>> Yanjun.Zhu
>>
>> 在 2025/11/10 7:26, Pasha Tatashin 写道:
>>> On Mon, Nov 10, 2025 at 8:16 AM Pratyush Yadav <pratyush@kernel.org> wrote:
>>>> On Sun, Nov 09 2025, Zhu Yanjun wrote:
>>>>
>>>>> 在 2025/11/8 10:13, Pasha Tatashin 写道:
>>>>>> On Fri, Nov 7, 2025 at 6:36 PM Yanjun.Zhu <yanjun.zhu@linux.dev> wrote:
>>>>>>> On 11/7/25 4:02 AM, Pasha Tatashin wrote:
>>>>>>>> On Fri, Nov 7, 2025 at 7:00 AM Pasha Tatashin <pasha.tatashin@soleen.com> wrote:
>>>>>>>>>> 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
>>>>>>>> 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?
>>>>>> 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:
>>>>> 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.
>>>> 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
>>>
>>>> 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


^ permalink raw reply	[flat|nested] 42+ messages in thread

* Re: [PATCH v9 1/9] kho: make debugfs interface optional
  2025-11-13  1:41                       ` Yanjun.Zhu
@ 2025-11-13  2:11                         ` Yanjun.Zhu
  2025-11-13 19:59                           ` Pasha Tatashin
  0 siblings, 1 reply; 42+ messages in thread
From: Yanjun.Zhu @ 2025-11-13  2:11 UTC (permalink / raw)
  To: Pasha Tatashin
  Cc: Pratyush Yadav, akpm, brauner, corbet, graf, jgg, linux-kernel,
	linux-kselftest, linux-mm, masahiroy, ojeda, rdunlap, rppt, tj


On 11/12/25 5:41 PM, Yanjun.Zhu wrote:
>
> On 11/11/25 7:26 AM, Pasha Tatashin wrote:
>> On Mon, Nov 10, 2025 at 11:11 PM Zhu Yanjun <yanjun.zhu@linux.dev> 
>> wrote:
>>> 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.
>> 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


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.

diff --git a/tools/testing/selftests/liveupdate/Makefile 
b/tools/testing/selftests/liveupdate/Makefile
index 6ee6efeec62d..b226b9976150 100644
--- a/tools/testing/selftests/liveupdate/Makefile
+++ b/tools/testing/selftests/liveupdate/Makefile
@@ -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

>
>
>>
>> Pasha
>>
>>> The call trace is in the attachment.
>>>
>>> Yanjun.Zhu
>>>
>>> 在 2025/11/10 7:26, Pasha Tatashin 写道:
>>>> On Mon, Nov 10, 2025 at 8:16 AM Pratyush Yadav 
>>>> <pratyush@kernel.org> wrote:
>>>>> On Sun, Nov 09 2025, Zhu Yanjun wrote:
>>>>>
>>>>>> 在 2025/11/8 10:13, Pasha Tatashin 写道:
>>>>>>> On Fri, Nov 7, 2025 at 6:36 PM Yanjun.Zhu <yanjun.zhu@linux.dev> 
>>>>>>> wrote:
>>>>>>>> On 11/7/25 4:02 AM, Pasha Tatashin wrote:
>>>>>>>>> On Fri, Nov 7, 2025 at 7:00 AM Pasha Tatashin 
>>>>>>>>> <pasha.tatashin@soleen.com> wrote:
>>>>>>>>>>> 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
>>>>>>>>> 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?
>>>>>>> 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:
>>>>>> 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.
>>>>> 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
>>>>
>>>>> 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


^ permalink raw reply related	[flat|nested] 42+ messages in thread

* Re: [PATCH v9 1/9] kho: make debugfs interface optional
  2025-11-11 15:26                     ` Pasha Tatashin
  2025-11-13  1:41                       ` Yanjun.Zhu
@ 2025-11-13 19:55                       ` Yanjun.Zhu
  2025-11-13 20:10                         ` Pasha Tatashin
  1 sibling, 1 reply; 42+ messages in thread
From: Yanjun.Zhu @ 2025-11-13 19:55 UTC (permalink / raw)
  To: Pasha Tatashin
  Cc: Pratyush Yadav, akpm, brauner, corbet, graf, jgg, linux-kernel,
	linux-kselftest, linux-mm, masahiroy, ojeda, rdunlap, rppt, tj


On 11/11/25 7:26 AM, Pasha Tatashin wrote:
> On Mon, Nov 10, 2025 at 11:11 PM Zhu Yanjun <yanjun.zhu@linux.dev> wrote:
>> 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.
> 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 <yanjun.zhu@linux.dev>
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
     "

     Signed-off-by: Zhu Yanjun <yanjun.zhu@linux.dev>

diff --git a/tools/testing/selftests/liveupdate/do_kexec.sh 
b/tools/testing/selftests/liveupdate/do_kexec.sh
index bb396a92c3b8..4ee59abd0dd4 100755
--- a/tools/testing/selftests/liveupdate/do_kexec.sh
+++ b/tools/testing/selftests/liveupdate/do_kexec.sh
@@ -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

>> The call trace is in the attachment.
>>
>> Yanjun.Zhu
>>
>> 在 2025/11/10 7:26, Pasha Tatashin 写道:
>>> On Mon, Nov 10, 2025 at 8:16 AM Pratyush Yadav <pratyush@kernel.org> wrote:
>>>> On Sun, Nov 09 2025, Zhu Yanjun wrote:
>>>>
>>>>> 在 2025/11/8 10:13, Pasha Tatashin 写道:
>>>>>> On Fri, Nov 7, 2025 at 6:36 PM Yanjun.Zhu <yanjun.zhu@linux.dev> wrote:
>>>>>>> On 11/7/25 4:02 AM, Pasha Tatashin wrote:
>>>>>>>> On Fri, Nov 7, 2025 at 7:00 AM Pasha Tatashin <pasha.tatashin@soleen.com> wrote:
>>>>>>>>>> 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
>>>>>>>> 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?
>>>>>> 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:
>>>>> 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.
>>>> 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
>>>
>>>> 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


^ permalink raw reply related	[flat|nested] 42+ messages in thread

* Re: [PATCH v9 1/9] kho: make debugfs interface optional
  2025-11-13  2:11                         ` Yanjun.Zhu
@ 2025-11-13 19:59                           ` Pasha Tatashin
  2025-11-13 20:07                             ` Yanjun.Zhu
  0 siblings, 1 reply; 42+ messages in thread
From: Pasha Tatashin @ 2025-11-13 19:59 UTC (permalink / raw)
  To: Yanjun.Zhu
  Cc: Pratyush Yadav, akpm, brauner, corbet, graf, jgg, linux-kernel,
	linux-kselftest, linux-mm, masahiroy, ojeda, rdunlap, rppt, tj

On Wed, Nov 12, 2025 at 9:11 PM Yanjun.Zhu <yanjun.zhu@linux.dev> wrote:
>
>
> On 11/12/25 5:41 PM, Yanjun.Zhu wrote:
> >
> > On 11/11/25 7:26 AM, Pasha Tatashin wrote:
> >> On Mon, Nov 10, 2025 at 11:11 PM Zhu Yanjun <yanjun.zhu@linux.dev>
> >> wrote:
> >>> 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.
> >> 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
>
>
> 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.
>
> diff --git a/tools/testing/selftests/liveupdate/Makefile
> b/tools/testing/selftests/liveupdate/Makefile
> index 6ee6efeec62d..b226b9976150 100644
> --- a/tools/testing/selftests/liveupdate/Makefile
> +++ b/tools/testing/selftests/liveupdate/Makefile
> @@ -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

>   OUTPUT ?= .
>
>   # --- Test Configuration (Edit this section when adding new tests) ---
>
> Yanjun.Zhu
>
> >
> >
> >>
> >> Pasha
> >>
> >>> The call trace is in the attachment.
> >>>
> >>> Yanjun.Zhu
> >>>
> >>> 在 2025/11/10 7:26, Pasha Tatashin 写道:
> >>>> On Mon, Nov 10, 2025 at 8:16 AM Pratyush Yadav
> >>>> <pratyush@kernel.org> wrote:
> >>>>> On Sun, Nov 09 2025, Zhu Yanjun wrote:
> >>>>>
> >>>>>> 在 2025/11/8 10:13, Pasha Tatashin 写道:
> >>>>>>> On Fri, Nov 7, 2025 at 6:36 PM Yanjun.Zhu <yanjun.zhu@linux.dev>
> >>>>>>> wrote:
> >>>>>>>> On 11/7/25 4:02 AM, Pasha Tatashin wrote:
> >>>>>>>>> On Fri, Nov 7, 2025 at 7:00 AM Pasha Tatashin
> >>>>>>>>> <pasha.tatashin@soleen.com> wrote:
> >>>>>>>>>>> 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
> >>>>>>>>> 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?
> >>>>>>> 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:
> >>>>>> 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.
> >>>>> 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
> >>>>
> >>>>> 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


^ permalink raw reply	[flat|nested] 42+ messages in thread

* Re: [PATCH v9 1/9] kho: make debugfs interface optional
  2025-11-13 19:59                           ` Pasha Tatashin
@ 2025-11-13 20:07                             ` Yanjun.Zhu
  0 siblings, 0 replies; 42+ messages in thread
From: Yanjun.Zhu @ 2025-11-13 20:07 UTC (permalink / raw)
  To: Pasha Tatashin
  Cc: Pratyush Yadav, akpm, brauner, corbet, graf, jgg, linux-kernel,
	linux-kselftest, linux-mm, masahiroy, ojeda, rdunlap, rppt, tj

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


On 11/13/25 11:59 AM, Pasha Tatashin wrote:
> On Wed, Nov 12, 2025 at 9:11 PM Yanjun.Zhu<yanjun.zhu@linux.dev> wrote:
>>
>> On 11/12/25 5:41 PM, Yanjun.Zhu wrote:
>>> On 11/11/25 7:26 AM, Pasha Tatashin wrote:
>>>> On Mon, Nov 10, 2025 at 11:11 PM Zhu Yanjun<yanjun.zhu@linux.dev>
>>>> wrote:
>>>>> 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.
>>>> 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
>>
>> 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.
>>
>> diff --git a/tools/testing/selftests/liveupdate/Makefile
>> b/tools/testing/selftests/liveupdate/Makefile
>> index 6ee6efeec62d..b226b9976150 100644
>> --- a/tools/testing/selftests/liveupdate/Makefile
>> +++ b/tools/testing/selftests/liveupdate/Makefile
>> @@ -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.

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

>
> Thank you,
> Pasha
>
>>    OUTPUT ?= .
>>
>>    # --- Test Configuration (Edit this section when adding new tests) ---
>>
>> Yanjun.Zhu
>>
>>>
>>>> Pasha
>>>>
>>>>> The call trace is in the attachment.
>>>>>
>>>>> Yanjun.Zhu
>>>>>
>>>>> 在 2025/11/10 7:26, Pasha Tatashin 写道:
>>>>>> On Mon, Nov 10, 2025 at 8:16 AM Pratyush Yadav
>>>>>> <pratyush@kernel.org> wrote:
>>>>>>> On Sun, Nov 09 2025, Zhu Yanjun wrote:
>>>>>>>
>>>>>>>> 在 2025/11/8 10:13, Pasha Tatashin 写道:
>>>>>>>>> On Fri, Nov 7, 2025 at 6:36 PM Yanjun.Zhu<yanjun.zhu@linux.dev>
>>>>>>>>> wrote:
>>>>>>>>>> On 11/7/25 4:02 AM, Pasha Tatashin wrote:
>>>>>>>>>>> On Fri, Nov 7, 2025 at 7:00 AM Pasha Tatashin
>>>>>>>>>>> <pasha.tatashin@soleen.com> wrote:
>>>>>>>>>>>>> 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
>>>>>>>>>>> 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?
>>>>>>>>> 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:
>>>>>>>> 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.
>>>>>>> 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
>>>>>>
>>>>>>> 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

[-- Attachment #2: Type: text/html, Size: 9849 bytes --]

^ permalink raw reply	[flat|nested] 42+ messages in thread

* Re: [PATCH v9 1/9] kho: make debugfs interface optional
  2025-11-13 19:55                       ` Yanjun.Zhu
@ 2025-11-13 20:10                         ` Pasha Tatashin
  2025-11-13 20:13                           ` Pasha Tatashin
  0 siblings, 1 reply; 42+ messages in thread
From: Pasha Tatashin @ 2025-11-13 20:10 UTC (permalink / raw)
  To: Yanjun.Zhu
  Cc: Pratyush Yadav, akpm, brauner, corbet, graf, jgg, linux-kernel,
	linux-kselftest, linux-mm, masahiroy, ojeda, rdunlap, rppt, tj

>   set -e
>
> -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


^ permalink raw reply	[flat|nested] 42+ messages in thread

* Re: [PATCH v9 1/9] kho: make debugfs interface optional
  2025-11-13 20:10                         ` Pasha Tatashin
@ 2025-11-13 20:13                           ` Pasha Tatashin
  2025-11-13 20:28                             ` Yanjun.Zhu
  0 siblings, 1 reply; 42+ messages in thread
From: Pasha Tatashin @ 2025-11-13 20:13 UTC (permalink / raw)
  To: Yanjun.Zhu
  Cc: Pratyush Yadav, akpm, brauner, corbet, graf, jgg, linux-kernel,
	linux-kselftest, linux-mm, masahiroy, ojeda, rdunlap, rppt, tj

On Thu, Nov 13, 2025 at 3:10 PM Pasha Tatashin
<pasha.tatashin@soleen.com> wrote:
>
> >   set -e
> >
> > -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.

> 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


^ permalink raw reply	[flat|nested] 42+ messages in thread

* Re: [PATCH v9 1/9] kho: make debugfs interface optional
  2025-11-13 20:13                           ` Pasha Tatashin
@ 2025-11-13 20:28                             ` Yanjun.Zhu
  0 siblings, 0 replies; 42+ messages in thread
From: Yanjun.Zhu @ 2025-11-13 20:28 UTC (permalink / raw)
  To: Pasha Tatashin
  Cc: Pratyush Yadav, akpm, brauner, corbet, graf, jgg, linux-kernel,
	linux-kselftest, linux-mm, masahiroy, ojeda, rdunlap, rppt, tj


On 11/13/25 12:13 PM, Pasha Tatashin wrote:
> On Thu, Nov 13, 2025 at 3:10 PM Pasha Tatashin
> <pasha.tatashin@soleen.com> wrote:
>>>    set -e
>>>
>>> -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

>
>> 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


^ permalink raw reply	[flat|nested] 42+ messages in thread

end of thread, other threads:[~2025-11-13 20:29 UTC | newest]

Thread overview: 42+ messages (download: mbox.gz follow: Atom feed
-- links below jump to the message on this page --
2025-11-01 14:23 [PATCH v9 0/9] liveupdate: Rework KHO for in-kernel users Pasha Tatashin
2025-11-01 14:23 ` [PATCH v9 1/9] kho: make debugfs interface optional Pasha Tatashin
2025-11-07  6:03   ` Zhu Yanjun
2025-11-07 12:00     ` Pasha Tatashin
2025-11-07 12:02       ` Pasha Tatashin
2025-11-07 23:35         ` Yanjun.Zhu
2025-11-08 18:13           ` Pasha Tatashin
2025-11-10  0:20             ` Zhu Yanjun
2025-11-10 13:16               ` Pratyush Yadav
2025-11-10 15:26                 ` Pasha Tatashin
2025-11-11  4:11                   ` Zhu Yanjun
2025-11-11 15:26                     ` Pasha Tatashin
2025-11-13  1:41                       ` Yanjun.Zhu
2025-11-13  2:11                         ` Yanjun.Zhu
2025-11-13 19:59                           ` Pasha Tatashin
2025-11-13 20:07                             ` Yanjun.Zhu
2025-11-13 19:55                       ` Yanjun.Zhu
2025-11-13 20:10                         ` Pasha Tatashin
2025-11-13 20:13                           ` Pasha Tatashin
2025-11-13 20:28                             ` Yanjun.Zhu
2025-11-01 14:23 ` [PATCH v9 2/9] kho: drop notifiers Pasha Tatashin
2025-11-06  8:41   ` kernel test robot
2025-11-06 21:46     ` Pasha Tatashin
2025-11-06 22:14       ` Pasha Tatashin
2025-11-01 14:23 ` [PATCH v9 3/9] kho: add interfaces to unpreserve folios, page ranges, and vmalloc Pasha Tatashin
2025-11-03 18:05   ` Pratyush Yadav
2025-11-01 14:23 ` [PATCH v9 4/9] memblock: Unpreserve memory in case of error Pasha Tatashin
2025-11-02  6:51   ` Mike Rapoport
2025-11-05 10:26   ` Pratyush Yadav
2025-11-01 14:23 ` [PATCH v9 5/9] test_kho: " Pasha Tatashin
2025-11-01 14:23 ` [PATCH v9 6/9] kho: don't unpreserve memory during abort Pasha Tatashin
2025-11-05 10:28   ` Pratyush Yadav
2025-11-01 14:23 ` [PATCH v9 7/9] liveupdate: kho: move to kernel/liveupdate Pasha Tatashin
2025-11-06  7:21   ` kernel test robot
2025-11-07 22:23   ` Andrew Morton
2025-11-08 18:01     ` Pasha Tatashin
2025-11-01 14:23 ` [PATCH v9 8/9] MAINTAINERS: update KHO maintainers Pasha Tatashin
2025-11-01 16:36   ` Mike Rapoport
2025-11-01 14:23 ` [PATCH v9 9/9] liveupdate: kho: Use %pe format specifier for error pointer printing Pasha Tatashin
2025-11-01 19:45   ` Zhu Yanjun
2025-11-02  6:59   ` Mike Rapoport
2025-11-03 12:59   ` Pratyush Yadav

This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox;
as well as URLs for NNTP newsgroup(s).