[PATCH v2 07/13] kho: Simplify serialization and remove __kho_abort

Pasha Tatashin
2025-11-14T19:00:15Z

Currently, __kho_finalize() performs memory serialization in the middle
of FDT construction. If FDT construction fails later, the function must
manually clean up the serialized memory via __kho_abort().

Refactor __kho_finalize() to perform kho_mem_serialize() only after the
FDT has been successfully constructed and finished. This reordering has
two benefits:
1. It avoids expensive serialization work if FDT generation fails.
2. It removes the need for cleanup in the FDT error path.

As a result, the internal helper __kho_abort() is no longer needed for
internal error handling. Inline its remaining logic (cleanup of the
preserved memory map) directly into kho_abort() and remove the helper.

Signed-off-by: Pasha Tatashin <pasha.tatashin@soleen.com>
Reviewed-by: Mike Rapoport (Microsoft) <rppt@kernel.org>
Reviewed-by: Pratyush Yadav <pratyush@kernel.org>
---
kernel/liveupdate/kexec_handover.c | 41 +++++++++++++-----------------
1 file changed, 17 insertions(+), 24 deletions(-)

diff --git a/kernel/liveupdate/kexec_handover.c b/kernel/liveupdate/kexec_handover.c
index 3e32c61a64b1..297136054f75 100644
--- a/kernel/liveupdate/kexec_handover.c
+++ b/kernel/liveupdate/kexec_handover.c
@@ -1214,14 +1214,6 @@ void kho_restore_free(void *mem)
}
EXPORT_SYMBOL_GPL(kho_restore_free);

-static void __kho_abort(void)
-{
- if (kho_out.preserved_mem_map) {
- kho_mem_ser_free(kho_out.preserved_mem_map);
- kho_out.preserved_mem_map = NULL;
- }
-}
-
int kho_abort(void)
{
if (!kho_enable)
@@ -1231,7 +1223,8 @@ int kho_abort(void)
if (!kho_out.finalized)
return -ENOENT;

- __kho_abort();
+ kho_mem_ser_free(kho_out.preserved_mem_map);
+ kho_out.preserved_mem_map = NULL;
kho_out.finalized = false;

return 0;
@@ -1239,12 +1232,12 @@ int kho_abort(void)

static int __kho_finalize(void)
{
- int err = 0;
- u64 *preserved_mem_map;
void *root = kho_out.fdt;
struct kho_sub_fdt *fdt;
+ u64 *preserved_mem_map;
+ int err;

- err |= fdt_create(root, PAGE_SIZE);
+ 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);
@@ -1257,13 +1250,7 @@ static int __kho_finalize(void)
sizeof(*preserved_mem_map),
(void **)&preserved_mem_map);
if (err)
- goto abort;
-
- err = kho_mem_serialize(&kho_out);
- if (err)
- goto abort;
-
- *preserved_mem_map = (u64)virt_to_phys(kho_out.preserved_mem_map);
+ goto err_exit;

mutex_lock(&kho_out.fdts_lock);
list_for_each_entry(fdt, &kho_out.sub_fdts, l) {
@@ -1277,13 +1264,19 @@ static int __kho_finalize(void)

err |= fdt_end_node(root);
err |= fdt_finish(root);
+ if (err)
+ goto err_exit;

-abort:
- if (err) {
- pr_err("Failed to convert KHO state tree: %d\n", err);
- __kho_abort();
- }
+ err = kho_mem_serialize(&kho_out);
+ if (err)
+ goto err_exit;
+
+ *preserved_mem_map = (u64)virt_to_phys(kho_out.preserved_mem_map);
+
+ return 0;

+err_exit:
+ pr_err("Failed to convert KHO state tree: %d\n", err);
return err;
}

--
2.52.0.rc1.455.g30608eb744-goog