diff options
| author | Pasha Tatashin <pasha.tatashin@soleen.com> | 2026-06-03 15:43:53 +0000 |
|---|---|---|
| committer | Mike Rapoport (Microsoft) <rppt@kernel.org> | 2026-06-03 21:15:45 +0300 |
| commit | cf071b3536df76a2a75b83ca1fe8c043824352c3 (patch) | |
| tree | 2e9baa0fd357c760cabcecf85ba700dee7a59ef5 /kernel | |
| parent | d376e4b55c9a0adb3e701c7eaff21d9ba655a1c6 (diff) | |
| download | lwn-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.c | 85 |
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; |
