This is simple test and playground useful kstate subsystem development.
It contains some structure with different kind of data which migrated
across kexec to the new kernel using kstate.
Signed-off-by: Andrey Ryabinin <arbn@yandex-team.com>
---
MAINTAINERS | 1 +
include/linux/kstate.h | 2 +
kernel/liveupdate/Kconfig | 8 +++
lib/Makefile | 2 +
lib/test_kstate.c | 116 ++++++++++++++++++++++++++++++++++++++
5 files changed, 129 insertions(+)
create mode 100644 lib/test_kstate.c
diff --git a/MAINTAINERS b/MAINTAINERS
index 2cd9e49abee5..e96da6d97e75 100644
--- a/MAINTAINERS
+++ b/MAINTAINERS
@@ -13723,6 +13723,7 @@ M: Andrey Ryabinin <ryabinin.a.a@gmail.com>
S: Maintained
F: include/linux/kstate.h
F: kernel/livupdate/kstate.c
+F: lib/test_kstate.c
KTD253 BACKLIGHT DRIVER
M: Linus Walleij <linus.walleij@linaro.org>
diff --git a/include/linux/kstate.h b/include/linux/kstate.h
index 5a95960e5b03..0ced0da37c8f 100644
--- a/include/linux/kstate.h
+++ b/include/linux/kstate.h
@@ -95,6 +95,8 @@ struct kstate_field {
enum kstate_ids {
KSTATE_FOLIO_ID = 1,
KSTATE_KHO_FDT_ID,
+ KSTATE_TEST_ID,
+ KSTATE_TEST_ID_V2,
KSTATE_LAST_ID = -1,
};
diff --git a/kernel/liveupdate/Kconfig b/kernel/liveupdate/Kconfig
index b6ea861006bf..af9a25bdcd6e 100644
--- a/kernel/liveupdate/Kconfig
+++ b/kernel/liveupdate/Kconfig
@@ -69,6 +69,14 @@ config KSTATE
state, save it into the memory and restore the state after kexec
in new kernel.
+config KSTATE_TEST
+ bool "KSTATE test code"
+ help
+ Build a simple test/playground code that is useful for kstate
+ subsystem development. It contains some structure with different
+ kind of data which migrated across kexec to the new kernel
+ using KSTATE.
+
config KEXEC_HANDOVER
bool "kexec handover"
depends on ARCH_SUPPORTS_KEXEC_HANDOVER && ARCH_SUPPORTS_KEXEC_FILE
diff --git a/lib/Makefile b/lib/Makefile
index 392ff808c9b9..46616577caf3 100644
--- a/lib/Makefile
+++ b/lib/Makefile
@@ -316,6 +316,8 @@ obj-$(CONFIG_PARMAN) += parman.o
obj-y += group_cpus.o
+obj-$(CONFIG_KSTATE_TEST) += test_kstate.o
+
# GCC library routines
obj-$(CONFIG_GENERIC_LIB_ASHLDI3) += ashldi3.o
obj-$(CONFIG_GENERIC_LIB_ASHRDI3) += ashrdi3.o
diff --git a/lib/test_kstate.c b/lib/test_kstate.c
new file mode 100644
index 000000000000..70534e8c718f
--- /dev/null
+++ b/lib/test_kstate.c
@@ -0,0 +1,116 @@
+// SPDX-License-Identifier: GPL-2.0
+#define pr_fmt(fmt) "kstate test: " fmt
+#include <linux/io.h>
+#include <linux/kexec_handover.h>
+#include <linux/kstate.h>
+#include <linux/mm.h>
+#include <linux/module.h>
+
+static unsigned long ulong_val;
+struct kstate_test_data {
+ int i;
+ unsigned long *p_ulong;
+ char s[10];
+ struct folio *folio;
+};
+
+#define KSTATE_TEST_DATA_ID 123
+
+struct kstate_description test_state_v2 = {
+ .name = "test_v2",
+ .version_id = 1,
+ .id = KSTATE_TEST_ID_V2,
+ .fields = (const struct kstate_field[]) {
+ KSTATE_BASE_TYPE(i, struct kstate_test_data, int),
+ KSTATE_END_OF_LIST()
+ },
+};
+
+struct kstate_description test_state = {
+ .name = "test",
+ .version_id = 2,
+ .id = KSTATE_TEST_ID,
+ .fields = (const struct kstate_field[]) {
+ KSTATE_BASE_TYPE(s, struct kstate_test_data, char [10]),
+ KSTATE_POINTER(p_ulong, struct kstate_test_data),
+ KSTATE_FOLIO(folio, struct kstate_test_data),
+ KSTATE_BASE_TYPE_DEPRECATED(k, u16, 1),
+ KSTATE_END_OF_LIST()
+ },
+ .subsections = (const struct kstate_description *[]){
+ &test_state_v2,
+ NULL
+ },
+};
+
+static struct kstate_test_data test_data;
+
+static int init_test_data(void)
+{
+ struct folio *folio;
+ int i;
+
+ test_data.i = 10;
+ ulong_val = 20;
+ memcpy(test_data.s, "abcdefghk", sizeof(test_data.s));
+ folio = folio_alloc(GFP_KERNEL, 0);
+ if (!folio)
+ return -ENOMEM;
+
+ for (i = 0; i < folio_size(folio)/sizeof(u32); i += 4)
+ *((u32 *)folio_address(folio) + i) = 0xdeadbeef;
+ test_data.folio = folio;
+ return 0;
+}
+
+static void validate_test_data(void)
+{
+ int i;
+
+ if (WARN_ON(test_data.i != 10))
+ return;
+ if (WARN_ON(*test_data.p_ulong != 20))
+ return;
+ if (WARN_ON(strcmp(test_data.s, "abcdefghk") != 0))
+ return;
+
+ for (i = 0; i < folio_size(test_data.folio)/4; i += 4) {
+ u32 val = *((u32 *)folio_address(test_data.folio) + i);
+
+ if (WARN_ON_ONCE(val != 0xdeadbeef))
+ return;
+ }
+}
+
+static int __init test_kstate_init(void)
+{
+ int ret = 0;
+
+ test_data.p_ulong = &ulong_val;
+
+ ret = kstate_register(&test_state, &test_data, KSTATE_TEST_DATA_ID);
+ if (ret) {
+ pr_err("register failed %d\n", ret);
+ goto out;
+ }
+
+ if (!is_kho_boot()) {
+ ret = init_test_data();
+ if (ret)
+ goto out;
+ } else {
+ pr_info("restoring data\n");
+ ret = kstate_restore(&test_state, &test_data, KSTATE_TEST_DATA_ID);
+ if (ret) {
+ pr_err("restore failed %d\n", ret);
+ goto out;
+ }
+
+ }
+
+ validate_test_data();
+
+out:
+ return ret;
+}
+late_initcall(test_kstate_init);
--
2.49.1
On 9/9/25 1:14 PM, Andrey Ryabinin wrote: > diff --git a/kernel/liveupdate/Kconfig b/kernel/liveupdate/Kconfig > index b6ea861006bf..af9a25bdcd6e 100644 > --- a/kernel/liveupdate/Kconfig > +++ b/kernel/liveupdate/Kconfig > @@ -69,6 +69,14 @@ config KSTATE > state, save it into the memory and restore the state after kexec > in new kernel. > > +config KSTATE_TEST > + bool "KSTATE test code" > + help > + Build a simple test/playground code that is useful for kstate Build simple > + subsystem development. It contains some structure with different structures ? > + kind of data which migrated across kexec to the new kernel kinds which are migrated > + using KSTATE. > + -- ~Randy
On 9/10/25 2:33 AM, Randy Dunlap wrote: > > > On 9/9/25 1:14 PM, Andrey Ryabinin wrote: >> diff --git a/kernel/liveupdate/Kconfig b/kernel/liveupdate/Kconfig >> index b6ea861006bf..af9a25bdcd6e 100644 >> --- a/kernel/liveupdate/Kconfig >> +++ b/kernel/liveupdate/Kconfig >> @@ -69,6 +69,14 @@ config KSTATE >> state, save it into the memory and restore the state after kexec >> in new kernel. >> >> +config KSTATE_TEST >> + bool "KSTATE test code" >> + help >> + Build a simple test/playground code that is useful for kstate > > Build simple > >> + subsystem development. It contains some structure with different > > structures > ? > >> + kind of data which migrated across kexec to the new kernel > > kinds which are migrated > >> + using KSTATE. >> + > Thanks, Randy. I'll fix this up, and the documentation as well.
© 2016 - 2025 Red Hat, Inc.