From: Tarun Sahu <tarunsahu@google.com>
To: Pasha Tatashin <pasha.tatashin@soleen.com>,
Mike Rapoport <rppt@kernel.org>,
robin.murphy@arm.com, maz@kernel.org, will@kernel.org,
David Matlack <dmatlack@google.com>,
Alexander Graf <graf@amazon.com>,
seanjc@google.com, jgg@nvidia.com, loganodell@google.com,
arnd@arndb.de, dwmw2@infradead.org, baolu.lu@linux.intel.com,
Bjorn Helgaas <bhelgaas@google.com>,
oupton@kernel.org, alex@shazbot.org, gle.com@google.com,
pbonzini@redhat.com, Andrew Morton <akpm@linux-foundation.org>,
kevin.tian@intel.com, joro@8bytes.org
Cc: kvmarm@lists.linux.dev, linux-pci@vger.kernel.org,
Pratyush Yadav <pratyush@kernel.org>,
kexec@lists.infradead.org, kvm@vger.kernel.org,
iommu@lists.linux.dev, linux-arm-kernel@lists.infradead.org,
skhawaja@google.com, sagis@google.com,
linux-arch@vger.kernel.org, linux-mm@kvack.org,
linux-kernel@vger.kernel.org, Tarun Sahu <tarunsahu@google.com>
Subject: [PATCH v4 09/19] liveupdate: Add feature header to struct luo_ser
Date: Tue, 10 Nov 2026 05:01:52 +0000 [thread overview]
Message-ID: <20261110050202.529473-10-tarunsahu@google.com> (raw)
In-Reply-To: <20261110050202.529473-1-tarunsahu@google.com>
LUO and its file handlers currently rely solely on coarse-grained
compatibility strings (such as luo-v6 and memfd-v3) to validate
handed-over state across kexec. Because compatibility is checked only
at the whole-structure level, any change to a serialized structure,
even an optional additive field, requires bumping the compatibility
string and breaks live update between adjacent kernels.
Precede the centralized struct luo_ser with struct kho_ser_hdr using
DECLARE_KHO_SER. Subsystems can now evolve their serialized state at
per-feature granularity. Each subsystem groups the fields of its
serialized structure under feature indices, starting with index 0 for the
base fields. When a subsystem adds a new capability, it appends any new
fields to the end of its payload structure under a new feature index.
Retired fields are kept in place so existing field offsets never shift;
if the type or format of a field needs to change, the existing field and
feature are kept intact until retired and a new feature index with an
appended field of the new type is added. Only when a change requires a
complete break in the serialized layout or semantics that feature flags
cannot handle, a new handler can be introduced with an incremented version
number in its compatibility string.
Signed-off-by: Logan Odell <loganodell@google.com>
Signed-off-by: Tarun Sahu <tarunsahu@google.com>
---
include/linux/kho/abi/luo.h | 64 +++++++++++++++---------------------
kernel/liveupdate/luo_core.c | 39 +++++++++++++---------
2 files changed, 50 insertions(+), 53 deletions(-)
diff --git a/include/linux/kho/abi/luo.h b/include/linux/kho/abi/luo.h
index f1152470f71a..dfa7ea434d0d 100644
--- a/include/linux/kho/abi/luo.h
+++ b/include/linux/kho/abi/luo.h
@@ -9,29 +9,26 @@
* DOC: Live Update Orchestrator ABI
*
* Live Update Orchestrator uses the stable Application Binary Interface
- * defined below to pass state from a pre-update kernel to a post-update
- * kernel. The ABI is built upon the Kexec HandOver framework and registers
- * the central `struct luo_ser` via the KHO raw subtree API.
+ * defined below to pass state from a source kernel to a target kernel.
+ * The ABI is built upon the Kexec HandOver framework and registers the
+ * central `struct luo_ser` via the KHO raw subtree API.
*
- * This interface is a contract. Any modification to the structure fields,
- * compatible strings, or the layout of the `__packed` serialization
- * structures defined here constitutes a breaking change. Such changes require
- * incrementing the version number in the relevant `_COMPATIBLE` string to
- * prevent a new kernel from misinterpreting data from an old kernel.
- *
- * Changes are allowed provided the compatibility version is incremented;
- * however, backward/forward compatibility is only guaranteed for kernels
- * supporting the same ABI version.
+ * This interface is a contract. `struct luo_ser`, and the serialized state
+ * of each file handler that uses it, are preceded by `struct kho_ser_hdr`.
+ * See the KHO Serialization Feature Header ABI documentation in
+ * include/linux/kho/abi/feature.h for the header layout, the feature rules
+ * and validation.
*
* KHO Structure Overview:
* The entire LUO state is encapsulated within a single KHO entry named "LUO".
- * This entry contains the `struct luo_ser` structure.
+ * This entry contains a `struct kho_ser_hdr` followed by the
+ * `struct luo_ser` payload.
*
* Serialization Structures:
* - struct luo_ser:
- * The central ABI structure that contains the overall state of the LUO.
- * It includes the compatibility string, the liveupdate-number, and pointers
- * to sessions and FLBs.
+ * The central ABI payload structure that contains the overall state of
+ * the LUO (the liveupdate-number and physical pointers to sessions and
+ * FLBs), preceded by `struct kho_ser_hdr`.
*
* - struct luo_session_ser:
* Metadata for a single session, including its name and a physical pointer
@@ -40,7 +37,7 @@
*
* - struct luo_file_ser:
* Metadata for a single preserved file. Contains the `compatible` string to
- * find the correct handler in the new kernel, a user-provided `token` for
+ * find the correct handler in the target kernel, a user-provided `token` for
* identification, and an opaque `data` handle for the handler to use.
*
* - struct luo_flb_header_ser:
@@ -57,39 +54,36 @@
#ifndef _LINUX_KHO_ABI_LUO_H
#define _LINUX_KHO_ABI_LUO_H
-#include <linux/align.h>
#include <linux/build_bug.h>
#include <linux/kconfig.h>
#include <linux/kho/abi/block.h>
+#include <linux/kho/abi/feature.h>
#include <linux/kho/abi/kexec_handover.h>
+#include <linux/types.h>
#include <uapi/linux/liveupdate.h>
/*
* The LUO state is registered under this KHO entry name.
*/
#define LUO_KHO_ENTRY_NAME "LUO"
-#define LUO_ABI_COMPATIBLE "luo-v6"
-#define LUO_ABI_COMPAT_LEN ALIGN(sizeof(LUO_ABI_COMPATIBLE), 8)
/**
- * struct luo_ser - Centralized LUO ABI header.
- * @compatible: Compatibility string identifying the LUO ABI version.
+ * struct luo_ser - Centralized LUO ABI payload.
* @liveupdate_num: A counter tracking the number of successful live updates.
* @sessions_pa: Physical address of the first session block header.
* @flbs_pa: Physical address of the FLB header.
*
- * This structure is the root of all preserved LUO state.
+ * This structure is the root payload of all preserved LUO state, preceded by
+ * &struct kho_ser_hdr.
*/
struct luo_ser {
- char compatible[LUO_ABI_COMPAT_LEN];
u64 liveupdate_num;
u64 sessions_pa;
u64 flbs_pa;
};
-static_assert(sizeof(struct luo_ser) == 32);
-static_assert(!IS_ENABLED(CONFIG_64BIT) ||
- __alignof__(struct luo_ser) == 8);
+/* Register luo_ser with KHO serialization accessors */
+DECLARE_KHO_SER(luo_ser, 24, 0, 0);
#define LIVEUPDATE_HNDL_COMPAT_LENGTH 48
@@ -98,8 +92,6 @@ static_assert(!IS_ENABLED(CONFIG_64BIT) ||
* @compatible: File handler compatible string.
* @data: Private data
* @token: User provided token for this file
- *
- * If this structure is modified, `LUO_ABI_COMPATIBLE` must be updated.
*/
struct luo_file_ser {
char compatible[LIVEUPDATE_HNDL_COMPAT_LENGTH];
@@ -138,10 +130,8 @@ static_assert(!IS_ENABLED(CONFIG_64BIT) ||
*
* This structure is used to package session-specific metadata for transfer
* between kernels via Kexec Handover. An array of these structures (one per
- * session) is created and passed to the new kernel, allowing it to reconstruct
- * the session context.
- *
- * If this structure is modified, `LUO_ABI_COMPATIBLE` must be updated.
+ * session) is created and passed to the target kernel, allowing it to
+ * reconstruct the session context.
*/
struct luo_session_ser {
char name[LIVEUPDATE_SESSION_NAME_LENGTH];
@@ -180,13 +170,13 @@ static_assert(!IS_ENABLED(CONFIG_64BIT) ||
/**
* struct luo_flb_ser - Represents the serialized state of a single FLB object.
* @name: The unique compatibility string of the FLB object, used to find the
- * corresponding &struct liveupdate_flb handler in the new kernel.
+ * corresponding &struct liveupdate_flb in the target kernel.
* @data: The opaque u64 handle returned by the FLB's .preserve() operation
- * in the old kernel. This handle encapsulates the entire state needed
- * for restoration.
+ * in the source kernel. This handle encapsulates the entire state
+ * needed for restoration.
* @count: The reference count at the time of serialization; i.e., the number
* of preserved files that depended on this FLB. This is used by the
- * new kernel to correctly manage the FLB's lifecycle.
+ * target kernel to correctly manage the FLB's lifecycle.
*
* An array of these structures is created in a preserved memory region and
* passed to the new kernel. Each entry allows the LUO core to restore one
diff --git a/kernel/liveupdate/luo_core.c b/kernel/liveupdate/luo_core.c
index 1b2bda22902d..d0f72f27001d 100644
--- a/kernel/liveupdate/luo_core.c
+++ b/kernel/liveupdate/luo_core.c
@@ -66,7 +66,7 @@
static struct {
bool enabled;
- struct luo_ser *luo_ser_out;
+ DECLARE_KHO_SER_HDR(luo_ser, *luo_ser_out);
u64 liveupdate_num;
} luo_global;
@@ -83,6 +83,7 @@ early_param("liveupdate", early_liveupdate_param);
static int __init luo_early_startup(void)
{
+ DECLARE_KHO_SER_HDR(luo_ser, *fhdr);
phys_addr_t luo_ser_phys;
struct luo_ser *luo_ser;
size_t len;
@@ -107,17 +108,21 @@ static int __init luo_early_startup(void)
return 0;
}
- if (len < sizeof(*luo_ser)) {
- pr_err("LUO state is too small (%zu < %zu)\n", len, sizeof(*luo_ser));
- return -EINVAL;
+ fhdr = phys_to_virt(luo_ser_phys);
+ if (len < sizeof(*fhdr) || fhdr->size > len) {
+ pr_err("LUO state size invalid (source kernel header size=%u, KHO len=%zu)\n",
+ len >= sizeof(*fhdr) ? fhdr->size : 0, len);
+ err = -EINVAL;
+ goto out_free_ser;
}
- 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;
+ err = kho_ser_validate(fhdr, luo_ser);
+ if (err) {
+ pr_err("LUO state feature validation failed: %pe\n", ERR_PTR(err));
+ goto out_free_ser;
}
+ luo_ser = kho_ser_payload(fhdr, luo_ser);
luo_global.liveupdate_num = luo_ser->liveupdate_num;
pr_info("Retrieved live update data, liveupdate number: %lld\n",
luo_global.liveupdate_num);
@@ -131,7 +136,7 @@ static int __init luo_early_startup(void)
err = 0;
out_free_ser:
- kho_restore_free(luo_ser);
+ kho_restore_free(fhdr);
return err;
}
@@ -153,16 +158,18 @@ early_initcall(liveupdate_early_init);
/* Called during boot to create outgoing LUO state */
static int __init luo_state_setup(void)
{
+ DECLARE_KHO_SER_HDR(luo_ser, *fhdr);
struct luo_ser *luo_ser;
int err;
- luo_ser = kho_alloc_preserve(sizeof(*luo_ser));
- if (IS_ERR(luo_ser)) {
+ fhdr = kho_alloc_preserve(kho_ser_size(luo_ser));
+ if (IS_ERR(fhdr)) {
pr_err("failed to allocate/preserve LUO state memory\n");
- return PTR_ERR(luo_ser);
+ return PTR_ERR(fhdr);
}
+ kho_ser_init(fhdr, luo_ser);
- strscpy(luo_ser->compatible, LUO_ABI_COMPATIBLE, sizeof(luo_ser->compatible));
+ luo_ser = kho_ser_payload(fhdr, luo_ser);
luo_ser->liveupdate_num = luo_global.liveupdate_num + 1;
luo_session_setup_outgoing(&luo_ser->sessions_pa);
@@ -171,16 +178,16 @@ static int __init luo_state_setup(void)
if (err)
goto exit_free_luo_ser;
- err = kho_add_subtree(LUO_KHO_ENTRY_NAME, luo_ser, sizeof(*luo_ser));
+ err = kho_add_subtree(LUO_KHO_ENTRY_NAME, fhdr, fhdr->size);
if (err)
goto exit_free_luo_ser;
- luo_global.luo_ser_out = luo_ser;
+ luo_global.luo_ser_out = fhdr;
return 0;
exit_free_luo_ser:
- kho_unpreserve_free(luo_ser);
+ kho_unpreserve_free(fhdr);
pr_err("failed to prepare LUO state: %d\n", err);
return err;
--
2.56.0.506.g506a7eabc5-goog
next prev parent reply other threads:[~2026-11-10 5:02 UTC|newest]
Thread overview: 20+ messages / expand[flat|nested] mbox.gz Atom feed top
2026-11-10 5:01 [PATCH v4 00/19] kho, liveupdate: Add feature header for fine-grained ABI compatibility Tarun Sahu
2026-11-10 5:01 ` [PATCH v4 01/19] liveupdate, kho: Remove __packed from KHO, LUO and memfd ABI structures Tarun Sahu
2026-11-10 5:01 ` [PATCH v4 02/19] kho: block: Record the entry size in the block header Tarun Sahu
2026-11-10 5:01 ` [PATCH v4 03/19] kho, memfd_luo: Reference struct kho_vmalloc via serialized pointer Tarun Sahu
2026-11-10 5:01 ` [PATCH v4 04/19] liveupdate: Reference struct luo_file_set_ser " Tarun Sahu
2026-11-10 5:01 ` [PATCH v4 05/19] kho: Add feature header for fine-grained ABI compatibility Tarun Sahu
2026-11-10 5:01 ` [PATCH v4 06/19] kho: kexec_metadata: Add the feature header Tarun Sahu
2026-11-10 5:01 ` [PATCH v4 07/19] kho: vmalloc: " Tarun Sahu
2026-11-10 5:01 ` [PATCH v4 08/19] kho: block: Add the feature header to blocks Tarun Sahu
2026-11-10 5:01 ` Tarun Sahu [this message]
2026-11-10 5:01 ` [PATCH v4 10/19] liveupdate: Add feature header to struct luo_session_ser Tarun Sahu
2026-11-10 5:01 ` [PATCH v4 11/19] liveupdate: Add feature header to struct luo_file_set_ser Tarun Sahu
2026-11-10 5:01 ` [PATCH v4 12/19] liveupdate: Add feature header to struct luo_file_ser Tarun Sahu
2026-11-10 5:01 ` [PATCH v4 13/19] liveupdate: Add feature header to struct luo_flb_header_ser Tarun Sahu
2026-11-10 5:01 ` [PATCH v4 14/19] liveupdate: Add feature header to struct luo_flb_ser Tarun Sahu
2026-11-10 5:01 ` [PATCH v4 15/19] PCI: liveupdate: Add feature header to struct pci_ser Tarun Sahu
2026-11-10 5:01 ` [PATCH v4 16/19] PCI: liveupdate: Add feature header to struct pci_dev_ser Tarun Sahu
2026-11-10 5:02 ` [PATCH v4 17/19] mm: memfd_luo: Add feature header to struct memfd_luo_ser Tarun Sahu
2026-11-10 5:02 ` [PATCH v4 18/19] mm: memfd_luo: Add feature header to struct memfd_luo_folio_ser Tarun Sahu
2026-11-10 5:02 ` [PATCH v4 19/19] kho: Add KUnit test for the feature header helpers Tarun Sahu
Reply instructions:
You may reply publicly to this message via plain-text email
using any one of the following methods:
* Save the following mbox file, import it into your mail client,
and reply-to-all from there: mbox
Avoid top-posting and favor interleaved quoting:
https://en.wikipedia.org/wiki/Posting_style#Interleaved_style
* Reply using the --to, --cc, and --in-reply-to
switches of git-send-email(1):
git send-email \
--in-reply-to=20261110050202.529473-10-tarunsahu@google.com \
--to=tarunsahu@google.com \
--cc=akpm@linux-foundation.org \
--cc=alex@shazbot.org \
--cc=arnd@arndb.de \
--cc=baolu.lu@linux.intel.com \
--cc=bhelgaas@google.com \
--cc=dmatlack@google.com \
--cc=dwmw2@infradead.org \
--cc=gle.com@google.com \
--cc=graf@amazon.com \
--cc=iommu@lists.linux.dev \
--cc=jgg@nvidia.com \
--cc=joro@8bytes.org \
--cc=kevin.tian@intel.com \
--cc=kexec@lists.infradead.org \
--cc=kvm@vger.kernel.org \
--cc=kvmarm@lists.linux.dev \
--cc=linux-arch@vger.kernel.org \
--cc=linux-arm-kernel@lists.infradead.org \
--cc=linux-kernel@vger.kernel.org \
--cc=linux-mm@kvack.org \
--cc=linux-pci@vger.kernel.org \
--cc=loganodell@google.com \
--cc=maz@kernel.org \
--cc=oupton@kernel.org \
--cc=pasha.tatashin@soleen.com \
--cc=pbonzini@redhat.com \
--cc=pratyush@kernel.org \
--cc=robin.murphy@arm.com \
--cc=rppt@kernel.org \
--cc=sagis@google.com \
--cc=seanjc@google.com \
--cc=skhawaja@google.com \
--cc=will@kernel.org \
/path/to/YOUR_REPLY
https://kernel.org/pub/software/scm/git/docs/git-send-email.html
* If your mail client supports setting the In-Reply-To header
via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line
before the message body.
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox
all inboxes | Powered by JetHome®