summaryrefslogtreecommitdiff
path: root/kernel
diff options
context:
space:
mode:
authorPasha Tatashin <pasha.tatashin@soleen.com>2026-06-03 15:43:53 +0000
committerMike Rapoport (Microsoft) <rppt@kernel.org>2026-06-03 21:15:45 +0300
commitcf071b3536df76a2a75b83ca1fe8c043824352c3 (patch)
tree2e9baa0fd357c760cabcecf85ba700dee7a59ef5 /kernel
parentd376e4b55c9a0adb3e701c7eaff21d9ba655a1c6 (diff)
downloadlwn-cf071b3536df76a2a75b83ca1fe8c043824352c3.tar.gz
lwn-cf071b3536df76a2a75b83ca1fe8c043824352c3.zip
liveupdate: register luo_ser as KHO subtree
Entirely remove the LUO FDT wrapper since the FDT only carries the compatible string and the pointer to the centralized struct luo_ser. Instead, register the struct luo_ser via the KHO raw subtree API, placing the compatibility string inside the structure itself. Acked-by: Mike Rapoport (Microsoft) <rppt@kernel.org> Reviewed-by: Pratyush Yadav (Google) <pratyush@kernel.org> Signed-off-by: Pasha Tatashin <pasha.tatashin@soleen.com> Link: https://patch.msgid.link/20260603154402.468928-5-pasha.tatashin@soleen.com Signed-off-by: Mike Rapoport (Microsoft) <rppt@kernel.org>
Diffstat (limited to 'kernel')
-rw-r--r--kernel/liveupdate/luo_core.c85
1 files changed, 25 insertions, 60 deletions
diff --git a/kernel/liveupdate/luo_core.c b/kernel/liveupdate/luo_core.c
index 085c0dfc1ef1..69b00e7d0f8f 100644
--- a/kernel/liveupdate/luo_core.c
+++ b/kernel/liveupdate/luo_core.c
@@ -54,7 +54,6 @@
#include <linux/kexec_handover.h>
#include <linux/kho/abi/luo.h>
#include <linux/kobject.h>
-#include <linux/libfdt.h>
#include <linux/liveupdate.h>
#include <linux/miscdevice.h>
#include <linux/mm.h>
@@ -67,8 +66,7 @@
static struct {
bool enabled;
- void *fdt_out;
- void *fdt_in;
+ struct luo_ser *luo_ser_out;
u64 liveupdate_num;
} luo_global;
@@ -85,11 +83,10 @@ early_param("liveupdate", early_liveupdate_param);
static int __init luo_early_startup(void)
{
+ phys_addr_t luo_ser_phys;
struct luo_ser *luo_ser;
- int err, header_size;
- phys_addr_t fdt_phys;
- const void *ptr;
- u64 luo_ser_pa;
+ size_t len;
+ int err;
if (!kho_is_enabled()) {
if (liveupdate_enabled())
@@ -98,40 +95,29 @@ static int __init luo_early_startup(void)
return 0;
}
- /* Retrieve LUO subtree, and verify its format. */
- err = kho_retrieve_subtree(LUO_FDT_KHO_ENTRY_NAME, &fdt_phys, NULL);
+ /* Retrieve LUO state from KHO. */
+ err = kho_retrieve_subtree(LUO_KHO_ENTRY_NAME, &luo_ser_phys, &len);
if (err) {
if (err != -ENOENT) {
- pr_err("failed to retrieve FDT '%s' from KHO: %pe\n",
- LUO_FDT_KHO_ENTRY_NAME, ERR_PTR(err));
+ pr_err("failed to retrieve LUO state '%s' from KHO: %pe\n",
+ LUO_KHO_ENTRY_NAME, ERR_PTR(err));
return err;
}
return 0;
}
- luo_global.fdt_in = phys_to_virt(fdt_phys);
- err = fdt_node_check_compatible(luo_global.fdt_in, 0,
- LUO_FDT_COMPATIBLE);
- if (err) {
- pr_err("FDT '%s' is incompatible with '%s' [%d]\n",
- LUO_FDT_KHO_ENTRY_NAME, LUO_FDT_COMPATIBLE, err);
-
+ if (len < sizeof(*luo_ser)) {
+ pr_err("LUO state is too small (%zu < %zu)\n", len, sizeof(*luo_ser));
return -EINVAL;
}
- header_size = 0;
- ptr = fdt_getprop(luo_global.fdt_in, 0, LUO_FDT_ABI_HEADER, &header_size);
- if (!ptr || header_size != sizeof(u64)) {
- pr_err("Unable to get ABI header '%s' [%d]\n",
- LUO_FDT_ABI_HEADER, header_size);
-
+ luo_ser = phys_to_virt(luo_ser_phys);
+ if (strncmp(luo_ser->compatible, LUO_ABI_COMPATIBLE, LUO_ABI_COMPAT_LEN)) {
+ pr_err("LUO state is incompatible with '%s'\n", LUO_ABI_COMPATIBLE);
return -EINVAL;
}
- luo_ser_pa = get_unaligned((u64 *)ptr);
- luo_ser = phys_to_virt(luo_ser_pa);
-
luo_global.liveupdate_num = luo_ser->liveupdate_num;
pr_info("Retrieved live update data, liveupdate number: %lld\n",
luo_global.liveupdate_num);
@@ -164,37 +150,20 @@ static int __init liveupdate_early_init(void)
}
early_initcall(liveupdate_early_init);
-/* Called during boot to create outgoing LUO fdt tree */
-static int __init luo_fdt_setup(void)
+/* Called during boot to create outgoing LUO state */
+static int __init luo_state_setup(void)
{
struct luo_ser *luo_ser;
- u64 luo_ser_pa;
- void *fdt_out;
int err;
- fdt_out = kho_alloc_preserve(LUO_FDT_SIZE);
- if (IS_ERR(fdt_out)) {
- pr_err("failed to allocate/preserve FDT memory\n");
- return PTR_ERR(fdt_out);
- }
-
luo_ser = kho_alloc_preserve(sizeof(*luo_ser));
if (IS_ERR(luo_ser)) {
- err = PTR_ERR(luo_ser);
- goto exit_free_fdt;
+ pr_err("failed to allocate/preserve LUO state memory\n");
+ return PTR_ERR(luo_ser);
}
- luo_ser_pa = virt_to_phys(luo_ser);
-
- err = fdt_create(fdt_out, LUO_FDT_SIZE);
- err |= fdt_finish_reservemap(fdt_out);
- err |= fdt_begin_node(fdt_out, "");
- err |= fdt_property_string(fdt_out, "compatible", LUO_FDT_COMPATIBLE);
- err |= fdt_property(fdt_out, LUO_FDT_ABI_HEADER, &luo_ser_pa,
- sizeof(luo_ser_pa));
- err |= fdt_end_node(fdt_out);
- err |= fdt_finish(fdt_out);
- if (err)
- goto exit_free_luo_ser;
+
+ strscpy(luo_ser->compatible, LUO_ABI_COMPATIBLE, sizeof(luo_ser->compatible));
+ luo_ser->liveupdate_num = luo_global.liveupdate_num + 1;
err = luo_session_setup_outgoing(&luo_ser->sessions_pa);
if (err)
@@ -204,21 +173,17 @@ static int __init luo_fdt_setup(void)
if (err)
goto exit_free_luo_ser;
- luo_ser->liveupdate_num = luo_global.liveupdate_num + 1;
-
- err = kho_add_subtree(LUO_FDT_KHO_ENTRY_NAME, fdt_out,
- fdt_totalsize(fdt_out));
+ err = kho_add_subtree(LUO_KHO_ENTRY_NAME, luo_ser, sizeof(*luo_ser));
if (err)
goto exit_free_luo_ser;
- luo_global.fdt_out = fdt_out;
+
+ luo_global.luo_ser_out = luo_ser;
return 0;
exit_free_luo_ser:
kho_unpreserve_free(luo_ser);
-exit_free_fdt:
- kho_unpreserve_free(fdt_out);
- pr_err("failed to prepare LUO FDT: %d\n", err);
+ pr_err("failed to prepare LUO state: %d\n", err);
return err;
}
@@ -234,7 +199,7 @@ static int __init luo_late_startup(void)
if (!liveupdate_enabled())
return 0;
- err = luo_fdt_setup();
+ err = luo_state_setup();
if (err)
luo_global.enabled = false;