[RFC PATCH 2/3] luo: Export feature support to vmlinux section

Pratyush Yadav pratyush at kernel.org
Thu Oct 15 06:05:26 PDT 2026


Hi Logan,

On Wed, Sep 02 2026, Logan Odell wrote:

> Create a liveupdate_features section that contains the feature
> information for a given liveupdate component. Add the LUO component
> first. These can be compared between two kernels to determine live
> update compatibility. Features marked as required in the running kernel
> will need to have that feature marked as supported in the next kernel to
> be eligible for compatibility.
>
> Suggested-by: Pratyush Yadav <pratyush at kernel.org>
> Signed-off-by: Logan Odell <loganodell at google.com>

I was thinking about this a bit more. We don't really ship the vmlinux
directly. On x86 it is a PE/COFF image, on arm64 the Image format strips
ELF information and is a raw binary file.

So this information would not be accessible to the kexec loader/luod. So
perhaps as part of the build we parse the section and output a file with
the versions? And then it can be packaged with the likes of System.map
for example?

> ---
>  include/asm-generic/vmlinux.lds.h | 12 +++++++++++
>  include/linux/kho/abi/luo.h       | 34 +++++++++++++++++++++++++++++++
>  include/linux/liveupdate.h        | 12 +++++++++++
>  kernel/liveupdate/luo_core.c      | 16 +++++++++++++++
>  4 files changed, 74 insertions(+)
>
> diff --git a/include/asm-generic/vmlinux.lds.h b/include/asm-generic/vmlinux.lds.h
> index 5659f4b5a125..aed4e282a78c 100644
> --- a/include/asm-generic/vmlinux.lds.h
> +++ b/include/asm-generic/vmlinux.lds.h
> @@ -359,6 +359,17 @@
>  #define THERMAL_TABLE(name)
>  #endif
>  
> +#ifdef CONFIG_LIVEUPDATE
> +#define LIVEUPDATE_FEATURES						\
> +	. = ALIGN(8);							\
> +	.liveupdate_features : AT(ADDR(.liveupdate_features) - LOAD_OFFSET) {	\
> +		KEEP(*(.liveupdate_sec_hdr))				\
> +		KEEP(*(.liveupdate_features))				\
> +	}
> +#else
> +#define LIVEUPDATE_FEATURES
> +#endif
> +
>  #define KERNEL_DTB()							\
>  	STRUCT_ALIGN();							\
>  	__dtb_start = .;						\
> @@ -554,6 +565,7 @@
>  	RO_EXCEPTION_TABLE						\
>  	NOTES								\
>  	BTF								\
> +	LIVEUPDATE_FEATURES						\
>  									\
>  	. = ALIGN((align));						\
>  	__end_rodata = .;
> diff --git a/include/linux/kho/abi/luo.h b/include/linux/kho/abi/luo.h
> index 0a7662a0cf9a..5b25e1b48cf5 100644
> --- a/include/linux/kho/abi/luo.h
> +++ b/include/linux/kho/abi/luo.h
> @@ -230,4 +230,38 @@ struct luo_flb_ser {
>  #define LIVEUPDATE_TEST_FLB_COMPATIBLE(i)	"liveupdate-test-flb-v" #i
>  #endif
>  
> +#define LIVEUPDATE_VER_HDR_MAGIC	0x4c565550 /* 'LVUP' */
> +#define LIVEUPDATE_VER_HDR_VER		1
> +
> +/**
> + * struct liveupdate_ver_hdr - Header of vmlinux section with version lists
> + * @magic:     Magic number ('LVUP').
> + * @version:   Version of the header format.
> + *
> + * This struct is the header for the vmlinux section ".liveupdate_features". The
> + * section contains the list of feature/version entries that the kernel supports.
> + */
> +struct liveupdate_ver_hdr {
> +	u32 magic;
> +	u32 version;

Should we do feature flags along with the version to extend in
backwards-compatible way?

> +} __packed;
> +
> +/**
> + * struct liveupdate_feature_entry - Live update feature/version entry
> + * @name:       Name of the subsystem or feature ("luo" for core).
> + * @feat_bytes: Number of bytes covered by supp, req, and active bitmaps (e.g. 8).
> + * @reserved:   Reserved / padding for alignment.
> + * @supp:       Bitmask of supported features.
> + * @req:        Bitmask of required features.
> + * @active:     Bitmask of active features.
> + */

How should we model FLB dependencies here? And how do we export FLB
capabilities?

> +struct liveupdate_feature_entry {
> +	char name[LIVEUPDATE_HNDL_COMPAT_LENGTH];
> +	u32 feat_bytes;
> +	u32 reserved;
> +	u64 supp;
> +	u64 req;
> +	u64 active;
> +} __packed;
> +
>  #endif /* _LINUX_KHO_ABI_LUO_H */
> diff --git a/include/linux/liveupdate.h b/include/linux/liveupdate.h
> index 6051abc0612c..e058df23fed1 100644
> --- a/include/linux/liveupdate.h
> +++ b/include/linux/liveupdate.h
> @@ -229,6 +229,16 @@ struct liveupdate_flb {
>  
>  #ifdef CONFIG_LIVEUPDATE
>  
> +#define LIVEUPDATE_FEATURE_ENTRY(_id, _name, _supp, _req, _active)	\
> +	static const struct liveupdate_feature_entry __lu_feat_##_id	\
> +	__used __section(".liveupdate_features") __aligned(8) = {	\
> +		.name       = _name,					\
> +		.feat_bytes = sizeof(u64),				\
> +		.supp       = (_supp),					\
> +		.req        = (_req),					\
> +		.active     = (_active),				\
> +	}
> +
>  /* Return true if live update orchestrator is enabled */
>  bool liveupdate_enabled(void);
>  
> @@ -259,6 +269,8 @@ int liveupdate_get_token_outgoing(struct liveupdate_session *s,
>  
>  #else /* CONFIG_LIVEUPDATE */
>  
> +#define LIVEUPDATE_FEATURE_ENTRY(_id, _name, _supp, _req, _active)
> +
>  static inline bool liveupdate_enabled(void)
>  {
>  	return false;
> diff --git a/kernel/liveupdate/luo_core.c b/kernel/liveupdate/luo_core.c
> index 6add1ecc463f..27413f895174 100644
> --- a/kernel/liveupdate/luo_core.c
> +++ b/kernel/liveupdate/luo_core.c
> @@ -64,6 +64,22 @@
>  #include "kexec_handover_internal.h"
>  #include "luo_internal.h"
>  
> +/*
> + * This is the header for the ".liveupdate_features" section in vmlinux.
> + * The linker makes sure that this header precedes the entries.
> + */
> +static const struct liveupdate_ver_hdr ver_hdr
> +	__used __section(".liveupdate_sec_hdr") __aligned(8) = {
> +	.magic   = LIVEUPDATE_VER_HDR_MAGIC,
> +	.version = LIVEUPDATE_VER_HDR_VER,
> +};
> +
> +/* Core LUO features */
> +LIVEUPDATE_FEATURE_ENTRY(luo_core, "luo",
> +			 LUO_CORE_FEATURES_SUPP,
> +			 LUO_CORE_FEATURES_REQ,
> +			 LUO_CORE_FEATURES_ACTIVE);
> +
>  static struct {
>  	bool enabled;
>  	struct luo_ser *luo_ser_out;

-- 
Regards,
Pratyush Yadav



More information about the kexec mailing list